本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
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)。