本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

Kubernetes 中的拓撲感知卷製備

透過拓撲感知動態卷供應 Beta 版功能,Kubernetes 1.12 中多區域叢集與持久卷的體驗得到了改進。此功能允許 Kubernetes 在動態供應卷時做出智慧決策,透過排程器輸入來確定為 Pod 供應卷的最佳位置。在多區域叢集中,這意味著卷將在適合執行 Pod 的區域中供應,讓您能夠輕鬆地跨故障域部署和擴充套件有狀態工作負載,以提供高可用性和容錯能力。

以往的挑戰

在此功能之前,在多區域叢集中使用區域持久磁碟(例如 AWS ElasticBlockStore、Azure Disk、GCE PersistentDisk)執行有狀態工作負載面臨許多挑戰。動態供應與 Pod 排程是獨立處理的,這意味著一旦您建立了 PersistentVolumeClaim (PVC),就會立即供應卷。這意味著供應器不知道哪些 Pod 正在使用該卷,以及它可能對排程產生影響的任何 Pod 約束。

這導致 Pod 無法排程,因為卷在以下區域中供應:

  • 沒有足夠的 CPU 或記憶體資源來執行 Pod
  • 與節點選擇器、Pod 親和性或反親和性策略衝突
  • 由於汙點而無法執行 Pod

另一個常見問題是,使用多個持久卷的非 StatefulSet Pod 可能會在不同的區域中供應每個卷,再次導致 Pod 無法排程。

次優的解決方案包括節點過度供應或在正確區域手動建立卷,這使得動態部署和擴充套件有狀態工作負載變得困難。

拓撲感知動態供應功能解決了上述所有問題。

支援的卷型別

在 1.12 中,以下驅動程式支援拓撲感知動態供應:

  • AWS EBS
  • Azure Disk
  • GCE PD(包括區域 PD)
  • CSI (alpha) - 目前只有 GCE PD CSI 驅動程式實現了拓撲支援

設計原則

雖然最初支援的外掛都基於區域,但我們設計此功能以符合 Kubernetes 在不同環境之間可移植性的原則。拓撲規範是通用的,並使用類似於 Pod nodeSelectors 和 nodeAffinity 中的基於標籤的規範。此機制允許您定義自己的拓撲邊界,例如本地叢集中的機架,而無需修改排程器來理解這些自定義拓撲。

此外,拓撲資訊從 Pod 規範中抽象出來,因此 Pod 不需要了解底層儲存系統的拓撲特性。這意味著您可以在多個叢集、環境和儲存系統中使用相同的 Pod 規範。

入門

要啟用此功能,您只需建立一個 StorageClass,並將 volumeBindingMode 設定為 WaitForFirstConsumer

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: topology-aware-standard
provisioner: kubernetes.io/gce-pd
volumeBindingMode: WaitForFirstConsumer
parameters:
  type: pd-standard

此新設定指示卷供應器不要立即建立卷,而是等待使用相關 PVC 的 Pod 執行排程。請注意,以前的 StorageClass zonezones 引數不再需要指定,因為 Pod 策略現在決定在哪個區域供應卷。

接下來,使用此 StorageClass 建立一個 Pod 和 PVC。此序列與以前相同,但 PVC 中指定了不同的 StorageClass。以下是一個假設示例,透過指定許多 Pod 約束和排程策略來演示新功能的能力:

  • 一個 Pod 中的多個 PVC
  • 跨區域子集的節點親和性
  • 區域上的 Pod 反親和性
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:   
  serviceName: "nginx"
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: failure-domain.beta.kubernetes.io/zone
                operator: In
                values:
                - us-central1-a
                - us-central1-f
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - nginx
            topologyKey: failure-domain.beta.kubernetes.io/zone
      containers:
      - name: nginx
        image: gcr.io/google_containers/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
        - name: logs
          mountPath: /logs
 volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: topology-aware-standard
      resources:
        requests:
          storage: 10Gi
  - metadata:
      name: logs
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: topology-aware-standard
      resources:
        requests:
          storage: 1Gi

之後,您可以看到卷是根據 Pod 設定的策略在區域中供應的。

$ kubectl get pv -o=jsonpath='{range .items[*]}{.spec.claimRef.name}{"\t"}{.metadata.labels.failure\-domain\.beta\.kubernetes\.io/zone}{"\n"}{end}'
www-web-0       us-central1-f
logs-web-0      us-central1-f
www-web-1       us-central1-a
logs-web-1      us-central1-a

我如何瞭解更多資訊?

有關拓撲感知動態供應功能的官方文件可在此處獲取:這裡

CSI 驅動程式的文件可在此處獲取:https://kubernetes-csi.github.io/docs/

下一步是什麼?

我們正在積極努力改進此功能以支援:

  • 更多卷型別,包括本地卷的動態供應
  • 每個節點的動態卷可連線數量和容量限制

我如何參與?

如果您對此功能有反饋或有興趣參與設計和開發,請加入 Kubernetes 儲存特別興趣小組 (SIG)。我們正在迅速發展,並始終歡迎新的貢獻者。

特別感謝所有幫助將此功能帶到 Beta 版的貢獻者,包括 Cheng Xing (verult)、Chuqiang Li (lichuqiang)、David Zhu (davidz627)、Deep Debroy (ddebroy)、Jan Šafránek (jsafrane)、Jordan Liggitt (liggitt)、Michelle Au (msau42)、Pengfei Ni (feiskyer)、Saad Ali (saad-ali)、Tim Hockin (thockin) 和 Yecheng Fu (cofyc)。