在機器學習或巨量資料分析類作業中,Pod與Pod間通常有較大的網路通訊需求。在預設情況下原生Kubernetes調度器會將Pod均勻打散在叢集的每台機器上,但是這樣會增大Pod間的通訊距離,導致作業完成時間變長。在ACK靈駿叢集中可以通過網路拓撲感知調度,將Pod聲明調度到相同的一層轉寄域或二層轉寄域下,以此減少機器間的網路通訊時延,進而縮短作業完成時間。
方案概述
網路拓撲感知調度通過貪心策略將任務放置在跨越更少拓撲的靈駿節點上。
假設當前ACK靈駿叢集中存在PoD(Point of Delivery)和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。
聲明配置拓撲結構
在ACK靈駿叢集中使用網路拓撲感知調度,需要定義叢集層級的拓撲調度需求,最後在任務中標識網路拓撲感知調度資訊。
建立
cluster-network-topology.yaml聲明兩級的拓撲結構。建立
sample-network-topology.yaml聲明任務中的網路拓撲感知調度需求。建立
pi.yaml標識網路拓撲感知調度資訊。提交任務時需要指定關聯的
JobNetworkTopology資訊。執行命令在叢集中部署上述YAML檔案。
kubectl apply -f cluster-network-topology.yaml kubectl apply -f sample-network-topology.yaml kubectl apply -f pi.yaml
調度效果展示
通過kubectl串連叢集擷取當前網路拓撲結構資訊。
在ACK靈駿叢集中,叢集中組件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" }