Kampanya günü geliyor, trafiğin dört katına çıkacağını biliyorsun ve gece yarısı elle kubectl scale yazmak istemiyorsun. Ya da tam tersi: gecenin üçünde sekiz replika boşa CPU yakıyor ve faturayı sen ödüyorsun. Kubernetes HPA (Horizontal Pod Autoscaler) tam olarak bu iki problemi çözmek için var — bir Deployment'ın replika sayısını, ölçtüğü metriğe bakarak kendisi artırıp azaltıyor.
Ama HPA, dokümantasyondaki üç satırlık örneği kopyalayıp yapıştırınca çalışan bir şey değil. Metrik kaynağı kurulu değilse hiçbir şey yapmaz, container'a resources.requests yazmadıysan hedef yüzdeyi hesaplayamaz, behavior bloğunu dokunmadan bırakırsan trafik dalgalandığında replikalar yukarı aşağı zıplar. Bu rehberde HPA'nın replika sayısını hangi formülle bulduğunu, metrics-server'ı nasıl doğru kurduğunu, CPU dışındaki metriklerle nasıl ölçekleneceğini ve üretimde en sık karşılaştığım tuzakları gerçek komutlarla anlatacağım.
HPA Ne Yapar, Ne Yapmaz#
HPA bir kontrol döngüsüdür. Varsayılan olarak 15 saniyede bir uyanır, hedef aldığı iş yükünün (Deployment, StatefulSet, ReplicaSet) hazır durumdaki pod'larının metriklerini okur, bunları senin belirlediğin hedefle karşılaştırır ve gerekiyorsa spec.replicas alanını günceller. Yani HPA pod sayısını değiştirir; pod'un içindeki container'a daha fazla CPU veya bellek vermez. Container'ın kendi limitlerini büyütmek isteyen mekanizma VPA'dır (Vertical Pod Autoscaler) ve HPA ile aynı metrik üzerinde birlikte kullanılması önerilmez, çünkü ikisi birbirinin kararını sürekli bozar.
HPA'nın yapamadığı ikinci şey de düğüm eklemektir. On beş replika istedin ama kümede o kadar CPU yok ise, fazladan pod'lar Pending durumunda bekler ve HPA bu konuda hiçbir şey yapamaz. Düğüm eklemek Cluster Autoscaler'ın (veya bulut sağlayıcının yönettiği eşdeğerinin) işidir. Üçünün rollerini karıştırmamak, "HPA çalışmıyor" diye saatlerce yanlış yerde arama yapmanı engeller:
| Bileşen | Neyi değiştirir | Tetikleyicisi | Tipik kullanım |
|---|---|---|---|
| HPA | Pod sayısı | CPU / bellek / özel metrik | Web ve API katmanı |
| VPA | Pod'un request/limit değerleri | Geçmiş kullanım | Tek replikalı iş yükleri |
| Cluster Autoscaler | Düğüm sayısı | Pending pod'lar | Kümenin kendisi |
Bu ayrım oturmadan HPA yazmak, Docker'ın temel kavramlarını bilmeden Compose dosyası yazmaya benziyor: çalışıyor gibi görünür, sonra ilk gerçek yükte dağılır.
Ön Koşul: metrics-server Kurulumu#
HPA metrikleri kendisi toplamaz; metrics.k8s.io API'sini sorgular ve bu API'yi kümene metrics-server sağlar. Managed bir Kubernetes hizmeti kullanıyorsan büyük ihtimalle kuruludur, kendi kurduğun bir kümede ise neredeyse kesinlikle değildir. Önce kontrol et:
# metrics API kayıtlı mı?
kubectl get apiservices | grep metrics
# Beklenen çıktı:
# v1beta1.metrics.k8s.io kube-system/metrics-server True
# Pod metrikleri geliyor mu?
kubectl top pods -n default
kubectl top komutu "error: Metrics API not available" diyorsa kurulum yapman gerekiyor:
# Resmi bileşen manifestini uygula
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# Dağıtımın ayağa kalkmasını bekle
kubectl -n kube-system rollout status deployment/metrics-server
Kendi kurduğun kümelerde metrics-server'ın pod'u çoğu zaman CrashLoopBackOff ya da 0/1 Running durumunda takılır. Sebebi neredeyse her seferinde aynıdır: kubelet kendi kendine imzaladığı bir sertifika sunar, metrics-server de bunu doğrulayamaz. Log'a bakınca x509: cannot validate certificate satırını görürsün. Test ve iç ağ kümelerinde çözüm, doğrulamayı kapatan argümanı eklemektir:
# metrics-server dağıtımına doğrulama bayrağını ekle
kubectl -n kube-system patch deployment metrics-server --type=json \
-p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
Container'ın neden çöktüğünü anlamak için log okuma alışkanlığı burada da işe yarar; yöntem Docker container loglarını okuma yazısındakiyle aynı mantıkta, sadece komut kubectl logs oluyor.
İlk HPA'yı Oluşturmak#
HPA'nın çalışması için hedef container'da mutlaka resources.requests tanımlı olmalı. Bunun sebebi basit: HPA "CPU yüzde 60'a ulaşınca ölçekle" derken yüzdeyi request değerine göre hesaplar. Request yoksa payda yoktur, hesap yapılamaz. Önce Deployment'ını düzelt:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 2
selector:
matchLabels: { app: web }
template:
metadata:
labels: { app: web }
spec:
containers:
- name: web
image: nginx:stable
resources:
requests: # HPA yüzdeyi BU değere göre hesaplar
cpu: 200m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
Ardından HPA'yı tanımla. Tek satırlık hızlı yöntem kubectl autoscale komutudur, ama üretimde manifest dosyası tutmanı öneririm:
# Hızlı yöntem (deneme için)
kubectl autoscale deployment web --cpu-percent=60 --min=2 --max=10
# hpa-web.yaml — sürüm kontrolüne girecek hâli
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
Uygulayıp durumu izle:
kubectl apply -f hpa-web.yaml
kubectl get hpa web --watch
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
# web Deployment/web cpu: 18%/60% 2 10 2
TARGETS sütununda cpu: <unknown>/60% görüyorsan iki şeyden biri eksiktir: ya metrics-server veri döndürmüyordur ya da request tanımlamamışsındır. kubectl describe hpa web çıktısının Events bölümü ikisini birbirinden ayırır.
Replika Sayısı Hangi Formülle Bulunur#
HPA'nın kararı sihirli değil, tek satırlık bir aritmetik. İstenen replika sayısı şu şekilde hesaplanır: mevcut replika sayısı, ölçülen ortalama metriğin hedef metriğe oranıyla çarpılır ve yukarı yuvarlanır. Yani dört replikayla çalışıyorsun, ortalama CPU kullanımı yüzde 90, hedefin yüzde 60 ise: 4 × (90 / 60) = 6 replika.
Bu formülün pratikte iki önemli ayrıntısı var. Birincisi tolerans: oran 1'e çok yakınsa (varsayılan olarak yüzde 10 bant içindeyse) HPA hiçbir şey yapmaz. Hedefin yüzde 60 iken ölçüm yüzde 63'e çıktı diye replika eklenmez; bu, küçük dalgalanmalarda sürekli ölçeklenmeyi engelleyen bilinçli bir frendir. İkincisi hazır olmayan pod'lar hesaba katılmaz: Ready olmayan veya metriği henüz gelmemiş pod'lar ortalamaya dahil edilmez, böylece yeni açılan ve ısınma sırasında CPU yakan bir pod ölçek kararını bozmaz.
| Mevcut replika | Ölçülen | Hedef | Oran | Yeni replika |
|---|---|---|---|---|
| 2 | %90 | %60 | 1.50 | 3 |
| 4 | %90 | %60 | 1.50 | 6 |
| 6 | %63 | %60 | 1.05 | 6 (tolerans içinde) |
| 6 | %20 | %60 | 0.33 | 2 |
| 10 | %5 | %60 | 0.08 | 2 (minReplicas) |
Son satır önemli: hesap minReplicas altına inse bile HPA asla o sınırın altına düşmez. Aynı şekilde maxReplicas da mutlak tavandır — kümede kaynak olsa dahi HPA o sayının üstüne çıkmaz. Bu iki değeri, "en kötü gün" ve "boşta gece" senaryolarını düşünerek seç.
CPU Dışındaki Metriklerle Ölçeklemek#
CPU her iş yükü için doğru sinyal değildir. Bir kuyruk tüketicisi CPU'yu neredeyse hiç kullanmadan saatlerce mesaj bekleyebilir; onun için doğru metrik bekleyen mesaj sayısıdır. autoscaling/v2 API'si dört metrik tipini destekler ve bunları tek bir HPA içinde birleştirebilirsin:
| Tip | Kaynağı | Örnek |
|---|---|---|
| Resource | metrics-server | CPU / bellek yüzdesi |
| Pods | Özel metrik API'si | Pod başına saniyedeki istek |
| Object | Özel metrik API'si | Ingress üzerindeki toplam istek |
| External | Harici metrik API'si | Kuyruk uzunluğu, bulut metriği |
Bellekle ölçekleme, Resource tipiyle tek satır fark eder:
metrics:
- type: Resource
resource:
name: cpu
target: { type: Utilization, averageUtilization: 60 }
- type: Resource
resource:
name: memory
target: { type: AverageValue, averageValue: 512Mi }
Birden fazla metrik tanımladığında HPA her biri için ayrı ayrı replika sayısı hesaplar ve en büyüğünü seçer. Yani metrikler yarışmaz, en talepkâr olan kazanır. Bellekle ölçeklemede dikkat etmen gereken nokta şudur: çoğu uygulama belleği bırakmaz, sadece alır. JVM veya Node.js tabanlı bir servis belleği bir kez şişirdikten sonra kullanım grafiği aşağı inmez, dolayısıyla HPA da hiçbir zaman küçülmez. Bellek metriğini, gerçekten bellekle orantılı büyüyen iş yükleri için kullan; onun dışında CPU ya da uygulama seviyesinde bir sayaç daha dürüst bir sinyaldir.
Pods ve External tipleri için kümene bir metrik adaptörü (yaygın olarak Prometheus Adapter veya KEDA) kurman gerekir; metrics-server bu API'leri sağlamaz. Kurulum yükünü göze alamayacaksan, uygulamanın kendi istek sayacını CPU'ya bağlı hâle getirmek çoğu zaman yeterince iyi bir yaklaşımdır.
Ölçek Davranışını Ayarlamak#
Varsayılan HPA yukarı doğru çok hızlı, aşağı doğru ise nispeten yavaştır. Trafiği dalgalı bir serviste bu, replika sayısının sürekli zıplamasına (flapping) yol açar: her zıplama yeni pod açılması, imaj çekilmesi ve bağlantıların kopması demektir. behavior bloğu tam da bunu dizginlemek için var.
spec:
behavior:
scaleUp:
stabilizationWindowSeconds: 0 # yukarı çıkarken bekleme yok
policies:
- type: Percent # her 60 sn'de en fazla %100 büyü
value: 100
periodSeconds: 60
- type: Pods # ya da en fazla 4 pod ekle
value: 4
periodSeconds: 60
selectPolicy: Max # ikisinden büyüğünü uygula
scaleDown:
stabilizationWindowSeconds: 300 # 5 dk boyunca en yüksek öneriyi kullan
policies:
- type: Percent # her 60 sn'de en fazla %20 küçül
value: 20
periodSeconds: 60
stabilizationWindowSeconds en kritik alandır: HPA, o pencere içindeki tüm önerilerin en yükseğini uygular. Aşağı yönde 300 saniye vermek, "son beş dakikada bir kez bile yük gördüysen küçülme" demektir ve ani düşüşlerde servisin çıplak kalmasını engeller. Yukarı yönde ise 0 bırakmak doğrudur; trafik geldiğinde beklemek istemezsin.
selectPolicy: Max yukarıda agresif, selectPolicy: Min aşağıda muhafazakâr davranmanı sağlar. Ayrıca selectPolicy: Disabled ile bir yönü tamamen kapatabilirsin — örneğin kritik bir kuyruk tüketicisinin asla otomatik küçülmemesini istiyorsan scaleDown için bunu kullan. Ölçek kararlarını sonradan incelemek için kubectl describe hpa web çıktısındaki Events listesi en iyi kaynaktır; hangi metrikle, hangi anda kaç replikaya çıkıldığı orada satır satır yazar. Kümeyi terminal üzerinden canlı izlemeyi seviyorsan k9s ve Lens gibi Kubernetes yönetim araçları bu olayları çok daha okunabilir hâlde gösteriyor.
Sık Yapılan Hatalar ve Tuzaklar#
Deployment manifestinde replicas alanını bırakmak. HPA replika sayısını yönetiyorsa, aynı alanı senin manifestin de yönetmeye çalışıyor demektir. GitOps ya da bir CI hattı her deploy'da manifesti yeniden uyguluyorsa, HPA'nın on'a çıkardığı replikayı deploy iki'ye geri düşürür ve dakikalar içinde tekrar on'a çıkar. Çözüm: HPA yönetimindeki iş yüklerinde replicas alanını manifestten tamamen kaldırmak ya da CI'da bu alanı yamalamamaktır. GitHub Actions ile kurduğun CI/CD hattında bu ayrıntıyı atlamak, "otomatik ölçekleme neden çalışmıyor" sorusunun en sık cevabıdır.
Request'i gerçekçi olmayan bir değere koymak. Request'i çok düşük yazarsan (örneğin gerçekte 300m harcayan bir servise 50m vermek) HPA sürekli yüzde 600 kullanım görür ve tavan replikaya yapışır. Çok yüksek yazarsan hiçbir zaman ölçeklenmez. Doğru yöntem, birkaç gün kubectl top pods çıktısını izleyip tipik kullanımın biraz üstünü request olarak vermektir.
Hedef yüzdeyi 90'a koymak. "Kaynağı sonuna kadar kullanayım" diye hedefi çok yükseğe çekmek, ölçekleme tetiklendiğinde yeni pod'un ayağa kalkması için gereken sürede servisin zaten boğulmuş olması demektir. Uygulamanın açılış süresi ne kadar uzunsa hedefi o kadar düşük tut; 60-70 bandı çoğu web servisi için makul bir başlangıçtır.
PodDisruptionBudget'i unutmak. HPA aşağı ölçeklerken pod'ları kapatır. Aynı anda bir düğüm bakımı da devrede ise, iki mekanizma birlikte servisi sıfır replikaya kadar götürebilir. Kritik servislere minAvailable tanımlı bir PDB koymak bu senaryoyu engeller.
Ölçeklenen pod'un başlangıç sağlığını yanlış tanımlamak. readinessProbe yoksa Kubernetes yeni pod'u hemen trafik almaya uygun sayar; henüz hazır olmayan pod'a istek gider ve kullanıcı hata görür. HPA'yı devreye almadan önce her iş yükünde doğru bir readinessProbe olduğundan emin ol.
Sıkça Sorulan Sorular#
HPA çalışması için metrics-server şart mı#
CPU veya bellek gibi Resource tipi metriklerle ölçekleme yapacaksan evet, metrics-server (ya da metrics.k8s.io API'sini sağlayan başka bir bileşen) zorunludur. HPA metrikleri kendisi toplamaz, bu API'yi sorgular. Yalnızca özel veya harici metriklerle çalışacaksan metrics-server yerine Prometheus Adapter ya da KEDA gibi bir adaptör yeterli olur, ama pratikte çoğu küme her ikisini birden barındırır.
HPA neden unknown gösteriyor#
TARGETS sütununda <unknown> görmenin iki klasik sebebi vardır. Birincisi metrik kaynağının veri döndürmemesidir; kubectl top pods komutu da hata veriyorsa sorun metrics-server'dadır. İkincisi ve daha yaygını, hedef container'da resources.requests tanımının eksik olmasıdır — HPA yüzde hesabını request değerine bölerek yaptığı için payda olmadan sonuç üretemez. kubectl describe hpa çıktısındaki olay satırları hangisi olduğunu net söyler.
HPA ile replika sayısı ne kadar sürede değişir#
Kontrol döngüsü varsayılan olarak 15 saniyede bir çalışır, dolayısıyla karar birkaç on saniye içinde verilir. Ancak kararın etkisini görmen pod'un ayağa kalkma süresine bağlıdır: imaj çekme, başlatma ve readinessProbe beklemesi toplamda dakikaları bulabilir. Aşağı yönde ise scaleDown.stabilizationWindowSeconds değeri kadar (varsayılan 5 dakika) ek bekleme vardır, bu yüzden küçülme her zaman büyümekten yavaştır.
minReplicas değerini 1 yapabilir miyim#
Yapabilirsin ama üretimde önermem. Tek replikayla çalışırken o pod yeniden başlatıldığı, düğümü boşaltıldığı veya güncellendiği anda servis tamamen kesilir. İki replika, sıradan bakım işlemlerinde bile kesintisiz kalmanı sağlar. Yalnızca geliştirme ortamlarında veya kesinti toleransı yüksek toplu iş süreçlerinde minReplicas: 1 mantıklı bir tercihtir.
HPA ve VPA aynı anda kullanılır mı#
Aynı metrik üzerinde kullanılmamalıdır. HPA CPU'ya bakarak pod ekler, VPA aynı CPU'ya bakarak request'i büyütür; request büyüyünce HPA'nın gördüğü yüzde düşer ve pod'ları kapatır, ardından yüzde tekrar yükselir. Bu döngü hiç oturmaz. İkisini birlikte kullanmak istiyorsan VPA'yı yalnızca bellek için, HPA'yı yalnızca CPU veya özel bir metrik için yapılandır.
HPA maliyeti gerçekten düşürür mü#
Doğru yapılandırıldığında evet, çünkü boşta kalan replikaları kapatır. Ancak kazanç, kümenin kendisinin de küçülebilmesine bağlıdır: pod'lar kapansa bile düğümler ayakta kalıyorsa fatura değişmez. Gerçek tasarruf için HPA'yı bir Cluster Autoscaler ile birlikte kullanmak veya sabit kaynaklı bir sunucu üzerinde çalışıyorsan aynı düğüme daha fazla iş yükü sığdırmak gerekir.
Kapanış#
HPA'yı üretimde sorunsuz kullanmanın özeti dört alışkanlıkta toplanıyor: her container'a gerçekçi bir resources.requests yaz, metrics-server'ın veri döndürdüğünü kubectl top ile doğrula, behavior bloğuyla aşağı yönde en az beş dakikalık bir sabitleme penceresi tanımla ve HPA yönetimindeki Deployment'lardan replicas alanını kaldır. Bu dördü yerinde olduğunda HPA'nın kararlarını kubectl describe hpa çıktısından okumak, "neden ölçeklenmedi" sorusunu dakikalar içinde cevaplamana yeter.
Kubernetes kümesini ayağa kaldırmak için altında güvenilir ve kaynağı öngörülebilir bir makine gerekiyor. Kontrol düzlemi ve düğümler için tam root erişimli VDS ya da esnek büyüyebilen bulut sunucu paketlerimizi kullanabilir, kümenin kurulumu ve güncellemeleriyle uğraşmak istemiyorsan sunucu yönetimi hizmetimizle bu yükü bize bırakabilirsin. Ölçekleyeceğin trafiğin ne kadar bant genişliği tutacağını önceden görmek istersen bant genişliği hesaplayıcı aracımız işini kolaylaştırır.