Resource Request & Limit #
Resource request dan limit adalah dua angka yang kamu tulis di Pod spec, tapi implikasinya jauh lebih dalam dari sekadar angka. Request mempengaruhi di mana Pod dijadwalkan. Limit menentukan apa yang terjadi saat aplikasi memakai resource lebih dari yang diizinkan. Salah menetapkan keduanya — terlalu rendah atau terlalu tinggi — menyebabkan masalah yang berbeda tapi sama-sama menyakitkan di produksi.
Request vs Limit: Dua Kontrak yang Berbeda #
Request — kontrak dengan Scheduler:
"Node harus bisa menjamin saya minimal resource ini."
→ Digunakan saat penjadwalan Pod ke node
→ Node harus punya resource tersedia minimal sebesar request
→ Setelah Pod berjalan, request tidak membatasi penggunaan aktual
Limit — kontrak dengan Container Runtime:
"Saya tidak boleh pakai lebih dari ini."
→ Diberlakukan saat runtime, bukan saat scheduling
→ Jika dilanggar: CPU di-throttle, memory di-kill (OOMKill)
→ Tidak mempengaruhi di mana Pod dijadwalkan
Ini berarti Pod bisa dijadwalkan ke node berdasarkan request-nya, lalu di runtime memakai resource lebih banyak dari request (sampai batas limit). Inilah yang memungkinkan overcommitment — menjadwalkan lebih banyak Pod dari kapasitas node yang sebenarnya, dengan asumsi tidak semua Pod akan memakai resource maksimalnya secara bersamaan.
Implikasi di Runtime #
CPU #
Skenario: container punya request 250m, limit 500m
Saat node tidak sibuk:
Container bisa pakai hingga 500m CPU → tidak ada masalah
Saat node sangat sibuk (semua Pod butuh CPU maksimal):
Kubernetes membagi CPU proporsional berdasarkan REQUEST, bukan limit
→ Container dengan request 500m dapat 2x lebih banyak dari request 250m
Saat container coba pakai lebih dari 500m (limit):
→ CPU di-throttle, proses melambat
→ Container TIDAK di-kill
→ Performa turun, tapi layanan tetap berjalan
Memory #
Skenario: container punya request 128Mi, limit 256Mi
Saat container coba alokasikan lebih dari 256Mi:
→ OOMKill: kernel langsung membunuh proses
→ Container di-restart oleh kubelet
→ Status: OOMKilled
Jika ini terus terjadi:
→ CrashLoopBackOff
→ Harus naikan memory limit atau fix memory leak di aplikasi
Cara Menentukan Nilai yang Tepat #
Menetapkan nilai request dan limit yang tepat butuh data aktual dari penggunaan aplikasi di lingkungan yang mirip produksi.
Langkah 1: Jalankan Tanpa Limit, Pantau Penggunaan Aktual #
# Lihat penggunaan resource Pod secara real-time
kubectl top pods
# Output:
# NAME CPU(cores) MEMORY(bytes)
# api-deployment-abc123 120m 89Mi
# api-deployment-def456 95m 92Mi
# api-deployment-ghi789 140m 87Mi
# Lihat penggunaan resource per node
kubectl top nodes
Dari data di atas, rata-rata penggunaan CPU sekitar 120m dan memory sekitar 90Mi. Tapi ini adalah penggunaan saat cluster tidak dalam kondisi puncak.
Langkah 2: Tentukan Request dari Penggunaan Rata-rata #
Panduan umum untuk menentukan request:
CPU request = ~50-70% dari penggunaan rata-rata di kondisi normal
→ Memberikan ruang untuk fluktuasi normal
→ Contoh: rata-rata 120m → request 70-100m
Memory request = ~90% dari penggunaan rata-rata
→ Memory lebih prediktif dari CPU (tidak bisa di-throttle)
→ Contoh: rata-rata 90Mi → request 80Mi
Langkah 3: Tentukan Limit dari Penggunaan Puncak #
CPU limit = 2-4x dari request
→ Beri ruang untuk lonjakan traffic sementara
→ CPU di-throttle jika terlampaui, tidak di-kill
→ Contoh: request 100m → limit 300-400m
Memory limit = 1.5-2x dari request, tapi lebih konservatif
→ Memory OOMKill jika terlampaui → pilih nilai yang cukup aman
→ Pantau aplikasi di bawah load tinggi sebelum menetapkan limit
→ Contoh: request 80Mi → limit 150-200Mi
Hasil dari Contoh di Atas #
resources:
requests:
cpu: "100m"
memory: "90Mi"
limits:
cpu: "400m"
memory: "200Mi"
Anti-Pattern yang Harus Dihindari #
ANTI-PATTERN 1: tidak menetapkan request dan limit sama sekali
spec:
containers:
- name: api
image: my-api:v1
# tidak ada resources field ← BERBAHAYA
Masalah:
✗ Scheduler tidak tahu resource apa yang dibutuhkan Pod
✗ Pod bisa memakai resource tanpa batas → starve Pod lain di node
✗ Pod mendapat QoS class BestEffort → pertama dievict saat node kehabisan resource
ANTI-PATTERN 2: request sama dengan limit (Guaranteed QoS)
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "500m"
memory: "512Mi"
Masalah:
✗ Tidak ada ruang untuk lonjakan — CPU langsung di-throttle
✗ Utilisasi node rendah karena resource di-reserve tapi tidak dipakai
✗ Scheduling lebih sulit karena setiap Pod "melamar" resource penuh
Pengecualian yang valid:
✓ Workload yang benar-benar membutuhkan resource yang sangat konsisten
✓ Latency-critical service yang tidak boleh di-throttle sama sekali
ANTI-PATTERN 3: limit terlalu kecil relatif terhadap request
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "250m" # sama dengan request → throttle saat beban normal
memory: "100Mi" # lebih kecil dari request? → ini tidak valid
Masalah:
✗ Limit memory lebih kecil dari request tidak masuk akal
(Kubernetes justru akan menolak atau berperilaku tidak terprediksi)
✗ CPU limit = CPU request berarti tidak ada ruang burst sama sekali
LimitRange: Default Resource untuk Namespace #
LimitRange memungkinkan administrator cluster menetapkan default resource untuk semua Pod dalam sebuah namespace, dan membatasi nilai minimum/maksimum yang bisa diminta:
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: production
spec:
limits:
- type: Container
default: # limit default jika tidak dispesifikasikan
cpu: "500m"
memory: "256Mi"
defaultRequest: # request default jika tidak dispesifikasikan
cpu: "100m"
memory: "128Mi"
max: # maksimum yang boleh diminta
cpu: "2000m"
memory: "2Gi"
min: # minimum yang boleh diminta
cpu: "50m"
memory: "64Mi"
Dengan LimitRange, Pod yang tidak mendefinisikan resources secara eksplisit akan otomatis mendapat nilai default — menghindarkan cluster dari Pod tanpa limit.
ResourceQuota: Batas Total per Namespace #
Sementara LimitRange mengatur per container, ResourceQuota membatasi total resource yang boleh digunakan oleh seluruh namespace:
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "10" # total CPU request semua Pod di namespace
requests.memory: "20Gi" # total memory request semua Pod
limits.cpu: "20" # total CPU limit
limits.memory: "40Gi" # total memory limit
pods: "50" # maksimum jumlah Pod
services: "20" # maksimum jumlah Service
persistentvolumeclaims: "10" # maksimum jumlah PVC
ResourceQuota mencegah satu tim atau satu namespace memonopoli seluruh resource cluster.
Ringkasan #
- Request untuk scheduling, limit untuk runtime — request menentukan di mana Pod dijadwalkan; limit membatasi penggunaan saat berjalan.
- CPU di-throttle, memory di-kill — CPU limit yang terlampaui memperlambat aplikasi; memory limit yang terlampaui membunuh container dengan OOMKill.
- Tentukan berdasarkan data aktual —
kubectl top podsdan Prometheus adalah sumber kebenaran; jangan tebak request dan limit tanpa data penggunaan nyata.- Request ≠ limit untuk sebagian besar workload — beri ruang burst dengan limit 2-4x request untuk CPU; lebih konservatif untuk memory.
- LimitRange untuk default namespace — tanpa LimitRange, Pod tanpa resource spec berjalan tanpa batas dan bisa starve Pod lain.
- ResourceQuota untuk isolasi tim — batasi total resource per namespace untuk mencegah satu tim memonopoli seluruh cluster.