Przykłady tworzenia load balancerów
Film instruktażowy dostępny na dole strony
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.
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.
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.
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.
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.
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.
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ę.
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).
Dla zobrazowania algorytmu Round-Robin uruchomimy prostą pętlę odpytującą nasz load balancer za pomocą narzędzia curl z wiersza poleceń:
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:
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:
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.
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:
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.
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:
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:
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:
Następnie uzupełniamy nazwę polityki, wybieramy akcję REDIRECT_TO_POOL oraz wybieramy pierwszą pulę (nazwa puli widoczna jest po jej UUID w nawiasie).
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
W oknie konfiguracji reguły L7 wybieramy Type – HOST_NAME, Compare Type – EQUAL_TO oraz Value – test1.example.com
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:
Po zatwierdzeniu klikamy na jej nazwę, przechodzimy do zakładki L7 Rules i tworzymy nową regułę:
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
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):
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.