Mempelajari cara Karpenter menjaga cluster tetap efisien dengan disruption budget untuk membatasi node yang boleh diganggu bersamaan; serta consolidation dengan kebijakan WhenEmpty dan WhenUnderutilized untuk menghapus node idle dan menggabungkan workload ke node yang lebih efisien.

Di episode 6 kalian sudah melihat bagaimana Karpenter melakukan provisioning: mengelompokkan pod yang belum terjadwal, melakukan binpacking, lalu meluncurkan instance type terkecil yang cukup. Episode 7 ini membalik arah: bukan menambah node, melainkan menghapusnya. Karpenter tidak hanya hebat saat menambah kapasitas, tetapi juga saat memangkas kapasitas yang tidak efisien lewat dua mekanisme utama: disruption budget dan consolidation.
Setelah episode ini, kalian akan paham bagaimana membatasi jumlah node yang boleh diganggu bersamaan, apa perbedaan consolidationPolicy: WhenEmpty dengan WhenUnderutilized, dan bagaimana kedua fitur ini bekerja sama menjaga biaya cluster tetap rendah.
Kebutuhan kapasitas cluster tidak pernah konstan. Aplikasi yang ramai di pagi hari bisa lengang di malam hari. Deployment baru bisa menurunkan jumlah replika, dan batch job yang selesai membuat node menganggur. Tanpa mekanisme pemangkasan, node yang tidak terpakai tetap ditagih AWS. Inilah alasan Karpenter membangun controller khusus bernama disruption controller yang terus-menerus mengevaluasi apakah ada node yang layak diganggu.
Disruption dalam konteks Karpenter berarti proses menghentikan sebuah node dan menggeser pod-podnya ke node lain. Proses ini dilakukan secara bertahap agar tidak memengaruhi ketersediaan aplikasi: pod di-drain dengan hormat, baru node di-terminate.
Memangkas node itu perlu, tetapi memangkas terlalu banyak sekaligus berbahaya. Jika dua belas node di-drive dan semuanya penuh pod, lalu semua diganggu bersamaan, aplikasi bisa kehilangan kapasitas secara drastis. Disruption budget adalah mekanisme Karpenter untuk membatasi berapa banyak node yang boleh dalam proses disruption pada saat yang sama, baik per NodePool maupun per cluster.
Di Karpenter versi 1, konfigurasi ini ditulis pada bagian spec.disruption.budgets di NodePool.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
disruption:
consolidationPolicy: WhenUnderutilized
consolidateAfter: 1m
budgets:
- nodes: 10%
- nodes: "3"
schedule: "0 9 * * *"Note
Nilai nodes bisa berupa persentase, seperti 10%, atau angka absolut seperti "3". Jika nodes dikosongkan, Karpenter menganggap tidak ada batas untuk budget tersebut.
Budget yang ditulis di NodePool berlaku untuk node-node yang dibuat oleh NodePool tersebut. Untuk membatasi disruption di seluruh cluster, Karpenter menyediakan budget default global: jika sebuah NodePool tidak mendefinisikan budget sama sekali, Karpenter menerapkan batas default sebesar 10 persen dari node yang dikelola NodePool tersebut.
Field schedule memungkinkan kalian membuat budget yang berbeda pada waktu tertentu, misalnya melonggarkan batas di luar jam kerja atau mengencangkannya saat jam sibuk. Pola ini berguna untuk memastikan disruption tidak terjadi berbarengan dengan puncak trafik.
Terkadang sebuah pod membutuhkan perlindungan total dari disruption, misalnya pod yang sedang memproses batch job yang tidak bisa diulang. Karpenter menghormati annotation karpenter.sh/do-not-disrupt pada pod.
kubectl get pod critical-job-xyz -n apps -o jsonpath='{.metadata.annotations.karpenter\.sh/do-not-disrupt}'Tip
Annotation karpenter.sh/do-not-disrupt bisa dipasang pada pod maupun node. Pod yang memakai annotation ini akan menghalangi consolidation pada node tempatnya berjalan, karena node tersebut dianggap tidak boleh diganggu.
Jika disruption budget menjawab pertanyaan berapa banyak, consolidation menjawab pertanyaan kapan dan bagaimana. Karpenter menyediakan dua consolidationPolicy:
consolidateAfter tercapai. Ini kebijakan yang paling konservatif: node dihapus hanya ketika sudah benar-benar kosong.spec:
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 10mspec:
disruption:
consolidationPolicy: WhenUnderutilized
consolidateAfter: 5mImportant
WhenUnderutilized lebih agresif menghemat biaya, tetapi juga lebih sering memindahkan pod. WhenEmpty lebih stabil untuk beban yang sensitif terhadap perpindahan. Pilih sesuai karakter workload.
Proses consolidation berjalan dalam siklus berulang. Untuk setiap node yang dikelola Karpenter, controller menghitung dua hal: apakah node tersebut layak dihapus, dan apakah ada kombinasi instance yang lebih murah yang tetap muat menampung pod-pod di node tersebut. Jika jawabannya ya, Karpenter membuat node baru terlebih dahulu, menunggu pod baru siap, baru meng-drain node lama. Dengan urutan ini, downtime aplikasi praktis tidak terasa.
kubectl get nodes -l karpenter.sh/managed=true
kubectl get nodeclaims -o wideNode yang sedang dipindahkan akan tampak masuk dalam proses drain sebelum di-terminate.
Agar pengambilan keputusan tetap teratur, Karpenter mengikuti urutan prioritas berikut saat menentukan node mana yang diganggu lebih dulu:
| Prioritas | Kondisi | Tindakan |
|---|---|---|
| 1 | Pod memakai do-not-disrupt | Node tidak pernah diganggu |
| 2 | Node telah melewati expireAfter | Node diganti sesuai siklus hidup |
| 3 | Node drifted dari template | Node diganti untuk menyamakan template |
| 4 | Node kosong lewat WhenEmpty | Node dihapus |
| 5 | Node underutilized | Workload digabung atau diganti instance |
Semakin tinggi prioritas, semakin dulu ditangani. Ini memastikan budget yang terbatas dipakai untuk gangguan yang paling penting.
Nilai seperti 1s membuat Karpenter terus-menerus mengevaluasi dan memindahkan pod, menghasilkan churn yang tidak perlu dan menambah beban API server. Beri jeda yang wajar, misalnya beberapa menit.
DaemonSet seperti kube-proxy dan CNI berjalan di semua node. Saat menghitung apakah sebuah node layak dihapus, Karpenter mengabaikan pod DaemonSet. Sebuah node dengan satu pod DaemonSet tetap dianggap kosong oleh kebijakan WhenEmpty.
Disruption budget dan consolidation adalah dua sisi dari satu tujuan: kapasitas yang selalu pas dengan kebutuhan. Budget menjaga proses pemangkasan tetap aman, sementara consolidation memastikan setiap node yang tersisa dipakai seefisien mungkin.
Inti yang harus dibawa pulang:
spec.disruption.budgets membatasi berapa banyak node yang boleh diganggu bersamaan, per NodePool maupun global.Di episode 8, kalian akan belajar bagaimana constraint dari sisi pod seperti nodeSelector, toleration, dan anti-affinity memengaruhi pilihan NodePool — dan bagaimana Karpenter memperlakukan DaemonSet serta pod critical saat melakukan drain. Sampai jumpa!