
Klaster Docker Swarm
Dzisiaj postanowiłem dla ćwiczeń pokazać postawienie klastra Docker Swarm. To naprawdę proste.
Zacznijmy od tego co to jest klaster? Najczęściej podawaną definicją jest grupa urządzeń/usług, które z zewnątrz mogą być widziane jak jeden system. W przypadku, który będę pokazywał – kilka wirtualnych maszyn połączonych ze soboą w ramach klastra Docker Swarm.
Co dzięki temu mogę zyskać? Powiedziałbym, że głównym plusem jest redundancja. Jeśli na klastrze docker swarm podniesiemy zestaw kontenerów i jeden z node’ów (wirtualnych maszyn, na których działa klaster) przestanie działać, to nasze kontenery zostaną odtworzone i uruchomione na pozostałych działających node’ach. Zwiększamy dzięki temu też dostępność naszego systemu. To tylko w skrócie, nie chcę się tu rozwodzić nad plusami i minusami takiego rozwiązania – można znaleźć masę informacji na ten temat w innych miejscach. Przejdźmy więc do praktyki.
Zacznijmy od wirtualnych maszyn które wykorzystamy. Nie będę tu opisywał ich tworzenia, wystarczy wrzucić w google jak stworzyć wirtualną maszynę w Azure, czy AWS. Ja dla testu i ze względu na mniejsze koszy wykorzystam Digital Ocean. Oczywiście Linux (ja wykorzystam Ubuntu) – jeśli chcesz się bawić kontenerami na poważnie to raczej odradzam Windows (chyba, że wiesz co robisz).
Najpierw połączmy się do wirtualnych maszyn i zainstalujmy Docker’a. Tutaj jedyną możliwością jest SSH, wirtualne maszyny z Linux’em niemal nigdy nie mają zainstalowanego środowiska graficznego by default (w sumie i tak nie będzie potrzebne, jeśli jednak chcesz to polecam zajrzeć na: https://docs.microsoft.com/pl-pl/azure/virtual-machines/linux/use-remote-desktop można to zrobić w kilka poleceń).
Instalacja docker’a: https://docs.docker.com/engine/install/ubuntu/ . Kopiujemy polecenia po kolei i z głowy, ew. tutaj cały skrypt (wklejamy do konsoli poprzez Shift+Insert). Jedna uwaga – w poniższym poleceniu trzeba zmienić fragment [arch=amd64] tak aby wskazywał na architekturę procesora z jakiej korzysta wirtualna maszyna (można to sprawdzić poleceniem uname -i), w powyższym linku są dostępne możliwe wartości do wstawienia.
(
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo apt-key fingerprint 0EBFCD88
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
sudo docker run hello-world
)
Przygotowujemy w ten sposób co najmniej dwie wirtualne maszyny.
Teraz czas przejść do dania głównego, czyli klaster.
Wybieramy jedną z maszyn i uruchamiamy na niej polecenie:
docker swarm init --advertise-addr <ADRES_IP_WIRTUALNEJ_MASZYNY>
Jeśli polecenie wykonało się poprawnie to powinniśmy otrzymać komunikat taki jak ten:

Na drugiej maszynie zaś uruchamiamy polecenie, które dostaliśmy w wyniku pierwszej (w poniższym poleceniu podmieniłem token i port na placeholder’y, jednakże w wyniku polecenie wyżej powinieneś mieć poprawne wartości):
docker swarm join --token <TOKEN> <ADRES_IP_WIRTUALNEJ_MASZYNY>:2377
Zależnie od dostawcy chmury może być konieczne otworzenie odpowiednich portów na maszynach: https://docs.docker.com/engine/swarm/swarm-tutorial/ .
Jeśli wszystko poszło poprawnie to na drugiej maszynie powinniśmy otrzymać komunikat:

Teraz mamy już działający klaster z dwoma maszynami. Czas na mały test. Najpierw wylistujmy nasze node’y poleceniem sudo docker node ls, powinniśmy otrzymać w wyniku dwa wpisy, np.:

Teraz uruchomimy kilka kontenerów poleceniem:
sudo docker service create --replicas 4 --name busybox_container busybox sleep 3600
W ten sposób uruchomiliśmy 4 identyczne kontenery, które po prostu działają i nie robią nic 😉 .
Sprawdźmy teraz na jakich node’ach zostały umieszczone poleceniem sudo docker service ps busybox_container , przykładowy wynik niżej:

By default docker swarm rozrzucił nasze kontenery równomiernie po node’ach.
Teraz czas na prawdziwy test – co się stanie jak „ubijemy” jednego node’a. Sprawdźmy zatrzymując z zewnątrz (np. z panelu dostawcy chmury) jedną z wirtualnych maszyn (tą, którą dołączyliśmy jako drugą do klastra).
Jak teraz sprawdzimy stan node’ów to zobaczymy, że wyłączony ma status Down.

A co z kontenerami:

Aby spełnić nasze wcześniejsze wymagania, teraz na głównym node’zie działają 4 repliki naszego kontenera.
Na sam koniec przywróćmy zatrzymany node. Po chwili już powinniśmy zobaczyć, że docker swarm go wykrył.


Jak widać rozłożenie kontenerów na node’ach się nie zmieniło. Tak naprawdę nie miałoby by to sensu – zatrzymywać i uruchamiać replik na innych node’ach w momencie, gdy zostaną uruchomione. Jeśli jednak jest taka potrzeba można to wymusić.

Jak teraz widać kontenery zostały z powrotem rozrzucone po node’ach.
A co jeśli padłby nam główny node (leader). Tutaj polecam poszukać informacji o rolach node’ów w docker swarm: leader, manager, worker. W skrócie, trzeba mieć kilka node’ów, które mają rolę manager (leader też jest manager’em) i jeśli leader przestanie działać to automatycznie któryś z manager’ów zostanie nowym leader’em. Symulację takiego zachowania zostawiam jednak jako pracę domową dla chętnych ;).
Podsumowując, Docker Swarm jest prosty w konfiguracji i wykorzystaniu. Oczywiście pominąłem tu dużo elementów, ale jeśli przyjrzeć się oficjalnej dokumentacji Docker Swarm to nie ma tego tak dużo.
Oczywiście ta prostota ma pewien minus – bardziej skomplikowane scenariusze mogą być trudne lub niemożliwe do zrealizowania. W takich przypadkach konieczne może być rozważenie popularnego Kubernetesa lub innego bardziej zaawansowanego orkiestratora.
PS Nie zapomnij po sobie posprzątać – chmura niestety jest droga ;).