Neden load balancer'a ihtiyacınız var ve nereden başlamalısınız?
Web sitenizin trafiği tek bir sunucunun kapasitesini aştığında veya high availability ihtiyacınız olduğunda, aklınıza gelen ilk çözüm daha fazla sunucu eklemektir. Ancak ek sunucular, bir load balancer olmadan sorunu çözmediği gibi, isteklerin sunucular arasında yönetilmemesi bazı sunucuların aşırı yüklenmesine ve diğerlerinin boş kalmasına neden olur. Load balancer, gelen istekleri birden fazla backend sunucusu arasında dağıtır, sağlıklarını kontrol eder ve biri arızalandığında trafiği sağlıklı sunuculara yönlendirir.
Bu makalede Nginx ile operasyonel bir load balancer kuracağız. Nginx, düşük kaynak tüketimi ve yüksek performansı nedeniyle bu iş için yaygın bir seçimdir. 10.0.0.11 ve 10.0.0.12 adreslerinde, 8080 portunda bir web uygulaması çalıştıran iki backend sunucunuz olduğunu varsayıyoruz. Load balancer, 10.0.0.10 adresindeki ayrı bir sunucuya kurulur.
Load balancer'ın temel kurulumu ve yapılandırması
Öncelikle Nginx'i load balancer sunucusuna kurun. Debian/Ubuntu tabanlı dağıtımlarda:
sudo apt update
sudo apt install nginx -y
Ardından ana yapılandırma dosyasını düzenleyin. /etc/nginx/sites-available/ yolunda ayrı bir dosya oluşturup sites-enabled dizinine bağlamak daha iyidir:
sudo nano /etc/nginx/sites-available/loadbalancer
Basit round-robin dağıtımı için ilk içerik:
upstream backend_servers {
server 10.0.0.11:8080;
server 10.0.0.12:8080;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Bu yapılandırma istekleri iki sunucu arasında sırayla dağıtır. X-Forwarded-* başlıklarını mutlaka ekleyin ki uygulamanız kullanıcının gerçek IP adresini görsün, load balancer'ın adresini değil. Aksi takdirde, uygulama günlükleri ve trafik analiz araçlarınız yanlış bilgiler gösterir.
Dosyayı kaydedin ve sembolik bağlantı oluşturun:
sudo ln -s /etc/nginx/sites-available/loadbalancer /etc/nginx/sites-enabled/
sudo nginx -t
Çıktı syntax is ok ise, servisi yeniden başlatın:
sudo systemctl restart nginx
Uygun dağıtım algoritmasını seçme
Varsayılan round-robin algoritması çoğu kullanım için uygundur, ancak her zaman en iyi seçim değildir. Sunucularınız farklı işlem gücüne sahipse, weight kullanın:
upstream backend_servers {
server 10.0.0.11:8080 weight=3;
server 10.0.0.12:8080 weight=1;
}
Bu ayar, her 4 istekten 3'ünün ilk sunucuya, 1'inin ikinci sunucuya gönderilmesi anlamına gelir. Uygulamanız oturum tabanlıysa ve kullanıcının sunucular arasında geçiş yapmasını istemiyorsanız, ip_hash kullanın:
upstream backend_servers {
ip_hash;
server 10.0.0.11:8080;
server 10.0.0.12:8080;
}
ip_hash ile her kullanıcının istekleri her zaman belirli bir sunucuya gönderilir. Bu yöntem oturum yönetimi için en basit yoldur, ancak kullanıcı değişken bir IP kullanıyorsa (mobil gibi) etkinliğini kaybeder. Bu durumda oturum yapışkanlığını load balancer'da değil, uygulama düzeyinde uygulamanız gerekir.
Arızalı sunucuları tespit etmek için health check yapılandırması
Yukarıdaki yapılandırmanın sorunu, backend sunucularından biri çalışmayı durdurursa Nginx'in yine de istekleri ona göndermesi ve kullanıcıların 502 hatası almasıdır. Bu sorunu çözmek için health check özelliğini etkinleştirmeniz gerekir. Nginx'in varsayılan olarak yalnızca bağlantı anında sunucuyu kontrol eden devre dışı bir health check'ü vardır. Ancak periyodik ve daha ayrıntılı kontrol için ticari modülü veya alternatif çözümleri kullanmanız gerekir.
En basit ücretsiz çözüm, max_fails ve fail_timeout kullanmaktır:
upstream backend_servers {
server 10.0.0.11:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.12:8080 max_fails=3 fail_timeout=30s;
}
Bu ayar, 30 saniyelik bir süre içinde bir sunucuya 3 kez bağlantı başarısız olursa, o sunucunun 30 saniye boyunca döngüden çıkarılması anlamına gelir. Ancak bu yöntem yalnızca bağlantı hatalarını tespit eder, uygulama hatalarını değil. Uygulamanız HTTP 500 yanıtı verirse, bağlantı kurulur ve Nginx onu sağlıklı kabul eder.
Uygulamanın yanıtını kontrol eden gerçek health check için nginx-upstream-check-module modülünü kullanabilir veya harici bir betik yazabilirsiniz. Daha basit bir yöntem, uygulamada özel bir endpoint kullanmaktır:
location /health {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
}
location / {
proxy_pass http://backend_servers;
proxy_next_upstream error timeout http_500 http_502 http_503;
}
proxy_next_upstream ile, ilk sunucu 500 veya 502 hatası döndürürse, Nginx isteği otomatik olarak bir sonraki sunucuya gönderir. Bu yöntem basit ve etkilidir, ancak sunucuların sağlığını periyodik olarak tespit etmek için yeterli değildir.
Harici betikle health check uygulama
Daha kapsamlı bir çözüm için, her 10 saniyede bir her sunucunun sağlık endpoint'ini kontrol eden ve arıza durumunda sunucuyu upstream'ten çıkaran bir bash betiği yazabilirsiniz. Ancak bu yöntem karmaşıktır ve bakımı zordur. Önerim, gerçek health check için HAProxy kullanmanızdır, ancak Nginx ile kalmak istiyorsanız, proxy_next_upstream ve max_fails kombinasyonu çoğu kullanım için yeterlidir.
Yaygın hata: Birçok kişi yalnızca max_fails ayarlar ve sorunun çözüldüğünü düşünür. Ancak uygulamanız hata içeren 200 yanıtı döndürürse (HTML'de görüntülenen PHP hatası gibi), Nginx onu sağlıklı kabul eder. Uygulamada her zaman yalnızca gerçek durumu döndüren ayrı bir sağlık endpoint'i tanımlayın.
Load balancer'da SSL sonlandırma
Load balancer'ın en önemli görevlerinden biri SSL sonlandırmadır. Bu, kullanıcıdan load balancer'a kadar olan HTTPS trafiğinin şifrelenmesi, ancak load balancer ile backend sunucuları arasında HTTP olarak iletilmesi anlamına gelir. Bu, şifreleme yükünü uygulama sunucularından alır ve sertifika yönetimini basitleştirir.
Öncelikle SSL sertifikasını load balancer sunucusuna kurun. Sertifikanız yoksa, Let's Encrypt ile ücretsiz bir sertifika alın:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d example.com -d www.example.com
Ardından load balancer yapılandırmasını SSL için ayarlayın:
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Önemli not: X-Forwarded-Proto başlığını mutlaka ayarlayın. Uygulamanız, load balancer ile backend arasında HTTP kullanılsa bile, orijinal isteğin HTTPS üzerinden geldiğini bilmelidir. Bu başlığı ayarlamazsanız, uygulama HTTP bağlantıları oluşturabilir veya güvenli olmayan yönlendirmeler yapabilir.
Daha iyi performans için SSL optimizasyonu
Handshake süresini azaltmak ve performansı artırmak için oturum önbelleğini etkinleştirebilirsiniz:
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
Bu ayar, Nginx'in SSL oturumlarını farklı bağlantılar arasında paylaşmasına olanak tanır. 10m değeri, yaklaşık 40.000 oturum için yeterli olan yaklaşık 10 megabayt oturum önbelleği anlamına gelir.
Ayrıca, tüm backend sunucularınız güvenli bir özel ağdaysa, load balancer ile backend arasında basit HTTP kullanabilirsiniz. Ancak ağınız güvenilir değilse, load balancer ile backend arasında da SSL'i etkinleştirmeniz gerekir. Bu durumda, proxy_pass http:// yerine proxy_pass https:// kullanın ve sertifikaları her backend sunucusuna kurun.
Yaygın hatalar ve çözümleri
Aşağıda, load balancer kurarken karşılaşabileceğiniz birkaç yaygın hata ve çözümlerini bulacaksınız:
502 Bad Gateway hatası
Bu hata, Nginx'in backend sunucusuna bağlanamadığı anlamına gelir. Öncelikle backend sunucusundaki servisin çalıştığını kontrol edin:
curl -I http://10.0.0.11:8080
Yanıt alamıyorsanız, backend sunucusunun güvenlik duvarını kontrol edin. 8080 portu load balancer adresinden erişilebilir olmalıdır:
sudo ufw allow from 10.0.0.10 to any port 8080
504 Gateway Timeout hatası
Bu hata, backend sunucusunun yanıtı belirlenen sürede döndürmediği anlamına gelir. Nginx'in varsayılan zaman aşımı 60 saniyedir. Uygulamanız uzun süreli işlemler yapıyorsa, bu değeri artırın:
location / {
proxy_pass http://backend_servers;
proxy_read_timeout 120s;
proxy_connect_timeout 10s;
}
Oturum ve giriş sorunu
Kullanıcılarınız giriş yaptıktan sonra ana sayfaya yönlendiriliyorsa veya oturumları sürekli kesiliyorsa, sorun isteklerin farklı sunucular arasında dağıtılmasından kaynaklanıyor olabilir. ip_hash kullanın veya oturum yapışkanlığını uygulamada uygulayın. Ayrıca, X-Forwarded-For başlığının doğru ayarlandığından emin olun, çünkü bazı uygulamalar kullanıcıyı tanımlamak için bu başlığı kullanır.
Özet ve sonraki adımlar
Bu makalede Nginx ile operasyonel bir load balancer kurduk, backend sunucularını ekledik, health check yapılandırdık ve SSL'i balancer'da sonlandırdık. Bu temel ayarlar çoğu üretim kullanımı için yeterlidir, ancak trafiğiniz çok yüksekse veya rate limiting ve caching gibi daha gelişmiş özelliklere ihtiyacınız varsa, HAProxy veya yönetilen load balancer hizmetlerini kullanabilirsiniz.
Altyapınız bulut sunucularında çalışıyorsa, ServerNet özel load balancer kurulumu veya yönetilen hizmetler sunar ve bu da kurulum süresini önemli ölçüde azaltabilir. Ancak her durumda, bu makalede ele alınan kavramları anlamak, daha iyi kararlar vermenize ve altyapı sorunlarınızı daha hızlı gidermenize yardımcı olacaktır.
Son olarak, load balancer ayarlarını her zaman staging ortamında test edin ve backend sunucuları ile load balancer'ın kendisi için uygun izleme kurun. İzlemesiz bir load balancer, yalnızca yeni bir arıza noktasıdır.