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

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.
Kubernetes' default HPA scale berdasarkan CPU dan memory usage. Ini bekerja untuk beberapa workloads tetapi gagal untuk yang lain:
Skenario 1: Queue Processing
Skenario 2: Batch Processing
Skenario 3: API Serving
Dalam semua kasus ini, masalah nyata bukan CPU usageāini adalah workload volume. CPU adalah side effect, bukan penyebabnya.
CPU dan memory adalah indirect metrics. Mereka memberitahu Anda tentang resource consumption, bukan tentang actual work. Pertimbangkan:
Tanpa memahami apa yang sebenarnya dilakukan pod, Anda terbang buta.
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:
KEDA mendukung 50+ scalers out of the box: message queues, databases, cloud services, HTTP endpoints, dan banyak lagi. Anda juga bisa menulis custom scalers.
Traditional HPA:
KEDA:
Pikirkan seperti ini: HPA seperti thermostat yang scale berdasarkan room temperature. KEDA seperti thermostat yang scale berdasarkan berapa banyak orang di ruangan.
Scaler adalah plugin yang terhubung ke sistem eksternal dan mengekstrak metrics. KEDA mencakup scalers untuk:
Setiap scaler tahu cara query sistemnya dan mengekstrak meaningful metrics.
ScaledObject adalah resource Kubernetes yang memberitahu KEDA cara scale deployment. Ini menentukan:
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.
Mari implementasikan skenario paling umum: scaling workers berdasarkan queue depth.
Pertama, deploy RabbitMQ (atau gunakan instance yang ada):
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: managementInstall KEDA menggunakan Helm:
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm install keda kedacore/keda --namespace keda --create-namespaceVerifikasi KEDA berjalan:
kubectl get pods -n kedaBuat simple worker yang memproses messages dari RabbitMQ:
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: 512MiSekarang beritahu KEDA untuk scale worker berdasarkan queue depth:
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:
queue-workerJika queue memiliki 50 messages, KEDA menghitung: 50 / 5 = 10 pods dibutuhkan.
Publish messages ke 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 100Amati pods scale:
kubectl get pods -l app=queue-worker --watchAnda 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.
Scale berdasarkan HTTP request rate alih-alih CPU:
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.
Scale berdasarkan active 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.
Scale berdasarkan multiple conditions:
KEDA menggunakan highest desired replica count dari semua triggers. Jika queue depth mengatakan 10 pods dan CPU mengatakan 5, KEDA scale ke 10.
Scale Kafka consumers berdasarkan 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.
Kontrol seberapa agresif KEDA scale:
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: 60Konfigurasi ini:
Ini mencegah rapid scaling up dan down sambil tetap merespons dengan cepat terhadap load increases.
Jika external metric tidak tersedia, fallback ke CPU scaling:
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.
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".
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.
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.
KEDA adalah komponen lain yang bisa fail. Jika KEDA crash, scaling berhenti.
Lebih Baik: Monitor KEDA's health, setup alerts, dan pastikan highly available.
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.
Jangan coba scale berdasarkan lima metrics sekaligus. Mulai dengan yang paling penting (queue depth, request rate, dll.), dapatkan bekerja, kemudian tambahkan yang lain.
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).
KEDA mengekspor metrics ke Prometheus. Monitor mereka:
# Current desired replicas
keda_scaler_active_count
# Metric value dari scaler
keda_scaler_metrics_value
# Scaling errors
keda_scaler_errors_totalSebelum deploy ke production, test bagaimana aplikasi Anda scale:
KEDA scale jumlah pods, tetapi setiap pod masih memerlukan resource requests dan limits. Set ini appropriately:
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512MiIni memastikan cluster Anda memiliki cukup capacity untuk scaled pods.
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.
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.
Mulai simple, test thoroughly, dan scale intelligently.