Przykłady tworzenia load balancerów ======================================================= **Instrukcja wideo dostępna na [dole strony](#instrukcja-wideo)** Load balancer HTTP -------------------- W niniejszym przykładzie stworzymy prosty **load balancer typu HTTP**, który będzie przekierowywał ruch **HTTP (port 80) z vIP** load balancera na adresy IP dwóch instancji stworzonych w tym samym projekcie za pomocą algorytmu **Round-Robin**. Aktualnie w projekcie stworzona jest sieć **project-net-1** wraz z podsiecią **project-subnet-1** o adresacji **10.10.0.0/24**. Sieć ta posiada dostęp do Internetu za pomocą routera w tym samym projekcie. Dodatkowo zostały stworzone 2 instancje **backend-1** (10.10.0.106) **backend-2** (10.10.0.195), posiadające serwery www nasłuchujące na **porcie 80**, które zwracają informacje z nazwą hosta do którego przychodzi zapytanie. **KROK 1 – Stworzenie load balancera** W pierwszym kroku przechodzimy do zakładki **Project -> Network > Load Balancers** gdzie klikamy na przycisk “**+ CREATE LOAD BALANCER**”, który uruchomi kreator tworzenia load balancera. Ustawiamy **nazwę, opis, wybieramy flavour** oraz **podsieć**, w której zostanie utworzony adres vIP, na którym load balancer będzie nasłuchiwać (adres ten może być z klasy prywatnej, w późniejszym kroku dołączymy do niego adres floating IP z sieci publicznej). Pola **IP address** oraz **Availability Zones** pozostawiamy puste. ![pic1](images/LB_str5_1.png) **KROK 2 – Stworzenie listenera** W kolejnym kroku **tworzymy listener**, czyli definiujemy **protokół** oraz **port** na którym nasz load balancer będzie nasłuchiwał nadchodzących połączeń. Uzupełniamy **nazwę, opis, wybieramy protokół (HTTP), port (80)**. Pozostałe pola pozostawiamy uzupełnione domyślnie. Pozwalają one dostosować podstawowe właściwości load balancera z listenerem typu HTTP oraz ewentualnie dodać popularne nagłówki używane w load balancingu. ![pic2](images/LB_str6_1.png) **KROK 3 – Stworzenie puli oraz wybranie algorytmu load balancingu** W kolejnym kroku tworzymy **pulę**, w której umieścimy backendy obsługujące zapytania przesłane do load balancera. Uzupełniamy **nazwę, opis** oraz wybieramy **algorytm (ROUND_ROBIN)**. Pozostałe pola pozostawiamy domyślne. ![pic3](images/LB_str7_1.png) **KROK 4 – Dodanie backendów do puli** W kolejnym kroku dodajemy **backendy (members)** do puli, którą stworzyliśmy wcześniej. Przy dostępnych instancjach klikamy przycisk **ADD**. Uzupełniamy **porty**, na których nasłuchują nasze serwery HTTP (80). Wagi pozostawiamy domyślne, co pozwoli na równomierne przekazywanie połączeń do obu serwerów. ![pic4](images/LB_str8_1.png) **KROK 5 – Skonfigurowanie Health Monitora** W ostatnim kroku kreatora **konfigurujemy sposób monitorowania dostępności backendów** w puli. W naszym przykładzie monitoring będzie polegać na **periodycznym (5 sekund) odpytywaniu backendów na porcie HTTP (80) i sprawdzaniu czy otrzymamy poprawną odpowiedź (kod HTTP 200)**. Ustawiamy **nazwę, typ HTTP** oraz pozostawiamy pozostałe pola domyślne. ![pic5](images/LB_str9_1.png) Na końcu potwierdzamy tworzenie load balancera klikając przycisk “**CREATE LOAD BALANCER**”. Proces tworzenia load balancera trwa od kilku sekund do ok 3 minut (w zależności od wybranego typu load balancera – flavouru). Gdy load balancer będzie gotowy jego parametry: **Operating Status** powinien być ustawiony jako **Online** oraz **Provisioning Status** jako **Active**. Finalnie aby nasz load balancer dostępny był z publicznego Internetu przypisujemy do niego **adres floating IP**. W tym celu na liście load balancerów klikamy na strzałkę opcji oraz wybieramy **Associate Floating IP**. ![pic6](images/LB_str9_2.png) W dalszym menu wybieramy **adres floating IP** przypisany do naszego projektu lub **pulę**, z której przypiszemy **nowy adres IP (EXTERNAL)**. Po przypisaniu adresu floating IP będzie on widoczny we właściwościach load balancera dostępnych po kliknięciu na jego nazwę. ![pic7](images/LB_str10_1.png) W tym momencie nasz load balancer jest utworzony i możemy przetestować jego działanie. Wpisujemy **adres floating IP** load balancera w pasek adresu przeglądarki. Oczywiście musimy pamiętać, żeby backendy posiadały poprawne ustawienia **Security Groups akceptujące ruch HTTP (port TCP/80)**. ![pic8](images/LB_str10_2.png) Dla zobrazowania algorytmu Round-Robin uruchomimy prostą pętlę odpytującą nasz load balancer za pomocą narzędzia ``curl`` z wiersza poleceń: ![pic9](images/LB_str10_3.png) Aby **stworzyć podobny load balancer** wykorzystując **OpenStack CLI** wydajemy następujące polecenia: ``openstack loadbalancer create --name loadbalancer-1 --vip-subnet-id project-subnet-1 --flavor 1000Mbps-HA`` Poczekajmy na stworzenie load balancera, aż kolejne polecenie wskaże **operating_status ONLINE** oraz **provisioning_status ACTIVE** ``openstack loadbalancer show loadbalancer-1`` ``openstack loadbalancer listener create --name listener-http --protocol HTTP --protocol-port 80 loadbalancer-1`` ``openstack loadbalancer pool create --name pool-1 --lb-algorithm ROUND_ROBIN --listener listener-http --protocol HTTP`` ``openstack loadbalancer member create --subnet-id project-subnet-1 --address 10.10.0.106 --protocol-port 80 pool-1`` ``openstack loadbalancer member create --subnet-id project-subnet-1 --address 10.10.0.195 --protocol-port 80 pool-1`` ``openstack loadbalancer healthmonitor create --name monitor-http --delay 5 --max-retries 3 --max-retries-down 3 --timeout 5 --type HTTP pool-1`` Wyszukujemy **ID portu vIP** z właściwości load balancera oraz **nadajemy adres floating IP** wcześniej zaalokowany do naszego projektu ``openstack floating ip set --port cf50d069-0e43-40ec-ae3e-e16119b9aae0 185.2.112.48`` Loadbalancer HTTPS_TERMINATED -------------------------------- Kolejny przykład opisuje **tworzenie load balancera**, który **otrzymuje zapytania HTTPS**, następnie **za pomocą klucza prywatnego oraz certyfikatu SSL przesyła zaszyfrowany ruch pomiędzy load balancerem a klientem** (przeglądarką). Load balancer w wewnętrznej wirtualnej sieci komunikuje się z backendami za pomocą zwykłego **protokołu HTTP** (ruch nieszyfrowany). **Architekturę takiego rozwiązania przedstawia poniższy schemat:** ![pic10](images/LB_str13_1.png) Zanim zaczniemy przygotowanie load balancera, uprzednio **należy przesłać klucz prywatny oraz wygenerowany na jego podstawie certyfikat SSL**, a następnie **utworzyć z tej pary tzw. bundle**. W Atman Cloud jest to możliwe wyłącznie za pomocą CLI/API. W niniejszym przykładzie wykorzystamy paczki python-openstackclient oraz python-barbicanclient (odpowiedzialną za komunikację z tzw. secret store) zainstalowane w systemie Linux za pomocą narzędzia PIP. W przykładzie wygenerujemy również certyfikaty self-signed dla przykładowej domeny **test.example.com**. **Wygenerowanie klucza RSA** o rozmiarze 3072 bajty (niezabezpieczonego hasłem) ``openssl genrsa -out test.example.com.pem 3072`` **Przekonwertowanie klucza** z formatu pem do formatu pkcs8 akceptowalnego przez secret store ``openssl pkcs8 -topk8 -in test.example.com.pem -out text.example.com.pk8 -nocrypt`` **Przesłanie klucza do secret store** w Atman Cloud, z wyniku komendy zapisujemy na później Secret href rozpoczynający się od **http://controller…** jest to wewnętrzny identyfikator podobny do standardowego adresu URL ``openstack secret store --secret-type private --name test.example.com_key --file test.example.com.pk8`` **Wygenerowanie certyfikatu SSL** z użyciem wcześniej wygenerowanego klucza prywatnego (pole DN musi zgadzać się z żądaną domeną) ``openssl req -new -x509 -days 365 -key test.example.com.pk8 -out cert-test.example.com.pem`` **Przesłanie certyfikatu do secret store** w Atman Cloud, tutaj również z wyniku komendy zapisujemy na później identyfikator Secret href ``openstack secret store --secret-type certificate --name 'test.example.com_cert' --file cert-test.example.com.pem`` Finalnie za pomocą wcześniej zapisanych odnośników do klucza oraz certyfikatu tworzymy tzw. bundle zaimplementowane w Atman Cloud jako “Secret container”, podczas tworzenia load balancera wybierzemy go za pomocą nazwy (parametr –name) w panelu Atman Cloud ``openstack secret container create --type certificate --name cert-key-bundle-test.example.com --secret "certificate=http://controller.c2a.eco.atman.pl:9311/v1/secrets/d69361e6-b626-4867-b2c0-8d7f7f2bc970" --secret "private_key=http://controller.c2a.eco.atman.pl:9311/v1/secrets/cf07644c-17b9-4859-95eb-e3482670cb45"`` Następnie przechodzimy do tworzenia load balancera w panelu webowym Atman Cloud. W dalszej części przykładu odniesiemy się do różnic tworzenia terminowanego load balancera HTTPS oraz wcześniej przywołanego load balancera HTTP. **Punkt 1**. odnośnie tworzenia samego load balancera jest identyczny, natomiast w punkcie 2. w polu **Protocol** wybieramy **TERMINATED_HTTPS**: ![pic11](images/LB_str15_1.png) Następnie identycznie jak dla load balancera HTTP tworzymy pulę, dodajemy do niej **backendy** oraz tworzymy **health monitor**. Ostatnim krokiem będzie wskazanie certyfikatu SSL dla naszego **listenera**. Po wybraniu z lewej strony menu “SSL Certificates” klikamy na znak (+) przy nazwie wcześniej stworzonego bundle oraz finalnie klikamy **CREATE LOAD BALANCER**. ![pic12](images/LB_str16_1.png) Po utworzeniu load balancera podobnie jak w poprzednim przykładzie przypisujemy mu adres floating IP. Gdy **Operating Status** load balancera zmieni się na **Online** oraz **Provisioning Status** na **ACTIVE**, nasze backendy będą dostępne za pomocą protokołu **HTTPS (port TCP/443)**, np. **https://test.example.com**. Zwróćmy uwagę, że w niniejszym przykładzie certyfikat SSL jest poddpisany samodzielnie (self-signed), stąd przeglądarka będzie zwracała błąd niezaufanego certyfikatu. W celu utworzenia przykładowego loadbalancera z terminowanym połączeniem SSL można też wykonać następujące polecenia poprzez OpenStack CLI (pominięto tworzenie oraz przesyłanie certyfikatów opisane powyżej): ``openstack loadbalancer create --name loadbalancer-1-terminated-https --vip-subnet-id project-subnet-1 --flavor 1000Mbps-HA`` Poczekajmy na stworzenie load balancera, aż kolejne polecenie wskaże **operating_status ONLINE** oraz **provisioning_status ACTIVE** ``openstack loadbalancer show loadbalancer-1-terminated-https`` Podczas tworzenia listenera podajemy identyfikator **href** kontenera z certyfikatem oraz kluczem prywatnym, który uprzednio stworzyliśmy w secret store, odnośniki do kontenerów można wyświetlić wykorzystując polecenie “**openstack secret container list**” ``openstack loadbalancer listener create --name listener-terminated-https --protocol TERMINATED_HTTPS --protocol-port 443 --default-tls-container-ref http://controller.c2a.eco.atman.pl:9311/v1/containers/a8119383-afce-4cd8-aec9-767e30ae5189 loadbalancer-1-terminated-https`` ``openstack loadbalancer pool create --name pool-1 --lb-algorithm ROUND_ROBIN --listener listener-terminated-https --protocol HTTP`` ``openstack loadbalancer member create --subnet-id project-subnet-1 --address 10.10.0.106 --protocol-port 80 pool-1`` ``openstack loadbalancer member create --subnet-id project-subnet-1 --address 10.10.0.195 --protocol-port 80 pool-1`` ``openstack loadbalancer healthmonitor create --name monitor-http --delay 5 --max-retries 3 --max-retries-down 3 --timeout 5 --type HTTP pool-1`` **Wyszukujemy ID portu vIP** z właściwości load balancera oraz nadajemy **adres floating IP** wcześniej zaalokowany do naszego projektu ``openstack floating ip set --port cf50d069-0e43-40ec-ae3e-e16158b9aae0 185.2.112.48`` Loadbalancer HTTP wraz z regułami warstwy 7 (L7 load balacing) ----------------------------------------------------------------- Jako przykład **load balancera z wykorzystaniem reguł warstwy 7**, utworzymy **jeden load balancer**, posiadający pojedynczy **listener** nasłuchujący na **porcie 80** oraz **dwie pule serwerów**, w każdej **po jednym backendzie**. Wybór puli będzie następował na podstawie nazwy hosta (odpowiedniego nagłówka protokołu HTTP) do którego będziemy się odwoływać. W naszym przypadku host **test1.example.com** będzie przekierowywał ruch do pierwszej puli a tym samym serwera **backend-1** oraz ruch do **test2.example.com** będzie przekazywany do drugiej puli oraz serwera **backend-2**. Architektura którą stworzymy przedstawiona jest na poniższym schemacie: ![pic13](images/LB_str18_1.png) **KROK 1 – Tworzenie load balancera** Kreator tworzenia load balancerów (uruchamiany po kliknięciu na **CREATE LOAD BALANCER**) pozwala na stworzenie jedynie jednej, domyślnej puli dla listenera. Stąd na początku tworzymy sam load balancer. W kroku **Load Balancer Details** uzupełniamy wszystkie istotna dane oraz w kroku **Listener Details** ustawiamy opcję **Create Listener** na **NO**, kończymy kreator wybierając przycisk **CREATE LOAD BALANCER**. ![pic14](images/LB_str19_1.png) ![pic15](images/LB_str19_2.png) **KROK 2 – Tworzenie listenera oraz domyślnej puli** Kolejnym krokiem jest **stworzenie listenera typu HTTPS** oraz **domyślnej puli**, do której przekazywane będą wszystkie zapytania otrzymywane przez listener. W tym celu klikamy na nazwę wcześniej utworzonego load balancera, następnie przechodzimy do zakładki **Listeners** oraz wybieramy **+ CREATE LISTENER**. W tym momencie ukaże nam się kreator tworzenia listernera, który uzupełniamy podobnie jak w pierwszym przykładzie zwykłego load balancera HTTP (bez polityk warstwy 7). Pamiętamy żeby do pierwszej puli dołączyć jedynie serwer **backend-1**. Całość przedstawiona jest na poniższych zrzutach ekranu: ![pic16](images/LB_str20_1.png) ![pic17](images/LB_str21_1.png) ![pic18](images/LB_str21_2.png) ![pic19](images/LB_str22_1.png) Na końcu wybieramy **CREATE LISTENER**. **KROK 3 – Tworzenie drugiej puli oraz przypisanie serwera backend-2** Kolejnym krokiem jest stworzenie drugiej puli oraz dodanie do niej serwera **backend-2**. W tym celu przechodzimy do zakładki **Pools** w ustawieniach load balancera (gdzie powinna znajdować się już pierwsza pula) oraz wybieramy **+ CREATE POOL**. Ukaże nam się kreator tworzenia nowej puli, uzupełniamy wszystkie kroki jak wcześniej, pamiętając o dodaniu jedynie serwera **backend-2**: ![pic20](images/LB_str23_1.png) ![pic21](images/LB_str23_2.png) ![pic22](images/LB_str24_1.png) Zatwierdzamy kreator wybierając **CREATE POOL**. **KROK 4 – Tworzenie polityk i reguł warstwy 7** W obecnym przykładzie cały ruch nadal przekierowany jest do puli **pool-1**, ze względu na to, że została ona utworzona jako pula domyślna dla listenera (stworzona podczas tworzenia listenera). Stąd, kolejnym krokiem jest **utworzenie reguł przekierowujących ruch do serwera backend-1** przy zapytaniach do load balancera posiadającego w nagłówku nazwę hosta **test1.example.com** oraz do serwera **backend-2** przy nazwie hosta w **test2.example.com**. Pierwsza reguła jest oczywiście zbędna (ze względu na domyślną rolę puli pool-1), aczkolwiek stworzony ją dla czytelności konfiguracji. W ustawieniach load balancera (dostępnych po kliknięciu na jego nazwę) przechodzimy do zakładki **Listeners** oraz klikamy na **nazwę listenera** aby przejść do jego ustawień. Następnie przechodzimy do zakładki **L7 Policies** oraz wybieramy **+ CREATE L7 POLICY**, jak na zrzucie ekranu poniżej: ![pic23](images/LB_str25_1.png) Następnie uzupełniamy nazwę polityki, wybieramy akcję **REDIRECT_TO_POOL** oraz wybieramy pierwszą pulę (nazwa puli widoczna jest po jej UUID w nawiasie). ![pic24](images/LB_str25_2.png) Zatwierdzamy konfigurację wybierając **CREATE L7 POLICY**. Aby utworzyć regułę do danej polityki klikamy na nazwę puli, następnie przechodzimy do zakładki **L7 Rules** oraz klikamy na **+ CREATE L7 RULE** jak na zrzucie ekranu poniżej ![pic25](images/LB_str25_3.png) W oknie konfiguracji **reguły L7** wybieramy **Type – HOST_NAME, Compare Type – EQUAL_TO oraz Value – test1.example.com** ![pic26](images/LB_str26_1.png) Następnie zatwierdzamy konfigurację poprzez kliknięcie na **CREATE L7 RULE**. Kolejnym krokiem jest **utworzenie polityki oraz reguły warstwy 7** dla nazwy hosta **test2.example.com** oraz przekierowaniu takiego ruchu do drugiej puli. W tym celu, tak jak wcześniej, przechodzimy do ustawień load balancera następnie w zakładce **Listeners** klikamy na **nazwę listenera** oraz w zakładce **L7 Policies** tworzymy **nową politykę L7 przekierowującą do puli pool-2**: ![pic27](images/LB_str27_1.png) Po zatwierdzeniu klikamy na jej nazwę, przechodzimy do zakładki **L7 Rules** i tworzymy **nową regułę**: ![pic28](images/LB_str27_2.png) **KROK 5 – Przypisanie adresu Floating IP** Ostatnim krokiem jest przypisanie adresu **Floating IP**, do load balancera. Na liście load balancerów rozwijamy menu akcji oraz wybieramy **Associate Floating IP** ![pic29](images/LB_str28_1.png) Następnie wybieramy żądany adres publiczny oraz zatwierdzamy akcję. W tym momencie nasz load balancer jest gotowy a jego działanie za pomocą narzędzia **Curl** przedstawione jest poniżej (proszę zwrócić uwagę, że domyślnie przekierowanie ustawione jest na serwer **backend-1**): ![pic30](images/LB_str28_2.png) Powyższą konfigurację możemy stworzyć również za pomocą **OpenStack CLI**: Na początku tworzymy load balancer w identyczny sposób jak w dla **LB HTTP** ``openstack loadbalancer create --name loadbalancer-1-http-l7 --vip-subnet-id project-subnet-1 --flavor 1000Mbps-HA`` Czekamy na stworzenie load balancera, aż kolejne polecenie wskaże **operating_status ONLINE** oraz **provisioning_status ACTIVE** ``openstack loadbalancer show loadbalancer-1-http-l7`` Następnie tworzymy **listener typu HTTP na porcie 80** ``openstack loadbalancer listener create --name listener-http-l7 --protocol HTTP --protocol-port 80 loadbalancer-1-http-l7`` **Tworzymy dwie pule**, w których umieścimy nasze backendy, zwróćmy uwagę, ze pierwsza pula jest przypisana do listenera (jest zarazem pulą domyślną), stąd będą trafiały do niej wszystkie zapytania, nawet te niespełniające żadnych warunków (np. bezpośredni dostęp przez adres IP w polu hosta). ``openstack loadbalancer pool create --name pool-1 --lb-algorithm ROUND_ROBIN --listener listener-http-l7 --protocol HTTP`` ``openstack loadbalancer pool create --name pool-2 --lb-algorithm ROUND_ROBIN --loadbalancer loadbalancer-1-http-l7 --protocol HTTP`` Następnie **tworzymy politykę oraz regułę przekierowującą** zapytania z nazwą hosta **test1.example.com** do pierwszej puli (jak zaznaczony powyżej ta polityka jest opcjonalna gdyż pierwsza pula jest pulą domyślną). ``openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool pool-1 --name policy-1 listener-http-l7`` ``openstack loadbalancer l7rule create --compare-type EQUAL_TO --type HOST_NAME --value test1.example.com policy-1`` Kolejno **tworzymy drugą politykę oraz regułę przekierowującą** zapytania z nazwą hosta **test2.example.com** do drugiej puli ``openstack loadbalancer l7policy create --action REDIRECT_TO_POOL --redirect-pool pool-2 --name policy-2 listener-http-l7`` ``openstack loadbalancer l7rule create --compare-type EQUAL_TO --type HOST_NAME --value test2.example.com policy-2`` Następnie dodajemy poszczególne backendy do osobnych pul ``openstack loadbalancer member create --subnet-id project-subnet-1 --address 10.10.0.106 --protocol-port 80 pool-1`` ``openstack loadbalancer member create --subnet-id project-subnet-1 --address 10.10.0.195 --protocol-port 80 pool-2`` Kolejnym krokiem jest **stworzenie health monitorów dla obydwu pul** (krok opcjonalny) ``openstack loadbalancer healthmonitor create --name monitor-http --delay 5 --max-retries 3 --max-retries-down 3 --timeout 5 --type HTTP pool-1`` ``openstack loadbalancer healthmonitor create --name monitor-http --delay 5 --max-retries 3 --max-retries-down 3 --timeout 5 --type HTTP pool-2`` Finalnie **wyszukujemy ID portu vIP** z właściwości load balancera oraz **nadajemy adres floating IP** wcześniej zaalokowany do naszego projektu ``openstack floating ip set --port cf50d069-0e43-40ec-ae3e-e16119b9aae0 185.2.112.48`` Udostępnienie endpointu metryk w formacie Prometheus ------------------------------------------------------ Aby udostępnić metryki loadbalancera w formacie parsowalnym przez system Prometheus do aktualnego load balancera należy dodać nowy listener, który wystawi zbiorcze metryki. Aktualnie dodanie takiego listenera możliwe jest jedynie przez API lub klienta CLI razem z odpowiednią wtyczką. Aby zainstalować klienta razem z wtyczką należy wykonać polecenie (przykład dla systemu Ubuntu, aczkolwiek dla innych systemów lub instalacji poprzez PIP nazwa paczki będzie podobna): ``sudo apt install python3-octaviaclient`` Następnie zakładając uruchomienie takiego listenera (exportera Prometheus dla modułu Octavia w OpenStacku) na porcie 9885, który dla loadablancera lb-1 wystawi metryki jedynie dla klientów (serwerów Prometheus, które ściągają metryki) łączących się spod konkretnego adresu IP należy wydać polecenie: ``openstack loadbalancer listener create --name prometheus_exporter --protocol PROMETHEUS --protocol-port 9385 --wait --allowed-cidr 123.123.123.123/32 lb-1`` Od tego momentu na porcie 9385 dostępną będą metryki z load balancera w ramach którego został utworzony powyższy listener. **UWAGA:** Przy każdej zmianie w/w listenera metryki będą wyzerowane. Instrukcja wideo ------------------- [![Watch the video](https://img.youtube.com/vi/hqbXcQnSdAA/maxresdefault.jpg)](https://youtu.be/hqbXcQnSdAA) ### [Otwórz ten film na YouTube](https://youtu.be/hqbXcQnSdAA)