Probe nedir, neden gerekli?
Kubernetes bir pod'un "çalışıyor" olduğunu bilir — container ayaktaysa çalışıyor demek. Ama "çalışıyor" ile "sağlıklı" aynı şey değil. Uygulama deadlock'a girmiş olabilir, DB bağlantısını kaybetmiş olabilir, henüz başlamayı tamamlamamış olabilir.
Probe'lar Kubernetes'e şunu söyler: "Bu container'ın içindeki uygulamayı benim istediğim şekilde kontrol et."
Üç probe türü var, her biri farklı bir soruyu cevaplıyor:
| Probe | Soru | Başarısız olursa |
|---|---|---|
| Startup | Uygulama başladı mı? | Pod restart |
| Readiness | Traffic almaya hazır mı? | Traffic kesilir, pod durmaz |
| Liveness | Uygulama sağlıklı mı? | Pod restart |
En kritik fark readiness ile liveness arasında — birinde pod ölür, diğerinde ölmez.
Lab ortamı
Docker Desktop üzerinde kind cluster, tek node:
kind create cluster --name probe-lab
kubectl create namespace probe-lab
kubectl config set-context --current --namespace=probe-lab
Senaryo 1 — Bozuk Liveness Probe
Nginx 80 portunda çalışıyor ama liveness probe 9999'a bakıyor. Ne olacak?
apiVersion: apps/v1
kind: Deployment
metadata:
name: liveness-broken
namespace: probe-lab
spec:
replicas: 1
selector:
matchLabels:
app: liveness-broken
template:
metadata:
labels:
app: liveness-broken
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 9999 # nginx burada dinlemiyor
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3 # 3 başarısız → restart
kubectl apply -f liveness-broken.yaml
kubectl get pods -w
Çıktı:
NAME READY STATUS RESTARTS AGE
liveness-broken-xxx 1/1 Running 0 8s
liveness-broken-xxx 1/1 Running 1 23s
liveness-broken-xxx 1/1 Running 2 38s
liveness-broken-xxx 0/1 CrashLoopBackOff 3 53s
Events'e bakınca:
Warning Unhealthy Liveness probe failed: dial tcp: connection refused
Warning Killing Container failed liveness probe, will be restarted
Ne öğrendim: Liveness başarısız olunca Kubernetes container'ı öldürüp yeniden başlatıyor. Ama sorun devam ettiği için sonsuz döngüye giriyor — buna CrashLoopBackOff deniyor. Production'da bu alarm tetikler, on-call mühendisi uyandırır.
Senaryo 2 — Bozuk Readiness Probe
Aynı nginx, bu sefer readiness probe var olmayan bir path'e bakıyor: /nonexistent. Liveness doğru. Ne olacak?
livenessProbe:
httpGet:
path: / # doğru — pod ölmeyecek
port: 80
readinessProbe:
httpGet:
path: /nonexistent # 404 dönecek — probe başarısız
port: 80
initialDelaySeconds: 3
periodSeconds: 5
failureThreshold: 3
kubectl get pods -w
Çıktı:
NAME READY STATUS RESTARTS AGE
readiness-broken-xxx 0/1 Running 0 10s
readiness-broken-xxx 0/1 Running 0 60s
readiness-broken-xxx 0/1 Running 0 2m
RESTARTS hiç artmıyor. Pod ölmüyor. Ama 0/1 — traffic almıyor.
Service endpoint'e bakınca:
kubectl get endpoints readiness-broken
NAME ENDPOINTS AGE
readiness-broken <none> 2m
<none> — Kubernetes bu pod'u endpoint listesinden çıkardı. Hiçbir istek buraya gelmiyor.
Ne öğrendim: Readiness ile liveness'ın farkı tam burada netleşiyor. Liveness başarısız → pod restart. Readiness başarısız → pod Running kalıyor, sadece traffic kesiliyor. Pod'u öldürmek her zaman doğru cevap değil — bazen sadece "biraz bekle, hazır olunca gönder" demek yeterli.
Senaryo 3 — Startup Probe Olmadan Yavaş Uygulama
Uygulama başlamak için 40 saniye bekliyor. Startup probe yok, liveness 20 saniyede restart ediyor.
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "sleep 40"] # 40 saniye beklet
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3 # 5 + (3*5) = 20 saniyede restart
# uygulama 40 saniyede hazır — hiç hazır olamaz
Sonuç: CrashLoopBackOff. Uygulama hiç ayağa kalkamıyor çünkü liveness onu hazır olmadan öldürüyor.
Şimdi startup probe ekle:
startupProbe:
httpGet:
path: /
port: 80
periodSeconds: 5
failureThreshold: 12 # 12 * 5 = 60 saniye bekler
# startup geçene kadar liveness çalışmaz
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
failureThreshold: 3
Sonuç:
NAME READY STATUS RESTARTS
slow-app-fixed-xxx 1/1 Running 0 ← restart yok
Ne öğrendim: Startup probe, liveness için bir "koruma kalkanı" görevi görüyor. "Ben hazır olana kadar dokunma" diyor. Spring Boot, JVM tabanlı uygulamalar, büyük model yükleyen ML servisleri — bunların hepsinde startup probe zorunlu.
Senaryo 4 — HPA ile Readiness Entegrasyonu
Bu senaryoda yük testi yaparak HPA'yı tetikledim ve yeni açılan pod'ların readiness geçene kadar traffic almadığını gözlemledim.
Önce metrics-server'ı kur:
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
kubectl patch deployment metrics-server \
-n kube-system \
--type='json' \
-p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"}]'
HPA tanımı:
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: hpa-demo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: hpa-demo
minReplicas: 1
maxReplicas: 4
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 20
Yük testi:
kubectl run load-generator \
--image=busybox:1.28 \
--restart=Never \
-n probe-lab \
-- /bin/sh -c "while true; do wget -q -O- http://hpa-demo; done"
HPA çıktısı:
NAME TARGETS REPLICAS
hpa-demo 2%/20% 1
hpa-demo 198%/20% 2 ← scale-out başladı
hpa-demo 156%/20% 4
hpa-demo 2%/20% 4
hpa-demo 2%/20% 1 ← scale-in, yük durdu
Yeni pod açılırken endpoint listesi:
NAME ENDPOINTS
hpa-demo 10.x.x.x:80 ← sadece hazır pod
hpa-demo 10.x.x.x:80,10.x.x.x:80 ← ikinci pod readiness geçince eklendi
Ne öğrendim: HPA pod açtığında o pod hemen traffic almıyor. Readiness probe geçene kadar endpoint listesine girmiyor. Bu çok kritik — yük altında açılan pod hazır olmadan traffic alırsa hata oranı artar. Readiness probe bu geçiş sürecini güvenli hale getiriyor.
Production'da Dikkat Ettiğim Şeyler
Liveness probe'a bağımlı servis kontrolü koyma:
# YANLIŞ — DB geçici kapanırsa tüm pod'lar cascade restart yapar
livenessProbe:
httpGet:
path: /health/db
port: 8080
# DOĞRU — liveness sadece "ben ayaktayım" sorusunu sormalı
livenessProbe:
httpGet:
path: /health/live
port: 8080
readinessProbe:
httpGet:
path: /health/ready # DB bağlantısı burada kontrol edilir
port: 8080
Threshold değerlerini varsayılan bırakma:
livenessProbe:
failureThreshold: 5 # 3 değil — geçici ağ sorunlarına tolerans
periodSeconds: 10
timeoutSeconds: 5 # 1 saniye çok kısa
Startup probe'u atlama: Eğer uygulamanın başlangıç süresi değişkense — farklı ortamlarda farklı sürebiliyorsa — startup probe yaz. initialDelaySeconds ile tahmin yürütmek yerine gerçek hazırlık durumunu kontrol et.
Özet
Bu lab'dan önce probe'ları biliyordum ama gözlemlememştim. Şimdi şunu rahatlıkla söyleyebiliyorum:
- Liveness → "uygulama dondu mu?" — başarısız olursa restart
- Readiness → "traffic almaya hazır mı?" — başarısız olursa sadece traffic kesilir
- Startup → "uygulama başlamayı tamamladı mı?" — liveness için koruma kalkanı
Ve en önemli şey: readiness ile liveness'ı aynı endpoint'e bağlamak işe yarıyor ama doğru değil. İkisi farklı soruları soruyor, farklı endpoint'ler hak ediyorlar.
Bu yazı, bir mülakatta aldığım geri bildirimi uygulamalı olarak çalışma serim. Serinin ilk yazısı: Terraform + Terragrunt + Ansible: A Hands-On Learning Journey
Top comments (0)