在機器學習或大數據分析類作業中,Pod與Pod間通常有較大的網絡通信需求。在默認情況下原生Kubernetes調度器會將Pod均勻打散在集群的每臺機器上,但是這樣會增大Pod間的通信距離,導致作業完成時間變長。在靈駿集群中可以通過網絡拓撲感知調度,將Pod聲明調度到相同的一層轉發域或二層轉發域下,以此減少機器間的網絡通信時延,進而縮短作業完成時間。
方案概述
網絡拓撲感知調度通過貪心策略將任務放置在跨越更少拓撲的節點上。
假設當前靈駿集群中存在Pod和ASW兩層網絡拓撲,ASW為靈駿機器的直接接口,Pod為范圍更大的網絡拓撲,所以跨靈駿節點的網絡傳輸需要至少1跳的網絡轉發,跨ASW的網絡傳輸需要至少2跳的網絡轉發。
若您提交了一個需要兩臺節點的任務,網絡拓撲感知調度會將任務放置在Node A-B或Node E-F上。
若您提交了一個需要四臺節點的任務,網絡拓撲感知調度會將任務放置在Node A-D或Node E-H上。
在ACK靈駿集群中,如何判斷節點之間是否在相同的ASW下或相同的Pod下呢?
您可以查看節點上已配置包含網絡位置信息的標簽alibabacloud.com/asw-id
和alibabacloud.com/point-of-delivery
。
聲明配置拓撲結構
在靈駿集群中使用網絡拓撲感知調度,需要定義集群級別的拓撲調度需求,最后在任務中標識網絡拓撲感知調度信息。
創建
cluster-network-topology.yaml
聲明兩級的拓撲結構。apiVersion: scheduling.koordinator.sh/v1alpha1 kind: ClusterNetworkTopology metadata: # 保持不變 name: default spec: networkTopologySpec: # parentTopologyLayer用于聲明上層拓撲結構 - parentTopologyLayer: ASWTopologyLayer # 定義節點級別拓撲,最低一級必須為NodeTopologyLayer topologyLayer: NodeTopologyLayer # 以下部分定義跨機網絡拓撲,通常不需要進行修改 - labelKey: - alibabacloud.com/point-of-delivery topologyLayer: PoDTopologyLayer - labelKey: - alibabacloud.com/asw-id parentTopologyLayer: PoDTopologyLayer topologyLayer: ASWTopologyLayer
創建
sample-network-topology.yaml
聲明任務中的網絡拓撲感知調度需求。apiVersion: scheduling.koordinator.sh/v1alpha1 kind: JobNetworkTopology metadata: labels: network-topology-permit-wait-time: "999999" # 任務名稱 name: sample-network-topology # 任務所在命名空間 namespace: sample-network-topology spec: topologyStrategy: # 允許跨ASW調度 - layer: ASWTopologyLayer # 當前支持PreferGather以及MustGather兩種策略。PreferGather表示Pod調度可以跨該拓撲 # 進行調度,MustGather表示Pod只能調度在相同的該拓撲下 strategy: PreferGather - layer: NodeTopologyLayer strategy: PreferGather # 不允許跨Pod調度 - layer: PoDTopologyLayer strategy: MustGather # 任務的Pod數量 workerNum: 2
創建
pi.yaml
標識網絡拓撲感知調度信息。提交任務時需要指定關聯的
JobNetworkTopology
信息。apiVersion: batch/v1 kind: Job metadata: name: pi spec: # 任務的Pod數量,保持與JobNetworkTopology中的數量一致 parallelism: 2 template: metadata: labels: # 任務的Pod數量,保持與JobNetworkTopology中的數量一致 pod-group.scheduling.sigs.k8s.io/min-available: "2" pod-group.scheduling.sigs.k8s.io/name: sample-gang # 引用剛剛提交的任務拓撲信息 network-topology-job-name: sample-network-topology network-topology-job-namespace: sample-network-topology spec: schedulerName: default-scheduler containers: - name: pi image: perl:5.34.0 command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] resources: limits: # 示例中使用單卡作為示例,實際使用中可按需填寫 nvidia.com/gpu: 1 restartPolicy: Never backoffLimit: 4
執行命令在集群中部署上述YAML文件。
kubectl apply -f cluster-network-topology.yaml kubectl apply -f sample-network-topology.yaml kubectl apply -f pi.yaml
調度效果展示
通過kubectl連接集群獲取當前網絡拓撲結構信息。
在靈駿集群中,集群中組件lingjun-networktopology-collector從節點上采集并以label的方式標記在節點上。
而對于其他節點或其他類型集群,需要您手動標記label,標記時使用的labelkey需要與上文中ClusterNetworkTopology中的labelKey對應。
# network topology is like: # test-pod-1 test-pod-2 # / | \ | # test-1 test-2 test-3 test-4 # / \ | | | # 0.12 0.14 0.15 0.16 0.17 ? network kubectl get no -l alibabacloud.com/asw-id,alibabacloud.com/point-of-delivery -ojson | jq '.items[] | {"Name":.metadata.name, "ASW":.metadata.labels."alibabacloud.com/asw-id", "POD":.metadata.labels."alibabacloud.com/point-of-delivery"}' { "Name": "cn-hongkong.10.1.0.12", "ASW": "test-1", "POD": "test-pod-1" } { "Name": "cn-hongkong.10.1.0.14", "ASW": "test-1", "POD": "test-pod-1" } { "Name": "cn-hongkong.10.1.0.15", "ASW": "test-2", "POD": "test-pod-1" } { "Name": "cn-hongkong.10.1.0.16", "ASW": "test-3", "POD": "test-pod-1" } { "Name": "cn-hongkong.10.1.0.17", "ASW": "test-4", "POD": "test-pod-2" }
提交上文中配置的Job任務,可以看到任務運行在test-1下的兩個節點上。
? kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pi-8p89l 1/1 Running 0 4s 172.30.240.197 cn-hongkong.10.1.0.14 <none> <none> pi-p8swv 0/1 ContainerCreating 0 4s <none> cn-hongkong.10.1.0.12 <none> <none>
若將任務中的Pod數量設置為4。
(需要同時更改上文Job的parallelism以及label中的pod-group.scheduling.sigs.k8s.io/min-available和JobNetworkTopology的workerNum),可以看到只有test-pod-2上的節點沒有被調度。
? kubectl get pod -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES pi-2kwq9 1/1 Running 0 4s 172.30.241.123 cn-hongkong.10.1.0.12 <none> <none> pi-87hm5 0/1 ContainerCreating 0 4s <none> cn-hongkong.10.1.0.16 <none> <none> pi-bsvx8 1/1 Running 0 4s 172.30.240.198 cn-hongkong.10.1.0.14 <none> <none> pi-dvwhl 0/1 ContainerCreating 0 4s <none> cn-hongkong.10.1.0.15 <none> <none>
若將任務中的Pod數量設置為5。
(需要同時更改上文Job的parallelism以及label中的pod-group.scheduling.sigs.k8s.io/min-available和JobNetworkTopology的workerNum),可以看到任務調度失敗,其中第一個調度的Pod中帶有調度失敗信息,其中說明了調度失敗是由于跨Pod調度被禁止(
all fail topology paths by MustGather reason: [path:RootNode->test-pod-1, freeSlotNum:4], [path:RootNode->DefaultTopologyName, freeSlotNum:0], [path:RootNode->test-pod-2, freeSlotNum:1]
)。? kubectl get pod NAME READY STATUS RESTARTS AGE pi-75qf5 0/1 Pending 0 2s pi-8k4nd 0/1 Pending 0 2s pi-b2pmc 0/1 Pending 0 2s pi-n7c2b 0/1 Pending 0 2s pi-wf4zn 0/1 Pending 0 2s ? kubectl get pod -ojson | jq '.items[].status' { "conditions": [ { "lastProbeTime": null, "lastTransitionTime": "2024-05-29T07:46:27Z", "message": "0/6 nodes are available: 1 Insufficient nvidia.com/gpu, 1 [NetworkTopology begin] cluster total nodes:6, 5 node provide 5 freeSlot, 1 node unavailable cause Insufficient nvidia.com/gpu, job desireNum:5, all fail topology paths by MustGather reason: [path:RootNode->test-pod-1, freeSlotNum:4], [path:RootNode->DefaultTopologyName, freeSlotNum:0], [path:RootNode->test-pod-2, freeSlotNum:1] [NetworkTopology end], 4 NetworkTopology bestPlan empty. network topology job sample-network-topology/sample-network-topology gets rejected due to pod is unschedulable, preemption: 0/6 nodes are available: 1 No victims found on node cn-hongkong.10.1.0.10 for preemptor pod pi-75qf5, 5 Preemption is not helpful for scheduling..", "reason": "Unschedulable", "status": "False", "type": "PodScheduled" } ], "phase": "Pending", "qosClass": "BestEffort" } { "phase": "Pending", "qosClass": "BestEffort" } { "phase": "Pending", "qosClass": "BestEffort" } { "phase": "Pending", "qosClass": "BestEffort" } { "phase": "Pending", "qosClass": "BestEffort" }