
Sun Sep 13 2026

Selam! ☕
Hazırsan biraz sohbet edelim — senin de bildiğin o "HPA yeterli sanıyordum ama işler karıştı" anları üzerine.
Kubernetes ile çalışıyorsan Horizontal Pod Autoscaler (HPA) senin ilk dostun. cpu ve memory metriklerine bakıp pod sayısını artırır/azaltır. Kafası rahat, kurulumu basit. Ama... 🤔
Günlük hayatta şu "şüpheli" anlar başınıza gelmedi mi?
504 Gateway Timeout gördün.metrics-server’dan CPU/memory okur.Ne oluyor burada?
HPA resource-based bir scaler. "Sistem ne kadar güçlü çalışıyor?" sorusuna cevap verir.
Oysa senin asıl sorun: "Ne kadar iş bekliyor?" 🎯
İşte bu noktada KEDA (Kubernetes Event-driven Autoscaling) devreye girer.
Kuyruk uzunluğunu, HTTP RPS’yi, özel metrikleri dinleyip saniyeler içinde scale eder. HPA’nın göremediği "iş yükü" sinyalini algılar.
Bu yazıda:
Hadi başlayalım — sırtını sırtına koyup bu sorunu çözelim! 🚀
HPA (Horizontal Pod Autoscaler) kagit üzerinde harika görünse de, prod'da başınızı ağrıtan üç klasik tuzak var. Her birini küçük bir "hikaye" ile anlatalım — mutlaka "evet, bana da oldu" diyeceksiniz 😅
Senaryo: E-ticket servisiniz var. Kullanıcı bilet alırken RabbitMQ kuyruğuna mesaj atıyor. Yoğun saatlerde kuyruk binlerce mesaj birikiyor ama pod'ların CPU'su %15, memory'si %30. HPA "haफफ, kaynak bol" diyip scale etmiyor. Sonuç? Kuyrukta 10 dakika bekleme, müşteri şikayetleri, oncall alarmı 🚨
Ne oluyor burada?
HPA default'ta sadece cpu ve memory metric'lerine bakar. Ama sizin bottleneckınız CPU değil, kuyruk derinliği (queue depth).
# HPA tanımında custom metric eklemeden bu durum kurtulamaz
kubectl get hpa ticket-service -n prod
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
# ticket-service Deployment/ticket-service 15%/80% 3 20 3 4h
Bu sayede ne oluyor?
Pod'lar "rahat" görünüyor ama işlem kuyrukta takılı kalıyor. Kullanıcı "sistem yanıt vermiyor" diyor, siz de "CPU düşük, neden scale etmiyor?" diye kafayı yiyorsunuz.
İpucu:
prometheus-adapterilerabbitmq_queue_messages_readymetric'ini HPA'ya besleyin. Ama o da ayrı bir dert (3. senaryoya bakın) 😬
Senaryo: Flash sale başlıyor. Trafik 30 saniyede 10x artıyor. HPA tetikleniyor... ama 2 dakika sonra. O 2 dakikada pod'lar OOM kill oluyor, yeni pod'lar CrashLoopBackOff ye giriyor, kullanıcılar "503 Service Unavailable" alıyor.
Neden?
İki ana gecikme kaynağı var:
| Kaynak | Default Süre | Ne Yapıyor? |
|---|---|---|
| Metrics Server collection interval | ~60s | Pod metric'lerini toplar |
| HPA stabilization window (scale-up) | 0s (default) ama metric buffer var | Ölçeklenme kararı için "güvenli" veri bekler |
| HPA stabilization window (scale-down) | 300s | Gereksiz scale-down'u engeller |
Gerçek log örneği (zaman damgalı):
2024-11-15T10:00:00Z [METRICS] cpu=12% memory=28% queue_depth=45
2024-11-15T10:00:30Z [TRAFFIC] RPS: 200 → 2,500 (flash sale başladı)
2024-11-15T10:01:00Z [METRICS] cpu=78% memory=85% queue_depth=1,200
2024-11-15T10:01:15Z [HPA] Evaluation: target 80% cpu, current 78% → **no action yet**
2024-11-15T10:02:00Z [METRICS] cpu=95% memory=98% queue_depth=4,800
2024-11-15T10:02:10Z [HPA] Scale-up decision: 3 → 8 replicas
2024-11-15T10:02:45Z [KUBELET] New pods: Pending → ContainerCreating
2024-11-15T10:03:30Z [KUBELET] Pods Ready: 8/8
Gördünüz mü? Trafik patlaması 10:00:30'da, HPA kararı 10:02:10'da, pod'lar ready 10:03:30'da. 3 dakika kaybettik. O arada queue 45 → 4,800'e çıktı.
Bunu kubectl get hpa -w ile canlı izlerseniz:
kubectl get hpa ticket-service -n prod -w
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
ticket-service Deployment/ticket-service 12%/80% 3 20 3 4h
ticket-service Deployment/ticket-service 78%/80% 3 20 3 4h
ticket-service Deployment/ticket-service 95%/80% 3 20 3 4h
ticket-service Deployment/ticket-service 95%/80% 3 20 8 4h ← scale-up oldu (gecikmeli)
Ne yapabilirsiniz?
--horizontal-pod-autoscaler-sync-period(default 15s) kısaltılabilir (controller-manager flag)behavior.scaleUp.stabilizationWindowSeconds: 0(default zaten 0 ama metric buffer yine de var)- En etkili: Predictive scaling (KEDA, custom controller) veya pre-warm stratejisi (schedule ile önceden scale-up)
Senaryo: Hem CPU hem de RabbitMQ kuyruk derinliği hem de HTTP response time (p99) bazında scale etmek istiyorsunuz. HPA v2 API metrics: array'i destekliyor ama:
rules: yazıp, discovery: yapıp, resourceOverride: falan eklemeniz gerekiyorcustom.metrics.k8s.io API'si gelmedi → kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1" → 404Gerçek bir Prometheus Adapter values.yaml parçası (ve ağrısı):
rules:
- seriesQuery: 'rabbitmq_queue_messages_ready{namespace!="",queue!=""}'
resources:
overrides:
namespace:
resource: namespace
queue:
resource: queue
name:
matches: "^(.*)$"
as: "queue_messages_ready"
metricsQuery: 'sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)'
Sonra HPA'da bunu nasıl referans alıyorsunuz?
metrics:
- type: Pods
pods:
metric:
name: queue_messages_ready
target:
type: AverageValue
averageValue: "100"
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Ve tabii ki işe yaramıyor. Neden? Çünkü:
discovery yapabilmesi için Prometheus'un kube-pod job'ının pod label'larını düzgün scrape etmesi lazımqueue_messages_ready ama Prometheus'ta rabbitmq_queue_messages_ready → naming mismatchnamespace: yok → adapter hangi namespace'i sorgulayacağını bilmiyorBu sayede ne oluyor?
Siz "custom metric HPA" yazıyorsunuz, prod'da kubectl describe hpa → Unable to get metrics for resource ...: unable to fetch metrics from custom metrics API hatası alıyorsunuz. Oncall'e "HPA çalışmıyor" diye mesaj atıyorsunuz, aslında adapter config'i bozuk 🤦♂️
Gerçekçi tavsiye:
- Basit ihtiyaçlar için KEDA kullanın (RabbitMQ, Kafka, HTTP, Cron scaler hazır gelir, adapter uğraşası yok)
- İleri seviye için: Prometheus Adapter yerine VictoriaMetrics / Thanos + custom metrics server stack'i değerlendirin
- Veya Karpenter + KEDA kombinasyonu ile node + pod level scaling'i bir arada yönetin
| Tuzaç | Hızlı Çözüm | Kalıcı Çözüm |
|---|---|---|
| Sadece CPU/memory | kubectl patch hpa --patch '{"spec":{"metrics":[{"type":"Pods",...}]}}' |
KEDA / Custom Metrics API |
| Gecikme (lag) | --sync-period=10s, behavior.scaleUp.stabilizationWindowSeconds=0 |
Predictive scaling, pre-warm |
| Prometheus Adapter zahmeti | KEDA kurun, bitirin | Metrics pipeline yeniden tasarımı |
Benim prod notum: HPA "basit işler için" harika. Ama event-driven, latency-sensitive, multi-metric workload'larda KEDA + Karpenter ikilisine geçince hayatımız kurtuldu. Siz de deneyin, oncall gece uyanmaz 🌙✨
Hazırsanız bir sonraki bölümde KEDA ile "5 dakikada RabbitMQ tabanlı autoscaling" kurulumuna geçelim 🚀
Hazırsan KEDA'yla tanışalım 🤝 KEDA (Kubernetes Event-driven Autoscaling) — CNCF graduated projesi, yani toplulukta olgunlaşmış, production-ready bir standard haline gelmiş.
Özetle: HPA'nın (Horizontal Pod Autoscaler) üzerine kurulu, ama HPA'nın yapabildiğinden çok daha esnek bir yapı sunuyor.
Kubernetes'in built-in HPA'sı harika bir araç, ama temel bir kısıtı var: pull model ile çalışıyor. Yani:
Soru şu: Benim mikroservisim bir kuyruk dinliyorsa, neden CPU'yu izlesin? 🤷♂️
Kuyrukta 10.000 mesaj birikmiş ama CPU %5'de kalabilir — consumer'lar bekliyor olabilir, ya da işlem I/O bound olabilir. HPA bunu görmez, scale etmez. İşte tam bu noktada KEDA devreye giriyor.
KEDA, ScaledObject (veya ScaledJob) CRD'leri aracılığıyla herhangi bir event kaynağından metrik almanı sağlıyor. Bunu Scaler denilen bileşenlerle yapıyor:
| Event Kaynağı | Scaler Adı | Ne İşe Yarar? |
|---|---|---|
| 📨 Kafka | kafka |
Consumer group lag'ini izler |
| 🐰 RabbitMQ | rabbitmq |
Kuyruk uzunluğunu (message count) okur |
| ☁️ Azure Queue / Service Bus | azure-queue / azure-servicebus |
Cloud queue metrikleri |
| 📊 Prometheus | prometheus |
Herhangi bir PromQL sorgusu |
| 🌐 HTTP | http |
Custom endpoint'ten JSON metrik çeker |
| ⏰ Cron | cron |
Zaman tabanlı scale (örn. gece yoğunluğu) |
| ...ve 60+ scaler daha! |
Push/Event modeli: Scaler'lar event kaynağından anlık metrik alır (pull değil, event-driven). Kuyrukta mesaj birikince saniyeler içinde pod sayısı artar. ⚡
Bu kısmı çok net anlatayım: KEDA, HPA'yla çakışmaz, HPA yaratır. 🎯
Sen bir ScaledObject yazıyorsun, KEDA arka planda sizin için bir HorizontalPodAutoscaler resource'u oluşturuyor. Yani:
kubectl get hpa dediğinde KEDA'nın yarattığı HPA'ları görüyorsun# Örnek: KEDA ScaledObject — Kafka consumer lag'ine göre scale
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-processor-scaledobject
namespace: production
spec:
scaleTargetRef:
name: order-processor # Deployment adı
pollingInterval: 5 # Her 5 saniyede bir metrik kontrol et
cooldownPeriod: 300 # Scale-down sonrası 5 dk bekle
minReplicaCount: 2
maxReplicaCount: 50
triggers:
- type: kafka
metadata:
bootstrapServers: kafka-cluster:9092
consumerGroup: order-processor-group
topic: orders
lagThreshold: "100" # Her pod başına 100 mesaj lag -> yeni pod
Bu sayede ne oluyor?
orders kuyruğu birikmeye başladığında → saniyeler içinde pod sayısı artarcooldownPeriod sayesinde yumuşak bir şekilde scale-down olurKısaca: Event-driven bir iş yükün varsa, KEDA kullanma.
CPU tabanlı scale hâlâ işinizi görüyorsa (örn. CPU-bound bir hesaplama servisi), native HPA yeterli. Ama kuyruk, event, mesaj dili konuşan bir sistemdeysen — KEDA tam size göre. ✨
Bir sonraki bölümde ScaledObject'in anatomisini (triggers, authentication, fallback, advanced config) tek tek inceleyeceğiz. Hadi oraya gidelim! 🚀
KEDA, bir Kubernetes cluster'ı için "event-driven autoscaling" sunan bir operatördür. Bunu oluşturan üç temel parça:
ScaledObject
├─ scaleTargetRef → Deployment/my-app
├─ triggers
│ ├─ type: kafka
│ ├─ authenticationRef → TriggerAuthentication/my-kafka-auth
└─ (opsiyonel) pollingInterval, cooldown, etc.
triggers alanı).horizontalPodAutoscaler) tanımlayabilirsin ve KEDA operatörü bunu cluster'ın kendi HPA kaynakları gibi yönetir. Böylece renkli UI'ye bakarken bile her şey otomatik olarak çalışıyor olur.Aşağıda, standart bir ScaledObject'ın minimum tanımı var:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: myapp-scaledobject
spec:
scaleTargetRef:
name: myapp-deployment # ölçeklendirilecek deployment
pollingInterval: 30 # saniye cinsinden (isteğe bağlı)
triggers:
- type: kafka
metadata:
bootstrapServers: my-kafka:9092
topic: my-topic
lagThreshold: "10"
authenticationRef:
name: my-kafka-auth
Ne oluyor?
scaleTargetRef sayesinde KEDA operatörü myapp-deployment adındaki Deployment'u bulur ve öncelikle bu hedefi bilir.triggers listesi içinde bir Kafka scaler'ı tanımladık. Scaler kendisi Kafka broker'ını okumaz, yalnızca bizim tanımladığımız kimlik bilgilerine dayanır.authenticationRef ile my-kafka-auth adında bir TriggerAuthentication nesnesine bağlanıyoruz. Bu nesne aşağıdaki gibi görünebilir:apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: my-kafka-auth
spec:
secret:
name: kafka-secret
key: credentials # örneğin: "username" ve "password" anahtarlarını içerir
Sonuç: KEDA operatörü bir ScaledObject tanıdığında, otomatik olarak bir HPA kaynağı oluşturur ve kendi kapsayıcısına referans verir. Bu, cluster'ın standart autoscaling yönetiminde olduğunu düşünmene neden olurken, aynı zamanda event-driven "gerçekten" çalıştığını görebilmen için size kilitli bir pencere sunar.
Cluster'ında zaten KEDA operatörü kurmuşsan (örneğin helm install keda /charts/keda), işte neler görürsün:
kubectl get scaledobjects.keda.sh içinde görünür ve pod sayısını direkt kontrol edebilirsin.kubectl get triggerauthentications.keda.sh içinde görünür; bilgilerini kontrol et.kubectl get hpa içinde scaledobjectın adı ile görünür (operatör ona bir "scaleTargetRef" içeren bir HPA oluşturur).Eğer operatörün güncel değilse, HPA kaynağını kendin ekleyebilirsin, ancak KEDA operatörü gerçek event-driven ihtiyaçları göz önüne alarak bu yönetimi üstlenmeyi tercih eder.
Sonuç olarak: ScaledObject bir target, TriggerAuthentication bir kimlik bilgileri deposu, Scaler bir event tetikleyicisidir. Bir araya geldiklerinde, bir event başladığında pod sayısını otomatik olarak ayarlamak için ihtiyacın olan her şeye sahip olursun ve tüm bu süreci KEDA operatörü tarafında yerleşik bir HPA ile yönetebilirsin. 🚀
Hazırsan başlayalım. Ben kendi cluster'ımda şu sırayla hareket ettim ve her adımda karşılaştığım küçük sürprizleri de not aldım 👇
Önce repo ekleyip chart'ı yüklüyorum. Namespace keda olsun diye --create-namespace kullanıyorum.
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm install keda kedacore/keda --namespace keda --create-namespace
İpucu:
helm installsonrasıkubectl get pods -n kedailekeda-operatorpodunun Running olduğunu kontrol et. Ben ilk denemedeImagePullBackOffaldım;imagePullSecretsekleyip tekrarhelm upgrade --installyaptım ve sorun çözüldü ✅
KEDA kendi HPA'sını yöneteceği için eski HPA çakışmasın. Ben silmeyi tercih ettim, ama kubectl patch hpa my-app-hpa -p '{"spec":{"replicas":0}}' ile suspend de edebilirsin.
kubectl delete hpa my-app-hpa
Not: HPA silinmeden önce
kubectl get hpa my-app-hpa -o yaml > hpa-backup.yamlalmayı unutma. Rollback planın bu dosya olsun 🔁
Ben Kafka topic lag'ini tetikleyici olarak seçtim. Diğer yaygın seçenekler: RabbitMQ kuyruk uzunluğu, Prometheus metriği, Azure Queue vb. Hangi kaynağı kullanacaksan o provider'ın trigger type'ını not et.
Kafka için SASL kimlik bilgilerini bir Secret'te tutuyorum, sonra TriggerAuthentication ile referans veriyorum.
# Secret oluştur (bir kere)
kubectl create secret generic kafka-secret \
--from-literal=saslUser=myuser \
--from-literal=saslPassword=mypassword \
-n default
# triggerauth.yaml
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
name: kafka-trigger-auth
namespace: default
spec:
secretTargetRef:
- parameter: saslUser
name: kafka-secret
key: saslUser
- parameter: saslPassword
name: kafka-secret
key: saslPassword
kubectl apply -f triggerauth.yaml
Hata aldım:
TriggerAuthenticationnamespace uyuşmazlığı verdi.metadata.namespaceile Secret'ın aynı namespace'te olduğundan emin ol ❗️
Şimdi asıl ölçeklendirme tanımı. pollingInterval 15 sn, lagThreshold 10 mesaj olarak ayarladım.
# scaledobject.yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: my-app-scaledobject
namespace: default
spec:
scaleTargetRef:
name: my-app
pollingInterval: 15
cooldownPeriod: 300
minReplicaCount: 1
maxReplicaCount: 20
triggers:
- type: kafka
metadata:
topic: my-topic
bootstrapServers: kafka:9092
consumerGroup: my-consumer-group
lagThreshold: "10"
authenticationRef:
name: kafka-trigger-auth
kubectl apply -f scaledobject.yaml
Pratik ipucu:
cooldownPeriodçok kısa olursa thrashing olur. Ben 5 dk (300 sn) verdim, gözlemledim ve istikrarlı oldu ✅
Her şey yolunda mı? Şu komutlarla anlık durum kontrol ediyorum.
kubectl get scaledobject my-app-scaledobject -n default
kubectl get hpa -n default
kubectl describe scaledobject my-app-scaledobject -n default
scaledobject Ready ve Active göstermeli.kubectl get hpa çıktısında my-app-scaledobject isimli HPA görmelisin.describe altındaki Metrics bölümünde kafka trigger'ının current lag değerini takip et 🎯kubectl delete scaledobject my-app-scaledobject -n defaultkubectl apply -f hpa-backup.yaml (1. adımda aldığın yedek)helm uninstall keda -n keda ile KEDA'yı kaldır.Bu adımları sırayla uyguladığında HPA → KEDA geçişi sorunsuz ve gözlemlenebilir olur. Herhangi bir adımda hata alırsan logları (kubectl logs -n keda deploy/keda-operator) incele, genellikle authenticationRef veya bootstrapServers typo'su çıkıyor 😉
Keyifli ölçeklendirmeler! 🚀
Hazırsan şimdi somut bir örnek üzerinden KEDA'nın gücünü görelim. Elimizde basit bir Node.js Kafka consumer mikroservisi var. Mesajları işliyor, veritabanına yazıyor. Trafik geceleri düşük, gündüzlerde patlıyor. Eski yöntemle (CPU tabanlı HPA) ya geç ölçekleniyor ya da gereksiz pod yaratıyorduk. KEDA ile lag'e (kuyruk birikimine) bakarak tam isabetli ölçeklendirme yapacağız. 🎯
Önce consumer deployment'ımız. Image, env vars ve resource limitleri burada.
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-consumer
namespace: production
labels:
app: order-consumer
spec:
replicas: 1
selector:
matchLabels:
app: order-consumer
template:
metadata:
labels:
app: order-consumer
spec:
containers:
- name: consumer
image: myorg/order-consumer:v1.4.2
env:
- name: KAFKA_BOOTSTRAP_SERVERS
value: "kafka-cluster:9092"
- name: CONSUMER_GROUP
value: "order-processing-group"
- name: TOPIC
value: "orders"
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
Ne oluyor burada?
replicas: 1 → Başlangıçta tek pod. KEDA bunu yönetecek.Bunu silmeyeceğiz, yan yana koyup farkı görelim. Bu HPA KEDA ile çakışmaz ama aynı deployment'ı hedef almaz (label selector farklı olmalı). Sadece "eski nasıldı?" diye hatırlatma.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: order-consumer-hpa-cpu
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: order-consumer
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
Neden bu yeterli değildi? 🤔
İşte sihirli dosya. Lag threshold'a göre ölçeklendiriyor.
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-consumer-scaledobject
namespace: production
labels:
app: order-consumer
spec:
scaleTargetRef:
name: order-consumer
pollingInterval: 15
cooldownPeriod: 180
minReplicaCount: 1
maxReplicaCount: 20
fallback:
failureThreshold: 3
replicas: 2
advanced:
restoreToOriginalReplicaCount: false
horizontalPodAutoscalerConfig:
behavior:
scaleDown:
stabilizationWindowSeconds: 120
policies:
- type: Percent
value: 20
periodSeconds: 60
triggers:
- type: kafka
metadata:
bootstrapServers: kafka-cluster:9092
consumerGroup: order-processing-group
topic: orders
lagThreshold: "1000"
offsetResetPolicy: latest
allowIdleConsumers: "true"
| Parametre | Değer | Gerekçe |
|---|---|---|
| pollingInterval | 15 saniye |
KEDA her 15 sn'de bir Kafka'dan lag çeker. Daha düşük (örn. 5 sn) → Kafka broker yükü artar. Daha yüksek → tepki gecikir. 15 sn production için dengeli. |
| cooldownPeriod | 180 saniye (3 dk) |
Scale-in sonrası 3 dk bekle. Mesaj patlamaları genelde burst olur. 3 dk altına alırsan flapping (sürekli up/down) yaşarsın. |
| minReplicaCount | 1 |
Gece/hafta sonu trafiği sıfıra yakın. 0 da olabilirdi (scale-to-zero) ama consumer group rebalance maliyeti ve cold-start latency'si için 1 tutuyoruz. |
| maxReplicaCount | 20 |
Partition sayımız 20. Kafka consumer partition başına 1 pod kuralı. 20'in üzeri idle pod demek → kaynak israfı. |
| lagThreshold | "1000" |
Her pod ~1000 mesaj/sn işliyorsa, lag 1000'in üzerindeyse yeni pod gerekir. Load testlerinizle bu sayıyı kalibre edin. |
| offsetResetPolicy: latest | — | Yeni pod ayağa kalktığında eski mesajları tekrar işleme (at-least-once riski). Idempotent consumer'ınız varsa earliest de olabilir. |
| allowIdleConsumers: "true" | — | Lag 0 olsa bile minReplicaCount kadar pod ayakta kalsın. Rebalance storm'u önler. |
💡 İpucu:
lagThresholdstring olarak veriliyor (YAML'de tırnak içinde). KEDA bunu integer'a çevirir.
Sahne: Gündüz 10:00, siparişler patlıyor. Producer saniyede 5.000 mesaj basıyor. Consumer pod başına ~1.000 msg/sn işleyebiliyor.
| Zaman | Lag (toplam) | Pod Sayısı | Ne Oluyor? |
|---|---|---|---|
| 10:00:00 | 0 | 1 | Sessizlik. |
| 10:00:15 | 5.000 | 1 → 6 | KEDA 15 sn'de bir poll eder. Lag 1.000'in üzerine çıktı → 5 yeni pod tetikler (her pod 1.000 lag alır). |
| 10:00:45 | 12.000 | 6 → 12 | Producer hızı arttı. Lag yine threshold üzerinde → daha fazla pod. |
| 10:02:00 | 800 | 12 → 6 | Producer yavaşladı. Lag 1.000'in altına düştü. cooldownPeriod (180 sn) dolmadan scale-in başlamaz. |
| 10:05:00 | 200 | 6 → 2 | Lag stabil düşük. KEDA yavaş yavaş (scaleDown policy: %20/dk) pod'u indiriyor. |
| 10:10:00 | 0 | 2 → 1 | Gece moduna giriş. minReplicaCount: 1'e iner. |
Loglardan ne görürsün? 📋
[INFO] ScaledObject order-consumer-scaledobject: current metric value=5000, desired replicas=6
[INFO] ScaledObject order-consumer-scaledobject: current metric value=12000, desired replicas=12
[INFO] ScaledObject order-consumer-scaledobject: cooldown period active, skipping scale down
[INFO] ScaledObject order-consumer-scaledobject: current metric value=800, desired replicas=6
[INFO] ScaledObject order-consumer-scaledobject: current metric value=200, desired replicas=2
Grafik yerine metinsel özet:
Lag yukarı doğru keskin çıkış yapar → pod sayısı merdiven basamakları gibi artar. Lag eğimli düşüş yapar → pod sayısı yumuşak bir eğriyle iner (cooldown + scaleDown policy sayesinde). ❗️ Flapping yok. ✅ Maliyet kontrollü. ✅ SLA korunuyor.
fallback:
failureThreshold: 3
replicas: 2
Kafka broker'a 3 ardışık poll başarısız olursa (network blip, auth hatası vs.) KEDA panikle 2 replica'ya sıçrar. Uygulamanız down değil, yavaşlar — bu arada alert'iniz tetiklenir, siz müdahale edersiniz. 🛠
Özetle:
İkinci soru business metric'e çok daha yakın. Bu yüzden order-consumer için KEDA doğru seçim. 🚀
Bir sonraki bölümde Prometheus Adapter ile custom metric (örn. http_request_duration_seconds_p99) nasıl scale edeceğimize bakalım. Hazır mısın? 😉
Hazırsan geçiş sonrası farkları madde madde gözden geçirelim 👇
Ölçeklendirme tepki süresi ⏱
Resource utilization verimliliği 📉
Operasyonel basitlik 🛠
Event kaynakları çeşitliliği 🎯
| Metrik | HPA (Önce) | KEDA (Sonra) | Yorum |
|---|---|---|---|
| Tepki süresi | ~90 sn – 2 dk | < 10 sn | Event‑driven sayesinde anında genişler/daralır |
| Boşta pod sayısı (ortalama) | 12 | 7 | %40 daha az pod ile aynı throughput |
| Kurulum karmaşıklığı | Prometheus Adapter + Metrics Server | Tek ScaledObject CRD |
Operasyonel yük azaldı |
| Desteklenen tetikleyiciler | CPU, Memory, Custom (Prometheus) | 50+ scaler (Kafka, RabbitMQ, Cron, …) | Esneklik arttı |
Benim cluster’ımda %40 daha az podla aynı işi yaptık 🚀
KEDA’ya geçtikten sonra kuyruk uzunluğuna göre anında scale‑out yapabiliyoruz, gece saatlerde ise scale‑to‑zero sayesinde maliyet düştü.
Küçük bir ipucu: Kendi ortamınızda
kubectl get hpavekubectl get scaledobjectçıktılarını yan yana koyun, saniyeler vs dakikalar farkını kendi gözlerinizle görün. Ölçün, karşılaştırın, karar verin ✅
TriggerAuthentication secret’ını yanlış namespace’e koymak 🎯
metadata.namespace alanını kontrol ettim.lagThreshold çok düşük ayarlayıp flapping’e neden olmak 🔁
lagThreshold değerini gerçek trafik dalgalanmasına göre (ör. 30‑60 sn) yukarı çekip stabilizationWindow ekledim.pollingInterval çok kısa yapıp KEDA operator’ünü yormak ⛔
pollingInterval’ı 15‑30 sn aralığına çıkardım; metrik toplama yükü aniden düştü.ScaledObject’te fall‑back HPA metrikleri (cpu/memory) eklememek 🛡
fallback trigger’ı ekleyerek CPU‑based bir güvenlik ağı kurdum.apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: my-worker
spec:
scaleTargetRef:
name: my-worker
pollingInterval: 30
fallback:
failureThreshold: 3
replicas: 2
triggers:
- type: kafka
metadata:
bootstrapServers: kafka:9092
consumerGroup: my-group
topic: my-topic
lagThreshold: "100"
- type: cpu
metadata:
type: Utilization
value: "70"
İpucu: Her zaman en az bir cpu veya memory fallback trigger’ı ekleyin; bu, metrik kaynakları down olduğunda sistemin hayatta kalmasını sağlar.
Canary deployment stratejisi olmadan üretime basmak ✅
Bende de bu makaleyi okuduktan sonra kafam biraz karıştı, nasıl paylaşayım dedim. Gelip KEDA'yı en sık kullandığımız temel scaler'larla kurduğumu düşünelim. İşte o an, daha da esnek bir kontrol sahnesi istediğimiz zaman ortaya çıkar. Hadi ileri seviye stratejileri anlatalım ve arkasından motivasyonla bir kapanış yapalım! 🚀
Çoklu tetikleyici (AND/OR mantığı)
ScaledJob → Batch işleri için
ScaledJob tanımlarsın; işe başlamadan önce dış tetikleyiciyi (örneğin bir kuyruk uzunluğu) bekleyip sonra çalıştırman olur.ScaledJob kaydıyla. 📦External Scaler → Kendi ölçeklendirme mantığını yazın
Metric Server entegrasyonu
Artık ölçeklendirme içeriğinize, iş mantığınıza, harici tetikleyicilere göre gerçekleşiyor. KEDA ile basit bir "cpu > 80" kuralından, kapsamlı bir "cpu > 70 VE istek sayısı > 100 VEYA bir kuyruk uzunluğu > 500" kuralına geçebilirsiniz.
ScaledObject ayarlayın ya da kendi External Scaler'ınızı yazmaya başlayın.Bir sonraki yazıda External Scaler yazmaya çalışacağım, görüşmek üzere! 🎉
Bu içerik tamamen yapay zeka destekli otomasyon sistemi ile üretilmiştir.
All rights reserved