Kodeloka
  1. Kodeloka
  2. Kelas Kubernetes
  3. Materi

7 · Operasi · Modul 10 dari 14

Penjadwalan: Affinity, Taint & Topology Spread

Mengendalikan di mana pod ditempatkan: menyebar replika antar zona, memisahkan beban kerja, dan menjaga ketersediaan saat pemeliharaan node.

Kenapa Penempatan Itu Penting

🚫 Tiga replika di satu node bukan ketersediaan tinggi

Penjadwal berusaha menyebarkan pod, tetapi tanpa aturan eksplisit ia bisa saja menempatkan ketiga replika Anda di node yang sama. Satu node mati, layanan Anda mati — padahal Anda mengira sudah punya tiga replika. Ini penemuan yang menyakitkan saat insiden pertama.

Topology Spread Constraints

spec:
  topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: topology.kubernetes.io/zone
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchLabels: { app: layanan-pesanan }

    - maxSkew: 1
      topologyKey: kubernetes.io/hostname
      whenUnsatisfiable: ScheduleAnyway   # lebih longgar
      labelSelector:
        matchLabels: { app: layanan-pesanan }
FieldArti
maxSkewSelisih maksimum jumlah pod antar domain topologi
topologyKeyLabel node yang menjadi pembeda domain (zona, hostname, rak)
DoNotScheduleAturan keras — pod tetap Pending bila tak terpenuhi
ScheduleAnywayAturan lunak — diusahakan, tapi tetap dijadwalkan
📌 Pola yang seimbang

Gunakan DoNotSchedule untuk penyebaran antar zona (ini yang benar-benar melindungi dari kegagalan besar) dan ScheduleAnyway untuk penyebaran antar node. Dua aturan keras sekaligus sering membuat pod tidak bisa dijadwalkan sama sekali di kluster kecil.

Node Affinity

affinity:
  nodeAffinity:
    # Syarat KERAS
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: node.kubernetes.io/instance-type
              operator: In
              values: [m6i.xlarge, m6i.2xlarge]

    # PREFERENSI lunak
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
            - key: topology.kubernetes.io/zone
              operator: In
              values: [ap-southeast-1a]
⚠️ Arti "IgnoredDuringExecution"

Nama panjang itu bermakna: aturan hanya diperiksa saat penjadwalan. Bila label node berubah setelah pod berjalan, pod tidak akan dipindahkan. Kubernetes tidak melakukan penjadwalan ulang secara otomatis untuk pod yang sudah berjalan.

Pod Anti-Affinity

affinity:
  podAntiAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          topologyKey: kubernetes.io/hostname
          labelSelector:
            matchLabels: { app: layanan-pesanan }

Artinya: "usahakan jangan menempatkan pod ini di node yang sudah punya pod dengan label yang sama". Untuk penyebaran sederhana, topology spread constraints lebih dianjurkan karena lebih murah secara komputasi — anti-affinity harus membandingkan setiap pod dengan setiap node dan menjadi lambat di kluster besar.

Taint dan Toleration

Affinity adalah pod yang memilih node. Taint adalah kebalikannya: node yang menolak pod.

# Menandai node khusus GPU
kubectl taint nodes node-gpu-1 khusus=gpu:NoSchedule

# Hanya pod dengan toleration ini yang boleh masuk
tolerations:
  - key: khusus
    operator: Equal
    value: gpu
    effect: NoSchedule
EffectPerilaku
NoSchedulePod baru tanpa toleration ditolak
PreferNoScheduleDiusahakan dihindari, tapi tidak dipaksakan
NoExecutePod yang sudah berjalan pun diusir
💡 Kombinasi untuk node khusus yang benar

Taint saja hanya mencegah pod lain masuk — ia tidak menarik pod GPU Anda ke sana. Untuk node khusus, gunakan keduanya: taint agar beban kerja umum menjauh, dan node affinity agar beban kerja GPU memang mengarah ke sana.

PodDisruptionBudget

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: pdb-pesanan
spec:
  minAvailable: 2            # atau maxUnavailable: 1
  selector:
    matchLabels: { app: layanan-pesanan }
🚫 Tanpa PDB, satu perintah drain bisa mematikan layanan

Saat memutakhirkan node, kubectl drain mengusir semua pod dari node tersebut. Bila ketiga replika Anda kebetulan berada di node itu, semuanya diusir sekaligus dan layanan mati sampai pod terjadwal ulang di tempat lain. PDB memberi tahu Kubernetes berapa banyak yang wajib tetap hidup, sehingga proses drain menunggu alih-alih mengusir semuanya.

⚠️ PDB hanya berlaku untuk gangguan TERENCANA

PDB melindungi dari drain, penskalaan node, dan operasi pemeliharaan lainnya. Ia tidak melindungi dari node yang mati mendadak, kehabisan memori, atau kegagalan perangkat keras. Untuk itu, andalkan jumlah replika yang memadai dan penyebaran antar zona.

Perhatikan juga: PDB dengan minAvailable sama dengan jumlah replika akan memblokir drain selamanya — pastikan selalu ada ruang gerak.

kubectl get pods -o wide --sort-by=.spec.nodeName
kubectl get pdb -A
kubectl describe node node-1 | grep -A5 Taints
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data
kubectl uncordon node-1