Toplam Sayfa Görüntüleme Sayısı

17 Temmuz 2020 Cuma

NGINX LOAD BALANCING ve DOCKER COMPOSE SCALE SERVICE

Merhaba uzun zaman oldu, umarım iyisinizdir? Bu paylaşımda  docker compose üzerinde nginx ve web uygulama sunucusu çalıştırıp, bu uygulama sunucusunun ölçeğini (scale) değiştirerek yük anında container sayısını arttırmaya değineceğim. Anlatımda kullanılan işletim sistemi, Ubuntu 16.04 LTS, docker versiyon, community 19.03.6, docker compose versiyon 1.25.4'tür. Size kurulumların nasıl yapılacağı konusunda yardımcı olması adına kurulum işlemlerinin bulunduğu offical docker linklerini paylaşıyorum, ilgili dokümanlara aşağıdaki linklere tıklayarak ulaşabilirsiniz.




Docker ve docker-compose kurulumu yapıldığını varsayarak anlatıma geçiyorum. Örnek anlatımda aynı fiziksel makine üzerinde, ön tarafta nginx (load balancer) olarak konfigüre edilmiş ve onun arkasında maksimum (5) ölçeğe sahip web sunucusu container olarak çalıştırılacaktır. Ölçek arttırma ve azaltma işlemlerini kısa bir sürede yapabilmek için özel parametrelere ve Nginx konfigürasyonunda üç (3) farklı yük dengeleme moduna (oturum kalıcılığı, en az bağlantı ve round robin gibi algoritmalara) değinilecektir. Aşağıdaki linkten docker-compose.yml, nginx konfigürasyon dosyası ve sertifikalara ulaşılabilir.


Docker-compose yardımcı dosyaları indirip," tar -zxf scale.tar.gz " komutu ile "home" dizine çıkarttıktan sonra, "nginx dizini içinde bulunan mocal.conf dosyasındaki 192.168.56.40 ip adresini kendi makine ip adresi ile değiştirmelisiniz, yine docker-compose-yml içimde geçen extra-host kısmındaki 192.168.56.40 ip adresinide kendi sunucu ip adresi ile değiştirmelisiniz" Tüm dosya ve klasörler aynı dizinde olmalıdır. 
Örnek ekran görüntüsü;

Dosyalarla ilgili düzenleme yapıldıktan sonra docker-compose.yml dosyamızı çalıştırma sıra geldi. Bu işlem için docker-compose.yml dosyasını bir değişkene atıyorum, birden fazla compose file olduğuda yada farklı bir süreç işletileceğinde "-f" parametresi ile docker-compose file dosyalarını kullanılabilmekte. Konuyla ilgili komutlar aşağıda sırasıyla verilmiştir.

FL=docker-compose.yml
docker-compose -f $FL up -d


Herşey yolunda nginx 80 ve 443 portu dinlemekte, web uygulaması 3004 portu açmış ve çalışmakta, sorun yok iyi yoldayız. Kullanıdığımız docker-compose.yml dosyasını aşağıda paylaşıyorum.

Docker-compose.yml dosyasınında web servisi olarak, remnux/jsdetox:latest imajı kullanması gerektiği, port olarak içerde 3000'i dışarda 3001'den 3005'e kadar bağlayabileceğini belirtmektedir. Web servisi şu anda 1 instance olarak çalışmakta, birazdan scale parametresi ile 5 adet web servis çalıştıracağız. Nginx ise restart always ile yeniden başlayabilmekte, imaj olarak son nginx offical sürümünü kullanmakta, port olarak 80 ve 443'ü dinlemekte, volume kısmında ise sertifika ve nginx konfigürasyon dosyasını host makineden alacağı path bilgileri yer almakta, link ve depends alanlarında web servisine bağımlı olduğunu bildirdik.

Daha güvenli bir hali mevcut onuda kullanabilirsiniz. Çünkü yukarıdaki konfigürasyonda 3001-3005 arası portlar 0.0.0.0 üzerinden bind edilebilmekte, ama aşağıda paylaştığım "docker-compose.yml"da bu açıklığı giderdim, bu konfigürasyonu kullanmanızı öneririm. Bu konfigürasyonda sadece nginx'te bulunan mocal.conf dosyasındaki 192.168.56.40 ip adresini değiştirmeniz yeterli,docker-compose.yml içinde geçen 192.98.0.1 ip adresi dockerin kullandığı iç ip blogu olduğundan dış bacaktan doğrudan bir erişim söz konusu değil ve bu yöntem ilkine göre daha güvenli. Ayrıca 192.168.0.0/24 blogu statik olduğundan, bu konfigürasyonu kullanan her sunucuda gateway 192.98.0.1 olacaktır, bu sebeple nginx konfigürasyonunda sadece "server_name 192.168.56.40;" kısmı sizin host makinenin fiziksel ip adresi olmalı, bunun dışında bir değişiklik söz konusu değil. Bu yöntemin daha güvenli ve kolay olduğunu düşünüyorum. Seçim size kalmış.
*****************************************************************
services:

  web:
    image: remnux/jsdetox:latest  
    ports:
      - "192.98.0.1:3001-3005:3000"
    networks:
      mocal_net:

  nginx:
    restart: always
    networks:
      mocal_net:
#        ipv4_address: 192.98.0.5
    image: nginx:latest
    ports:
      - "0.0.0.0:80:80"
      - "0.0.0.0:443:443"
    volumes:
      - ./nginx:/etc/nginx/conf.d
      - ./certs:/etc/nginx/certs
    extra_hosts:
      - "web:192.98.0.1"
    links:
      - web
    depends_on:
      - web

networks:
    mocal_net:
        ipam:
            driver: default
            config:
                - subnet: 192.98.0.0/24
*****************************************************************

Test için benim local makinemde 2 farklı ortamdan https://192.168.56.40 ip adresine " curl " komutu ile istek yaparak, nginx logunda yapılan bu isteklere dönen cevapları kontrol edelim.

Linux ortam

 
Sağ köşede akan loga bakarsanız 3004 porta ait erişilemedi ibaresi yok.
Windows ortam

" curl.sh " Aşağıdaki içeriği kopyalayıp, bash -x curl.sh olarak çalıştırarak testinizi yapabilirsiniz. 192.168.56.40 ip adresini kendi host makinenizin ip adresi ile değiştirmeyi unutmayın. 
#************************************
#!/bin/bash
while true 
do
clear
curl --insecure -I https://192.168.56.40
sleep 2
done
#************************************

Windows batch script;
" curl.bat "
#************************************
@echo off 
:x
cd /d "c:\curl\bin\"
curl.exe --insecure -l https://192.168.56.40 -v
echo Sunucu istegi yapildi.
TIMEOUT 2
cls
goto x
#************************************

Şimdi docker servisleri durdurmadan 1 instance çalışan web servisi 5 adet çalıştırmaya sıra geldi.  bu işlemi yapabilmek için aşağıdaki komutu kullanmalıyız.

docker-compose -f $FL up -d --force-recreate --no-deps --scale web=5 web

Görüldüğü üzere 3001'den 3005 portuna kadar 5 adet web servis başladı. Nginx logları akmakta, herhangi hatalı bir durum söz konusu değil. Browserdan adresi görüntüleyelim.

Nginx konfigürasyonu inceleyip paylaşımı bitirelim. Nginx konfigürasyon dosyası içeriği:
volumes:
      - ./nginx:/etc/nginx/conf.d
ile volume maping yaptığımız dosya içeriği;

*****************************************************************
map $http_upgrade $connection_upgrade {
        default   upgrade;
        ''        close;
}


upstream mocal {
#    ip_hash; ## sticky
#    least_conn; ## Yuke gore enaz
    server web:3001;
    server web:3002;
    server web:3003;
    server web:3004;
    server web:3005;
  }

  server {
    listen 80;
    server_name 192.168.56.40;
    return 301 https://$server_name$request_uri;
  }

  server {
    listen 443 ssl default_server;
    listen [::]:443 ssl default_server;
    ssl on;
    server_name _;
    gzip off;
    ssl_certificate     /etc/nginx/certs/foobar.crt;
    ssl_certificate_key /etc/nginx/certs/foobar.key;
    ssl_session_timeout 5m;
    ssl_ciphers     EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH:+CAMELLIA256:+AES256:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!ECDSA:CAMELLIA256-SHA:AES256-SHA:CAMELLIA128-SHA:AES128-SHA;
    ssl_prefer_server_ciphers on;

    location / {
      proxy_pass http://mocal;
      proxy_redirect          off;
      proxy_next_upstream     error timeout invalid_header http_500;
      proxy_connect_timeout   2;
      proxy_set_header        Host            $host;
      proxy_set_header        X-Real-IP       $remote_addr;
      proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    }
  }

*****************************************************************

Location kısmında kısaca upstream sunuculardan kapalı yada erişilemez olanları 2 saniyede bir taraması ve çalışan sunuculara load balance yapması istenmekte, ayrıca " upstream mocal " kısmında " ip_hash; sticky session oturum kalıcığı, "least_conn;" düşük bağlantı olan sunucuya yönlendirme ve round robin için ise bu alanı boş bırakmak server dışında bişi yazmamak gerekiyor. Sertifika oluşturmak için aşağıdaki komutları sırasıyla çalıştırmalı ülke, şehir, email gibi alanlar doldurularak sertifika oluşturulmalıdır.
  • openssl genrsa -out foobar.key 2048
  • openssl req -new -key foobar.key -out foobar.csr
  • openssl x509 -req -days 365 -in foobar.csr -signkey foobar.key -out foobar.crt



Başka bir paylaşımda görüşmek üzere, kendinize iyi bakın. Selda BAĞCAN ile veda ediyorum.