Cost Optimization #
Kubernetes menawarkan kemudahan luar biasa untuk melakukan penskalaan aplikasi secara otomatis. Namun, kemudahan ini juga mempermudah pemborosan anggaran infrastruktur cloud jika tidak dikelola dengan disiplin. Sangat mudah bagi tim engineering untuk meluncurkan kluster pengujian lalu melupakannya, menyetel batas permintaan sumber daya (resource requests) Pod yang jauh melebihi kebutuhan aktualnya, atau membiarkan lingkungan pengembangan (development) dan pengujian (staging) menyala penuh 24/7 padahal hanya digunakan selama 8 jam sehari. Tanpa adanya kontrol biaya yang sistematis, tagihan cloud dapat melonjak secara eksponensial (cloud spend explosion). Cost Optimization adalah penerapan metodologi FinOps (Financial Operations) di tingkat kluster Kubernetes untuk mengidentifikasi, mengukur, dan memangkas pemborosan komputasi tanpa mengorbankan keandalan (reliability) sistem produksi. Artikel ini membahas strategi taktis penghematan biaya komputasi, pemanfaatan Spot Node dengan fallback otomatis, teknik scale-to-zero, konsolidasi jaringan, serta tata kelola alokasi biaya berbasis namespace.
Arsitektur Komponen Biaya Kubernetes di Cloud #
Sebelum kita melakukan optimasi, kita harus memetakan ke mana saja pengeluaran biaya kluster Kubernetes di cloud mengalir. Biaya kluster terbagi menjadi empat pilar utama:
flowchart TD
TotalCost["Total Biaya Kluster Kubernetes"] --> Compute["1. Compute (70-80%)\nCPU & RAM Virtual Machines"]
TotalCost --> Storage["2. Storage (10-20%)\nPersistent Volumes, Registry, Snapshots"]
TotalCost --> Network["3. Networking (5-15%)\nLoad Balancers, Egress, NAT Gateway Data"]
TotalCost --> Management["4. Management Fee (Fixed)\nControl Plane SLA Fee"]
1. Compute (Porsi Terbesar: 70-80%) #
Biaya sewa VM fisik/virtual yang bertindak sebagai worker nodes. Kita membayar kapasitas total CPU dan RAM yang disediakan oleh Node, baik kapasitas tersebut sedang digunakan secara aktif oleh kontainer maupun sedang menganggur (idle).
2. Storage (10-20%) #
Biaya untuk Persistent Volumes (SSD/HDD) yang di-mount oleh database, biaya penyimpanan snapshot cadangan (backup snapshots), serta biaya penyimpanan citra kontainer di dalam Container Registry.
3. Networking (5-15%) #
Pilar biaya yang sering terabaikan namun dapat membengkak secara misterius:
- Load Balancer (LB) Fee: Biaya per instansi Load Balancer yang dibuat oleh Service bertipe
LoadBalancer. - NAT Gateway Data Processing: Biaya pemrosesan data keluar dari private cluster ke internet. Cloud provider mengenakan tarif per GB data yang melewati NAT Gateway, yang sering kali lebih mahal dari biaya VM NAT itu sendiri.
- Egress Traffic: Biaya transfer data lintas wilayah ketersediaan (cross-AZ traffic) atau ke internet luar.
4. Control Plane Management Fee #
Biaya flat yang dikenakan oleh cloud provider untuk mengelola master plane (misalnya AWS EKS mengenakan biaya $0.10/jam per kluster, atau sekitar $72/bulan).
Identifikasi Pemborosan Menggunakan Kueri PromQL #
Langkah pertama dalam FinOps adalah Inform (Mengidentifikasi). Kita tidak boleh mengurangi alokasi tanpa data pembanding yang valid. Gunakan kueri PromQL Prometheus berikut untuk mendeteksi kontainer yang mengalami over-provisioning ekstrem (alokasi requests jauh lebih besar dari konsumsi riil).
1. Deteksi Kontainer dengan Penggunaan CPU di Bawah 10% dari Requests #
Kueri ini menyaring kontainer yang membooking CPU dalam jumlah besar namun hampir tidak pernah menggunakannya.
# Mencari kontainer dengan rasio CPU aktif dibanding CPU Request < 10%
(
sum by (namespace, pod, container) (
rate(container_cpu_usage_seconds_total{container!=""}[30m])
)
/
sum by (namespace, pod, container) (
kube_pod_container_resource_requests{resource="cpu", container!=""}
)
) < 0.1
2. Analisis Persentase Efisiensi Memori per Namespace #
Mengingat memori adalah sumber daya fisik yang mahal, kita harus memantau efisiensi penggunaan RAM di setiap namespace.
# Menghitung persentase memori aktif terhadap total memori requests per namespace
sum by (namespace) (
container_memory_working_set_bytes{container!=""}
) /
sum by (namespace) (
kube_pod_container_resource_requests{resource="memory"}
) * 100
Spot / Preemptible Nodes: Strategi Hemat Hingga 80% #
Penyedia cloud menjual sisa kapasitas server kosong mereka dengan diskon ekstrem berkisar 60% hingga 80% dari tarif normal melalui instansi Spot (AWS) atau Preemptible VM (GCP). Kelemahannya adalah cloud provider berhak menarik kembali VM tersebut kapan saja jika ada pelanggan yang bersedia membayar dengan tarif normal (On-Demand), dengan memberikan peringatan dini (preemption notice) yang sangat singkat (2 menit di AWS, 30 detik di GCP).
Pengelompokan Jenis Workload #
Kita harus memilah secara disiplin jenis aplikasi yang boleh ditaruh di Spot Nodes:
| Workload yang Cocok untuk Spot | Workload yang Haram untuk Spot |
|---|---|
| Stateless Web API dengan jumlah replika > 2 | Stateful database primer (PostgreSQL, MySQL) |
| CI/CD Runner / Jenkins Agents | Aplikasi antrian dengan waktu pemrosesan sangat lama (>30 menit) |
| Batch Processing Jobs / Data Pipeline | Aplikasi replika tunggal (single replica) |
| Lingkungan Development dan Staging | Pod Kontroler Sistem Utama (CoreDNS, Ingress Controller) |
Konsekuensi Toleransi dan Fallback di Manifest Deployment #
Agar aplikasi kita dapat berjalan di atas Spot Nodes namun tetap aman jika sewaktu-waktu Spot Node ditarik massal oleh cloud provider, kita harus mengonfigurasi aturan nodeAffinity bertipe preferred (bukan required) dan menyertakan tolerations yang sesuai.
# File: k8s/production-spot-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: billing-worker
namespace: prod-apps
spec:
replicas: 4
template:
spec:
# 1. Toleransi agar Pod diizinkan dijadwalkan di atas Spot Nodes
tolerations:
- key: "eks.amazonaws.com/capacityType" # Untuk AWS EKS
operator: "Equal"
value: "SPOT"
effect: "NoSchedule"
- key: "cloud.google.com/gke-spot" # Untuk GKE
operator: "Equal"
value: "true"
effect: "NoSchedule"
# 2. Preferensi: Prioritaskan Spot, namun boleh fallback ke On-Demand jika Spot habis
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100 # Berikan bobot tertinggi untuk prioritas Spot
preference:
matchExpressions:
- key: eks.amazonaws.com/capacityType
operator: In
values: ["SPOT"]
- weight: 10 # Bobot rendah untuk On-Demand
preference:
matchExpressions:
- key: eks.amazonaws.com/capacityType
operator: In
values: ["ON_DEMAND"]
Otomatisasi Scale-to-Zero untuk Lingkungan Non-Produksi #
Lingkungan pengujian (development dan staging) biasanya hanya digunakan oleh tim engineer selama jam kerja kantor (Pukul 08:00 hingga 18:00 WIB, Senin sampai Jumat). Ini berarti selama 16 jam di hari kerja dan 48 jam penuh di akhir pekan, kluster menyala tanpa ada aktivitas pengujian apa pun, membuang 60% biaya sewa secara sia-sia.
Kita dapat mengotomatiskan penonaktifan (scale-to-zero) seluruh beban kerja di lingkungan non-produksi di luar jam kerja.
Opsi 1: Otomatisasi Jadwal via KEDA Cron Scaler #
Menggunakan KEDA untuk menskalakan replika Deployment menjadi 0 di luar jam kerja:
# File: k8s/dev-keda-autoscaler.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: dev-app-scaler
namespace: dev-apps
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: dev-api-service
minReplicaCount: 0 # Izinkan mati total (0 pod)
maxReplicaCount: 5
triggers:
- type: cron
metadata:
timezone: "Asia/Jakarta"
start: "0 8 * * 1-5" # Menyala (scale up ke 2) pukul 08:00 WIB, Senin-Jumat
end: "0 18 * * 1-5" # Mati total (scale down ke 0) pukul 18:00 WIB, Senin-Jumat
desiredReplicas: "2"
Opsi 2: CronJob Kubectl Sederhana #
Jika kita tidak menginstal KEDA, kita dapat menggunakan objek CronJob Kubernetes standar yang menjalankan perintah kubectl scale secara terjadwal:
# File: k8s/staging-shutdown-cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: staging-nightly-shutdown
namespace: staging-apps
spec:
schedule: "0 20 * * 1-5" # Pukul 20:00 WIB malam, Senin-Jumat
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
serviceAccountName: kubectl-scaler-sa # SA dengan izin RBAC update Deployment
restartPolicy: OnFailure
containers:
- name: kubectl
image: bitnami/kubectl:latest
command:
- /bin/sh
- -c
- "kubectl scale deployment --all --replicas=0 -n staging-apps"
Konsolidasi Jaringan dan Penyimpanan (Hidden Cost Savings) #
Sering kali tim berfokus pada biaya compute CPU/RAM namun mengabaikan kebocoran biaya di tingkat jaringan dan penyimpanan. Terapkan strategi konsolidasi berikut untuk memangkas pengeluaran tersembunyi:
1. Konsolidasi Load Balancer via Ingress Controller #
Secara default, jika kita membuat Service bertipe LoadBalancer untuk setiap aplikasi mikroservis, cloud provider akan meluncurkan satu instansi Load Balancer fisik baru (misal AWS ALB atau GCP LB) yang memakan biaya sekitar $15 hingga $22 per bulan per unit.
ANTI-PATTERN (1 Load Balancer per Service):
Service 1 (LoadBalancer) --> [AWS Network Load Balancer 1] --> $18/bulan
Service 2 (LoadBalancer) --> [AWS Network Load Balancer 2] --> $18/bulan
Service 3 (LoadBalancer) --> [AWS Network Load Balancer 3] --> $18/bulan
Total Biaya = $54/bulan
BENAR (Konsolidasi via Ingress Controller):
Ingress Path: /api/v1/payment --> Service 1
Ingress Path: /api/v1/billing --> Service 2 --> [Single Ingress (Shared LB)] --> $18/bulan
Ingress Path: /api/v1/auth --> Service 3
Total Biaya = $18/bulan (Hemat 67%)
2. NAT Gateway Data Processing Bypass #
NAT Gateway mengenakan biaya untuk memproses lalu lintas data keluar (data processing fee). Jika Pod aplikasi kita sering mengunduh data berukuran gigabyte dari AWS S3 atau Google Cloud Storage melalui jaringan publik, data tersebut akan melewati NAT Gateway dan memicu lonjakan tagihan.
✓ SOLUSI:
Pasang VPC Gateway Endpoints (AWS) atau Private Google Access (GCP) di subnet VPC Anda.
Lalu lintas data dari pod ke Cloud Storage akan diarahkan melalui jalur internal VPC
tanpa melewati NAT Gateway publik, memotong biaya data processing hingga 100% untuk akses storage internal.
3. Kebijakan Retensi Snapshot dan Container Registry #
Citra kontainer hasil build otomatis di pipa CI/CD yang menumpuk di Container Registry (seperti ECR/Harbor) dapat menghabiskan ruang penyimpanan terabyte. Terapkan aturan retensi otomatis (Lifecycle Rules) untuk menghapus citra kontainer yang berlabel tag pengembangan (dev-* atau temp-*) yang usianya sudah melebihi 14 hari.
Tata Kelola Alokasi Biaya (Cost Governance) #
Untuk mengoperasikan FinOps secara berkelanjutan, kita harus tahu tim mana atau proyek mana yang bertanggung jawab atas konsumsi biaya kluster. Perkakas observabilitas biaya seperti Kubecost atau OpenCost membutuhkan label metadata yang konsisten untuk mengelompokkan pengeluaran.
Kita wajib memasang kebijakan Kyverno di tingkat kluster untuk memaksa pengembang agar selalu menyertakan label alokasi biaya (team, environment, dan project) sebelum aplikasi mereka diizinkan dideploy ke kluster produksi.
# File: k8s-governance/require-cost-labels-policy.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: enforce-cost-allocation-labels
spec:
validationFailureAction: Enforce # Tolak manifest jika tidak patuh!
background: true
rules:
- name: check-mandatory-labels
match:
any:
- resources:
kinds: ["Deployment", "StatefulSet", "DaemonSet"]
validate:
message: "Gagal Deploy: Anda wajib menyertakan label 'team', 'environment', dan 'project' untuk alokasi FinOps."
pattern:
metadata:
labels:
team: "?*" # Karakter bebas, tidak boleh kosong
environment: "?*"
project: "?*"
Anti-Pattern dalam Praktik Cost Optimization #
Hindari kesalahan fatal operasional berikut yang sering kali dibungkus atas nama penghematan biaya:
1. Menempatkan Database Utama di Atas Spot Nodes (Risiko Data Loss) #
Mendeploy database relasional StatefulSet produksi utama (seperti PostgreSQL) di atas Spot Nodes untuk menghemat biaya penyimpanan.
# ANTI-PATTERN: Database StatefulSet di atas Spot Nodes
spec:
nodeSelector:
eks.amazonaws.com/capacityType: SPOT # JANGAN!
Risiko Operasional:
- Ketika cloud provider mengirimkan preemption notice (sinyal penarikan) 2 menit, database harus mematikan koneksi secara mendadak.
- Replikasi database di etcd dapat pecah (*split-brain*) jika semua node Spot mati bersamaan akibat pembersihan massal.
- Resiko kerusakan data (*data corruption*) sangat tinggi akibat proses shutdown paksa di tingkat OS node.
✓ SOLUSI: Tempatkan seluruh beban kerja stateful kritis produksi di atas Node pools bertipe On-Demand. Spot Node hanya digunakan untuk beban kerja stateless.
2. Mengaktifkan HPA Tanpa Membatasi Kapasitas Maksimum Autoscaler #
Menyetel parameter maxReplicas pada HPA atau max-nodes pada Cluster Autoscaler terlalu besar tanpa melakukan pembatasan kuota biaya di akun cloud.
# ANTI-PATTERN: HPA maxReplicas yang terlalu longgar
spec:
minReplicas: 3
maxReplicas: 200 # JANGAN: Potensi pembengkakan biaya ekstrem!
Risiko Operasional:
- Jika aplikasi kita mengalami bug kebocoran memori loop atau sedang diserang oleh sindikat peretas melalui serangan DDoS (Distributed Denial of Service).
- HPA akan mendeteksi kenaikan beban kerja dan terus menambah Pod hingga batas maksimal 200 pod.
- Cluster Autoscaler akan terpicu untuk terus menyewa VM baru di cloud provider untuk memuat 200 pod tersebut.
- Tagihan cloud Anda akan membengkak hingga puluhan ribu dolar hanya dalam waktu satu malam.
✓ SOLUSI: Batasi 'maxReplicas' ke angka realistis (misal 20-30 pod) dan pasang sistem alarm pembatas anggaran (Billing Alerts) di tingkat portal cloud provider.
Checklist Audit Cost Optimization #
Gunakan checklist FinOps ini untuk mengaudit efisiensi biaya kluster Kubernetes Anda:
AUDIT PENGGUNAAN COMPUTE (CPU/RAM):
□ Tidak ada kluster non-produksi (dev/test) yang berjalan 24/7 tanpa penjadwalan shutdown otomatis.
□ Fitur scale-to-zero (KEDA/kube-downscaler) aktif untuk menghemat biaya di akhir pekan.
□ Kueri PromQL digunakan untuk mengidentifikasi kontainer dengan utilisasi < 10% dari requests.
□ Menghapus VM worker node pools yang idle/under-utilized secara berkala.
□ Porsi Spot Node dikonfigurasi minimal 50% di lingkungan non-produksi.
OPTIMASI JARINGAN & PENYIMPANAN:
□ Seluruh aplikasi mikroservis dikonsolidasikan di bawah satu Ingress Controller (berbagi satu Load Balancer).
□ Mengaktifkan VPC Gateway Endpoints untuk mengakses S3/Object Storage tanpa biaya NAT Gateway.
□ Retensi snapshot volume dibatasi maksimal 7-14 hari untuk data pengujian non-critical.
□ Kebijakan retensi otomatis terpasang pada Container Registry untuk menghapus image tag dev yang usang.
TATA KELOLA BIAYA (GOVERNANCE):
□ Kebijakan Kyverno aktif dipasang untuk memaksa penyertaan label FinOps (team, project, env).
□ Menginstal Kubecost atau OpenCost untuk mendapatkan visualisasi pembagian biaya harian.
□ Notifikasi pembatas anggaran cloud (Cloud Billing Alerts) terkonfigurasi secara aktif.
□ Alokasi biaya didelegasikan ke masing-masing tim pengembang berdasarkan laporan namespace.
Ringkasan #
- Petakan Komponen Pengeluaran — Pahami pembagian biaya kluster (Compute, Storage, Network, Management Fee) agar Anda tahu area mana yang memberikan penghematan paling berdampak.
- Gunakan Spot Nodes Secara Bijak — Manfaatkan diskon hingga 80% dengan Spot Nodes untuk aplikasi stateless, runner CI, dan dev environment dengan fallback On-Demand.
- Muluskan Scale-to-Zero — Terapkan penjadwalan matikan total (0 replika) di lingkungan pengembangan luar jam kerja untuk menghemat hingga 60% tagihan infrastruktur pengujian.
- Konsolidasikan Load Balancer — Hindari pembuatan satu Load Balancer fisik per Service; gunakan satu Ingress Controller terbagi untuk memotong pengeluaran biaya LB.
- Pasang VPC Endpoints — Bypass biaya NAT Gateway data processing yang mahal dengan mengalirkan lalu lintas data internal S3 melalui VPC Gateway Endpoints.
- Terapkan Kyverno Label Enforcement — Pastikan pelacakan biaya Kubecost berjalan akurat dengan memaksa pengembang menyertakan label FinOps menggunakan Kyverno ClusterPolicy.
← Sebelumnya: High Availability Berikutnya: Disaster Recovery →