Yük Dengeleyici Arkasındaki Bağlantı Sorunlarını Giderme

Yük dengeleyici arkasındaki sunucularla uğraşmak, sysadmin hayatının en sinir bozucu deneyimlerinden biridir. Kullanıcılar “site açılmıyor” diyor, sen de backend’e direkt bağlanıyorsun ve her şey yolunda görünüyor. Sorun nerede? Yük dengeleyicide mi, backend’de mi, ağda mı? Bu yazıda bu tür sorunları sistematik olarak nasıl çözeceğinizi, hangi araçları kullanmanız gerektiğini ve gerçek hayatta karşılaştığım senaryoları paylaşacağım.

Önce Mimarıyı Anla

Hata ayıklamaya başlamadan önce kafanızda net bir resim olması lazım. Tipik bir yük dengeleyici mimarisinde paket şu yolu izler:

İstemci --> Yük Dengeleyici (VIP) --> Backend Sunucu 1
                                  --> Backend Sunucu 2
                                  --> Backend Sunucu 3

Bu mimaride sorun birkaç farklı katmanda olabilir: yük dengeleyiciye ulaşan trafik, yük dengeleyiciden backend’e giden trafik, backend’in yük dengeleyiciye döndürdüğü yanıt veya oturum yönetimi (sticky session) sorunları. Her katmanı ayrı ayrı test etmek zorundasın.

Önemli bir not: NAT tabanlı yük dengeleyicilerde (çoğu donanım LB ve HAProxy default modunda), backend sunucular istemcinin gerçek IP’sini değil, yük dengeleyicinin IP’sini görür. Bu, log analizini karmaşıklaştırır ve bazen sorunun kaynağını bulmayı zorlaştırır.

Temel Kontroller: Hızlı Triage

Bir ticket geldiğinde paniklemeden önce şu adımları takip et:

Yük Dengeleyici Sağlık Durumu

İlk iş yük dengeleyicinin kendisinin ayakta olup olmadığını kontrol et:

# VIP adresine basit bir bağlantı testi
curl -v --connect-timeout 5 http://10.0.0.100/health
nc -zv 10.0.0.100 80
nc -zv 10.0.0.100 443

# HTTPS için sertifika detaylarıyla birlikte
curl -vk https://10.0.0.100/health 2>&1 | head -50

Eğer VIP’e bağlanamıyorsan, sorun yük dengeleyicinin kendisinde veya ağ altyapısında. Backend’e bakmana gerek yok.

Backend Sunucuları Direkt Test Et

Yük dengeleyiciyi bypass ederek backend’lere direkt bağlan:

# Her backend'i tek tek test et
for backend in 10.0.1.10 10.0.1.11 10.0.1.12; do
    echo "=== Backend: $backend ==="
    curl -sv --connect-timeout 3 http://$backend/health 2>&1 | grep -E "(< HTTP|curl:|connect)"
done

Bu testte tüm backend’ler sağlıklıysa ama VIP üzerinden sorun yaşanıyorsa, sorun kesinlikle yük dengeleyicide veya health check konfigürasyonunda.

HAProxy ile Derinlemesine Debug

Ortamımızın büyük kısmında HAProxy kullandığımız için bu kısmı detaylı anlatacağım.

HAProxy Stats ve Log Analizi

HAProxy’nin stats socket’i altın değerindedir:

# HAProxy stats socket üzerinden anlık durum
echo "show stat" | socat stdio /var/run/haproxy/admin.sock | cut -d',' -f1,2,18,19,20 | column -t -s','

# Belirli bir backend'in durumu
echo "show stat" | socat stdio /var/run/haproxy/admin.sock | grep "backend_web"

# Anlık oturum sayıları
echo "show info" | socat stdio /var/run/haproxy/admin.sock | grep -E "(CurrConns|MaxConn|Uptime)"

HAProxy loglarını gerçek zamanlı izlemek için:

# HAProxy logları genellikle syslog'a gider
tail -f /var/log/haproxy.log | grep -E "(ERR|WARN|no server available|Connection refused)"

# Belirli bir backend'e ait logları filtrele
tail -f /var/log/haproxy.log | awk '/backend_web/ {print}'

Sık Karşılaşılan HAProxy Hata Kodları

HAProxy loglarında terminasyon kodlarını göreceksin. Bunların ne anlama geldiğini bilmek çok önemli:

  • — (çift tire): Normal bağlantı sonlanması, sorun yok
  • cD: İstemci bağlantıyı veri transferi sırasında kesti
  • sH: Sunucu yanıt başlığı gönderirken bağlantıyı kesti (backend sorunu!)
  • SC: Sunucu bağlantıyı kabul etmedi veya reddetti
  • sR: Sunucu yanıt okuma sırasında bağlantı koptu
  • cR: İstemci istek okuma sırasında bağlantı koptu

sH ve SC kodlarını çok görüyorsan, backend’de ciddi bir sorun var demektir.

Nginx Upstream Sorunları

Nginx’i yük dengeleyici olarak kullanıyorsan, upstream hataları farklı görünür:

# Nginx upstream hata logları
tail -f /var/log/nginx/error.log | grep -E "(upstream|failed|timed out)"

# Belirli bir upstream pool'unun durumunu görmek
# (nginx-module-vts veya nginx plus gerekir, açık kaynak için alternatif yol:)
nginx -T 2>/dev/null | grep -A5 "upstream"

# Upstream yanıt sürelerini access log'dan analiz et
awk '{print $NF}' /var/log/nginx/access.log | sort -n | tail -20

Nginx konfigürasyonunda upstream timeout değerlerini kontrol et:

grep -E "(proxy_connect_timeout|proxy_read_timeout|proxy_send_timeout)" /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf

Gerçek bir senaryodan bahsedeyim: Bir e-ticaret sitesinde yoğun saatlerde kullanıcılar intermittent 502 hataları alıyordu. Nginx loglarına baktığımda upstream timed out (110: Connection timed out) while reading response header hatası görüyordum. Backend’ler sağlıklıydı ama proxy_read_timeout değeri sadece 30 saniyeydi ve bazı ağır veritabanı sorguları 35-40 saniye sürüyordu. Timeout değerini artırmak kısa vadeli çözümdü, asıl sorun yavaş sorgulardı.

Ağ Katmanında Paket Analizi

Yük dengeleyici üzerinde paket yakalamak sorunun kaynağını bulmak için en güvenilir yöntemdir:

# Yük dengeleyicide frontend trafiğini yakala
tcpdump -i eth0 -w /tmp/lb_frontend.pcap host 10.0.0.100 and port 80

# Backend bağlantılarını yakala
tcpdump -i eth0 -w /tmp/lb_backend.pcap host 10.0.1.10 and port 8080

# TCP RST paketlerini filtrele (bağlantı sorunlarının işareti)
tcpdump -i eth0 'tcp[tcpflags] & (tcp-rst) != 0' -n

# SYN paketleri ama SYN-ACK yok (bağlantı kurulamıyor)
tcpdump -i eth0 'tcp[tcpflags] == tcp-syn' -n -c 100

Wireshark ile analiz: Pcap dosyasını yerel makinene çek ve Wireshark’ta tcp.analysis.retransmission veya tcp.analysis.reset_cause filtreleriyle bak. Retransmission oranı yüksekse ağ katmanında paket kaybı var demektir.

Sağlık Kontrol (Health Check) Sorunları

En sık gözden kaçan konulardan biri health check konfigürasyonudur. Yük dengeleyici bir backend’i “sağlıklı” görüyor ama aslında değil, ya da tam tersi.

# HAProxy health check'in ne gördüğünü simüle et
curl -v http://10.0.1.10:8080/healthz 
  -H "User-Agent: HAProxy" 
  --connect-timeout 2 
  --max-time 5

# Health check endpoint'inin döndürdüğü HTTP kodu
curl -o /dev/null -s -w "%{http_code}" http://10.0.1.10:8080/healthz

Gerçek bir sorun: Bir mikroservis ortamında health check endpoint’i /healthz dökümanı 200 OK veriyordu ama uygulama veritabanına bağlanamıyordu. Health check sadece “uygulama ayakta mı?” diye soruyordu, “bağımlılıklar sağlıklı mı?” diye değil. Yük dengeleyici backend’i havuzda tutuyordu ve kullanıcılar 500 hataları alıyordu. Çözüm: Health check endpoint’ini derinleştirek veritabanı bağlantısını da kontrol eder hale getirmek.

Sticky Session ve Oturum Sorunları

E-ticaret veya oturum gerektiren uygulamalarda sticky session (oturum yapışkanlığı) yanlış konfigüre edilmişse kullanıcılar sürekli oturum kaybeder.

# Birden fazla istek yapıp hangi backend'e gittiğini gör
for i in {1..10}; do
    curl -s -c /tmp/cookies.txt -b /tmp/cookies.txt 
      http://10.0.0.100/api/whoami
    echo ""
done

# HAProxy cookie-based sticky session kontrolü
# SERVERID cookie'sini kontrol et
curl -v http://10.0.0.100/ 2>&1 | grep -i "set-cookie"

HAProxy’de cookie tabanlı sticky session konfigürasyonu şöyle görünmeli:

# /etc/haproxy/haproxy.cfg içinde
# Doğru konfigürasyonu doğrulamak için:
grep -A20 "backend web_backend" /etc/haproxy/haproxy.cfg | grep -E "(cookie|balance|server)"

Dikkat: Yük dengeleyiciyi yeniden başlattığında veya backend sunucuyu havuzdan çıkardığında, o sunucuya “yapışmış” kullanıcıların oturumları kaybolur. Bunu bilerek planlama yapman gerekir.

SSL/TLS Terminasyonu Sorunları

HTTPS sorunları yük dengeleyici ortamında özellikle karmaşıklaşır.

# SSL el sıkışma detaylarını incele
openssl s_client -connect 10.0.0.100:443 -showcerts 2>/dev/null | head -30

# Sertifika geçerlilik tarihini kontrol et
echo | openssl s_client -connect 10.0.0.100:443 2>/dev/null | 
  openssl x509 -noout -dates

# TLS versiyonunu zorla test et
curl --tlsv1.2 -v https://10.0.0.100/ 2>&1 | grep -E "(SSL|TLS|version)"
curl --tlsv1.3 -v https://10.0.0.100/ 2>&1 | grep -E "(SSL|TLS|version)"

# Sertifika zinciri doğrulaması
openssl s_client -connect 10.0.0.100:443 -verify_return_error 2>&1 | grep -E "(Verify|error)"

Backend’e SSL pass-through mu yapılıyor yoksa yük dengeleyicide terminasyon mu oluyor? Bunu anlamak önemli:

# Yük dengeleyicide terminasyon varsa, backend HTTP üzerinden konuşur
curl -v http://10.0.1.10:8080/ 2>&1 | head -20

# X-Forwarded-Proto başlığının doğru iletilip iletilmediğini kontrol et
curl -s http://10.0.1.10:8080/debug/headers | grep -i "x-forwarded"

Yük Dağılımı Sorunları

Bazı backend’ler aşırı yüklenirken diğerleri boş kalıyor olabilir.

# Access loglarından backend dağılımını analiz et (Nginx örneği)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn

# HAProxy'den gerçek zamanlı istek dağılımı
watch -n2 'echo "show stat" | socat stdio /var/run/haproxy/admin.sock | 
  cut -d"," -f1,2,48 | grep "BACKEND|web_server"'

# Son 1 saatte her backend'e giden istek sayısı
grep "$(date -d '1 hour ago' '+%b %d %H')" /var/log/haproxy.log | 
  awk '{print $7}' | sort | uniq -c | sort -rn

Gerçek senaryo: Bir müşterimizin altyapısında 3 backend sunucu vardı. Yük dağılımı yaklaşık 70/20/10 şeklindeydi, ideal olan 33/33/33’tü. İncelediğimizde bir backend sunucunun RAM’inin az olduğunu ve swap kullandığını gördük. Yavaş yanıt süresi nedeniyle HAProxy’nin least-connections algoritması bu sunucuya daha az istek yönlendiriyordu. Bu teknik olarak doğruydu ama asıl sorun donanım dengesizliğiydi.

Bağlantı Limitlerini ve Timeout’ları Kontrol Et

# Sistem düzeyinde bağlantı durumunu kontrol et
ss -s
netstat -an | awk '{print $6}' | sort | uniq -c | sort -rn

# TIME_WAIT bağlantı sayısı (yüksekse sorun olabilir)
ss -tan state time-wait | wc -l

# HAProxy process sınırlarını kontrol et
cat /proc/$(pgrep haproxy)/limits | grep -E "(open files|Max open)"

# Kernel ağ parametrelerini incele
sysctl net.ipv4.ip_local_port_range
sysctl net.ipv4.tcp_tw_reuse
sysctl net.core.somaxconn

Port tükenmesi (ephemeral port exhaustion) yük dengeleyici ortamında gerçek bir problemdir. Yük dengeleyici backend’lere bağlanırken her bağlantı için bir kaynak port kullanır. Varsayılan ip_local_port_range değeri yaklaşık 28000 port sunar. Yoğun trafikte bu yetmeyebilir:

# Port aralığını genişlet
sysctl -w net.ipv4.ip_local_port_range="1024 65535"

# TIME_WAIT durumunu hızlandır
sysctl -w net.ipv4.tcp_tw_reuse=1
sysctl -w net.ipv4.tcp_fin_timeout=15

Firewall ve Network ACL Sorunları

Yük dengeleyici ile backend arasında bir firewall kuralı yanlış konfigüre edilmiş olabilir.

# Yük dengeleyiciden backend'e bağlantı testi
telnet 10.0.1.10 8080
nc -zv -w3 10.0.1.10 8080

# Yük dengeleyicideki iptables kurallarını kontrol et
iptables -L -n -v | grep -E "(DROP|REJECT)"
iptables -t nat -L -n -v | head -40

# Traceroute ile ağ yolunu izle
traceroute -T -p 80 10.0.1.10
mtr --report --tcp --port 80 10.0.1.10

Bir keresinde AWS ortamında Security Group kuralları yüzünden saatler kaybettim. Yük dengeleyici (ALB) backend’lere ulaşamıyordu çünkü backend Security Group’u sadece belirli IP’lerden gelen trafiğe izin veriyordu ve yük dengeleyicinin yeni eklenen IP’si listeye eklenmemişti. AWS ortamında IP yerine Security Group referansı kullanmak bu tür sorunları önler.

Gerçek Dünya Debug Checklist’i

Bir sonraki yük dengeleyici sorununda sistematik ilerlemeniz için:

  • Adım 1: VIP adresine direkt bağlantı test et (curl, telnet, nc)
  • Adım 2: Her backend’e VIP’i bypass ederek direkt bağlan
  • Adım 3: Yük dengeleyici loglarında hata kodlarını ara
  • Adım 4: Health check endpoint’lerinin doğru çalıştığını doğrula
  • Adım 5: Backend’lerin yük dengeleyici havuzunda “UP” durumda olduğunu kontrol et
  • Adım 6: Yük dengeleyici ile backend arasında ağ bağlantısını test et (firewall, ACL)
  • Adım 7: Timeout değerlerini (connect, read, send) gözden geçir
  • Adım 8: SSL/TLS sorunlarını kontrol et (sertifika süresi, uyumsuz protokol versiyonları)
  • Adım 9: Sistem kaynaklarını kontrol et (bağlantı limitleri, port tükenmesi, RAM)
  • Adım 10: Paket yakalama ile ağ katmanını doğrula

İzleme ve Proaktif Alarm

Sorunları kullanıcılar bildirmeden önce yakalamak için:

# Basit bir backend sağlık kontrol scripti
#!/bin/bash
BACKENDS=("10.0.1.10:8080" "10.0.1.11:8080" "10.0.1.12:8080")
ALERT_EMAIL="[email protected]"

for backend in "${BACKENDS[@]}"; do
    HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" 
      --connect-timeout 3 --max-time 5 
      http://$backend/healthz)
    
    if [ "$HTTP_CODE" != "200" ]; then
        echo "ALERT: Backend $backend sağlıksız! HTTP: $HTTP_CODE" | 
          mail -s "LB Backend Sorunu" $ALERT_EMAIL
        logger -t lb-monitor "Backend $backend DOWN - HTTP $HTTP_CODE"
    fi
done

Bunu crontab’a ekle:

# Her 1 dakikada bir çalıştır
* * * * * /usr/local/bin/check_backends.sh >> /var/log/backend-monitor.log 2>&1

Prometheus ve Grafana kullanıyorsan HAProxy için haproxy_exporter veya Nginx için nginx-prometheus-exporter kur. Backend’in havuzdan düşmesi, istek hata oranı ve yanıt süresi için alarm kur. Kullanıcılardan önce sen öğrenirsin.

Sonuç

Yük dengeleyici sorunları katmanlı yapıları nedeniyle zor görünse de sistematik yaklaşımla çözülmesi en kolay sorun türlerinden biridir. Anahtar nokta şu: her katmanı izole ederek test et. VIP’ten backend’e, backend’den uygulamaya kadar her adımda bağlantının sağlıklı olduğunu doğrula.

En sık yapılan hata, backend sunucular sağlıklıyken log bakmaya başlamadan “backend’i restart etmek” veya konfigürasyon değişikliği yapmak. Bu yaklaşım hem riski artırır hem de asıl sorunun kaynağını öğrenme fırsatını kaçırtır. Sabırlı ol, log oku, paket yakala.

Bir de şunu söyleyeyim: Yük dengeleyici konfigürasyon dosyalarını mutlaka versiyon kontrolüne (git) al. Üç ay önce yapılan bir timeout değişikliğinin bugün sorun çıkardığını ancak git blame ile anlayabilirsin. Altyapı kodu da koddur.

Benzer Konular

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir