Di episode ini kita akan coba bahas Kubernetes Affinity dan Anti-Affinity untuk intelligent Pod scheduling. Kita akan mempelajari bagaimana Node Affinity, Pod Affinity, dan Pod Anti-Affinity work, dan best practice untuk workload placement.

Catatan
Untuk kalian yang ingin membaca episode sebelumnya, bisa click thumbnail episode 34 di bawah ini
Di episode sebelumnya, kita menjelajahi Taints dan Tolerations, yang memungkinkan kita menolak Pod dari node tertentu. Sekarang kita akan mendalami Affinity dan Anti-Affinity, yang memberikan kontrol halus atas tempat Pod harus dijadwalkan berdasarkan karakteristik node dan lokasi Pod lainnya.
Catatan: Disini saya akan menggunakan Kubernetes Cluster yang di install melalui K3s.
Sementara Taints dan Tolerations bekerja pada model penolakan (menjaga Pod tetap jauh), Affinity bekerja pada model daya tarik (menarik Pod ke node tertentu atau menjauh dari Pod lain). Ini memungkinkan strategi penempatan beban kerja yang kuat seperti co-locating layanan terkait atau menyebarkan Pod di seluruh zona ketersediaan.
Advance Scheduling ConceptsAffinity dan Anti-Affinity adalah aturan penjadwalan yang mempengaruhi keputusan penempatan Pod. Pikirkan seperti pengaturan tempat duduk di konferensi. Taints dan Tolerations mengatakan "meja ini dicadangkan hanya untuk VIP." Affinity dan Anti-Affinity mengatakan "Saya ingin duduk dekat dengan anggota tim saya" atau "Saya ingin duduk jauh dari kerumunan yang bising."
Kubernetes menyediakan tiga jenis aturan affinity:
Node Affinity memungkinkan Anda membatasi node mana yang dapat dijadwalkan Pod Anda, berdasarkan label node. Ini lebih fleksibel daripada nodeSelector karena mendukung beberapa ekspresi pencocokan dan preferensi lunak.
requiredDuringSchedulingIgnoredDuringExecution (Persyaratan Keras)
Ini adalah batasan keras. Pod hanya akan dijadwalkan jika node cocok dengan aturan affinity. Jika tidak ada node yang cocok, Pod tetap tidak terjadwal.
apiVersion: v1
kind: Pod
metadata:
name: nginx-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In
values:
- compute
- gpu
containers:
- name: nginx
image: nginx:latestDalam contoh ini, Pod hanya akan dijadwalkan pada node dengan label node-type=compute atau node-type=gpu.
preferredDuringSchedulingIgnoredDuringExecution (Preferensi Lunak)
Ini adalah preferensi lunak. Penjadwal akan mencoba menempatkan Pod pada node yang cocok, tetapi jika tidak ada node yang cocok, Pod akan dijadwalkan pada node yang tersedia. Anda juga dapat menetapkan bobot untuk lebih memilih node tertentu daripada yang lain.
apiVersion: v1
kind: Pod
metadata:
name: nginx-preferred
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: disk-type
operator: In
values:
- ssd
- weight: 50
preference:
matchExpressions:
- key: zone
operator: In
values:
- us-east-1a
containers:
- name: nginx
image: nginx:latestPenjadwal akan lebih memilih node dengan disk SSD (bobot 100) daripada node di us-east-1a (bobot 50). Bobot yang lebih tinggi memiliki prioritas lebih tinggi.
Node Affinity mendukung beberapa operator untuk pencocokan:
apiVersion: v1
kind: Pod
metadata:
name: nginx-operators
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In
values:
- compute
- key: gpu
operator: Exists
- key: cpu-cores
operator: Gt
values:
- "4"
containers:
- name: nginx
image: nginx:latestPod ini memerlukan node dengan node-type=compute, label gpu (nilai apa pun), dan inti CPU lebih besar dari 4.
Pod Affinity memungkinkan Anda menjadwalkan Pod dekat dengan Pod lain. Ini berguna untuk co-locating beban kerja terkait untuk mengurangi latensi atau meningkatkan kinerja.
requiredDuringSchedulingIgnoredDuringExecution (Persyaratan Keras)
Pod hanya akan dijadwalkan pada node yang memiliki Pod lain yang cocok dengan aturan affinity.
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- database
topologyKey: kubernetes.io/hostname
containers:
- name: app
image: myapp:latestPod ini hanya akan dijadwalkan pada node yang sudah memiliki Pod dengan label app=database. topologyKey mendefinisikan cakupan - kubernetes.io/hostname berarti node yang sama, sementara topology.kubernetes.io/zone berarti zona ketersediaan yang sama.
preferredDuringSchedulingIgnoredDuringExecution (Preferensi Lunak)
Penjadwal akan mencoba menempatkan Pod dekat dengan Pod yang cocok, tetapi akan menjadwalkannya di tempat lain jika diperlukan.
apiVersion: v1
kind: Pod
metadata:
name: cache-pod
spec:
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
containers:
- name: cache
image: redis:latestPod ini lebih suka dijadwalkan pada node yang sama dengan Pod app=web, tetapi dapat dijadwalkan di tempat lain jika diperlukan.
topologyKey sangat penting untuk Pod affinity. Ini mendefinisikan cakupan aturan affinity:
kubernetes.io/hostname - Node yang samatopology.kubernetes.io/zone - Zona ketersediaan yang samatopology.kubernetes.io/region - Region yang samaPod Anti-Affinity memastikan Pod tersebar di seluruh node atau zona. Ini penting untuk ketersediaan tinggi dan toleransi kesalahan.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: web
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx:latestDeployment ini memastikan bahwa tidak ada dua Pod dengan app=web yang dijadwalkan pada node yang sama. Jika Anda memiliki 3 replika dan hanya 2 node, satu Pod akan tetap tidak terjadwal.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-soft
spec:
replicas: 5
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: web
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx:latestDeployment ini lebih suka menyebarkan Pod di seluruh node, tetapi akan co-locate mereka jika diperlukan. Dengan 5 replika dan 3 node, beberapa node akan memiliki beberapa Pod.
Anda dapat menggabungkan beberapa aturan affinity dalam spesifikasi Pod tunggal. Semua aturan harus dipenuhi agar Pod dapat dijadwalkan.
apiVersion: v1
kind: Pod
metadata:
name: complex-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-type
operator: In
values:
- compute
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: database
topologyKey: kubernetes.io/hostname
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: cache
topologyKey: kubernetes.io/hostname
containers:
- name: app
image: myapp:latestPod ini akan:
node-type=compute (diperlukan)app=database (lunak)app=cache (diperlukan)apiVersion: apps/v1
kind: Deployment
metadata:
name: web-ha
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: web
topologyKey: topology.kubernetes.io/zone
containers:
- name: web
image: nginx:latest
resources:
requests:
cpu: 100m
memory: 128MiIni memastikan setiap replika berada di zona ketersediaan yang berbeda untuk toleransi kesalahan maksimal.
apiVersion: v1
kind: Pod
metadata:
name: db-with-cache
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: database
topologyKey: kubernetes.io/hostname
containers:
- name: cache
image: redis:latest
resources:
requests:
cpu: 50m
memory: 256MiPod cache ini akan selalu berjalan pada node yang sama dengan Pod database untuk akses latensi rendah.
apiVersion: v1
kind: Pod
metadata:
name: ml-training
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: accelerator
operator: In
values:
- nvidia-gpu
- key: gpu-memory
operator: Gt
values:
- "8Gi"
containers:
- name: training
image: ml-training:latest
resources:
requests:
nvidia.com/gpu: 1Pod ini hanya akan dijadwalkan pada node dengan GPU NVIDIA dan setidaknya 8GB memori GPU.
Problem: Aturan affinity keras dapat menyebabkan Pod tetap tidak terjadwal jika tidak ada node yang cocok.
# JANGAN LAKUKAN INI - Pod mungkin tidak pernah dijadwalkan
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: ultra-rare-label
operator: In
values:
- valueSolusi: Gunakan preferensi lunak untuk fleksibilitas.
Problem: Aturan affinity bergantung pada label node. Jika node tidak diberi label, aturan affinity tidak akan berfungsi.
# Beri label node untuk aturan affinity
kubectl label nodes node-1 node-type=compute
kubectl label nodes node-2 node-type=storageProblem: Menggunakan topology key yang salah dapat menyebabkan perilaku penjadwalan yang tidak terduga.
# JANGAN LAKUKAN INI - topology key tidak ada
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: web
topologyKey: non-existent-labelProblem: Affinity dan Taints/Tolerations bekerja bersama tetapi melayani tujuan yang berbeda.
# Node memiliki taint: gpu=true:NoSchedule
# Pod memiliki toleration dan affinity
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
tolerations:
- key: gpu
operator: Equal
value: "true"
effect: NoSchedule
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: accelerator
operator: In
values:
- nvidia-gpu
containers:
- name: app
image: myapp:latestProblem: Terlalu banyak aturan affinity dapat membuat Pod tidak dapat dijadwalkan.
Solusi: Seimbangkan batasan dengan fleksibilitas.
Lebih suka preferredDuringSchedulingIgnoredDuringExecution daripada persyaratan keras kecuali benar-benar diperlukan. Ini memastikan Pod masih dapat dijadwalkan bahkan jika preferensi tidak dapat dipenuhi.
Gunakan PodDisruptionBudgets dengan anti-affinity untuk memastikan ketersediaan tinggi selama pemeliharaan.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: webUntuk beban kerja produksi, gunakan topology.kubernetes.io/zone sebagai topology key untuk menyebarkan Pod di seluruh zona ketersediaan.
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: web
topologyKey: topology.kubernetes.io/zoneTetapkan konvensi pelabelan untuk cluster Anda. Label umum meliputi:
node-type (compute, storage, gpu)zone (us-east-1a, us-east-1b)disk-type (ssd, hdd)workload-type (general, ml, database)Periksa apakah Pod dijadwalkan sesuai dengan aturan affinity. Gunakan kubectl describe pod untuk melihat informasi affinity dan keputusan penjadwalan.
kubectl describe pod <pod-name>
# Cari bagian "Events" untuk melihat keputusan penjadwalanSebelum menerapkan ke produksi, uji aturan affinity di lingkungan staging untuk memastikan mereka bekerja seperti yang diharapkan.
# Buat Pod uji dengan aturan affinity
kubectl apply -f test-affinity.yaml
# Periksa apakah Pod dijadwalkan
kubectl get pods -o wide
# Jelaskan Pod untuk melihat detail affinity
kubectl describe pod <pod-name>Sementara keduanya mengontrol penempatan Pod, mereka bekerja berbeda:
| Aspek | Affinity | Taints/Tolerations |
|---|---|---|
| Model | Daya tarik (tarik) | Penolakan (dorong) |
| Cakupan | Berpusat pada Pod | Berpusat pada Node |
| Kasus Penggunaan | Co-locate beban kerja | Cadangkan node |
| Fleksibilitas | Lebih fleksibel | Lebih ketat |
| Kinerja | Preferensi lunak tersedia | Hanya batasan keras |
Gunakan Taints/Tolerations untuk reservasi node dan Affinity untuk penempatan beban kerja yang cerdas.
Pada episode 35 ini, kita telah membahas Affinity dan Anti-Affinity di Kubernetes secara mendalam. Kita sudah belajar bagaimana Node Affinity memungkinkan Anda menargetkan node tertentu, Pod Affinity co-locate beban kerja terkait, dan Pod Anti-Affinity menyebarkan Pod untuk ketersediaan tinggi.
Key takeaway:
Dengan menggabungkan ini dengan pelabelan node yang tepat dan topology key, Anda dapat membangun cluster Kubernetes yang tangguh dan berkinerja tinggi.
Catatan
Untuk kalian yang ingin melanjutkan ke episode selanjutnya, bisa click thumbnail episode 36 di bawah ini