L4 load balancer (VIP) tarafında en tehlikeli arıza türü şudur: health check yeşildir ama kullanıcı trafiği düşer. Operasyon ekibi “pool up” görür, uygulama ekibi “servis down” der, herkes birbirine bakar. Bu senaryonun ortak adı: health check körlüğü.
Neden oluyor? (sahada en sık 6 kök neden)
- Check endpoint’i “gerçek iş” değil:
/healthz200 döner, ama DB/queue/downstream kopuktur. - Kısmi bozulma: sadece belirli path/tenant/region etkilenir.
- State/NAT/conntrack baskısı: VIP’den geçen bağlantılar ölür, check’ler yeni TCP ile “başarılı” görünür.
- Geri dönüş yolu bozuk (DSR / asymmetric routing): check LB’den gider, trafik farklı yoldan döner ve kaybolur.
- Timeout eşiği yanlış: check 2s, kullanıcı 200ms SLO ister; “UP” demek “iyi” demek değildir.
- LB tarafı değil, arka uç davranışı: thread pool dolu, accept kuyruğu dolu, GC baskısı var; check nadiren çakışır.
Tasarım prensibi: Aktif check + pasif sinyal birlikte
Ben L4 VIP tasarımında health check’i iki katmana bölerim:
- Aktif check: hızlı ve ucuz; “servis ayakta mı?” (L7 check bile olsa minimal)
- Pasif sinyal: gerçek trafik üzerinden; “servis iyi mi?” (error/latency/connection success)
Bu yaklaşım, “körlüğü” azaltır çünkü check’ler test trafiğiyle sınırlı kalmaz.
Pasif sinyale örnekler
- 5xx oranı / uygulama hata kodları
- TCP handshake başarısızlığı (SYN timeouts, RST artışı)
- p95/p99 latency (VIP sonrası)
- Backend connection pool doygunluğu (özellikle proxy/L7 katman varsa)
- “Outlier detection” (belirli node’lar sürekli daha kötü)
Blackhole önleme: Trafiği çekmenin 3 güvenli yolu
1) Pool member disable (klasik)
LB’nin pool member disable mekanizması en bilinen yöntemdir. Sorun: disable kararı çoğu zaman “tek sinyal”e dayanır.
İyileştirme: disable kararını iki şartla verin:
- Aktif check fail veya
- Pasif sinyal belirli eşiği aşıyor (ör. 1 dakikada 3x p95, 5xx>%)
2) Route withdraw (BGP / ECMP dünyasında çok temiz)
VIP veya service prefix’i BGP ile ilan ediyorsanız, geri çekme (withdraw) çok etkili bir “trafik kesme” aracıdır. Bu model özellikle anycast VIP’lerde hayat kurtarır.
Önemli kural: withdraw’i “script” ile değil, ölçülebilir sinyalle yapın (örn. local proxy error rate + connection success).
3) L7’de outlier ejection (proxy katmanı olanlarda)
Envoy/HAProxy/Nginx gibi bir L7 katmanı varsa, outlier ejection ile “kötü node”ları otomatik dışarı atabilirsiniz. L4 LB’ye göre daha zengin sinyal üretir.
Sağlıklı health check endpoint’i nasıl olmalı?
Health check endpoint’i için pratik çizgim:
- Readiness: kritik bağımlılık yoksa 200; varsa 503 (LB trafiği kesebilsin)
- Liveness: proses canlı mı? (bu ayrı; kube gibi orchestrator için)
Ve readiness için “en az bir gerçek bağımlılık” şart:
- DB bağlantısı (basit bir SELECT)
- Queue publish/consume (kısa timeout’la)
- Cache (varsa) erişimi
Ama bu testleri check’i “yavaşlatmadan” yapın: kısa timeout, hızlı fail, ölçümlü.
Operasyon: Incident sırasında hızlı teşhis akışı
Health check yeşil, ama trafik düşmüşse ben şu sırayla giderim:
- VIP’den backend’e TCP handshake başarılı mı? (SYN/SYN-ACK oranı, RST artışı)
- Backend tarafında accept queue / thread pool dolu mu?
- Asymmetric routing / DSR varsa, dönüş yolunu kontrol et (policy route, firewall state)
- LB cihazı/servisi üzerinde conntrack kapasitesi ve “drops” sinyali
- Pasif sinyal: belirli backend node’lar mı kötü, yoksa hepsi mi?
Bu akış “LB mi, uygulama mı?” tartışmasını 5–10 dakikada kanıta çevirir.
Sonuç: Failover bir ürün davranışıdır, checkbox değildir
İyi failover, sadece “node down olunca trafik gider” demek değildir. Asıl değer; node “up” görünürken bozulduğunda da trafiği kurtarmaktır. Aktif check’i pasif sinyalle tamamladığınızda, health check körlüğü azalır; incident’lar daha kısa sürer, blame değil kanıt kazanırsınız.