高可用以及高性能是分布式任务执行过程中的重要要求。在ACK Pro版集群中,您可以通过Kubernetes原生调度语义实现分布式任务的跨可用区打散,以达到高可用区部署的要求,或者通过Kubernetes原生调度语义实现分布式任务在指定可用区中的亲和性部署,以达到高性能部署的要求。本文介绍如何实现ECI Pod可用区打散以及亲和调度。
说明
本文功能目前处于白名单测试阶段,请提交工单后使用。
索引
-
前提条件
-
注意事项
-
相关概念
-
实现ECI Pod可用区打散以及亲和调度
-
示例一:通过拓扑分布约束(Topology Spread Constraints)实现跨可用区打散
-
示例二:通过nodeAffinity和podAffinity实现可用区亲和
-
-
ECI严格拓扑打散功能介绍
前提条件
-
已安装ACK Pro版集群,且集群版本高于1.20。详细信息,请参见创建Kubernetes托管版集群。
-
已确保ACK Pro版集群中Kube Scheduler组件版本满足以下表格中的要求。
ACK Pro版集群版本
Kube Scheduler最低版本要求
1.26.x
1.26.3-aliyun-5.2
1.24.x
1.24.6-aliyun-5.2
1.22.x
1.22.15-aliyun-5.2
低于1.22
说明
为了实现ECI Pod可用区打散以及亲和调度,建议您升级集群。相关操作,请参见升级ACK集群K8s版本。
不支持
说明
为了实现ECI Pod可用区打散以及亲和调度,建议您升级Kube Scheduler组件。相关操作,请参见kube-scheduler。
-
调度ECI Pod时,已确保您当前期望调度的目标可用区vSwitch已在ECI Profile中完成配置。
-
仅当Pod中带有Node亲和
nodeAffinity
、Pod亲和podAffinity
、污点容忍tolerations
和拓扑打散topologySpreadConstraints
四类字段或存在匹配的ResourcePolicy时才会启用该功能。
注意事项
-
调度ECI Pod时,目前仅支持设置
topologyKey
为topology.kubernetes.io/zone
的用法。 -
调度ECI Pod时,不支持通过Annotation的方式设定ECI Pod的vSwitch顺序。当Pod申明了vSwitch顺序时,该功能将被自动禁用。
-
调度ECI Pod不支持与FastFailed模式同时使用。当Pod申明了FastFailed模式时,该功能将被自动禁用。
相关概念
-
关于打散部署以及亲和部署的详细说明,请参见官方文档拓扑分布约束和将Pod指派给节点。
-
NodeAffinity
-
PodAffinity
-
maxSkew
实现ECI Pod可用区打散以及亲和调度
下文将在1.22版本的ACK Pro版本集群中演示ECI Pod可用区打散以及亲和调度功能。
示例一:通过拓扑分布约束(Topology Spread Constraints)实现跨可用区打散
-
在工作负载申明中增加拓扑分布约束。
Pod的
Spec
字段中或Deployment、Job等工作负载的PodTemplate的Spec
字段中,可以通过以下方式申明一个拓扑分布约束。topologySpreadConstraints: - maxSkew: minDomains: # 可选,从v1.25开始成为Beta。 topologyKey: whenUnsatisfiable: labelSelector:
本示例将创建一个在多个可用区上均匀分布的Deployment。以下为该Deployment的YAML文件。
展开查看YAML文件
apiVersion: apps/v1 kind: Deployment metadata: name: with-pod-topology-spread labels: app: with-pod-topology-spread spec: replicas: 10 selector: matchLabels: app: with-pod-topology-spread template: metadata: labels: app: with-pod-topology-spread spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: type operator: NotIn values: - virtual-kubelet topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: with-pod-topology-spread tolerations: - key: "virtual-kubelet.io/provider" operator: "Exists" effect: "NoSchedule" containers: - name: with-pod-topology-spread image: registry.k8s.io/pause:2.0 resources: requests: cpu: "1" memory: "256Mi"
参数
说明
preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: type operator: NotIn values: - virtual-kubelet
表示Pod将优先被调度到ECS节点上。
关于参数的详细信息,请参见节点亲和性。
topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: with-pod-topology-spread
表示Pod必须在多个可用区上均匀部署。
关于参数的详细信息,请参见topologySpreadConstraints字段。
tolerations: - key: "virtual-kubelet.io/provider" operator: "Exists" effect: "NoSchedule"
调度器容忍了Virtual Node上的污点,使得Pod能够被调度到Virtual Node上。
关于参数的详细信息,请参见容忍度。
说明
若您希望Pod能够调度到Arm架构的Virtual Node上,需要在Pod上添加对应污点的污点容忍。
-
创建工作负载。
将上面的代码保存为
deployment.yaml
,并执行以下命令将Deployment提交到集群中。kubectl apply -f deployment.yaml
-
验证工作负载调度结果。
-
通过以下命令查看生产出的Pod所在的节点。
kubectl get po -lapp=with-pod-topology-spread -ocustom-columns=NAME:.metadata.name,NODE:.spec.nodeName --no-headers | grep -v ""
-
通过以下命令查看生产出的Pod在各个可用区中的数量。
kubectl get po -lapp=with-pod-topology-spread -ocustom-columns=NODE:.spec.nodeName --no-headers | grep -v "" | xargs -I {} kubectl get no {} -ojson | jq '.metadata.labels["topology.kubernetes.io/zone"]' | sort | uniq -c
-
示例二:通过nodeAffinity和podAffinity实现可用区亲和
-
在工作负载申明中增加亲和性约束。
本示例将创建在单个可用区上聚集分布的Deployment。以下为该Deployment的YAML文件。
展开查看YAML文件
apiVersion: apps/v1 kind: Deployment metadata: name: with-affinity labels: app: with-affinity spec: replicas: 3 selector: matchLabels: app: with-affinity template: metadata: labels: app: with-affinity spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - with-affinity topologyKey: topology.kubernetes.io/zone nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: type operator: NotIn values: - virtual-kubelet tolerations: - key: "virtual-kubelet.io/provider" operator: "Exists" effect: "NoSchedule" containers: - name: with-affinity image: registry.k8s.io/pause:2.0
参数
说明
podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - with-affinity topologyKey: topology.kubernetes.io/zone
表示Pod必须部署在单个可用区上。
关于参数的详细信息,请参见节点亲和性。
nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: type operator: NotIn values: - virtual-kubelet
表示Pod将优先被调度到ECS节点上。
关于参数的详细信息,请参见节点亲和性。
tolerations: - key: "virtual-kubelet.io/provider" operator: "Exists" effect: "NoSchedule"
调度器容忍了Virtual Node上的污点,使得Pod能够被调度到Virtual Node上。
关于参数的详细信息,请参见容忍度。
若您希望指定可用区进行部署,可以将示例中的
podAffinity
删去,在nodeAffinity
添加如下约束。下方约束表明Pod必须在可用区cn-beijing-a上进行部署。requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: topology.kubernetes.io/zone operator: In values: - cn-beijing-a
-
创建工作负载。
将上面的代码保存为
deployment.yaml
,并执行以下命令将Deployment提交到集群中。kubectl apply -f deployment.yaml
-
验证工作负载调度结果。
-
通过以下命令查看生产出的Pod所在的节点。
kubectl get po -lapp=with-affinity -ocustom-columns=NAME:.metadata.name,NODE:.spec.nodeName --no-headers | grep -v ""
-
通过以下命令查看生产出的Pod在各个可用区中的数量。
kubectl get po -lapp=with-affinity -ocustom-columns=NODE:.spec.nodeName --no-headers | grep -v "" | xargs -I {} kubectl get no {} -ojson | jq '.metadata.labels["topology.kubernetes.io/zone"]' | sort | uniq -c
-
ECI严格拓扑打散功能介绍
在保持默认状态不变的情况下,当配置了强制打散约束时,Scheduler会将所有Pod均匀放置到所有可用区上,但并不考虑ECI Pod的生产结果。如下图所示,假设将打散功能的maxSkew设置为1。关于maxSkew,请参见maxSkew。
此时若可用区B和C中生产ECI Pod失败,则可用区A上会放置2个ECI Pod,其他两个可用区没有ECI Pod,从而破坏打散功能的maxSkew约束。
当严格拓扑打散功能开启后,在ACK Pro版集群中,调度器将严格保证Pod的强制打散需求得到满足。Scheduler会在可用区A、B、C上各放置1个Pod,剩下的Pod将处于Pending状态,等待现有Pod生产,如下图所示。
当PodA1生产成功后,Pending状态的Pod将继续Pending,这是由于可用区B以及可用区C上的ECI Pod仍然可能生产失败,Pod放置于任意可用区仍然可能导致生产结束后破坏maxSkew约束。当PodB1生产成功后,Scheduler将会放置一个Pod在可用区C。如下图所示,其中橙色背景的Pod为生产完成的Pod。
若您不需要严格拓扑打散功能,请将拓扑打散约束中的调度条件whenUnsatisfiable
设置为ScheduleAnyway
。详细信息,请参见分布约束定义。
内容没看懂? 不太想学习?想快速解决? 有偿解决: 联系专家
阿里云企业补贴进行中: 马上申请
腾讯云限时活动1折起,即将结束: 马上收藏
同尘科技为腾讯云授权服务中心。
购买腾讯云产品享受折上折,更有现金返利:同意关联,立享优惠
转转请注明出处:https://www.yunxiaoer.com/171624.html