本文发表时间已超过一年。较旧的文章可能包含过时的内容。请检查页面上的信息自发布以来是否已变得不正确。
Kubernetes 中感知拓扑的卷配置
在 Kubernetes 1.12 中,具有持久卷的多区域集群体验正在通过拓扑感知动态配置 beta 功能得到改进。此功能允许 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 规范。
入门
要启用此功能,您只需创建一个 volumeBindingMode
设置为 WaitForFirstConsumer
的 StorageClass。
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
- 跨越部分区域的 nodeAffinity
- 区域上的 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)。