在Container Service for Kubernetes中,可以結合Gang調度能力以及拓撲感知調度能力,實現Pod在多個拓撲域中重試,直到找到一個能夠滿足整個作業拓撲域的功能。更進一步,可以結合Container Service for Kubernetes的節點池以及ECS的部署集能力,將Pod調度到屬於同一低延時部署集的ECS中,實現低維度拓撲域的親和調度。本文介紹如何?拓撲感知調度。
拓撲感知調度介紹
在機器學習或巨量資料分析類作業中,Pod與Pod間通常有較大的網路通訊需求。預設情況下,原生Kubernetes調度器會將Pod均勻打散在叢集的每台機器上,這樣會增大Pod間的通訊距離,導致作業完成時間變長。
為了最佳化此類作業的執行時間,一種有效辦法是將Pod盡量部署在同一個可用性區域,甚至在同一個機架上,通過減少Pod之間通訊的跳數減少Pod間網路通訊時延,從而減少作業執行時間。目前Kubernetes原生支援了通過NodeAffinity以及PodAffinity的方式實現Pod親和調度,然而原生的節點或Pod親和調度方式存在以下的弊端。
Pod無法做到在多個不同的拓撲域上進行重試。在原生Kubernetes親和調度策略中,作業會以其中第一個Pod的調度結果為準進行調度。若第一個Pod的調度位置無法滿足所有Pod的需求,則部分Pod將會處於Pending狀態,且後續調度時即使有其他拓撲域能夠滿足整個作業需求也不會進行可用性區域的變更。
當前節點上僅有可用性區域層級的標籤,即Pod調度時僅能夠調度親和到同一個可用性區域下,而無法做到更進一步的親和到更低維度拓撲域中。
在Container Service for Kubernetes中,可以結合Gang調度能力以及拓撲感知調度能力,實現Pod在多個拓撲域中重試,直到找到一個能夠滿足整個作業拓撲域的功能。更進一步,可以結合Container Service for Kubernetes的節點池以及ECS的部署集能力,將Pod調度到屬於同一低延時部署集的ECS中,實現低維度拓撲域的親和調度。
Pod在多個拓撲域中重試
Container Service for Kubernetes調度器kube-scheduler可以通過為作業添加Gang調度標識來限制Pod必須同時獲得需求的資源,並通過儲存之前的調度結果來實現在多個拓撲域中進行重試的效果。啟用該功能需要在Pod上同時添加以下標記。
在Pod Label中添加Gang調度標識。關於Gang調度的資訊,請參見使用Gang scheduling。
labels: pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu # tf-smoke-gpu是PodGroup的名稱,需要自訂。 pod-group.scheduling.sigs.k8s.io/min-available: "3" # 該值可以保持與作業的Pod數相等。
在Pod的Annotation中添加拓撲調度約束。
annotations: alibabacloud.com/topology-aware-constraint: {\"name\":\"test\",\"required\":{\"topologies\":[{\"key\":\"kubernetes.io/hostname\"}],\"nodeSelectors\":[{\"matchLabels\":{\"test\":\"abc\"}}]}}
alibabacloud.com/topology-aware-constraint
的值必須是一個合法的JSON字串,否則將無法正常解析拓撲調度約束,同時該值需要滿足以下結構。{ "name": xxx # 任意的名稱。 "required": { "topologies": [ { "key": xxx # 需要親和的拓撲域的Key。 } ], "nodeSelectors": [ { # 該結構可以參考kubernetes原生的nodeaffinity中labelSelector的結構。 "matchLabels": {}, "matchExpressions": {} } ] } }
在設定了上述例子後,所有的Pod將會在滿足
test=abc
的所有節點中尋找一個能夠調度所有帶有pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
標籤的Pod。最終結果如下所示:> capacity k get po -ojson | jq '.items[] | {"name":.metadata.name,"ann":.metadata.annotations["alibabacloud.com/topology-aware-constraint"], "node": spec.nodeName}' { "name": "nginx-deployment-basic-69f47fc6db-6****" "ann": "{\"name\": \"test\", \"required\": {\"topologies\":[{\"key\": \"kubernetes.io/hostname\"}], \"nodeSelectors\": [{\"matchLabels\": {\"test\": \"a\"}}]}} " "node": "cn-shenzhen.10.0.2.4" } { "name":"nginx-deployment-basic-69f47fc6db-h****" "ann": "{\"name\": \"test\", \"required\": {\"topologies\":[{\"key\": \"kubernetes.io/hostname\"}], \"nodeSelectors\": [{\"matchLabels\": {\"test\": \"a\"}}]}} " "node": "cn-shenzhen.10.0.2.4" } { "name":"nginx-deployment-basic-69f47fc6db-j****" "ann": "{\"name\": \"test\", \"required\": {\"topologies\":[{\"key\": \"kubernetes.io/hostname\"}], \"nodeSelectors\": [{\"matchLabels\": {\"test\": \"a\"}}]}} " "node": "cn-shenzhen.10.0.2.4" } { "name":"nainx-deployment-basic-69f47fc6db-I****" "ann": "{\"name\": \"test\", \"required\": {\"topologies\":[{\"key\": \"kubernetes.io/hostname\"}], \"nodeSelectors\": [{\"matchLabels\": {\"test\": \"a\"}}]}} " "node": "cn-shenzhen.10.0.2.4" } { "name" :"nainx-deplovment-basic-69f47fc6db-x****" "ann": "{\"name\": \"test\", \"required\": {\"topologies\":[{\"key\": \"kubernetes.io/hostname\"}], \"nodeSelectors\": [{\"matchLabels\": {\"test\": \"a\"}}]}} " "node": "cn-shenzhen.10.0.2.4" }
將Pod調度到同一低延時部署集中
在一些特定情境中,僅僅在某一可用性區域中親和並不能滿足作業的需求,作業需要在更低維度拓撲域中親和來達成更優的效能。ECS提供了部署集的功能,您可以通過申明低延時部署集來限制ECS節點的建立位置。關於在ACK中使用部署集的相關資訊,請參見節點池部署集最佳實務。
當需要建立關聯一個低延時部署集的節點池時,您還需要在節點池的節點標籤中添加您自訂的節點標籤,用於將低延時部署集的節點池與其他節點池做區分,如下圖所示。
完成上述步驟後,您可以通過以下Annotation以及Label來申明一個低延時部署集中調度的作業。
在Pod Label中添加Gang調度標識。關於Gang調度的資訊,請參見使用Gang scheduling。
labels: pod-group.scheduling.sigs.k8s.io/name: xxx # xxx是PodGroup的名稱,需要自訂。 pod-group.scheduling.sigs.k8s.io/min-available: "x" # 該值可以保持與作業的Pod數相等。
在Pod的Annotation中添加拓撲調度約束。
重要該例子中的
matchLabels
需要更換成您自訂的低延時部署集的節點標籤,name
也需要按需修改。annotations: alibabacloud.com/topology-aware-constraint: {\"name\":\"test\",\"required\":{\"topologies\":[{\"key\":\"alibabacloud.com/nodepool-id\"}],\"nodeSelectors\":[{\"matchLabels\":{\"np-type\":\"low-latency\"}}]}}