高可用以及高性能是分布式任務執行過程中的重要要求。在ACK集群Pro版中,您可以通過Kubernetes原生調度語義實現分布式任務的跨可用區打散,以達到高可用區部署的要求,或者通過Kubernetes原生調度語義實現分布式任務在指定可用區中的親和性部署,以達到高性能部署的要求。
前提條件
已創建ACK集群Pro版,且集群版本為v1.20及以上。具體操作,請參見創建Kubernetes托管版集群。
已確保ACK集群Pro版中Kube Scheduler組件版本滿足以下要求。
ACK集群Pro版版本
Kube Scheduler最低版本要求
1.28
1.28.3-aliyun-5.9
1.26
1.26.3-aliyun-5.9
1.24
1.24.6-aliyun-5.9
1.22
1.22.15-aliyun-5.9
低于1.22
說明為了實現ECI Pod可用區打散以及親和調度,請手動升級集群。
不支持
說明為實現ECI Pod可用區打散以及親和調度,請升級Kube Scheduler組件。相關操作,請參見kube-scheduler。
調度ECI Pod時,已在ECI Profile中配置當前期望調度的目標可用區vSwitch。具體操作,請參見配置eci-profile。
已確保Pod中帶有
nodeAffinity
、podAffinity
和topologySpreadConstraints
字段或存在匹配的ResourcePolicy。說明若您希望Pod能夠調度到Arm架構的Virtual Node上,需要在Pod上添加對應污點的污點容忍字段
tolerations
。已開啟集群虛擬節點調度策略,且集群版本、組件版本符合要求。
注意事項
調度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可用區打散以及親和調度
下文將在v1.22版本的ACK集群Pro版中演示ECI Pod可用區打散以及親和調度功能。
示例一:通過拓撲分布約束(Topology Spread Constraints)實現跨可用區打散
在工作負載申明中增加拓撲分布約束。
Pod的
Spec
字段中或Deployment、Job等工作負載的PodTemplate的Spec
字段中,可以通過以下方式申明一個拓撲分布約束。topologySpreadConstraints: - maxSkew: <integer> minDomains: <integer> # 可選,從v1.25開始成為Beta。 topologyKey: <string> whenUnsatisfiable: <string> labelSelector: <object> matchLabelKeys: <list> # 可選,從v1.27開始成為Beta。 nodeAffinityPolicy: [Honor|Ignore] # 可選,從v1.26開始成為Beta。 nodeTaintsPolicy: [Honor|Ignore] # 可選,從v1.26開始成為Beta。
本示例將創建一個在多個可用區上均勻分布的Deployment。以下為該Deployment的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 "<none>"
通過以下命令查看生產出的Pod在各個可用區中的數量。
kubectl get po -lapp=with-pod-topology-spread -ocustom-columns=NODE:.spec.nodeName --no-headers | grep -v "<none>" | xargs -I {} kubectl get no {} -ojson | jq '.metadata.labels["topology.kubernetes.io/zone"]' | sort | uniq -c
示例二:通過nodeAffinity和podAffinity實現可用區親和
在工作負載申明中增加親和性約束。
本示例將創建在單個可用區上聚集分布的Deployment。以下為該Deployment的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 "<none>"
通過以下命令查看生產出的Pod在各個可用區中的數量。
kubectl get po -lapp=with-affinity -ocustom-columns=NODE:.spec.nodeName --no-headers | grep -v "<none>" | 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
。詳細信息,請參見分布約束定義。