Autoscaling #

Autoscaling adalah salah satu nilai utama Kubernetes — kemampuan menyesuaikan kapasitas secara otomatis sesuai beban. Tapi autoscaling yang tidak dirancang dengan baik bisa lebih berbahaya dari tidak ada autoscaling: Pod yang scale terlalu lambat, scale war antara HPA dan VPA, atau Cluster Autoscaler yang tidak bisa scale up karena Pod tidak bisa di-schedule. Artikel ini membahas tiga dimensi autoscaling dan cara mengombinasikannya.

Tiga Dimensi Autoscaling #

Horizontal Pod Autoscaler (HPA):
  → Tambah atau kurangi jumlah Pod replicas
  → Berdasarkan CPU, memory, atau custom metrics
  → "Lebih banyak instans untuk lebih banyak traffic"

Vertical Pod Autoscaler (VPA):
  → Sesuaikan resource requests dan limits per Pod
  → Berdasarkan observasi penggunaan aktual
  → "Beri setiap Pod ukuran yang tepat"
  ⚠ JANGAN gunakan HPA dan VPA bersamaan pada metrik yang sama

Cluster Autoscaler:
  → Tambah atau kurangi jumlah Node
  → Berdasarkan Pod yang tidak bisa di-schedule (Pending)
  → "Tambah server jika tidak ada cukup tempat untuk Pod baru"

Horizontal Pod Autoscaler (HPA) #

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api
  minReplicas: 3
  maxReplicas: 50
  metrics:
  # Scale berdasarkan CPU utilization
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60    # target 60% CPU utilization

  # Scale berdasarkan memory (hati-hati: memory bisa tidak turun setelah load berkurang)
  - type: Resource
    resource:
      name: memory
      target:
        type: AverageValue
        averageValue: "400Mi"     # target average memory per Pod

  # Scale berdasarkan custom metric dari Prometheus
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "1000"      # target 1000 req/s per Pod

  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60    # tunggu 60 detik sebelum scale up lagi
      policies:
      - type: Percent
        value: 100                # boleh double replicas setiap 60 detik
        periodSeconds: 60
      - type: Pods
        value: 5                  # atau tambah max 5 Pod setiap 60 detik
        periodSeconds: 60
      selectPolicy: Max           # pilih yang menghasilkan lebih banyak Pod

    scaleDown:
      stabilizationWindowSeconds: 300   # tunggu 5 menit sebelum scale down
      policies:
      - type: Percent
        value: 10                 # kurangi max 10% replicas setiap 60 detik
        periodSeconds: 60
# Lihat status HPA
kubectl get hpa -n production
# NAME      REFERENCE          TARGETS       MINPODS   MAXPODS   REPLICAS
# api-hpa   Deployment/api     45%/60%       3         50        8

# Detail HPA
kubectl describe hpa api-hpa -n production

Metrics Server: Syarat HPA #

HPA membutuhkan Metrics Server untuk mendapatkan CPU dan memory usage:

# Install Metrics Server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

# Verifikasi
kubectl top nodes
kubectl top pods -n production

# Jika di cluster lokal (minikube/kind), tambahkan flag:
# --kubelet-insecure-tls dalam args Metrics Server

KEDA: Scale Berbasis Event #

KEDA (Kubernetes Event-Driven Autoscaling) memungkinkan scale berdasarkan sumber eksternal — antrian pesan, jumlah pesan di Kafka, panjang antrian Redis, dan banyak lagi:

# Scale Worker berdasarkan panjang antrian RabbitMQ
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: worker-scaler
  namespace: production
spec:
  scaleTargetRef:
    name: worker-deployment
  minReplicaCount: 0            # bisa scale ke nol saat tidak ada antrian
  maxReplicaCount: 100
  triggers:
  - type: rabbitmq
    metadata:
      host: amqp://rabbitmq.production:5672
      queueName: tasks
      queueLength: "10"         # satu Worker per 10 pesan di antrian

---
# Scale berdasarkan panjang antrian Redis List
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: redis-worker-scaler
spec:
  scaleTargetRef:
    name: email-worker
  minReplicaCount: 0
  maxReplicaCount: 20
  triggers:
  - type: redis
    metadata:
      address: redis.production:6379
      listName: email-tasks
      listLength: "5"

---
# Scale ke nol di malam hari (berdasarkan waktu/cron)
apiVersion: keda.sh/v1alpha1
kind: ScaledCronJob
metadata:
  name: batch-job-scaler
spec:
  scaleTargetRef:
    name: batch-processor
  minReplicaCount: 0
  maxReplicaCount: 10
  triggers:
  - type: cron
    metadata:
      timezone: "Asia/Jakarta"
      start: "0 8 * * 1-5"     # mulai jam 8 pagi hari kerja
      end: "0 20 * * 1-5"      # stop jam 8 malam
      desiredReplicas: "5"

Cluster Autoscaler #

Cluster Autoscaler menambah node baru saat ada Pod yang Pending karena tidak cukup resource, dan menghapus node yang kosong untuk menghemat biaya:

# Konfigurasi untuk GKE (via cluster creation flags)
# --enable-autoscaling --min-nodes=3 --max-nodes=20

# Untuk self-managed cluster, deploy Cluster Autoscaler:
# Anotasi node group yang bisa di-scale
cluster-autoscaler.kubernetes.io/safe-to-evict: "true"
Cluster Autoscaler scale-up conditions:
  → Ada Pod dengan status Pending
  → Pod Pending karena kekurangan resource (CPU, memory, atau node selector)
  → Ada node group yang bisa menambah node (maxNodes belum tercapai)
  → Estimasi: Pod bisa di-schedule jika node baru ditambahkan

Cluster Autoscaler scale-down conditions:
  → Node utilization di bawah threshold (default 50%)
  → Semua Pod di node bisa di-pindah ke node lain
  → Tidak ada Pod dengan annotation `safe-to-evict: false`
  → Tidak ada Pod dari StatefulSet dengan local storage
  → Node sudah idle selama minimal 10 menit
# Pod yang tidak boleh di-evict (sistem kritikal)
metadata:
  annotations:
    cluster-autoscaler.kubernetes.io/safe-to-evict: "false"

Menghindari Scale War: HPA + VPA #

HPA dan VPA tidak boleh dikonfigurasi untuk metrik yang sama secara bersamaan:

Anti-pattern: HPA (scale by CPU) + VPA Auto mode
  → VPA naikan CPU limit → HPA lihat CPU utilization turun → HPA scale down
  → VPA lihat Pod butuh lebih banyak CPU → VPA naikan lagi
  → Loop yang tidak konvergen

Cara yang benar:
  Opsi 1: HPA untuk skala horizontal, VPA untuk memory saja
    HPA: scale by CPU
    VPA: tuning memory requests hanya (cpu tidak di-manage VPA)

  Opsi 2: VPA "Off" mode untuk rekomendasi, apply manual
    VPA updateMode: Off → hanya dapat rekomendasi
    Terapkan rekomendasi ke values.yaml saat deployment berikutnya
    HPA bebas berjalan tanpa konflik

Ringkasan #

  • HPA untuk traffic-driven workload, KEDA untuk event-driven — HPA cocok untuk API service yang scale berdasarkan CPU/memory/RPS; KEDA untuk worker yang scale berdasarkan panjang antrian.
  • behavior.scaleDown.stabilizationWindowSeconds: 300 — jangan biarkan HPA scale down terlalu agresif; tunggu 5 menit sebelum mulai kurangi Pod untuk menghindari oscillation.
  • KEDA minReplicaCount: 0 untuk hemat biaya — worker yang tidak ada pekerjaan bisa scale ke nol; jauh lebih hemat dari minimal 1 replica yang idle terus.
  • Cluster Autoscaler butuh node yang bisa di-evict — pastikan Pod system kritikal punya safe-to-evict: false; Pod tanpa annotation dianggap boleh di-evict untuk scale-down.
  • Jangan gunakan HPA dan VPA Auto untuk metrik yang sama — scale war bisa terjadi; gunakan VPA mode “Off” untuk rekomendasi saja, atau pisahkan metrik yang di-manage masing-masing.
  • minReplicas HPA minimal 2 untuk productionminReplicas: 1 berarti ada kemungkinan hanya satu Pod running; satu Pod restart = downtime singkat.

← Sebelumnya: Resource Management   Berikutnya: High Availability →

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