Cegah deadlock pada pekerjaan terdistribusi dengan memastikan semua Pod yang diperlukan dimulai secara bersamaan atau tidak sama sekali.
Cara kerja
ACK menerapkan gang scheduling melalui resource PodGroup. Setiap Pod ditetapkan ke PodGroup dengan jumlah Pod minimum (min-available). Penjadwal menahan grup dalam status Pending hingga jumlah minimum terpenuhi, lalu menjadwalkan semua Pod sekaligus.
ACK mendukung tiga metode untuk menentukan PodGroup:
| Metode | Cara pengelompokan Pod | Paling cocok untuk |
|---|---|---|
| Labels | kube-scheduler membuat PodGroup secara otomatis | Pekerjaan sederhana, tidak memerlukan objek PodGroup terpisah |
| PodGroup CRD | Resource PodGroup eksplisit dengan kontrol timeout | Pekerjaan yang memerlukan scheduleTimeoutSeconds |
| Anotasi Koordinator | Pengelompokan berbasis anotasi | Kluster yang menggunakan stack penjadwalan Koordinator |
Semua metode mengharuskan Pod dan PodGroup-nya berada dalam namespace yang sama. Semua Pod dalam satu PodGroup harus memiliki prioritas yang sama.
Prasyarat
Sebelum memulai, pastikan Anda telah memiliki:
-
Kluster ACK managed Pro yang menjalankan Kubernetes 1.16 atau lebih baru. Tingkatkan kluster jika diperlukan.
-
Untuk konfigurasi lanjutan (GangGroup dan kebijakan pencocokan): kluster yang menjalankan Kubernetes 1.22 atau lebih baru dengan versi kube-scheduler lebih baru dari
1.xx.xx-aliyun-4.0.
Pastikan pool node elastis memiliki kapasitas sumber daya maksimum yang mencukupi dan label node yang sesuai untuk penjadwalan Pod. Jika tidak, Pod mungkin gagal menggunakan node yang diskalakan oleh pool node elastis.
Aktifkan gang scheduling
Metode 1: Labels (direkomendasikan)
Tambahkan dua label ke setiap Pod. kube-scheduler secara otomatis membuat PodGroup dengan nama sesuai nilai pod-group.scheduling.sigs.k8s.io/name.
labels:
pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu # Nama PodGroup (harus berupa subdomain DNS yang valid)
pod-group.scheduling.sigs.k8s.io/min-available: "3" # Jumlah Pod minimum yang diperlukan untuk memulai pekerjaan
Nilai pod-group.scheduling.sigs.k8s.io/name harus berupa nama subdomain DNS yang valid.
Metode 2: PodGroup CRD
Buat resource PodGroup, lalu rujuk dari setiap Pod menggunakan label.
Sejak ACK 1.31, hanya scheduling.x-k8s.io/v1alpha1 yang didukung. scheduling.sigs.k8s.io/v1alpha1 tidak lagi didukung.
# Resource PodGroup
apiVersion: scheduling.x-k8s.io/v1alpha1
kind: PodGroup
metadata:
name: nginx
spec:
scheduleTimeoutSeconds: 10 # Jumlah detik menunggu sebelum menolak grup jika min-available tidak terpenuhi
minMember: 3 # Jumlah minimum Pod yang diperlukan untuk memulai pekerjaan
---
# Label Pod — harus sesuai dengan nama dan namespace PodGroup
labels:
pod-group.scheduling.sigs.k8s.io/name: nginx
Metode 3: Anotasi Koordinator
Tambahkan anotasi ke setiap Pod. Metode ini tidak mendukung parameter total-number atau mode dari API Koordinator.
annotations:
gang.scheduling.koordinator.sh/name: "gang-example"
gang.scheduling.koordinator.sh/min-available: "2"
Konfigurasi lanjutan
Grup beberapa gang (GangGroup)
Beberapa pekerjaan memiliki peran dengan persyaratan min-available yang berbeda — misalnya, pekerjaan PyTorch dengan server parameter dan worker. Satu PodGroup tidak dapat menyatakan jumlah minimum per peran, dan PodGroup terpisah tidak dapat berkoordinasi lintas peran.
GangGroup menghubungkan beberapa PodGroup. Pekerjaan dimulai hanya ketika setiap gang memenuhi min-available-nya sendiri. Tambahkan label berikut ke setiap Pod atau PodGroup (gunakan kunci anotasi untuk metode Koordinator):
| Metode | Resource | Kunci |
|---|---|---|
| Labels | Pod | pod-group.scheduling.sigs.k8s.io/groups |
| PodGroup CRD | PodGroup | pod-group.scheduling.sigs.k8s.io/groups |
| Anotasi Koordinator | Pod | gang.scheduling.koordinator.sh/groups |
Contoh nilai (array JSON berisi entri <namespace>/<gang-name>):
pod-group.scheduling.sigs.k8s.io/groups: "[\"default/gang-example1\", \"default/gang-example2\"]"
GangGroup memerlukan Kubernetes 1.22 atau lebih baru dengan versi kube-scheduler lebih baru dari 1.xx.xx-aliyun-4.0.
Konfigurasi kebijakan pencocokan
Secara default, PodGroup hanya menghitung Pod yang telah menyelesaikan prealokasi sumber daya (only-waiting). Gunakan match-policy untuk memasukkan Pod dalam status lain ke dalam perhitungan jumlah minimum — misalnya, saat Pod dari siklus sebelumnya masih berjalan.
Tambahkan label ke setiap Pod (metode labels) atau ke resource PodGroup (metode PodGroup CRD). Metode anotasi Koordinator hanya mendukung once-satisfied.
| Kebijakan pencocokan | Pod yang dihitung untuk ketersediaan minimum | Kapan digunakan |
|---|---|---|
only-waiting |
Pod yang telah menyelesaikan prealokasi sumber daya | Paling ketat. Gunakan untuk pekerjaan tanpa status yang tidak memiliki kelanjutan dari siklus sebelumnya. |
waiting-and-running |
Pod dalam status Running + Pod yang telah menyelesaikan prealokasi | Gunakan ketika Pod yang sedang berjalan dari siklus sebelumnya harus dihitung terhadap jumlah minimum. |
waiting-running-succeed |
Pod dalam status Succeeded + Running + yang telah menyelesaikan prealokasi | Gunakan untuk pekerjaan yang mentolerir restart parsial — Pod yang sudah berhasil tetap dihitung. |
once-satisfied |
Pod yang telah menyelesaikan prealokasi sumber daya; PodGroup menjadi tidak valid setelah terpenuhi | Gunakan untuk pekerjaan sekali jalan. Setelah gang dikirim, PodGroup menjadi tidak valid. |
Contoh berbasis labels:
pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"
Contoh PodGroup CRD (tambahkan ke PodGroup, bukan ke Pod):
pod-group.scheduling.sigs.k8s.io/match-policy: "waiting-and-running"
Konfigurasi kebijakan pencocokan memerlukan Kubernetes 1.22 atau lebih baru dengan versi kube-scheduler lebih baru dari 1.xx.xx-aliyun-4.0.
Contoh: pekerjaan TensorFlow terdistribusi
Contoh ini membandingkan pekerjaan TensorFlow terdistribusi dengan dan tanpa gang scheduling. Kluster memiliki 4 GPU. Pekerjaan terdiri dari 1 Pod PS dan 4 Pod worker, masing-masing memerlukan 2 GPU, dengan min-available diatur ke 5.
Langkah 1: Instal Arena dan siapkan kluster untuk pekerjaan TensorFlow.
Arena adalah subproyek Kubeflow untuk mengelola siklus hidup pekerjaan pembelajaran mesin — termasuk penyiapan lingkungan, persiapan data, pengembangan model, pelatihan, dan prediksi — melalui CLI atau SDK.
Langkah 2: Kirim pekerjaan TensorFlow. Baik templat PS maupun worker menyertakan label gang scheduling dengan min-available: "5".
apiVersion: "kubeflow.org/v1"
kind: "TFJob"
metadata:
name: "tf-smoke-gpu"
spec:
tfReplicaSpecs:
PS:
replicas: 1
template:
metadata:
creationTimestamp: null
labels:
pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
pod-group.scheduling.sigs.k8s.io/min-available: "5"
spec:
containers:
- args:
- python
- tf_cnn_benchmarks.py
- --batch_size=32
- --model=resnet50
- --variable_update=parameter_server
- --flush_stdout=true
- --num_gpus=1
- --local_parameter_device=cpu
- --device=cpu
- --data_format=NHWC
image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-cpu:v20171202-bdab599-dirty-284af3
name: tensorflow
ports:
- containerPort: 2222
name: tfjob-port
resources:
limits:
cpu: '1'
workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
restartPolicy: OnFailure
Worker:
replicas: 4
template:
metadata:
creationTimestamp: null
labels:
pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
pod-group.scheduling.sigs.k8s.io/min-available: "5"
spec:
containers:
- args:
- python
- tf_cnn_benchmarks.py
- --batch_size=32
- --model=resnet50
- --variable_update=parameter_server
- --flush_stdout=true
- --num_gpus=1
- --local_parameter_device=cpu
- --device=gpu
- --data_format=NHWC
image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-gpu:v20171202-bdab599-dirty-284af3
name: tensorflow
ports:
- containerPort: 2222
name: tfjob-port
resources:
limits:
nvidia.com/gpu: 2
workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
restartPolicy: OnFailure
Tanpa gang scheduling diaktifkan:
Periksa status Pod:
kubectl get pods
Dengan hanya 4 GPU, 2 worker mulai berstatus Running dan mengklaim semua GPU. Sisa 2 Pod tetap dalam status Pending, sehingga memblokir pekerjaan:
NAME READY STATUS RESTARTS AGE
tf-smoke-gpu-ps-0 1/1 Running 0 6m43s
tf-smoke-gpu-worker-0 1/1 Running 0 6m43s
tf-smoke-gpu-worker-1 1/1 Running 0 6m43s
tf-smoke-gpu-worker-2 0/1 Pending 0 6m43s
tf-smoke-gpu-worker-3 0/1 Pending 0 6m43s
Periksa log worker yang sedang berjalan:
kubectl logs -f tf-smoke-gpu-worker-0
Worker terhenti menunggu Pod yang berstatus Pending — GPU terblokir, pelatihan tidak berjalan:
INFO|2020-05-19T07:02:18|/opt/launcher.py|27| 2020-05-19 07:02:18.199696: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:worker/replica:0/task:3
INFO|2020-05-19T07:02:28|/opt/launcher.py|27| 2020-05-19 07:02:28.199798: I tensorflow/core/distributed_runtime/master.cc:221] CreateSession still waiting for response from worker: /job:worker/replica:0/task:2
Dengan gang scheduling diaktifkan:
Kelima Pod tetap dalam status Pending hingga kluster memiliki sumber daya yang cukup untuk memenuhi min-available: 5:
NAME READY STATUS RESTARTS AGE
tf-smoke-gpu-ps-0 0/1 Pending 0 43s
tf-smoke-gpu-worker-0 0/1 Pending 0 43s
tf-smoke-gpu-worker-1 0/1 Pending 0 43s
tf-smoke-gpu-worker-2 0/1 Pending 0 43s
tf-smoke-gpu-worker-3 0/1 Pending 0 43s
Setelah 4 GPU ditambahkan ke kluster, penjadwal menjadwalkan kelima Pod secara simultan:
kubectl get pods
Output yang diharapkan:
NAME READY STATUS RESTARTS AGE
tf-smoke-gpu-ps-0 1/1 Running 0 3m16s
tf-smoke-gpu-worker-0 1/1 Running 0 3m16s
tf-smoke-gpu-worker-1 1/1 Running 0 3m16s
tf-smoke-gpu-worker-2 1/1 Running 0 3m16s
tf-smoke-gpu-worker-3 1/1 Running 0 3m16s
Periksa log worker untuk memastikan pelatihan telah dimulai:
kubectl logs -f tf-smoke-gpu-worker-0
Output yang diharapkan:
INFO|2020-05-19T07:15:24|/opt/launcher.py|27| Running warm up
INFO|2020-05-19T07:21:04|/opt/launcher.py|27| Done warm up
INFO|2020-05-19T07:21:04|/opt/launcher.py|27| Step Img/sec loss
INFO|2020-05-19T07:21:05|/opt/launcher.py|27| 1 images/sec: 31.6 +/- 0.0 (jitter = 0.0) 8.318
INFO|2020-05-19T07:21:15|/opt/launcher.py|27| 10 images/sec: 31.1 +/- 0.4 (jitter = 0.7) 8.343
INFO|2020-05-19T07:21:25|/opt/launcher.py|27| 20 images/sec: 31.5 +/- 0.3 (jitter = 0.7) 8.142
Pemecahan masalah
Error: "rejected by podgroup xxx"
Ketika terdapat beberapa PodGroup, antrean backoff kube-scheduler dapat menolak Pod yang telah menyelesaikan prealokasi dalam satu siklus ketika PodGroup lain diproses kemudian.
Ini merupakan perilaku yang diharapkan. Abaikan error tersebut jika teratasi dalam waktu 20 menit. Jika berlanjut, kirim tiket.
Langkah selanjutnya
-
Bekerja dengan capacity scheduling — gunakan grup kuota elastis untuk meningkatkan pemanfaatan sumber daya kluster