Pada beban kerja pelatihan AI terdistribusi dan data besar, Pod berkomunikasi secara intensif. Penjadwal Kubernetes default menyebarluaskan Pod secara merata di seluruh node, sehingga Pod dapat berakhir di node yang dipisahkan oleh beberapa lompatan sakelar—setiap lompatan tambahan meningkatkan latensi dan mengurangi throughput. Penjadwalan sadar topologi jaringan mengatasi hal ini dengan menetapkan semua Pod dalam suatu pekerjaan ke node dalam domain forwarding Layer 1 atau Layer 2 yang sama, meminimalkan jumlah lompatan sakelar dan mempercepat penyelesaian pekerjaan.
Cara kerja
Penjadwalan sadar topologi jaringan menggunakan algoritma greedy untuk menetapkan pekerjaan ke node Lingjun dengan rentang topologis minimal.
Kluster ACK Lingjun memiliki topologi jaringan dua tingkat:
Access Switch (ASW): antarmuka langsung untuk node Lingjun. Node di bawah ASW yang sama memerlukan setidaknya satu lompatan untuk berkomunikasi.
Point of Delivery (Pod): pengelompokan topologi tingkat atas yang mencakup beberapa ASW. Node di bawah ASW berbeda dalam Pod yang sama memerlukan setidaknya dua lompatan.
Semakin sedikit lapisan sakelar di antara node, semakin rendah latensinya. Penjadwal berusaha menempatkan semua Pod pada tingkat topologi serendah mungkin terlebih dahulu:
Pekerjaan 2-node: ditetapkan ke node dalam ASW yang sama (misalnya, Pasangan Node A-B atau E-F).
Pekerjaan 4-node: ditetapkan ke node dalam Pod yang sama (misalnya, Pasangan Node A-D atau E-H).
Label node menunjukkan ASW dan Pod tempat node tersebut berada:
alibabacloud.com/asw-id: mengidentifikasi ASW.alibabacloud.com/point-of-delivery: mengidentifikasi Pod.
Di kluster ACK Lingjun, komponen lingjun-networktopology-collector secara otomatis mengumpulkan informasi ini dan menerapkan label tersebut ke node Lingjun. Untuk jenis node atau jenis kluster lainnya, tambahkan label secara manual dan pastikan kunci label sesuai dengan nilai labelKey dalam konfigurasi ClusterNetworkTopology Anda.
Strategi penjadwalan
Dua strategi mengatur seberapa ketat Pod dikelompokkan dalam satu tingkat topologi:
| Strategi | Perilaku |
|---|---|
PreferGather | Mengelompokkan Pod dalam lapisan jika memungkinkan; mengizinkan penjadwalan lintas lapisan jika sumber daya tidak mencukupi |
MustGather | Mengharuskan semua Pod berada dalam lapisan yang sama; penjadwalan gagal jika tidak ada satu lapisan pun yang dapat menampung pekerjaan tersebut |
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
Kluster ACK Lingjun
kubectl yang dikonfigurasi untuk terhubung ke kluster
Node yang cukup dengan label topologi yang telah diterapkan
Konfigurasi dan deploy penjadwalan sadar topologi jaringan
Mengonfigurasi penjadwalan sadar topologi jaringan memerlukan tiga file YAML: satu yang mendefinisikan struktur topologi tingkat kluster, satu yang menyatakan batasan penjadwalan untuk pekerjaan tertentu, dan satu lagi untuk pekerjaan itu sendiri.
Langkah 1: Definisikan topologi kluster
Buat cluster-network-topology.yaml untuk mendeklarasikan struktur topologi dua tingkat untuk kluster:
apiVersion: scheduling.koordinator.sh/v1alpha1
kind: ClusterNetworkTopology
metadata:
# Jangan ubah.
name: default
spec:
networkTopologySpec:
# parentTopologyLayer mendeklarasikan struktur topologi tingkat atas.
- parentTopologyLayer: ASWTopologyLayer
# Tingkat terendah harus berupa NodeTopologyLayer untuk node Lingjun.
topologyLayer: NodeTopologyLayer
# Berikut ini mendefinisikan pemetaan topologi lintas lapisan. Biasanya, tidak perlu dimodifikasi.
- labelKey:
- alibabacloud.com/point-of-delivery
topologyLayer: PoDTopologyLayer
- labelKey:
- alibabacloud.com/asw-id
parentTopologyLayer: PoDTopologyLayer
topologyLayer: ASWTopologyLayerLangkah 2: Deklarasikan batasan topologi pekerjaan
Buat sample-network-topology.yaml untuk menentukan strategi penjadwalan pada setiap tingkat topologi:
apiVersion: scheduling.koordinator.sh/v1alpha1
kind: JobNetworkTopology
metadata:
labels:
network-topology-permit-wait-time: "999999"
# Nama pekerjaan.
name: sample-network-topology
# Namespace tempat pekerjaan berada.
namespace: sample-network-topology
spec:
topologyStrategy:
# PreferGather: mengizinkan penjadwalan lintas-ASW jika sumber daya tidak mencukupi.
- layer: ASWTopologyLayer
strategy: PreferGather
- layer: NodeTopologyLayer
strategy: PreferGather
# MustGather: penjadwalan lintas-Pod tidak diizinkan.
- layer: PoDTopologyLayer
strategy: MustGather
# Harus sesuai dengan spec.parallelism dan pod-group.scheduling.sigs.k8s.io/min-available dalam manifes Pekerjaan.
workerNum: 2Langkah 3: Buat pekerjaan
Buat pi.yaml untuk mendefinisikan pekerjaan dan mereferensikan batasan topologi:
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
# Harus sesuai dengan workerNum dalam JobNetworkTopology.
parallelism: 2
template:
metadata:
labels:
# Harus sesuai dengan workerNum dalam JobNetworkTopology.
pod-group.scheduling.sigs.k8s.io/min-available: "2"
pod-group.scheduling.sigs.k8s.io/name: sample-gang
# Referensikan JobNetworkTopology yang dibuat pada Langkah 2.
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:
# Contoh ini menggunakan satu GPU. Sesuaikan sesuai kebutuhan.
nvidia.com/gpu: 1
restartPolicy: Never
backoffLimit: 4Langkah 4: Deploy konfigurasi
Terapkan ketiga file ke kluster:
kubectl apply -f cluster-network-topology.yaml
kubectl apply -f sample-network-topology.yaml
kubectl apply -f pi.yamlVerifikasi hasil penjadwalan
Periksa topologi kluster
Ambil label topologi pada node Anda untuk mengonfirmasi struktur topologi:
# Topologi jaringan:
# test-pod-1 test-pod-2
# / | \ |
# test-1 test-2 test-3 test-4
# / \ | | |
# 0.12 0.14 0.15 0.16 0.17
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"}'Output yang diharapkan:
{
"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"
}Skenario 1: Pekerjaan 2-Pod
Dengan workerNum: 2, kedua Pod dijadwalkan ke node dalam ASW yang sama (test-1):
kubectl get pod -owideNAME 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>Kedua Pod ditempatkan di test-1 (ASW), berbagi jalur jaringan dengan jumlah lompatan terendah.
Skenario 2: Pekerjaan 4-Pod
Perbarui parallelism dan pod-group.scheduling.sigs.k8s.io/min-available dalam pi.yaml, serta workerNum dalam sample-network-topology.yaml menjadi 4. Terapkan ulang kedua file tersebut.
Penjadwal menetapkan keempat Pod dalam test-pod-1, karena MustGather pada PoDTopologyLayer mencegah penjadwalan lintas-Pod. Node di bawah test-pod-2 tetap tidak dijadwalkan:
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>Skenario 3: Pekerjaan 5-Pod (kegagalan penjadwalan)
Perbarui parameter yang sama menjadi 5. Pekerjaan gagal karena test-pod-1 hanya memiliki 4 slot tersedia dan MustGather pada PoDTopologyLayer melarang penggunaan satu-satunya node di test-pod-2.
Semua Pod tetap dalam status Pending:
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 2sPeriksa pesan kegagalan penjadwalan:
kubectl get pod -ojson | jq '.items[].status'Pesan kegagalan penjadwalan berisi:
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...Bidang utama dalam pesan tersebut:
| Bidang | Nilai | Makna |
|---|---|---|
job desireNum | 5 | Penjadwal membutuhkan 5 slot dalam satu domain tingkat Pod |
path:RootNode->test-pod-1, freeSlotNum | 4 | test-pod-1 hanya memiliki 4 slot tersedia—tidak cukup untuk 5 Pod |
path:RootNode->test-pod-2, freeSlotNum | 1 | test-pod-2 memiliki 1 slot, tetapi MustGather melarang membagi pekerjaan lintas Pod |
NetworkTopology bestPlan empty | — | Tidak ada rencana topologi yang valid; penjadwalan diblokir |
Untuk mengatasi hal ini, kurangi workerNum agar muat dalam satu Pod, atau ubah strategi PoDTopologyLayer dari MustGather menjadi PreferGather untuk mengizinkan penjadwalan lintas-Pod.