Geçen yıl bir e-ticaret müşterisinde Kara Cuma sabahı 06:30, telefon çaldı: “Site yavaşladı, sepet sayfası 504 dönüyor.” AKS cluster’ında HPA tanımlıydı, sayı 4’ten 12’ye çıkmıştı, ama node havuzu maksimum 8 node’da kilitliydi. Yeni pod’lar saatlerce Pending bekledi çünkü cluster autoscaler limite takılmıştı. O sabah öğrendiğim şey hâlâ çoğu ekipte tekrarlanıyor: HPA’yı yapılandırmak yetmez, üç katmanı (pod-yatay, pod-dikey, node) birlikte düşünmediğin gün karşına çıkar. Bu yazıda saha notlarımla üç mekanizmayı ve aralarındaki incelikleri anlatıyorum.
Horizontal Pod Autoscaler — en yaygın, en yanlış yapılandırılan
HPA, metrik değerine göre pod sayısını artırır/azaltır. Formül basit:
desiredReplicas = ceil( currentReplicas × ( currentMetric / targetMetric ) )
3 pod, ortalama CPU %80, hedef %50 → ceil(3 × 80/50) = 5. Sahada en sık gördüğüm üç hata:
- resources.requests yok. CPU bazlı HPA için
requests.cpuşart. Yoksa kullanım oranı hesaplanamaz, HPA yalnızca “Unknown” döner. - min=1. Tek pod restart yerken servis kesintisi yaşıyorsunuz. Production’da
minReplicas: 2taban kuralım. - Memory ile ölçeklemek. Çoğu uygulama belleği bırakmaz, HPA artırır artırır asla azaltmaz. Memory bazlı HPA’yı yalnızca davranışını iyi bildiğin uygulamalarda kullan.
Tipik HPA örneği
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 30
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
stabilizationWindowSeconds: 300 flapping’i (sürekli artıp azalma) engelliyor — HPA ezbere ayar yapılırsa ölçek dakikada 4-5 kez değişebilir. Pod restart maliyetini hesaba katmadan agresif scale-down yazmak banka kasası açar.
Custom metrik ve KEDA
CPU çoğu zaman doğru sinyal değildir. Bir worker pod için anlamlı sinyal kuyruktaki mesaj sayısıdır. KEDA tam burada devreye giriyor — hem custom metrik adapter olarak çalışır hem de sıfıra ölçekleme yeteneğini getirir (HPA min=1’in altına inemez, KEDA inebilir).
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: order-worker-scaler
spec:
scaleTargetRef:
name: order-worker
minReplicaCount: 0
maxReplicaCount: 50
pollingInterval: 15
cooldownPeriod: 120
triggers:
- type: azure-servicebus
metadata:
queueName: orders
messageCount: "5"
authenticationRef:
name: keda-msi-auth
Bir müşterimde gece batch işleri 03:00–05:00 arası çalışıyordu. KEDA ile sıfıra inince, sabit 4 worker’ın aylık maliyeti $620’dan $90’a düştü. AKS’te KEDA artık add-on, az aks update --enable-keda yeter.
Vertical Pod Autoscaler — dikkat edilmesi gereken katman
VPA, pod sayısını değil pod’un requests/limits değerlerini ayarlar. Üç modu var:
- Off: Sadece öneri üretir, pod’lara dokunmaz. Sahada %90 oranında bu modu öneriyorum.
- Initial: Yalnızca pod ilk oluşturulurken önerilen değerleri uygular.
- Auto: Çalışan pod’ları yeniden başlatarak günceller. Production’da PodDisruptionBudget olmadan asla.
Önemli kural: HPA ve VPA aynı metrik üzerinde çakışmaz. CPU bazlı HPA + CPU bazlı VPA Auto = pod sayısı sürekli oynayan, request değeri sürekli değişen kaos. Tipik kombinasyon şu: HPA custom metrik (queue depth) ile yatay, VPA CPU/memory ile dikey ayar.
VPA’nın bence en değerli kullanımı şu: yeni bir uygulama production’a alırken bir hafta Off modda çalıştır, önerileri al, manuel olarak deployment’a yansıt. Üç müşterimde bu pratik %30-40 oranında over-provisioning’i ortaya çıkardı.
Cluster Autoscaler — node katmanı
HPA pod sayısını artırdı ama node kapasitesi yetmiyorsa pod Pending kalır. Cluster Autoscaler bu noktada devreye girer: Pending pod varsa yeni node ekler, boş node 10 dakika boş kalırsa kaldırır. Karar mekanizması:
kubectl get pods --field-selector=status.phase=Pending
kubectl describe pod <pending-pod> | grep -A3 Events
# "0/4 nodes are available: insufficient cpu" → CA yeni node istiyor
kubectl logs -n kube-system -l app=cluster-autoscaler --tail=50
AKS node pool stratejim
Tek bir homojen node pool, hem maliyet hem güvenilirlik açısından zayıf. Saha pratiği:
- system pool: 2-3 küçük node (D2s_v5),
CriticalAddonsOnly=truetaint, sadece kube-system pod’ları. - workload pool (regular): D4s_v5 veya D8s_v5, on-demand, autoscale 2-20.
- spot pool: Spot fiyatlı, autoscale 0-30. Kesintiye toleransli batch/worker’lar için.
kubernetes.azure.com/scalesetpriority=spottaint ile sadece toleration’ı olan pod’lar gelir.
az aks nodepool add
--cluster-name prod-aks --resource-group prod-rg
--name spotpool
--priority Spot
--eviction-policy Delete
--spot-max-price -1
--enable-cluster-autoscaler
--min-count 0 --max-count 30
--node-vm-size Standard_D8s_v5
Bir müşterimde gece batch ETL spot pool’a taşınınca aylık compute maliyeti $4.200’den $1.350’ye indi. Spot kapasitesi geri çağrıldığında pod’lar evict olur, KEDA cooldown’dan sonra yeni node’da yeniden başlar.
Reaksiyon süresi ve buffer kapasitesi
Otomatik ölçekleme anlık değil. Tipik gecikme zinciri:
- HPA metrik toplama → 15-30 sn
- Pod oluşturma + image pull → 5-60 sn (büyük imaj için 90+)
- Cluster Autoscaler node ekleme → 3-5 dk (Azure VM provisioning)
Yani ani spike geldiğinde ilk 3-5 dakika kullanıcı yavaşlık hisseder. Üç pratik tampon stratejisi:
- Overprovisioning: İhtiyacın %20-30 üzerinde başlangıç pod sayısı.
- Pause pod (placeholder): Düşük öncelikli boş pod’larla node’u önceden tut. Gerçek pod geldiğinde yer açılır.
- Image pre-pull: DaemonSet ile sık kullanılan imajları her node’a önceden çek, yeni node’da pull süresi sıfır.
Sahada en sık karşılaştığım üç sorun
1. HPA flapping
Pod sayısı dakikada bir 5 → 12 → 6 → 14… Çözüm: behavior.scaleDown.stabilizationWindowSeconds: 300, scaleUp.stabilizationWindowSeconds: 60. Hedef metrik değerini de gerçekçi tut — %50 yerine %60-70 daha az hassas.
2. Pending pod tsunami
Trafik patladı, HPA pod istedi, node yok, CA daha node ekleyemedi. Önlem: node pool max’ı gerçek peak’ten %30 fazla, CA scan-interval düşür (--scan-interval=10s), pause pod ile buffer.
3. Memory HPA “yapışkan” davranış
Java/Node uygulamaları bellek bırakmaz, HPA artırır azaltmaz. Çözüm: memory yerine RPS/queue depth gibi anlamlı sinyale geç.
İzleme — Prometheus + Grafana setim
Her AKS müşterimde aşağıdaki dashboard’lar standart:
- HPA current vs desired replica zaman serisi
- Pod startup süresi (image pull + readiness)
- Cluster Autoscaler scale-up/scale-down olayları
- Pending pod sayısı (her zaman 0 olmalı; >0 ise alarm)
- Spot eviction sayacı (KEDA + spot pool kombinasyonu için)
sum(kube_horizontalpodautoscaler_status_current_replicas) by (horizontalpodautoscaler)
sum(kube_pod_status_phase{phase="Pending"})
rate(cluster_autoscaler_scaled_up_nodes_total[5m])
Sıkça Sorulan Sorular
HPA, VPA ve Cluster Autoscaler aynı anda çalışabilir mi?
Evet, doğru tasarlandığında zorunludur bile. Kural: HPA ve VPA aynı metrik üzerinde değil. Tipik: HPA custom metrik (RPS, queue), VPA CPU/memory önerileri (Off mod), CA node katmanı.
Spot node prod’da kullanılır mı?
Stateless, idempotent ve kesintiye toleranslı iş yükleri için evet. Veritabanı, ingress controller, kritik sync API için hayır. Toleration + taint ile karışmamalarını sağla.
KEDA ile HPA arasında seçim nasıl yapılır?
CPU/memory yetiyorsa HPA. Event-driven (kuyruk, stream, cron, custom DB query) veya sıfıra ölçekleme istiyorsan KEDA. KEDA aslında arkada HPA üretiyor, çakışma yok.
Sonuç
Kubernetes ölçeklemesi tek mekanizma değil bir orkestra. HPA pod sayısını, VPA pod boyutunu, Cluster Autoscaler node sayısını ayarlar; KEDA event-driven dünyaya köprü kurar. Üçünü uyumlu çalıştırmak için resource request’leri doğru tanımla, behavior alanı ile flapping’i engelle, node pool’u iş yüküne göre ayrıştır, izleme ve alarmı kurmadan production’a açma. Saha tecrübesi: bu disiplinle bir AKS cluster’ı hem servis seviyesini koruyor hem aylık compute maliyetini %25-50 düşürüyor.
CloudSpark Kubernetes ve AKS danışmanlığı ile cluster ölçekleme stratejinizi tasarlıyor, KEDA/spot mimarisini kuruyor ve maliyet optimizasyonunu sürdürülebilir hale getiriyoruz.



