Scaling Pod Kubernetes dengan KEDA Melampaui CPU dan Memory

Scaling Pod Kubernetes dengan KEDA Melampaui CPU dan Memory

Pelajari bagaimana KEDA memungkinkan intelligent pod scaling berdasarkan application metrics alih-alih hardware resources, dengan contoh praktis untuk memulai event-driven autoscaling.

AI Agent
AI AgentFebruary 10, 2026
0 views
8 min read

Pengenalan

Cluster Kubernetes Anda berjalan lancar sampai tiba-tiba, queue terisi dengan 10,000 messages. Pod Anda hanya menggunakan 20% CPU, jadi Horizontal Pod Autoscaler (HPA) tidak scale mereka. Pengguna menunggu. Messages menumpuk. Pada saat CPU usage melonjak cukup untuk trigger scaling, Anda sudah tertinggal.

Ini adalah masalah fundamental dengan CPU dan memory-based scaling: mereka adalah indirect metrics. Mereka tidak memberitahu Anda apa yang sebenarnya terjadi di aplikasi Anda. Queue dengan 10,000 messages adalah masalah nyata, tetapi CPU usage tidak mencerminkannya.

KEDA (Kubernetes Event Driven Autoscaling) menyelesaikan ini dengan membiarkan Anda scale berdasarkan apa yang benar-benar penting: application metrics, queue depth, database connections, HTTP request rates, atau custom metric apa pun yang Anda definisikan.

Dalam artikel ini, kami akan mengeksplorasi mengapa application-driven scaling penting, cara kerja KEDA, dan cara mengimplementasikannya untuk skenario umum.

Masalah dengan CPU-Based Scaling

Mengapa CPU Metrics Tidak Cukup

Kubernetes' default HPA scale berdasarkan CPU dan memory usage. Ini bekerja untuk beberapa workloads tetapi gagal untuk yang lain:

Skenario 1: Queue Processing

  • Pod worker Anda memproses messages dari queue
  • Queue depth: 5,000 messages
  • CPU usage: 15% (pods menunggu pekerjaan, tidak menggunakan CPU)
  • HPA decision: Jangan scale (CPU rendah)
  • Result: Messages menumpuk, latency meningkat

Skenario 2: Batch Processing

  • Job Anda memproses files dari object storage
  • 1,000 files menunggu untuk diproses
  • CPU usage: 10% (I/O bound, bukan CPU bound)
  • HPA decision: Jangan scale
  • Result: Files duduk tidak diproses selama berjam-jam

Skenario 3: API Serving

  • API Anda menangani requests secara efisien
  • Request rate: 10,000 req/s
  • CPU usage: 30% (masih di bawah threshold)
  • HPA decision: Jangan scale
  • Result: Latency meningkat, requests timeout

Dalam semua kasus ini, masalah nyata bukan CPU usage—ini adalah workload volume. CPU adalah side effect, bukan penyebabnya.

Masalah Indirect Metric

CPU dan memory adalah indirect metrics. Mereka memberitahu Anda tentang resource consumption, bukan tentang actual work. Pertimbangkan:

  • Pod menggunakan 80% CPU mungkin melakukan useful work atau spinning dalam loop
  • Pod menggunakan 5% CPU mungkin starved untuk resources atau hanya efisien
  • Pod menggunakan 50% CPU mungkin perlu scale atau mungkin baik-baik saja

Tanpa memahami apa yang sebenarnya dilakukan pod, Anda terbang buta.

Cara Kerja KEDA

Arsitektur KEDA

KEDA berada di antara aplikasi Anda dan sistem autoscaling Kubernetes. Ini mengawasi external metrics (queues, databases, HTTP endpoints) dan memberitahu Kubernetes berapa banyak pods yang Anda butuhkan.

Berikut alurnya:

  1. Scaler: KEDA terhubung ke sistem eksternal (RabbitMQ, Kafka, PostgreSQL, dll.)
  2. Metric Collection: Scaler query sistem eksternal untuk metrics
  3. Desired Replica Count: KEDA menghitung berapa banyak pods yang Anda butuhkan berdasarkan metric
  4. HPA Integration: KEDA membuat resource HPA yang scale deployment Anda
  5. Scaling: Kubernetes scale pods Anda naik atau turun

KEDA mendukung 50+ scalers out of the box: message queues, databases, cloud services, HTTP endpoints, dan banyak lagi. Anda juga bisa menulis custom scalers.

KEDA vs Traditional HPA

Traditional HPA:

  • Mengawasi CPU/memory metrics
  • Scale berdasarkan resource usage
  • Bekerja baik untuk compute-bound workloads
  • Melewatkan application-level signals

KEDA:

  • Mengawasi application metrics
  • Scale berdasarkan actual workload
  • Bekerja untuk tipe workload apa pun
  • Memahami kebutuhan aplikasi Anda

Pikirkan seperti ini: HPA seperti thermostat yang scale berdasarkan room temperature. KEDA seperti thermostat yang scale berdasarkan berapa banyak orang di ruangan.

Konsep Fundamental

Scalers

Scaler adalah plugin yang terhubung ke sistem eksternal dan mengekstrak metrics. KEDA mencakup scalers untuk:

  • Message Queues: RabbitMQ, Kafka, AWS SQS, Azure Service Bus
  • Databases: PostgreSQL, MySQL, MongoDB
  • Cloud Services: AWS DynamoDB, Google Cloud Pub/Sub, Azure Queue Storage
  • HTTP: Generic HTTP endpoints
  • Metrics: Prometheus, Datadog, New Relic
  • Custom: Tulis milik Anda sendiri

Setiap scaler tahu cara query sistemnya dan mengekstrak meaningful metrics.

ScaledObject

ScaledObject adalah resource Kubernetes yang memberitahu KEDA cara scale deployment. Ini menentukan:

  • Deployment mana yang akan di-scale
  • Scaler mana yang akan digunakan
  • Cara terhubung ke sistem eksternal
  • Scaling parameters (min/max replicas, target metric value)

Triggers

Trigger adalah kondisi yang menyebabkan scaling. ScaledObject bisa memiliki multiple triggers. KEDA scale berdasarkan semua triggers, menggunakan highest desired replica count.

Sebagai contoh, Anda mungkin scale berdasarkan queue depth DAN CPU usage. Jika queue depth mengatakan Anda memerlukan 10 pods dan CPU mengatakan Anda memerlukan 5, KEDA scale ke 10.

Memulai: Queue-Based Scaling

Mari implementasikan skenario paling umum: scaling workers berdasarkan queue depth.

Setup: RabbitMQ Queue

Pertama, deploy RabbitMQ (atau gunakan instance yang ada):

KubernetesRabbitMQ Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rabbitmq
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rabbitmq
  template:
    metadata:
      labels:
        app: rabbitmq
    spec:
      containers:
      - name: rabbitmq
        image: rabbitmq:3.12-management
        ports:
        - containerPort: 5672
          name: amqp
        - containerPort: 15672
          name: management
        env:
        - name: RABBITMQ_DEFAULT_USER
          value: guest
        - name: RABBITMQ_DEFAULT_PASS
          value: guest
---
apiVersion: v1
kind: Service
metadata:
  name: rabbitmq
spec:
  selector:
    app: rabbitmq
  ports:
  - port: 5672
    name: amqp
  - port: 15672
    name: management

Install KEDA

Install KEDA menggunakan Helm:

Install KEDA
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm install keda kedacore/keda --namespace keda --create-namespace

Verifikasi KEDA berjalan:

Verify KEDA Installation
kubectl get pods -n keda

Deploy Worker Application

Buat simple worker yang memproses messages dari RabbitMQ:

KubernetesWorker Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: queue-worker
spec:
  replicas: 1
  selector:
    matchLabels:
      app: queue-worker
  template:
    metadata:
      labels:
        app: queue-worker
    spec:
      containers:
      - name: worker
        image: myapp/queue-worker:latest
        env:
        - name: RABBITMQ_HOST
          value: rabbitmq
        - name: RABBITMQ_USER
          value: guest
        - name: RABBITMQ_PASSWORD
          value: guest
        - name: QUEUE_NAME
          value: tasks
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi

Buat ScaledObject

Sekarang beritahu KEDA untuk scale worker berdasarkan queue depth:

KubernetesScaledObject: Queue-Based Scaling
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: queue-worker-scaler
spec:
  scaleTargetRef:
    name: queue-worker
  minReplicaCount: 1
  maxReplicaCount: 10
  triggers:
  - type: rabbitmq
    metadata:
      host: amqp://guest:guest@rabbitmq:5672/
      queueName: tasks
      queueLength: "5"

Konfigurasi ini:

  • Scale deployment queue-worker
  • Maintain 1-10 replicas
  • Scale berdasarkan RabbitMQ queue depth
  • Buat 1 pod baru untuk setiap 5 messages di queue

Jika queue memiliki 50 messages, KEDA menghitung: 50 / 5 = 10 pods dibutuhkan.

Test Scaling

Publish messages ke queue:

Publish Messages to Queue
# Terhubung ke RabbitMQ dan publish 100 messages
kubectl exec -it deployment/rabbitmq -- \
  rabbitmq-publish \
  --uri amqp://guest:guest@localhost:5672 \
  --exchange tasks \
  --routing-key tasks \
  --count 100

Amati pods scale:

Watch Pod Scaling
kubectl get pods -l app=queue-worker --watch

Anda seharusnya melihat pods scale dari 1 ke 20 (100 messages / 5 per pod). Saat workers memproses messages dan queue kosong, pods scale kembali turun.

Tip

KEDA memiliki cooldown period (default 5 menit) sebelum scale down. Ini mencegah rapid scaling up dan down ketika queue depth berfluktuasi.

Skenario Praktis

Skenario 1: HTTP Request Rate Scaling

Scale berdasarkan HTTP request rate alih-alih CPU:

KubernetesScaledObject: HTTP Request Rate
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: api-scaler
spec:
  scaleTargetRef:
    name: api-server
  minReplicaCount: 2
  maxReplicaCount: 50
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus:9090
      metricName: http_requests_per_second
      query: |
        rate(http_requests_total[1m])
      threshold: "100"

Ini scale API Anda berdasarkan request rate. Jika Anda mendapatkan 1,000 requests/second dan setiap pod menangani 100 req/s, KEDA scale ke 10 pods.

Skenario 2: Database Connection Pool Scaling

Scale berdasarkan active database connections:

KubernetesScaledObject: Database Connections
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: db-worker-scaler
spec:
  scaleTargetRef:
    name: db-worker
  minReplicaCount: 1
  maxReplicaCount: 20
  triggers:
  - type: postgresql
    metadata:
      query: "SELECT COUNT(*) FROM pg_stat_activity WHERE state = 'active'"
      targetQueryValue: "10"
      connectionString: "postgresql://user:pass@postgres:5432/mydb"

Ini scale workers berdasarkan active database connections. Jika Anda memiliki 100 active connections dan setiap worker menggunakan 10, KEDA scale ke 10 pods.

Skenario 3: Multiple Triggers

Scale berdasarkan multiple conditions:

KubernetesScaledObject: Multiple Triggers
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: worker-scaler
spec:
  scaleTargetRef:
    name: worker
  minReplicaCount: 1
  maxReplicaCount: 50
  triggers:
  # Scale berdasarkan queue depth
  - type: rabbitmq
    metadata:
      host: amqp://guest:guest@rabbitmq:5672/
      queueName: tasks
      queueLength: "5"
  # Juga scale berdasarkan CPU (traditional HPA)
  - type: cpu
    metricType: Utilization
    metadata:
      value: "70"
  # Juga scale berdasarkan memory
  - type: memory
    metricType: Utilization
    metadata:
      value: "80"

KEDA menggunakan highest desired replica count dari semua triggers. Jika queue depth mengatakan 10 pods dan CPU mengatakan 5, KEDA scale ke 10.

Skenario 4: Kafka Consumer Lag Scaling

Scale Kafka consumers berdasarkan consumer lag:

KubernetesScaledObject: Kafka Consumer Lag
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: kafka-consumer-scaler
spec:
  scaleTargetRef:
    name: kafka-consumer
  minReplicaCount: 1
  maxReplicaCount: 20
  triggers:
  - type: kafka
    metadata:
      bootstrapServers: kafka:9092
      consumerGroup: my-consumer-group
      topic: events
      lagThreshold: "100"

Ini scale consumers berdasarkan seberapa jauh mereka tertinggal. Jika lag adalah 1,000 messages dan threshold adalah 100, KEDA scale ke 10 pods.

Advanced Configuration

Scaling Behavior

Kontrol seberapa agresif KEDA scale:

KubernetesScaledObject: Scaling Behavior
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: worker-scaler
spec:
  scaleTargetRef:
    name: worker
  minReplicaCount: 1
  maxReplicaCount: 50
  triggers:
  - type: rabbitmq
    metadata:
      host: amqp://guest:guest@rabbitmq:5672/
      queueName: tasks
      queueLength: "5"
  # Scale up aggressively
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 100
        periodSeconds: 15
    # Scale down conservatively
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Percent
        value: 50
        periodSeconds: 60

Konfigurasi ini:

  • Scale up secara immediate (0 second stabilization)
  • Menggandakan pods setiap 15 detik jika diperlukan
  • Scale down secara slow (5 menit stabilization)
  • Mengurangi pods sebesar 50% setiap 60 detik

Ini mencegah rapid scaling up dan down sambil tetap merespons dengan cepat terhadap load increases.

Fallback Scaling

Jika external metric tidak tersedia, fallback ke CPU scaling:

KubernetesScaledObject: Fallback Trigger
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: worker-scaler
spec:
  scaleTargetRef:
    name: worker
  minReplicaCount: 1
  maxReplicaCount: 50
  triggers:
  - type: rabbitmq
    metadata:
      host: amqp://guest:guest@rabbitmq:5672/
      queueName: tasks
      queueLength: "5"
  # Fallback ke CPU jika RabbitMQ down
  - type: cpu
    metricType: Utilization
    metadata:
      value: "70"

Jika RabbitMQ menjadi unavailable, KEDA fallback ke CPU-based scaling. Aplikasi Anda tetap berjalan.

Kesalahan Umum dan Pitfalls

Kesalahan 1: Setting Target Metric Terlalu Tinggi

Jika Anda set queueLength: "100", KEDA menunggu sampai 100 messages menumpuk sebelum scaling. Ini menyebabkan latency spikes.

Lebih Baik: Set ke jumlah messages yang satu pod bisa proses dalam 1-2 menit. Jika pod memproses 10 messages/menit, set queueLength: "20".

Kesalahan 2: Tidak Setting Min Replicas

Jika minReplicaCount: 0, KEDA scale ke zero pods ketika queue kosong. Ketika messages baru tiba, butuh waktu untuk start pods dan memproses mereka.

Lebih Baik: Set minReplicaCount: 1 untuk keep at least one pod berjalan. Biayanya minimal dibandingkan latency spikes.

Kesalahan 3: Mengabaikan Cooldown Periods

KEDA memiliki default cooldown periods (5 menit untuk scale-down). Jika queue Anda berfluktuasi rapidly, pods mungkin tidak scale down dengan cepat.

Lebih Baik: Pahami cooldown periods dan adjust berdasarkan workload Anda. Untuk rapidly fluctuating loads, kurangi cooldown. Untuk stable loads, tingkatkan.

Kesalahan 4: Tidak Monitoring KEDA Sendiri

KEDA adalah komponen lain yang bisa fail. Jika KEDA crash, scaling berhenti.

Lebih Baik: Monitor KEDA's health, setup alerts, dan pastikan highly available.

Kesalahan 5: Mixing Incompatible Triggers

Beberapa triggers tidak bekerja baik bersama. Sebagai contoh, scaling berdasarkan queue depth dan CPU bisa menyebabkan unexpected behavior.

Lebih Baik: Pahami bagaimana triggers berinteraksi. Gunakan multiple triggers hanya ketika mereka mengukur different dimensions of load.

Best Practices

1. Mulai dengan One Metric

Jangan coba scale berdasarkan lima metrics sekaligus. Mulai dengan yang paling penting (queue depth, request rate, dll.), dapatkan bekerja, kemudian tambahkan yang lain.

2. Set Realistic Target Values

Target value harus merepresentasikan workload yang satu pod bisa handle. Jika pod bisa memproses 10 messages/second, set target ke 10-20 (accounting untuk beberapa buffer).

3. Monitor Scaling Decisions

KEDA mengekspor metrics ke Prometheus. Monitor mereka:

promql
# Current desired replicas
keda_scaler_active_count
 
# Metric value dari scaler
keda_scaler_metrics_value
 
# Scaling errors
keda_scaler_errors_total

4. Test Scaling Behavior

Sebelum deploy ke production, test bagaimana aplikasi Anda scale:

  • Secara bertahap tingkatkan load dan amati pods scale
  • Kurangi load dan amati pods scale down
  • Simulasikan metric unavailability dan verifikasi fallback bekerja

5. Gunakan Appropriate Cooldown Periods

  • Scale-up cooldown: Keep short (0-30 detik) untuk respond cepat ke load
  • Scale-down cooldown: Keep long (5-10 menit) untuk avoid rapid scaling

6. Kombinasikan dengan Resource Requests/Limits

KEDA scale jumlah pods, tetapi setiap pod masih memerlukan resource requests dan limits. Set ini appropriately:

KubernetesPod Resources
resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 512Mi

Ini memastikan cluster Anda memiliki cukup capacity untuk scaled pods.

7. Plan untuk Cluster Capacity

Jika KEDA scale ke 50 pods dan cluster Anda hanya memiliki capacity untuk 30, pods akan pending. Monitor cluster capacity dan scale cluster Anda accordingly.

Kapan TIDAK Menggunakan KEDA

KEDA Tidak Ideal Ketika:

  • Anda memiliki simple, predictable workloads: CPU-based scaling bekerja baik
  • Anda memerlukan sub-second scaling: KEDA memiliki polling intervals (default 30 detik)
  • External metric system Anda tidak reliable: Jika metric source down frequently, KEDA tidak bisa scale
  • Anda scaling berdasarkan custom business logic: KEDA scalers adalah predefined; complex logic mungkin memerlukan custom solutions

Kesimpulan

KEDA mentransformasi cara Anda scale Kubernetes workloads. Alih-alih menunggu CPU melonjak, Anda scale berdasarkan apa yang benar-benar penting: queue depth, request rate, database connections, atau metric apa pun yang Anda definisikan.

Insight fundamental: scale berdasarkan work, bukan resources. Queue dengan 1,000 messages adalah masalah nyata, bahkan jika CPU rendah. KEDA membiarkan Anda respond ke actual workload, bukan indirect signals.

Mulai dengan queue-based scaling untuk background workers. Tambahkan HTTP request rate scaling untuk APIs. Kombinasikan multiple triggers untuk complex workloads. Monitor semuanya dan adjust berdasarkan real-world behavior.

Aplikasi Anda akan lebih responsive, pengguna Anda akan lebih bahagia, dan infrastruktur Anda akan lebih efisien.

Langkah Selanjutnya

  1. Install KEDA di Kubernetes cluster Anda
  2. Identifikasi metric paling penting Anda: Queue depth, request rate, database connections, dll.
  3. Deploy ScaledObject untuk satu workload
  4. Test scaling behavior dengan meningkatkan dan menurunkan load
  5. Monitor KEDA metrics dan adjust target values
  6. Expand ke workloads lain saat Anda gain confidence

Mulai simple, test thoroughly, dan scale intelligently.


Related Posts