Mengoptimalkan biaya cluster dengan memprioritaskan Spot, memilih instance family yang efisien, dan menghindari overprovisioning; serta menangani interupsi EC2 Spot dan health events secara otomatis melalui queue processor Karpenter dengan drain dan re-schedule pod.

Di episode 8 kalian sudah melihat bagaimana constraint scheduling dari sisi pod menentukan pilihan NodePool. Episode 9 ini membahas sisi biaya: bagaimana membuat Karpenter bekerja sehemat mungkin tanpa mengorbankan ketersediaan. Dua tema besar akan kita bedah — cost-aware scaling yang menentukan strategi harga, dan interruption handling yang menjaga aplikasi tetap hidup saat AWS mengambil kembali kapasitas.
Setelah episode ini, kalian akan paham cara memprioritaskan Spot, memilih instance family yang efisien, menghindari overprovisioning, serta bagaimana Karpenter merespons notifikasi interupsi EC2 secara otomatis.
Spot adalah kunci penghematan terbesar di Karpenter. Harga instance Spot di AWS jauh lebih murah daripada On-Demand, dan Karpenter dirancang untuk memanfaatkannya lewat daftar values pada requirement karpenter.sh/capacity-type. Workload yang stateless dan fault tolerant — seperti API backend, worker queue, dan batch job — sangat cocok diletakkan di Spot.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: spot-first
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: defaultTip
Urutan nilai dalam values menentukan preferensi, bukan aturan keras. Nilai paling kiri seperti spot dicoba lebih dulu, dan nilai di kanannya menjadi cadangan ketika kapasitas pertama tidak tersedia.
Tidak semua instance type sama efisien untuk satu workload. Instance generasi baru biasanya menawarkan performa lebih baik per satuan harga dibandingkan pendahulunya. Karpenter mendukung requirement karpenter.k8s.aws/instance-generation untuk memfilter generasi instance.
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["4"]
- key: node.kubernetes.io/instance-type
operator: In
values:
- m7g.large
- m7g.xlarge
- c7g.large
- r7g.largeOperator Gt di atas meminta generasi lebih besar dari empat, sehingga Karpenter tidak memilih instance generasi lama yang boros untuk kebutuhan yang sama.
Overprovisioning terjadi ketika kapasitas yang tersedia jauh melebihi kebutuhan. Penyebab paling umum adalah instance type yang terlalu besar. Di sinilah binpacking yang sudah dibahas di episode 6 berperan: biarkan Karpenter memilih ukuran terkecil yang cukup, dan batasi daftar instance type agar tidak meleset jauh dari kebutuhan sebenarnya.
| Strategi | Efek terhadap Biaya |
|---|---|
| Spot lebih dulu | Diskon besar untuk beban toleran |
| Filter generasi terbaru | Performa lebih baik per rupiah |
| Batasi ukuran instance | Menghindari overprovisioning |
| Consolidation aktif | Node idle otomatis dipangkas |
Untuk workload yang tidak boleh terganggu, buat NodePool terpisah yang hanya berisi on-demand. Strategi ini membuat batas biaya dan ketersediaan jelas tanpa menyulitkan konfigurasi.
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]Kapasitas Spot bisa diambil kembali oleh AWS kapan saja. Sebelum dihentikan, AWS mengirimkan pemberitahuan dua menit. Selain itu, AWS juga mengirimkan event kesehatan seperti instance rebalance recommendation dan status check yang gagal. Jika hal ini terjadi pada node tanpa penanganan, pod di dalamnya hilang begitu saja.
Karpenter menangani hal ini lewat komponen yang disebut queue processor. Rangkaiannya adalah sebagai berikut:
Konfigurasi nama antrian diletakkan pada ConfigMap karpenter-global-settings di namespace karpenter.
apiVersion: v1
kind: ConfigMap
metadata:
name: karpenter-global-settings
namespace: karpenter
data:
aws.interruptionQueueName: karpenter-queue-productionImportant
Antrian SQS harus sudah dibuat dan terhubung ke EventBridge sebelum Karpenter dipasang. Tanpa antrian ini, Karpenter tidak bisa menerima notifikasi interupsi dan node Spot akan hilang tanpa drain.
Saat notifikasi interupsi diterima, Karpenter tidak langsung menghapus node. Prosesnya bertahap: annotation karpenter.sh/interruption dipasang pada node untuk menandai penyebab, pod mulai di-drain, node baru dibuat bila diperlukan, dan setelah semua pod pindah barulah instance dihentikan.
kubectl get nodes -l karpenter.sh/managed=true -o jsonpath='{.items[?(@.metadata.annotations.karpenter\.sh/interruption)].metadata.name}'Warning
Waktu dua menit yang diberikan AWS adalah batas keras. Pastikan workload tidak bergantung pada tahap yang memakan waktu lama saat drain, misalnya membuang persistensi yang besar, agar proses selesai sebelum instance dihentikan.
Selain interupsi Spot, queue processor juga merespons health events. Jika EC2 mendeteksi instance bermasalah lewat status check, Karpenter memperlakukan node tersebut layaknya node yang akan dihentikan: di-drain dan diganti. Ini membuat cluster tetap sehat meskipun underlying instance mulai gagal.
Meletakkan database atau queue replika tunggal di Spot adalah undangan masalah. Interupsi kapan saja akan memutus layanan. Batasi Spot hanya untuk beban yang bisa hilang dan lahir kembali.
Memasang Karpenter tanpa membuat antrian SQS membuat proteksi interupsi tidak aktif. Pastikan rangkaian EventBridge, SQS, dan ConfigMap sudah benar sebelum produksi.
Biaya dan ketersediaan bukan dua hal yang saling meniadakan. Dengan prioritas Spot yang tepat, pemilihan instance yang efisien, dan penanganan interupsi yang otomatis, Karpenter bisa menekan biaya sekaligus menjaga aplikasi tetap tersedia.
Inti yang harus dibawa pulang:
Di episode 10, kalian akan belajar memisahkan workload ke beberapa NodePool dengan weight dan taints, serta praktik terbaik menjalankan Karpenter di beberapa cluster. Sampai jumpa!