Memahami bagaimana Karpenter memilih instance type terkecil yang muat untuk sekelompok pod lewat binpacking; menyesuaikan spec.template NodePool agar hasil provisioning sesuai kebutuhan; serta mengatur kapasitas Spot dan On-Demand memakai label karpenter.sh/capacity-type dengan strategi fallback antar tipe.

Di episode 5 kalian sudah mengenal EC2NodeClass dan bagaimana object ini menentukan sisi infrastruktur dari node yang diluncurkan Karpenter: AMI mana yang dipakai, security group dan subnet yang mana, hingga instance profile untuk IAM. Di episode 6 ini kita naik satu tingkat: kita membahas bagaimana Karpenter memutuskan instance type apa yang akan dibuat, dan mengapa keputusan itu sering terasa ajaib padahal sebenarnya adalah hasil dari proses yang sangat deterministik bernama binpacking.
Setelah episode ini selesai, kalian akan paham tiga hal: apa itu binpacking dan bagaimana Karpenter mengelompokkan pod, bagaimana menyesuaikan spec.template NodePool untuk memengaruhi hasil provisioning, serta perbedaan kapasitas Spot dan On-Demand lewat label karpenter.sh/capacity-type.
Node Kubernetes tidak murah. Setiap node yang diluncurkan, baik on-demand maupun spot, tetap harus dibayar. Semakin besar instance type yang dipakai untuk beban kecil, semakin banyak uang yang terbuang. Cluster Autoscaler umumnya bekerja di level node group sehingga pilihan instance type sudah terkunci sejak awal. Karpenter berbeda karena memilih instance type secara granular untuk setiap batch pod.
Saat ada pod yang tidak bisa dijadwalkan ke node yang ada, Karpenter tidak meluncurkan node satu per satu. Controller Karpenter mengumpulkan sekelompok pod yang belum terjadwal dalam jendela waktu singkat, lalu menghitung kebutuhan agregat mereka: total CPU, memori, dan resource lain. Dari kebutuhan agregat ini, Karpenter mencari instance type terkecil yang sanggup menampung seluruh kelompok tersebut.
kubectl get pods -n workshop --field-selector=status.phase=Pending
kubectl get nodeclaimsKumpulan pod yang menunggu ini disebut batch. Semakin baik pod-pod tersebut terpack, semakin sedikit node yang dibutuhkan, dan semakin kecil total instance yang diluncurkan.
Kebutuhan agregat pod hanyalah satu input. Input lain datang dari spec.template NodePool. Bagian template menentukan batasan node yang boleh dibuat: label apa yang harus ada, taint apa yang dipasang, hingga requirement tipe instance. Karpenter menggabungkan kebutuhan pod dengan constraint template ini untuk mempersempit kandidat instance type.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
template:
metadata:
labels:
karpenter.sh/capacity-type: spot
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: node.kubernetes.io/instance-type
operator: In
values: ["m5.large", "m5.xlarge", "m5.2xlarge"]
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: defaultTip
Perhatikan bahwa nilai requirements adalah daftar pilihan, bukan permintaan. Karpenter tetap memilih instance terkecil dari kandidat yang tersedia, misalnya m5.large sebelum mencoba m5.xlarge.
Di sini karpenter.sh/capacity-type dan node.kubernetes.io/instance-type adalah dua requirement yang paling sering dipakai. Keduanya menjadi acuan binpacking.
Karpenter memperkenalkan label karpenter.sh/capacity-type untuk membedakan dua kelas kapasitas di AWS: spot dan on-demand. Saat Karpenter meluncurkan node, label ini dipasang pada node tersebut sehingga kalian bisa melihat tipe kapasitasnya langsung dari kubectl.
On-demand memberikan kapasitas yang stabil dan tidak dihentikan di tengah jalan, tetapi lebih mahal. Spot memanfaatkan kapasitas EC2 yang tidak terpakai dengan diskon besar, tetapi bisa dihentikan kapan saja oleh AWS dengan pemberitahuan dua menit.
| Aspek | On-Demand | Spot |
|---|---|---|
| Harga | Penuh, tanpa diskon | Diskon hingga puluhan persen |
| Stabilitas | Tidak dihentikan AWS | Bisa dihentikan kapan saja |
| Cocok untuk | Beban stateful, critical | Beban stateless, fault tolerant |
| Ketersediaan | Hampir selalu tersedia | Bergantung kapasitas saat itu |
Karpenter menangani Spot dan On-Demand dalam satu NodePool lewat daftar nilai pada requirement karpenter.sh/capacity-type. Urutan dalam daftar menentukan prioritas: nilai paling kiri dianggap lebih disukai, dan nilai paling kanan menjadi cadangan.
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]Konfigurasi di atas berarti: jika kapasitas spot tersedia, Karpenter akan memilih spot. Ketika spot sedang langka di availability zone yang dituju, Karpenter otomatis turun ke on-demand sehingga pod tetap berjalan tanpa intervensi manual.
Important
Fallback adalah jaring pengaman, bukan janji harga. Jika workload tertentu tidak boleh berjalan di spot, jangan menambahkan spot ke dalam daftar values — buat NodePool terpisah yang hanya berisi on-demand.
Kadang keputusan kapasitas bukan di tangan NodePool, melainkan di tangan workload itu sendiri. Kalian bisa memaksa pod hanya boleh dijadwalkan ke kapasitas tertentu dengan nodeSelector.
apiVersion: v1
kind: Pod
metadata:
name: stateful-worker
spec:
nodeSelector:
karpenter.sh/capacity-type: on-demand
containers:
- name: app
image: nginxDengan nodeSelector seperti di atas, pod tidak akan pernah dijadwalkan ke node spot karena label yang dipasang Karpenter tidak cocok.
Untuk melihat keputusan binpacking secara nyata, buat deployment dengan beban kecil lalu amati instance type yang dipilih Karpenter.
kubectl create deployment web --image=nginx --replicas=2
kubectl get nodes -l karpenter.sh/managed=true -o widePerhatikan kolom instance type pada output. Jika NodePool mengizinkan beberapa ukuran, Karpenter seharusnya memilih yang paling kecil yang cukup untuk dua replika tersebut.
Note
Karpenter tidak hanya melihat resource pod, tetapi juga overhead sistem. Setiap node buatan Karpenter menyisihkan kapasitas untuk komponen sistem seperti kubelet dan kube-proxy, sehingga pod tidak pernah mengambil seluruh kapasitas node.
Harga per jam yang murah belum tentu efisien untuk workload kalian. Sebuah instance dengan banyak CPU tapi sedikit memori bisa membuat Karpenter meluncurkan node ekstra hanya karena memori habis duluan. Pilih kandidat instance type yang proporsinya cocok dengan workload.
NodePool yang hanya mencantumkan satu tipe kapasitas akan kesulitan saat kapasitas tersebut langka. Selalu sediakan minimal dua nilai, atau siapkan NodePool cadangan.
Episode ini sudah memperlihatkan mengapa binpacking menjadi jantung efisiensi Karpenter: sekelompok pod dikemas ke instance terkecil yang cukup, sehingga jumlah node dan biaya tetap minimal.
Inti yang harus dibawa pulang:
karpenter.sh/capacity-type membedakan spot dan on-demand, dan urutannya menentukan prioritas.Di episode 7, kalian akan belajar bagaimana Karpenter menjaga cluster tetap sehat dan efisien dalam jangka panjang lewat disruption budget dan consolidation — mekanisme yang menghapus node yang tidak lagi dibutuhkan dan menggabungkan workload ke node yang lebih efisien. Sampai jumpa!