本文發表於一年多前。舊文章可能包含過時內容。請檢查頁面中的資訊自發布以來是否已變得不正確。
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 zone
和 zones
引數不再需要指定,因為 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)。