Kodeloka
  1. Kodeloka
  2. Kelas Kubernetes
  3. Materi

3 · Konfigurasi · Modul 6 dari 14

Resource Request, Limit & Quality of Service

Perbedaan request dan limit, kenapa CPU limit sering merugikan, dan bagaimana kelas QoS menentukan pod mana yang dikorbankan saat node kehabisan memori.

Request vs Limit

RequestLimit
ArtiJaminan minimumBatas maksimum
Dipakai untukKeputusan penjadwalanPenegakan saat runtime
Bila terlampaui (CPU)Boleh memakai lebih bila node senggangDi-throttle — proses dipaksa berhenti sesaat
Bila terlampaui (memori)Boleh memakai lebihOOMKilled — kontainer dibunuh
resources:
  requests:
    cpu: 100m           # 100 milicore = 0,1 inti
    memory: 128Mi
  limits:
    memory: 512Mi
    # CPU limit sengaja tidak disetel — alasannya di bawah
🚫 CPU limit menyebabkan throttling yang merusak latensi

CPU adalah sumber daya yang bisa dikompres. Ketika kontainer menyentuh limit CPU, kernel Linux (CFS) menghentikannya sampai periode kuota berikutnya — meskipun node masih punya CPU yang menganggur. Efeknya terasa langsung pada latensi p99: permintaan yang seharusnya selesai dalam 50 ms tiba-tiba butuh 150 ms karena prosesnya dijeda paksa.

Praktik yang banyak dianut sekarang: selalu setel memory limit (memori tidak bisa dikompres — kehabisan berarti OOM), tetapi hanya setel CPU request tanpa limit. Request sudah cukup menjamin pembagian yang adil saat node sibuk, sekaligus membiarkan aplikasi memanfaatkan kapasitas menganggur.

Tiga Kelas Quality of Service

KelasSyaratUrutan diusir saat node kehabisan memori
Guaranteedrequest = limit untuk semua sumber daya di semua kontainerTerakhir — paling terlindungi
BurstableAda request, tetapi tidak sama dengan limitKedua
BestEffortTidak ada request maupun limit sama sekaliPertama — paling dulu dikorbankan
kubectl get pod nama-pod -o jsonpath='{.status.qosClass}'
⚠️ Pod tanpa resources adalah bom waktu

Pod tanpa request sama sekali masuk kelas BestEffort dan akan menjadi yang pertama dibunuh ketika node kehabisan memori. Lebih buruk lagi, penjadwal tidak punya informasi untuk menempatkannya dengan bijak, sehingga bisa menumpuk beban di node yang sudah padat. Selalu setel setidaknya requests.

OOMKilled: Mendiagnosis dan Memperbaiki

kubectl describe pod nama-pod

# Yang perlu dicari:
#   Last State:  Terminated
#     Reason:    OOMKilled
#     Exit Code: 137

kubectl get events --sort-by=.lastTimestamp | grep OOM
kubectl top pods --sort-by=memory
💡 Menaikkan limit belum tentu jawabannya

OOMKilled berulang biasanya berarti salah satu dari dua hal: ada kebocoran memori di aplikasi, atau runtime tidak menyadari batas kontainer. Yang kedua sangat umum:

  • Java: JVM modern menghormati cgroup, tetapi pastikan memakai -XX:MaxRAMPercentage=75 alih-alih -Xmx tetap.
  • Node.js: setel --max-old-space-size sekitar 75% dari memory limit.
  • Go: setel GOMEMLIMIT agar garbage collector tahu batasnya.

Tanpa itu, runtime mengira ia punya seluruh memori node dan baru menjalankan pembersihan ketika sudah terlambat.

Menetapkan Batas di Tingkat Namespace

apiVersion: v1
kind: ResourceQuota
metadata:
  name: kuota-tim-a
  namespace: tim-a
spec:
  hard:
    requests.cpu: "20"
    requests.memory: 40Gi
    limits.memory: 80Gi
    persistentvolumeclaims: "10"
    count/deployments.apps: "30"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: batas-bawaan
  namespace: tim-a
spec:
  limits:
    - type: Container
      default:                 # limit bila tidak disebutkan
        memory: 512Mi
      defaultRequest:          # request bila tidak disebutkan
        cpu: 100m
        memory: 128Mi
      max:
        memory: 4Gi
📌 ResourceQuota dan LimitRange saling melengkapi

ResourceQuota membatasi total pemakaian sebuah namespace. LimitRange menetapkan nilai bawaan per kontainer sehingga pod tanpa resources tetap mendapat nilai yang wajar. Perhatikan bahwa bila ResourceQuota mengatur requests.cpu, maka setiap pod wajib menyebutkan request CPU atau akan ditolak — LimitRange menyelamatkan Anda dari keharusan menulisnya di setiap manifest.

Menemukan Angka yang Tepat

# Pemakaian nyata saat ini
kubectl top pods -n produksi --sort-by=memory
kubectl top nodes

# Vertical Pod Autoscaler dalam mode rekomendasi saja
kubectl get vpa layanan-pesanan -o yaml

Alur yang praktis: mulai dengan perkiraan kasar, jalankan di bawah beban nyata selama beberapa hari, lalu setel requests mendekati pemakaian rata-rata (persentil 50–70) dan memory limit di sekitar puncak ditambah margin 30–50%. Request yang terlalu besar membuang kapasitas kluster; yang terlalu kecil membuat pod dijadwalkan ke node yang sebenarnya sudah penuh.