Autoscaling #

Salah satu janji utama dari adopsi arsitektur cloud-native adalah elastisitas sumber daya yang dinamis. Di lingkungan tradisional, kita harus merancang infrastruktur berdasarkan kapasitas puncak lalu lintas (peak traffic capacity), yang berarti puluhan server akan menganggur tanpa aktivitas di malam hari, membuang-buang anggaran perusahaan. Di Kubernetes, kita dapat mengotomatiskan penyesuaian kapasitas komputasi secara real-time berdasarkan fluktuasi beban kerja. Namun, mengonfigurasi autoscaling yang tidak terencana dengan baik bisa sangat berbahaya: Pod yang terlambat melakukan penskalaan dapat menyebabkan pemadaman layanan (outage), bentrokan kebijakan antara penskalaan horizontal dan vertikal dapat memicu scale war, dan kluster autoscaler yang tidak terintegrasi dapat menyebabkan Pod baru terjebak selamanya dalam status Pending. Autoscaling di Kubernetes adalah sistem multi-dimensi. Artikel ini membahas secara komprehensif tiga dimensi utama autoscaling (HPA, VPA, Cluster Autoscaler), mekanisme penskalaan berbasis event menggunakan KEDA, mitigasi kegagalan operasional, serta integrasi sinergis di tingkat produksi.


Tiga Dimensi Autoscaling #

Untuk membangun sistem yang benar-benar elastis, kita harus memahami tiga dimensi autoscaling di Kubernetes dan bagaimana mereka berinteraksi lintas layer:

flowchart TD
    subgraph PodLevel["Layer Pod (Penskalaan Workload)"]
        direction LR
        HPA["HPA (Skala Horizontal: Tambah/Kurang Pod)"]
        VPA["VPA (Skala Vertikal: Ubah Ukuran Pod CPU/RAM)"]
    end
    
    subgraph NodeLevel["Layer Node (Penskalaan Server)"]
        CA["Cluster Autoscaler (Tambah/Kurang Node Fisik)"]
    end
    
    Traffic["Fluktuasi Traffic / Beban Kerja"] --> HPA
    Traffic --> VPA
    
    HPA -. "Pod Tidak Bisa Dijadwalkan (Pending)" .-> CA
    VPA -. "Node Kehabisan Ruang Komputasi" .-> CA
  1. Horizontal Pod Autoscaler (HPA): Menambah atau mengurangi jumlah replika Pod secara dinamis. “Banyaknya instans untuk membagi beban.”
  2. Vertical Pod Autoscaler (VPA): Mengubah kapasitas alokasi CPU dan memori (Requests/Limits) dari Pod yang ada. “Beri ukuran baju yang pas untuk Pod.”
  3. Cluster Autoscaler (CA): Menambah atau mengurangi jumlah Node fisik/virtual di tingkat cloud provider. “Tambah server baru jika rumah untuk Pod sudah penuh.”

Horizontal Pod Autoscaler (HPA) #

HPA bekerja dengan memantau metrik pemakaian kontainer melalui perantara API Metrics Server. Kube-controller-manager menjalankan siklus evaluasi HPA secara berkala (default setiap 15 detik).

Rumus Algoritma Penskalaan HPA #

HPA menghitung jumlah replika target menggunakan rumus matematika resmi berikut:

$$\text{TargetReplicas} = \left\lceil \text{CurrentReplicas} \times \left( \frac{\text{CurrentMetricValue}}{\text{DesiredMetricValue}} \right) \right\rceil$$

Contoh Kasus Produksi: #

  • Aplikasi kita saat ini berjalan dengan 3 replika (CurrentReplicas = 3).
  • Target penggunaan CPU yang kita inginkan adalah 50% (DesiredMetricValue = 50).
  • Prometheus melaporkan rata-rata penggunaan CPU aktif saat ini di seluruh pod adalah 80% (CurrentMetricValue = 80).

$$\text{TargetReplicas} = \left\lceil 3 \times \left( \frac{80}{50} \right) \right\rceil = \lceil 3 \times 1.6 \rceil = \lceil 4.8 \rceil = 5 \text{ replika}$$

Kubernetes akan segera mengirimkan perintah ke ReplicaSet untuk menaikkan jumlah pod menjadi 5 replika secara instan.

Manifest HPA Komprehensif (Sintaksis autoscaling/v2) #

Sejak rilis versi v2, HPA mendukung pemantauan multi-metrik secara bersamaan (misalnya memantau CPU, Memori, dan metrik HTTP RPS sekaligus) serta penyesuaian perilaku penskalaan (behavior policies).

# File: k8s/production-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: billing-api-hpa
  namespace: prod-apps
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: billing-api
  minReplicas: 3 # Jangan pernah set ke 1 di produksi untuk HA
  maxReplicas: 30
  metrics:
  # 1. Metrik internal: CPU Utilization
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 65 # Target utilitas CPU 65%
  
  # 2. Metrik internal: Memory (Gunakan nilai mutlak AverageValue, bukan persentase)
  - type: Resource
    resource:
      name: memory
      target:
        type: AverageValue
        averageValue: "350Mi"
  
  # 3. Custom Metric: HTTP Requests Per Second (RPS) via Prometheus Adapter
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "800" # Target 800 req/s per Pod
        
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0 # Langsung scale up tanpa menunggu jika beban melonjak
      policies:
      - type: Percent
        value: 100 # Izinkan melipatgandakan jumlah pod (100% growth)
        periodSeconds: 15
      - type: Pods
        value: 4 # Atau minimal tambah 4 pod baru
        periodSeconds: 15
      selectPolicy: Max # Pilih kebijakan yang menghasilkan jumlah pod terbanyak
      
    scaleDown:
      # Jendela stabilisasi menahan HPA agar tidak langsung mengurangi pod saat traffic drop sesaat
      stabilizationWindowSeconds: 300 # Tunggu 5 menit untuk mencegah flapping/oscillation
      policies:
      - type: Percent
        value: 10 # Kurangi maksimal 10% dari replika aktif setiap 60 detik
        periodSeconds: 60

Metrics Server: Jantung Observabilitas HPA #

HPA tidak dapat berfungsi tanpa adanya Metrics Server di dalam kluster. Metrics Server bertindak sebagai aggregator data ringan yang mengumpulkan metrik penggunaan CPU dan memori dari agen kubelet di setiap Node (melalui /stats/summary endpoint), lalu menyajikannya secara terstandarisasi ke Kubernetes API Server melalui ekstensi metrics.k8s.io.

# 1. Instalasi Metrics Server versi terbaru langsung dari repositori resmi
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# 2. Verifikasi status kesehatan pemantauan sumber daya
kubectl top nodes
kubectl top pods -A

[!NOTE] Konfigurasi untuk Kluster Lokal (Minikube/Kind): Secara default, Metrics Server akan gagal berjalan di kluster lokal karena sertifikat Kubelet tidak ditandatangani oleh CA resmi kluster. Kita harus mengedit objek Deployment Metrics Server dan menambahkan flag --kubelet-insecure-tls ke dalam parameter argumen kontainer agar ia mengabaikan validasi sertifikat SSL.


KEDA: Kubernetes Event-Driven Autoscaling #

HPA bawaan Kubernetes sangat andal ketika memantau metrik internal seperti penggunaan CPU dan memori. Namun, untuk aplikasi tipe pemroses antrian (worker queues), metrik CPU sering kali menipu.

Sebuah pod worker yang sedang memproses antrian tugas berat mungkin mengonsumsi 99% CPU untuk memproses satu pesan tunggal. Sebaliknya, ketika ada 10.000 pesan menumpuk di RabbitMQ namun worker sedang stuck menunggu koneksi database, penggunaan CPU worker justru berada di angka 1%. HPA standar akan mendeteksi CPU 1% tersebut dan membiarkan pod tetap berjumlah sedikit, menyebabkan antrian semakin mengular.

KEDA menyelesaikan masalah ini dengan bertindak sebagai jembatan yang menyajikan metrik dari puluhan sistem eksternal (RabbitMQ, Apache Kafka, Redis, PostgreSQL, AWS SQS) ke HPA API Server secara native.

flowchart LR
    ExternalSystem["Sistem Eksternal (RabbitMQ / Kafka Queue)"] <-->|"1. Pull Metrics"| KEDAOpertor["KEDA Operator Controller"]
    KEDAOpertor -->|"2. Sajikan Metrik via"| MetricsAdapter["KEDA Metrics Adapter (v1alpha1)"]
    MetricsAdapter <-->|"3. Kueri Target"| K8sHPA["Standard Kubernetes HPA"]
    K8sHPA -->|"4. Scale Replicas"| Deployment["Worker Deployment Pods"]

1. Penskalaan Berbasis Panjang Antrian RabbitMQ (ScaledObject) #

Berikut adalah berkas manifest KEDA untuk melakukan scaling Pod worker secara dinamis berdasarkan jumlah pesan di RabbitMQ:

# File: k8s/keda-rabbitmq-scaler.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: worker-rabbitmq-scaler
  namespace: prod-apps
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: task-worker
  minReplicaCount: 0 # KEDA mendukung scale-to-zero untuk menghemat biaya!
  maxReplicaCount: 50
  cooldownPeriod: 300 # Menahan replika selama 5 menit setelah antrian kosong
  triggers:
  - type: rabbitmq
    metadata:
      host: amqp://guest:[email protected]:5672
      queueName: payment-tasks
      queueLength: "15" # Tambah 1 Pod baru untuk setiap kelipatan 15 pesan di antrian

2. Penskalaan Berbasis Waktu (ScaledCronJob) #

Untuk beban kerja yang polanya sangat mudah diprediksi berdasarkan waktu (misalnya aplikasi absen karyawan yang selalu sibuk di jam 8 pagi dan sepi di malam hari), kita dapat menggunakan ScaledCronJob KEDA:

# File: k8s/keda-cron-scaler.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: office-hours-scaler
  namespace: prod-apps
spec:
  scaleTargetRef:
    name: employee-portal
  minReplicaCount: 2
  maxReplicaCount: 15
  triggers:
  - type: cron
    metadata:
      timezone: "Asia/Jakarta"
      start: "0 7 * * 1-5"       # Pukul 07:00 pagi WIB pada hari Senin-Jumat
      end: "0 18 * * 1-5"         # Pukul 18:00 sore WIB
      desiredReplicas: "10"      # Naikkan paksa menjadi minimal 10 replika di jam kerja

Vertical Pod Autoscaler (VPA) #

Ketika HPA melakukan penskalaan secara kuantitas (menambah pod), VPA melakukan penskalaan secara kualitas (mengubah ukuran CPU/Memory requests dari pod). VPA terdiri dari tiga komponen utama yang berjalan sebagai controller:

  1. Recommender: Memonitor penggunaan aktual kontainer secara terus-menerus dan menghitung rekomendasi target alokasi optimal.
  2. Updater: Memantau Pod aktif. Jika Pod aktif memiliki konfigurasi yang tidak sesuai dengan rekomendasi Recommender, Updater akan mematikan (evict) Pod tersebut agar dideploy ulang.
  3. Admission Controller: Webhook yang mencegat request pembuatan Pod baru oleh Kubernetes API Server, lalu mengganti nilai spec resources Kubelet sesuai dengan rekomendasi terbaru.
# File: k8s/production-vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: backend-vpa
  namespace: prod-apps
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: backend-service
  updatePolicy:
    # updateMode "Off" direkomendasikan untuk produksi. 
    # VPA hanya menghitung rekomendasi dan tidak melakukan restart paksa pada Pod aktif.
    # Kita dapat menerapkan rekomendasi secara aman di siklus CI/CD berikutnya.
    updateMode: "Off"
  resourcePolicy:
    containerPolicies:
    - containerName: app-container
      minAllowed:
        cpu: "100m"
        memory: "128Mi"
      maxAllowed:
        cpu: "2000m"
        memory: "4Gi"

Cluster Autoscaler (CA) #

Cluster Autoscaler beroperasi di tingkat infrastruktur fisik Node. Ia memantau kluster untuk mencari tanda-tanda kegagalan penjadwalan.

Kondisi Pemicu Penskalaan (Scaling Conditions) #

1. Kondisi Scale-Up (Menambah Node) #

CA terus memindai kluster untuk mendeteksi apakah ada Pod yang berstatus Pending dengan alasan spesifik: kekurangan kapasitas CPU, Memory, atau ketidakcocokan selector Node. Jika kondisi ini terpenuhi, CA akan berkomunikasi dengan API Cloud Provider (AWS Auto Scaling Groups, GCP Instance Groups, Azure VMSS) untuk meluncurkan VM baru dan memasukkannya ke dalam kluster sebagai Node tambahan.

2. Kondisi Scale-Down (Mengurangi Node) #

Sebuah Node dianggap kandidat untuk dihapus jika:

  • Total permintaan (Requests) dari seluruh Pod yang berjalan di Node tersebut berada di bawah ambang batas utilitas (default 50%).
  • Semua Pod yang berjalan di Node tersebut dapat dipindahkan ke Node lain yang sudah ada tanpa memicu status Pending baru.
  • Node telah berada dalam kondisi idle selama minimal 10 menit.

[!CAUTION] Mengamankan Pod Kritis dari Evikasi Skala-Turun: Secara default, Cluster Autoscaler diizinkan memindahkan Pod demi mengosongkan Node untuk penghematan biaya. Jika kita memiliki Pod kritis (seperti pod pemroses transaksi yang tidak boleh terganggu di tengah jalan), kita wajib menyematkan anotasi pengunci keamanan agar Node tempat ia berjalan tidak pernah dihapus oleh Cluster Autoscaler.

# Tambahkan di tingkat metadata Pod Template Deployment
metadata:
  annotations:
    # Mencegah Cluster Autoscaler mematikan Node ini demi efisiensi biaya
    cluster-autoscaler.kubernetes.io/safe-to-evict: "false"

Bentrokan Kebijakan: HPA vs VPA (Scale War) #

Salah satu kesalahan desain infrastruktur paling fatal adalah mengonfigurasi HPA dan VPA secara bersamaan untuk memantau metrik yang sama (misalnya CPU) pada target Deployment yang sama. Hal ini akan memicu kondisi Scale War:

Skenario Konflik HPA dan VPA:
  1. Beban lalu lintas naik -> Penggunaan CPU aktual di Pod melampaui limits.
  2. VPA mendeteksi beban tinggi -> VPA memutuskan menaikkan kapasitas CPU Request Pod (Vertikal).
  3. Untuk menerapkan CPU baru, VPA (mode Auto) mematikan Pod untuk direstart.
  4. Jumlah Pod aktif berkurang secara tiba-tiba di kluster.
  5. HPA mendeteksi jumlah pod aktif berkurang dan beban transaksi tinggi.
  6. HPA memutuskan menambah jumlah replika Pod (Horizontal).
  7. Ketika Pod replika baru menyala, beban kerja terbagi rata di seluruh pod.
  8. VPA mendeteksi penggunaan CPU rata-rata per pod menurun karena replika bertambah.
  9. VPA memutuskan mengurangi kapasitas CPU Request Pod.
  10. Proses ini berputar terus-menerus tanpa pernah mencapai titik stabil (flapping loop).

Panduan Integrasi yang Benar di Produksi #

Untuk menghindari bentrokan di atas, terapkan aturan desain berikut:

  • Aturan 1 (Pemisahan Metrik): Jika Anda ingin menggunakan keduanya secara aktif, konfigurasikan HPA untuk memantau CPU (scaling berdasarkan beban transaksi) dan konfigurasikan VPA hanya untuk memantau Memori (menyesuaikan kapasitas RAM secara vertikal agar tidak terkena OOMKilled).
  • Aturan 2 (Rekomendasi Non-Intrusif): Setel updateMode: "Off" pada spesifikasi VPA. Dengan demikian, VPA hanya bertindak sebagai penasihat cerdas (Recommender) yang menuliskan saran alokasi di status manifest. Tim pengembang dapat membaca rekomendasi tersebut secara terjadwal dan memperbarui berkas values.yaml Helm di pipa GitOps tanpa ada restart otomatis tak terduga.

Anti-Pattern dalam Praktik Autoscaling #

Hindari dua kesalahan konfigurasi berikut di kluster produksi Anda:

1. Menyetel HPA minReplicas: 1 di Lingkungan Produksi #

Menyetel jumlah minimal pod replika HPA ke angka 1 demi menghemat anggaran komputasi.

# File: k8s/production-hpa.yaml
# ANTI-PATTERN: Menyetel minReplicas terlalu sedikit di produksi
spec:
  minReplicas: 1 # JANGAN!
  maxReplicas: 10
Risiko Operasional:
- Ketiadaan High Availability: Ketika satu-satunya Pod tersebut mati mendadak (misalnya karena gangguan jaringan node atau OOMKilled), aplikasi akan mengalami pemadaman layanan total (*downtime*) selama beberapa puluh detik sampai Kubernetes selesai mendeteksi kegagalan dan membuat ulang pod pengganti.
- Cold-Start Delay: Saat terjadi lonjakan trafik tiba-tiba, satu pod tersebut akan kewalahan dan crash sebelum HPA sempat memicu pembuatan pod kedua.
✓ SOLUSI: Selalu setel 'minReplicas' minimal ke angka 2 (rekomendasi 3) di produksi agar lalu lintas dapat dibagi merata lintas zona ketersediaan fisik.

2. Jendela Stabilisasi yang Terlalu Pendek (Thrashing / Flapping) #

Menyetel parameter stabilizationWindowSeconds pada kebijakan scaleDown dengan durasi yang terlalu singkat (misalnya kurang dari 60 detik).

# ANTI-PATTERN: Kebijakan scaleDown yang terlalu agresif
behavior:
  scaleDown:
    stabilizationWindowSeconds: 10 # JANGAN: Terlalu sensitif!
Risiko Operasional:
- Kluster akan mengalami kondisi 'flapping' (atau thrashing). Ketika terjadi lonjakan transaksi singkat selama 10 detik, HPA akan memicu scale-up node/pod. Sepuluh detik kemudian saat transaksi menurun, HPA langsung mematikan pod tersebut. Hal ini berulang terus-menerus.
- Proses booting kontainer (terutama Java Spring Boot yang lambat menyala) menghabiskan banyak sumber daya CPU kluster hanya untuk proses inisialisasi yang sia-sia karena pod langsung dihancurkan sesaat setelah menyala.
✓ SOLUSI: Gunakan nilai default stabilisasi scaleDown minimal 300 detik (5 menit) untuk memberikan waktu tunggu yang cukup bagi lalu lintas sebelum memutuskan mengurangi instansi.

Checklist Audit Konfigurasi Autoscaling #

Gunakan checklist ini untuk memverifikasi fungsionalitas elastisitas kluster produksi Anda:

HORIZONTAL POD AUTOSCALER (HPA):
  □ Jumlah minimal replika ('minReplicas') di seluruh HPA produksi disetel minimal 2 (atau 3).
  □ Parameter 'behavior.scaleDown.stabilizationWindowSeconds' dikonfigurasi minimal 300 detik.
  □ Target utilitas CPU tidak disetel terlalu tinggi (rekomendasi batas aman 60-70% untuk menyisakan ruang burst).
  □ Metrik memori tidak digunakan sebagai satu-satunya pemicu HPA (kecuali digabung dengan metrik CPU/RPS).
  □ Metrics Server terinstall secara sehat dan melaporkan data tanpa hambatan sertifikat SSL.

KEDA & EVENT-DRIVEN SCALING:
  □ KEDA digunakan untuk menskalakan Pod worker berdasarkan metrik antrian riil (bukan CPU).
  □ Koneksi kredensial ke broker pesan (seperti RabbitMQ/Kafka) diamankan menggunakan TriggerAuthentication.
  □ Fitur scale-to-zero ('minReplicaCount: 0') diuji kestabilan cold-start jalurnya.
  □ ScaledCronJob dikonfigurasi menggunakan zona waktu lokal yang tepat ('timezone: Asia/Jakarta').

VERTISAL POD AUTOSCALER & CLUSTER AUTOSCALER:
  □ HPA dan VPA tidak dikonfigurasi memantau metrik yang sama pada Deployment yang sama.
  □ VPA disetel menggunakan mode 'Off' (rekomendasi) atau 'Initial' di lingkungan produksi.
  □ Cluster Autoscaler terintegrasi dengan ASG/Instance Groups cloud provider dengan batas max-nodes rasional.
  □ Pod sistem kritis (seperti CoreDNS, Ingress Controller) memiliki anotasi 'safe-to-evict: false'.

Ringkasan #

  • Pahami Tiga Dimensi — Kuasai pemisahan peran HPA (menambah pod), VPA (mengubah ukuran pod), dan Cluster Autoscaler (menambah node fisik) agar sistem elastis berjalan selaras.
  • Cegah Flapping dengan Stabilisasi — Selalu setel stabilizationWindowSeconds minimal 5 menit pada aturan scaleDown HPA untuk meredam osilasi penskalaan akibat lonjakan trafik sesaat.
  • HA Minimal 2 Replika — Jangan pernah menyetel minReplicas: 1 pada kluster produksi; kegagalan pod tunggal akan memicu pemadaman layanan instan bagi pengguna.
  • Gunakan KEDA untuk Antrian — Tinggalkan monitoring CPU untuk pod tipe worker; gunakan KEDA untuk mengukur panjang antrian riil di RabbitMQ atau Kafka.
  • Hindari Bentrokan HPA-VPA — Jauhkan skenario pertikaian alokasi dengan memisahkan metrik pemantauan HPA (CPU/RPS) dan VPA (Memori saja) secara tegas.
  • Amankan Pod Kritis dari Evikasi — Sematkan anotasi safe-to-evict: false pada pod sistem utama agar Cluster Autoscaler tidak mematikan node tempat ia berjalan demi efisiensi biaya.

← Sebelumnya: Resource Management   Berikutnya: High Availability →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact