Docker Swarm na trzech kontynentach: wysoka dostępność zaprojektowana z myślą o 100% uptime

Opublikowano 17 min czytania

Jedno centrum danych to pojedynczy punkt awarii. Ten artykuł pokazuje, jak zbudować Docker Swarm na trzech kontynentach, w którym może paść cała lokalizacja: kworum managerów, WireGuard, punkt wejścia na region, failover Geo-DNS, replikacja bazy danych i eksploatacja.

Serwer w jednym centrum danych to pojedynczy punkt awarii, niezależnie od tego, jak dobry jest sprzęt i jak dobra sieć. Gdy lokalizacja przestaje działać, na przykład z powodu awarii zasilania, zakłóceń w sieci albo po prostu błędu podczas prac serwisowych, aplikacja staje się niedostępna. Docker Swarm w wielu centrach danych rozwiązuje dokładnie ten problem: kontenery działają w trzech niezależnych lokalizacjach, najlepiej na trzech kontynentach, a jeśli jedna z nich ulegnie całkowitej awarii, jej zadania przejmują dwie pozostałe i użytkownicy niczego nie zauważają.

Ten artykuł pokazuje krok po kroku, jak zbudować klaster Docker Swarm zaprojektowany z myślą o 100% uptime: jeden serwer w Ameryce Północnej, jeden w Europie i jeden w Azji, szyfrowana sieć WireGuard między węzłami, kworum managerów, które przetrwa awarię całego kontynentu, jeden punkt wejścia na region oraz failover DNS, który automatycznie kieruje użytkowników do najbliższej sprawnej lokalizacji. Uczciwie wyjaśniamy też, co nawet przy takiej architekturze wciąż może zawieść i jak zabezpieczyć się także przed tymi zagrożeniami.

Czy Docker Swarm pozwala osiągnąć 100% uptime?

Docker Swarm rozpięty na trzech kontynentach jest zaprojektowany z myślą o 100% uptime: żaden pojedynczy serwer, żadne pojedyncze centrum danych ani żaden pojedynczy kontynent nie może sam zatrzymać aplikacji. Mimo to absolutnej dostępności nie może zagwarantować nikt, nawet wielcy dostawcy chmury, których najwyższe zobowiązania wynoszą od 99,99 do 99,999%. Przyczyną nie są centra danych, tylko elementy wspólne dla wszystkich lokalizacji. Właśnie nimi zajmuje się również ten artykuł, dzięki czemu zbliżysz się do 100% tak bardzo, jak to technicznie możliwe.

Co oznacza dostępność w liczbach

DostępnośćPrzestój w ciągu rokuPrzestój w ciągu miesiąca
99%87,6 godziny7,3 godziny
99,9%8,76 godziny43,8 minuty
99,99%52,6 minuty4,4 minuty
99,999%5,3 minuty26 sekund

Obliczenia zakładają 8760 godzin w roku i 730 godzin w miesiącu. Każda kolejna dziewiątka skraca dopuszczalny czas przestoju do jednej dziesiątej i właśnie tu zaczyna się praca, której pojedynczy serwer już nie udźwignie.

Dlaczego trzy kontynenty dają tak wiele

Trzy niezależne od siebie lokalizacje, każda o dostępności 99,9%, rachunkowo przestają działać jednocześnie tylko wtedy, gdy wszystkie trzy mają awarię w tym samym czasie: 0,1% razy 0,1% razy 0,1% daje 0,0000001%. Im dalej od siebie leżą lokalizacje, tym bardziej są faktycznie niezależne: osobne sieci energetyczne, osobne łącza sieciowe, osobne warunki pogodowe, osobne okna serwisowe. Dlatego rozłożenie klastra na Amerykę Północną, Europę i Azję to najsilniejsza forma odporności na awarie, jaką da się zbudować z serwerów.

Co może zawieść nawet przy trzech kontynentach

Pozostałe ryzyka to zależności wspólne dla wszystkich lokalizacji, a na każdą z nich istnieje środek zaradczy:

  • Wadliwą aktualizację klaster rozprowadzi do wszystkich lokalizacji równie niezawodnie jak dobrą. Środek zaradczy: health checki i automatyczny rollback, a do tego aktualizacje region po regionie.
  • DNS to ten jeden punkt, przez który przechodzą wszyscy użytkownicy. Środek zaradczy: dostawca DNS z siecią rozproszoną po całym świecie i failoverem oraz krótki TTL.
  • Baza danych musi mieć te same dane we wszystkich lokalizacjach. Środek zaradczy: replikacja z automatycznym przełączaniem, patrz sekcja o danych.
  • Wygasłe certyfikaty i domeny uderzają we wszystkie lokalizacje jednocześnie. Środek zaradczy: automatyczne odnawianie i monitorowanie dat wygaśnięcia.
  • Samo przełączenie trwa, dopóki nie zareagują health checki i DNS, zwykle od jednej do dwóch minut, w czasie których pojedyncze żądania mogą się nie powieść. Środek zaradczy: krótkie interwały sprawdzania, krótki TTL i aplikacje klienckie, które ponawiają nieudane żądania.

Przegląd architektury

Docker Swarm rozpięty na kilku kontynentach składa się z sześciu elementów. Każdy z nich eliminuje konkretny punkt awarii:

ElementZadaniePrzed jaką awarią chroni
Trzy węzły manager na trzech kontynentachUtrzymują stan klastra za pomocą konsensusu RaftAwaria całej lokalizacji lub kontynentu
Moc obliczeniowa workerów w każdym regionieUruchamia kontenery blisko użytkownikówAwaria pojedynczych serwerów
Sieć WireGuard między wszystkimi węzłamiSzyfruje cały ruch klastra przesyłany przez internetPodsłuch i manipulacja na trasie między centrami danych
Punkt wejścia (reverse proxy) w każdym regioniePrzyjmuje żądania użytkowników i obsługuje je lokalnieAwaria punktu wejścia jednego regionu
Geo-DNS z health checkamiKieruje użytkowników do najbliższej sprawnej lokalizacjiNiedostępne lokalizacje
Replikowane przechowywanie danych i kopie zapasoweUtrzymują bazy danych i pliki w kilku miejscachUtrata danych przy awarii lokalizacji

Ile managerów i gdzie?

Węzły manager w klastrze Swarm zarządzają jego stanem za pomocą algorytmu konsensusu Raft. Każda zmiana wymaga zgody większości managerów, czyli tak zwanego kworum. Gdy zabraknie większości, istniejące kontenery wprawdzie działają dalej, ale klaster nie może już ani ponownie planować rozmieszczenia, ani kompensować awarii, ani rozsyłać aktualizacji.

Liczba managerówWiększośćDopuszczalne awarie
321
532
743

Docker zaleca nieparzystą liczbę managerów i rozłożenie ich na co najmniej trzy strefy: przy trzech managerach w proporcji 1-1-1, przy pięciu w proporcji 2-2-1. Stąd wynika najważniejsza zasada tego artykułu: dwie lokalizacje nie wystarczą. Przy dwóch lokalizacjach w jednej z nich siłą rzeczy znajduje się więcej managerów, a jeśli awarii ulegnie właśnie ta, większość przepada. Dopiero przy trzech lokalizacjach kworum przetrwa awarię dowolnego centrum danych, a więc przy trzech kontynentach awarię całego kontynentu.

Trzy kontynenty czy jeden: plusy i minusy

Każda zmiana w klastrze, każde wdrożenie i każde ponowne zaplanowanie kontenera czeka na potwierdzenie od większości managerów. Między Europą, Ameryką Północną i Azją każde takie potwierdzenie kosztuje czas przesyłu pakietu wynoszący od około 80 do 250 milisekund. Dla użytkowników nie ma to znaczenia, bo ich żądania są obsługiwane lokalnie; wdrożenia i ponowne planowanie trwają jednak zauważalnie dłużej niż w klastrze o krótkich trasach.

WariantZaletyCena
Trzy kontynenty (USA, Europa, Azja)Maksymalna niezależność, użytkownicy na całym świecie blisko serwera, dopuszczalna jest awaria całego kontynentuWolniejsze zarządzanie klastrem, replikacja bazy danych na dużych odległościach, żądania muszą pozostać lokalne
Trzy lokalizacje na jednym kontynencie (na przykład Frankfurt, Strasburg, Warszawa)Szybkie zarządzanie klastrem, prosta replikacja synchronicznaZdarzenie o dużym zasięgu na kontynencie dotyka wszystkich lokalizacji, bardziej oddaleni użytkownicy mają dłuższą drogę

Dla aplikacji z użytkownikami na kilku kontynentach, od których wymaga się jak największej dostępności, właściwy jest wariant z trzema kontynentami i właśnie go budujemy w tym poradniku. Ważna jest przy tym zasada, która przewija się przez wszystkie kroki: każde żądanie jest obsługiwane w swoim regionie i nigdy nie podróżuje tam i z powrotem między kontynentami.

Które lokalizacje KernelHost się nadają

KernelHost prowadzi serwery w centrum danych maincubes we Frankfurcie nad Menem i oferuje serwery wirtualne w kolejnych lokalizacjach w Europie, Ameryce Północnej i Azji-Pacyfiku, między innymi: trzy lokalizacje w USA, Kanada, Londyn, Strasburg, Warszawa, Helsinki, Singapur, Japonia, Sydney i Mumbai. Pełna lista z mapą znajduje się na stronie Lokalizacje serwerów. W przykładzie z tego artykułu wybieramy Frankfurt nad Menem dla Europy, wschodnie wybrzeże USA dla Ameryki Północnej i Singapur dla Azji.

Poradnik: budowa klastra Docker Swarm na trzech kontynentach

Przykład wykorzystuje trzy serwery: swarm-eu we Frankfurcie nad Menem, swarm-us na wschodnim wybrzeżu USA i swarm-asia w Singapurze. Adresy publiczne pochodzą z sieci dokumentacyjnej 203.0.113.0/24, a sieć WireGuard korzysta z 10.10.0.0/24. Zastąp jedno i drugie własnymi wartościami. Wszystkie trzy węzły są jednocześnie managerami i workerami; jeśli potrzebujesz większej wydajności, później dodasz w każdym regionie węzły pełniące wyłącznie rolę workera.

Krok 1: przygotować serwery na trzech kontynentach

Zamów trzy serwery z Debianem 12 lub 13 w trzech regionach i wprowadź podstawowe zabezpieczenia: SSH wyłącznie z kluczem, automatyczne aktualizacje bezpieczeństwa, osobne konta użytkowników. Wszystko to opisuje lista kontrolna dla nowych serwerów root. Nadaj serwerom czytelne nazwy hostów, żeby w docker node ls od razu widzieć, który węzeł gdzie stoi.

hostnamectl set-hostname swarm-eu

Krok 2: zainstalować Dockera na wszystkich węzłach

Zainstaluj Docker Engine z oficjalnego repozytorium Dockera na wszystkich trzech serwerach, tak jak opisuje to artykuł Instalacja Dockera na Debianie i Ubuntu. Następnie sprawdź wersję na każdym węźle; wszystkie trzy powinny mieć tę samą wersję główną:

docker version --format '{{.Server.Version}}'

Krok 3: zbudować sieć WireGuard między kontynentami

Węzły komunikują się ze sobą przez publiczny internet. Żeby cały ruch klastra był szyfrowany, a porty Swarm nigdy nie były dostępne publicznie, trzy serwery łączy sieć WireGuard. Na każdym węźle najpierw wygeneruj parę kluczy:

apt-get install -y wireguard
umask 077
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key

Następnie każdy węzeł dostaje plik /etc/wireguard/wg0.conf. Tak wygląda on na swarm-eu; na pozostałych dwóch węzłach konfiguracja jest jego lustrzanym odbiciem:

[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = KLUCZ_PRYWATNY_SWARM_EU
MTU = 1420

[Peer]
PublicKey = KLUCZ_PUBLICZNY_SWARM_US
Endpoint = 203.0.113.12:51820
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25

[Peer]
PublicKey = KLUCZ_PUBLICZNY_SWARM_ASIA
Endpoint = 203.0.113.13:51820
AllowedIPs = 10.10.0.3/32
PersistentKeepalive = 25
systemctl enable --now wg-quick@wg0
ping -c 3 10.10.0.2

Jeśli wszystkie węzły odpowiadają pod swoimi adresami 10.10.0.x, sieć działa. PersistentKeepalive utrzymuje połączenie otwarte także za stanowymi firewallami. Czasy, które ping pokazuje teraz między kontynentami, to dokładnie te opóźnienia, z którymi będzie się wiązać każda zmiana w klastrze.

Krok 4: firewall: dostęp tylko dla węzłów Swarm

Docker Swarm potrzebuje między węzłami portu 2377/TCP do zarządzania klastrem, portu 7946/TCP i UDP do komunikacji węzłów między sobą oraz portu 4789/UDP dla sieci overlay. Zezwól na te porty wyłącznie na interfejsie WireGuard; publicznie otwarty pozostaje tylko sam WireGuard, i to wyłącznie dla pozostałych węzłów. Z ufw wygląda to na swarm-eu tak:

ufw allow from 203.0.113.12 to any port 51820 proto udp
ufw allow from 203.0.113.13 to any port 51820 proto udp
ufw allow in on wg0 to any port 2377 proto tcp
ufw allow in on wg0 to any port 7946
ufw allow in on wg0 to any port 4789 proto udp

Ważne: porty, które Docker publikuje dla kontenerów, omijają ufw, ponieważ Docker ustawia własne reguły iptables. Dlatego publikuj tylko porty punktu wejścia (80 i 443) i nigdy nie publikuj portów baz danych ani portów administracyjnych.

Krok 5: zainicjować Swarm i dodać węzły manager

Na swarm-eu zainicjuj Swarm i zadbaj o to, żeby zarządzanie i ruch danych przechodziły przez WireGuard:

docker swarm init --advertise-addr 10.10.0.1 --data-path-addr 10.10.0.1
docker swarm join-token manager

Drugie polecenie wypisuje komendę dołączenia dla kolejnych managerów. Wykonaj ją na swarm-us i swarm-asia, za każdym razem z własnym adresem WireGuard danego węzła, tutaj dla swarm-us:

docker swarm join --token SWMTKN-1-... --advertise-addr 10.10.0.2 --data-path-addr 10.10.0.2 10.10.0.1:2377
docker node ls

docker node ls pokazuje potem trzy węzły: jeden ze statusem Leader, a dwa pozostałe ze statusem Reachable. Token dołączenia jest sekretem: kto go zna, może przemycić do twojego klastra własny węzeł manager. Po zakończeniu budowy wymień go poleceniem docker swarm join-token --rotate manager.

Krok 6: włączyć autolock

Węzły manager przechowują stan klastra wraz z kluczami, którymi szyfrowane są logi Raft, w katalogu /var/lib/docker/swarm/. Dzięki funkcji autolock te klucze same zostają zaszyfrowane, a ponownie uruchomiony manager dołącza do klastra dopiero po podaniu klucza odblokowującego:

docker swarm update --autolock=true
docker swarm unlock

Pierwsze polecenie wypisuje klucz odblokowujący, który zapisujesz w menedżerze haseł. Drugiego potrzebujesz po każdym restarcie managera. Bez tego klucza klastra Swarm nie da się odtworzyć nawet z kopii zapasowej, dlatego przechowuj go oddzielnie od serwerów.

Krok 7: oznaczyć węzły według regionów

Etykiety mówią schedulerowi, gdzie stoi dany węzeł. Na nich opierają się reguły rozmieszczenia z kolejnych kroków:

docker node update --label-add region=eu swarm-eu
docker node update --label-add region=us swarm-us
docker node update --label-add region=asia swarm-asia

Krok 8: utworzyć sieć overlay z odpowiednim MTU

Kontenery w różnych lokalizacjach komunikują się ze sobą przez sieć overlay. Ponieważ biegnie ona przez tunel WireGuard, jej MTU musi być mniejsze: WireGuard pracuje z MTU 1420 bajtów, sieć overlay (VXLAN) zużywa z tego 50 bajtów na własne nagłówki, zostaje więc 1370 bajtów:

docker network create --driver overlay --attachable --opt com.docker.network.driver.mtu=1370 appnet

Zbyt duże MTU objawia się podstępnie: małe żądania działają, a duże odpowiedzi się zawieszają. Kto rezygnuje z sieci WireGuard, może zamiast tego zaszyfrować sieć overlay opcją --opt encrypted; wtedy między węzłami musi być dodatkowo dopuszczony protokół IP 50 (ESP), a Docker wprost ostrzega przed zauważalnym spadkiem wydajności. Polecamy WireGuard, ponieważ obejmuje cały ruch, łącznie z zarządzaniem.

Krok 9: uruchomić aplikację w każdym regionie

Zwykła usługa Swarm rozdziela żądania przez swój adres usługi na wszystkie repliki w klastrze, a więc także na pozostałe kontynenty. Przy trzech kontynentach co drugie albo co trzecie żądanie podróżowałoby wtedy przez pół świata. Dlatego każdy region dostaje własną usługę, którą reguła rozmieszczenia trzyma w obrębie tego regionu. Ustawienia aktualizacji sprawiają, że nowe wersje są wdrażane kontener po kontenerze, a w razie błędów automatycznie wycofywane:

for r in eu us asia; do
  docker service create --name web-$r --replicas 2 --network appnet \
    --constraint node.labels.region==$r \
    --update-parallelism 1 --update-delay 30s \
    --update-failure-action rollback \
    registry.example.com/web:1.0
done

Żeby Swarm rozpoznał, czy kontener faktycznie pracuje, a nie tylko jest uruchomiony, obraz powinien zawierać health check, na przykład taki wiersz w pliku Dockerfile twojej aplikacji:

HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD wget -qO- http://127.0.0.1:8080/health || exit 1

Kontener, którego health check trzy razy z rzędu zakończy się niepowodzeniem, zostaje zastąpiony, a w trakcie aktualizacji nieudany health check zatrzymuje wdrażanie.

Krok 10: jeden punkt wejścia na region

Rolę punktu wejścia pełni reverse proxy, taki jak Caddy, Traefik lub nginx. On również działa w każdym regionie jako osobna usługa i przekazuje żądania wyłącznie do aplikacji ze swojego regionu. W trybie host publikuje porty 80 i 443 bezpośrednio na serwerze swojego regionu. Wystarczy jedna wspólna konfiguracja, ponieważ Caddy odczytuje cel ze zmiennej środowiskowej:

example.com {
    reverse_proxy {$UPSTREAM}:80
}
docker config create caddyfile ./Caddyfile
for r in eu us asia; do
  docker service create --name edge-$r --network appnet \
    --constraint node.labels.region==$r \
    --env UPSTREAM=web-$r \
    --config source=caddyfile,target=/etc/caddy/Caddyfile \
    --publish mode=host,target=80,published=80 \
    --publish mode=host,target=443,published=443 \
    caddy:2
done

Wszystkie regiony potrzebują certyfikatu TLS dla tej samej domeny. Dlatego pobieraj certyfikaty przez wyzwanie DNS, które działa niezależnie od tego, na który region wskazuje akurat rekord DNS; Caddy potrzebuje do tego modułu twojego dostawcy DNS. Podstawy dotyczące proxy znajdziesz w artykule Konfiguracja nginx jako reverse proxy.

Krok 11: skonfigurować Geo-DNS z failoverem

Ostatni element prowadzi użytkowników do właściwego regionu. Usługa DNS z geo-routingiem i health checkami kieruje użytkowników z Europy do Frankfurtu nad Menem, z Ameryki na wschodnie wybrzeże USA, a z Azji do Singapuru. Gdy region ulegnie awarii, health check wykrywa to w ciągu 30 do 60 sekund i kieruje jego użytkowników do najbliższego sprawnego regionu. Ustaw czas życia (TTL) rekordów na 60 sekund, żeby resolvery szybko przejęły zmianę. Kilka rekordów A bez health checku to tylko prowizorka: przeglądarki wprawdzie często próbują kolejnego adresu, ale nie każdy klient tak robi, a region, który uległ awarii, pozostaje w odpowiedzi.

Policz uczciwie: między awarią a przełączeniem mija interwał sprawdzania plus TTL, w przykładzie więc od jednej do dwóch minut, podczas których część użytkowników z dotkniętego regionu nadal trafia do niedziałającej lokalizacji. Aplikacje webowe i mobilne, które po krótkiej przerwie ponawiają nieudane żądania, przeczekają ten czas niemal niezauważalnie.

Krok 12: przetestować awarię regionu

Failover, którego nigdy nie przećwiczono, rzadko działa, kiedy naprawdę jest potrzebny. Zasymuluj awarię regionu, wyłączając jego węzeł z pracy, i obserwuj, jak reagują klaster i DNS:

docker node update --availability drain swarm-asia
docker node ls
docker service ls
docker node update --availability active swarm-asia

Ponieważ usługi regionu są przypięte regułą rozmieszczenia do swojego węzła, nie przenoszą się, tylko wstrzymują pracę; użytkowników regionu przejmuje failover DNS. W tym teście sprawdź więc przede wszystkim, czy health check usuwa region z odpowiedzi i czy sąsiedni region udźwignie dodatkowe obciążenie. Jeśli chcesz przeprowadzić ostrzejszy test, całkowicie odetnij węzeł od sieci, na przykład zatrzymując WireGuard. Powtarzaj test po większych zmianach i co najmniej raz na kwartał.

Dane: najtrudniejsza część wysokiej dostępności

Docker Swarm replikuje kontenery, a nie dane. Wolumen zawsze leży na węźle, na którym działa kontener. Usługi bezstanowe, takie jak frontendy webowe i API, można więc bez problemu uruchomić w każdym regionie, ale wszystko, co przechowuje dane, wymaga osobnej replikacji.

Replikacja baz danych między kontynentami

Bazy danych mają własną replikację i zawsze jest ona lepszym wyborem niż współdzielona pamięć masowa rozciągnięta między centrami danych. Między kontynentami sprawdza się instancja główna w jednym regionie z asynchronicznymi replikami w dwóch pozostałych: w PostgreSQL na przykład przez streaming replication z narzędziem takim jak Patroni do automatycznego przełączania, a w MariaDB i MySQL przez wbudowaną replikację. Zapytania odczytu każdy region obsługuje wtedy lokalnie, a zapisy trafiają do instancji głównej. Szczerze mówiąc, asynchroniczność oznacza też, że po awarii regionu głównego może zabraknąć zapisów z ostatnich sekund. Kto chce zapisywać dane na całym świecie i niczego nie tracić, sięga po bazy danych zbudowane dla wielu regionów, takie jak CockroachDB lub YugabyteDB. Węzły bazy danych przypnij regułą rozmieszczenia na stałe do ich regionu, żeby Swarm nigdy nie przeniósł ich tam, gdzie nie ma ich danych:

docker service create --name db-asia --constraint node.labels.region==asia ...

Pliki i uploady

Przesłane pliki nie powinny trafiać do lokalnego wolumenu, tylko do zgodnego z S3 magazynu obiektowego z replikacją do drugiego regionu albo do własnego, replikowanego systemu przechowywania danych. Sieciowe systemy plików, takie jak NFS, rozciągnięte między kontynentami są powolne i same stanowią pojedynczy punkt awarii.

Sesje i cache

Jeśli aplikacja przechowuje sesje w pamięci operacyjnej kontenera, przy przełączeniu użytkownicy zostają wylogowani. Przechowuj sesje w replikowanej bazie danych lub w replikowanym cache, takim jak Redis, albo korzystaj z podpisanych tokenów, które każdy region może zweryfikować samodzielnie.

Kopie zapasowe nadal są obowiązkowe

Replikacja chroni przed awarią lokalizacji, ale nie przed błędami: przypadkowo usunięty rekord kilka sekund później znika we wszystkich regionach. Dlatego do każdej architektury wysokiej dostępności należą regularne, przetestowane kopie zapasowe przechowywane w niezależnym miejscu, tak jak opisuje to artykuł Strategia backupu serwera.

Eksploatacja: aktualizacje, prace serwisowe i monitoring

Aktualizacje region po regionie

Nie wdrażaj nowych wersji we wszystkich regionach jednocześnie, tylko po kolei, i obserwuj przez chwilę każdy region, zanim przejdziesz do następnego. Dzięki temu błąd, którego nie wykryje żaden health check, dotknie najwyżej jednego regionu, a dwa pozostałe dalej obsłużą jego użytkowników:

for r in asia us eu; do
  docker service update --image registry.example.com/web:1.1 web-$r || break
  sleep 300
done

Jeśli aktualizacja się nie powiedzie, Swarm dzięki ustawieniom z kroku 9 automatycznie ją wycofa, a || break przerwie pętlę, gdy tylko polecenie zgłosi błąd. Aktualizację, której problemy wyjdą na jaw dopiero później, wycofasz ręcznie poleceniem docker service rollback web-asia.

Prace serwisowe w regionie

Jeśli serwer trzeba zrestartować lub zaktualizować, wyłącz go z pracy poleceniem docker node update --availability drain, a wcześniej pozwól, żeby failover DNS przekierował jego użytkowników do sąsiednich regionów. Po zakończeniu prac przywróć go do pracy opcją --availability active. Z kolejnym managerem poczekaj, aż docker node ls znów pokaże wszystkie trzy jako osiągalne, żeby nigdy nie brakowało dwóch managerów naraz.

Monitoring z zewnątrz

Monitoruj każdy region osobno i spoza klastra: dostępność punktów wejścia, health checki usług, stan managerów, opóźnienie replikacji bazy danych oraz daty wygaśnięcia certyfikatów i domen. Alarm musi dotrzeć także wtedy, gdy milczy cały region. Jak zbudować to dla pojedynczych serwerów, pokazuje artykuł Konfiguracja monitoringu serwera.

Bezpieczna dystrybucja sekretów

Hasła i klucze nie powinny trafiać do zmiennych środowiskowych ani plików Compose, tylko do Docker Secrets. Są one przechowywane w zaszyfrowanym logu Raft i przekazywane wyłącznie tym usługom, którym jawnie je przypiszesz:

printf '%s' 'TWOJE_HASLO_DO_BAZY_DANYCH' | docker secret create db_password -
docker service update --secret-add db_password web-eu

Dlaczego KernelHost dla klastra Swarm na kilku kontynentach

Klaster rozpięty na kilku kontynentach stawia dostawcy inne wymagania niż pojedynczy serwer. W praktyce decydują te punkty:

WymaganieDlaczego ma znaczenieW KernelHost
Lokalizacje na kilku kontynentachKworum potrzebuje trzech niezależnych lokalizacji, a użytkownicy chcą krótkich trasFrankfurt nad Menem oraz lokalizacje w Europie, Ameryce Północnej i Azji-Pacyfiku u jednego dostawcy
Nielimitowany transferWireGuard, sieć overlay i replikacja bazy danych stale generują ruch między kontynentamiVPS z nielimitowanym transferem bez limitu ilości danych
Ochrona DDoSKażdy punkt wejścia jest dostępny publicznie, a więc stanowi cel atakuW cenie w każdej lokalizacji, w głównej lokalizacji we Frankfurcie nad Menem z filtrowaniem Arbor w czasie rzeczywistym o wydajności 3,2 Tbps, bez null-routingu
Pełny dostęp rootWireGuard, firewall i Docker Engine wymagają pełnej kontroliNa każdym serwerze root KVM i serwerze dedykowanym
Szybkie udostępnianieWęzły zastępcze i regiony testowe powinny być gotowe w kilka minutOkoło 30 sekund we Frankfurcie nad Menem, w innych lokalizacjach zwykle kilka minut
Bez zobowiązań umownych dla poszczególnych węzłówWęzły pojawiają się i znikają zależnie od potrzebPrePaid, bez minimalnego okresu umowy, bez opłaty aktywacyjnej
AutomatyzacjaNowe węzły powinny powstawać za pomocą skryptuZamawianie i sterowanie przez KernelHost API

Przegląd wszystkich pakietów chmurowych z cenami oraz porównanie kosztów z wielkimi dostawcami chmury znajdziesz na stronie Wynajem serwera w chmurze.

Częste błędy i jak ich unikać

  • Węzły manager tylko w dwóch lokalizacjach. Jeśli awarii ulegnie lokalizacja z większością, klaster staje. Rozwiązanie: trzy lokalizacje, podział 1-1-1 lub 2-2-1.
  • Parzysta liczba managerów. Cztery węzły manager nie tolerują więcej awarii niż trzy, ale zwiększają narzut na uzgadnianie. Rozwiązanie: 3, 5 lub 7.
  • Żądania podróżują między kontynentami. Jeden adres usługi dla wszystkich regionów wysyła użytkowników przez pół świata. Rozwiązanie: jedna usługa i jeden punkt wejścia na region.
  • Porty Swarm dostępne publicznie. Port 2377 i sieć overlay nigdy nie powinny być wystawione do otwartego internetu. Rozwiązanie: tylko przez WireGuard, publicznie wyłącznie 80, 443 i WireGuard dla pozostałych węzłów.
  • Zapomniane MTU. Duże odpowiedzi się zawieszają, małe działają. Rozwiązanie: MTU sieci overlay 1370 przy WireGuard z 1420.
  • Poleganie na ufw w przypadku portów kontenerów. Docker omija ufw przy opublikowanych portach. Rozwiązanie: publikować tylko punkt wejścia.
  • Baza danych w wolumenie bez replikacji. Gdy region ulegnie awarii, dane są niedostępne. Rozwiązanie: replikacja bazy danych i rozmieszczenie na stałe przypięte do regionu.
  • Aktualizacja we wszystkich regionach jednocześnie. Błąd dotyka wtedy wszystkich użytkowników na świecie. Rozwiązanie: wdrażanie region po regionie.
  • Wysoki TTL w DNS. Przy TTL wynoszącym jeden dzień failover zadziała dopiero następnego dnia. Rozwiązanie: 60 sekund.
  • Replikacja zamiast kopii zapasowej. Błąd jest replikowany tak samo jak poprawne dane. Rozwiązanie: dodatkowo przetestowane kopie zapasowe w niezależnym miejscu.

Krótkie podsumowanie

  • Docker Swarm rozpięty na trzech kontynentach jest zaprojektowany z myślą o 100% uptime: cała lokalizacja albo cały kontynent może ulec awarii, a aplikacja się nie zatrzyma.
  • Absolutnej dostępności nie może zagwarantować nikt; pozostałe ryzyka to DNS, wadliwe aktualizacje, baza danych i certyfikaty, a na każde z nich istnieje środek zaradczy.
  • Trzy węzły manager w trzech lokalizacjach to minimum, dwie lokalizacje nie wystarczą do kworum odpornego na awarie.
  • Każde żądanie pozostaje w swoim regionie: jedna usługa i jeden punkt wejścia na region, do tego Geo-DNS z health checkami i krótkim TTL.
  • WireGuard szyfruje ruch klastra, porty Swarm pozostają niewidoczne, a MTU sieci overlay spada do 1370.
  • Swarm replikuje kontenery, a nie dane: bazy danych potrzebują własnej replikacji, a kopie zapasowe pozostają obowiązkowe.
  • KernelHost oferuje lokalizacje w Europie, Ameryce Północnej i Azji-Pacyfiku, nielimitowany transfer, ochronę DDoS w każdej lokalizacji oraz rozliczenie PrePaid bez minimalnego okresu umowy.

Najczęstsze pytania

Czy Docker Swarm może zagwarantować 100% uptime?
Docker Swarm rozpięty na trzech kontynentach jest zaprojektowany z myślą o 100% uptime, ponieważ żaden pojedynczy serwer, żadne centrum danych ani żaden kontynent nie może samodzielnie zatrzymać aplikacji. Mimo to absolutnej dostępności nie może zagwarantować nikt, nawet wielcy dostawcy chmury. Pozostałe ryzyka to wspólne zależności, takie jak DNS, wadliwe aktualizacje, baza danych i certyfikaty. Chronią przed nimi health checki z automatycznym rollbackiem, aktualizacje region po regionie, replikacja bazy danych i monitoring.
Ile węzłów manager potrzebuje wysoko dostępny Docker Swarm?
Co najmniej trzy, rozłożone na trzy niezależne lokalizacje. Węzły manager utrzymują stan klastra za pomocą konsensusu Raft i każda zmiana wymaga ich większości: trzy węzły manager tolerują jedną awarię, pięć toleruje dwie, a siedem toleruje trzy. Docker zaleca nieparzystą liczbę managerów i rozłożenie ich na co najmniej trzy strefy, przy trzech managerach w proporcji 1-1-1.
Dlaczego dwa centra danych nie wystarczą dla Docker Swarm?
Ponieważ przy dwóch lokalizacjach w jednej z nich siłą rzeczy znajduje się więcej managerów. Jeśli awarii ulegnie właśnie ta lokalizacja, brakuje większości managerów, a klaster nie może ani ponownie planować rozmieszczenia, ani kompensować awarii, ani rozsyłać aktualizacji. Działające kontenery wprawdzie pracują dalej, ale klaster traci zdolność działania. Dopiero przy trzech lokalizacjach kworum przetrwa awarię dowolnego centrum danych.
Czy managerów Swarm można rozmieścić na różnych kontynentach?
Tak. Swarm z jednym managerem w Ameryce Północnej, jednym w Europie i jednym w Azji przetrwa awarię całego kontynentu. Ceną jest wolniejsze zarządzanie klastrem, ponieważ każda zmiana czeka na potwierdzenie przesyłane na duże odległości z opóźnieniem od 80 do 250 milisekund. Dla użytkowników nie ma to znaczenia, dopóki każde żądanie jest obsługiwane w swoim regionie, czyli przy jednej usłudze i jednym punkcie wejścia na region.
Jakich portów potrzebuje Docker Swarm?
Docker Swarm potrzebuje między węzłami portu 2377/TCP do zarządzania klastrem, portu 7946/TCP i UDP do komunikacji węzłów oraz portu 4789/UDP dla sieci overlay. Jeśli sieć overlay korzysta z wbudowanego szyfrowania, dodatkowo musi być dopuszczony protokół IP 50 (ESP). Żaden z tych portów nie powinien być wystawiony do otwartego internetu; najbezpieczniej, gdy ruch na nich biegnie wyłącznie przez sieć WireGuard między węzłami.
Czy potrzebuję WireGuard, czy wystarczy szyfrowana sieć overlay?
Szyfrowana sieć overlay (--opt encrypted) chroni tylko ruch danych kontenerów i według Dockera zauważalnie obniża wydajność. WireGuard szyfruje natomiast cały ruch między węzłami, także zarządzanie i komunikację węzłów, i odcina wszystkie porty Swarm od internetu. Dla klastra w kilku centrach danych polecamy WireGuard z MTU sieci overlay wynoszącym 1370 bajtów.
Jak działa failover między kontynentami?
Usługa DNS z geo-routingiem i health checkami kieruje każdego użytkownika do najbliższego regionu i co 30 do 60 sekund sprawdza, czy jego punkt wejścia odpowiada. Gdy region ulegnie awarii, usługa przestaje podawać jego adres i kieruje użytkowników do najbliższego sprawnego regionu. Przy TTL wynoszącym 60 sekund przełączenie kończy się zwykle po jednej do dwóch minut.
Jak utrzymać dostępność baz danych przy awarii lokalizacji?
Dzięki replikacji samej bazy danych, a nie dzięki Dockerowi. Swarm replikuje kontenery, a nie wolumeny. Sprawdza się instancja główna w jednym regionie z replikami w pozostałych, w PostgreSQL na przykład z Patroni do automatycznego przełączania. Między kontynentami replikacja działa asynchronicznie, więc w razie awarii może zabraknąć zapisów z ostatnich sekund. Kto musi zapisywać dane na całym świecie bez strat, korzysta z baz danych zbudowanych dla wielu regionów, takich jak CockroachDB lub YugabyteDB.
Docker Swarm czy Kubernetes dla wielu lokalizacji?
Docker Swarm jest znacznie prostszy w budowie i utrzymaniu, a dla wielu aplikacji w zupełności wystarcza. Kubernetes oferuje więcej możliwości w zakresie automatyzacji, skalowania i ekosystemu, ale wymaga większej wiedzy. Między kontynentami Kubernetes zwykle działa jako osobny klaster w każdym regionie, a klastry są wdrażane wspólnie przez GitOps, natomiast pojedynczy klaster Swarm można rozpiąć na kilka kontynentów.
Które lokalizacje KernelHost nadają się do klastra Swarm na trzech kontynentach?
KernelHost oferuje serwery we Frankfurcie nad Menem oraz w kolejnych lokalizacjach w Europie, Ameryce Północnej i Azji-Pacyfiku, w tym: trzy lokalizacje w USA, Kanada, Londyn, Strasburg, Warszawa, Helsinki, Singapur, Japonia, Sydney i Mumbai. Sprawdzonym zestawem dla trzech kontynentów jest Frankfurt nad Menem, wschodnie wybrzeże USA i Singapur. Wszystkie lokalizacje są dostępne u jednego dostawcy, z ochroną DDoS i rozliczeniem PrePaid.
Ile kosztuje Docker Swarm na trzech kontynentach?
Zasadniczo trzy serwery, po jednym na region, do tego usługa DNS z health checkami. Ponieważ WireGuard, sieć overlay i replikacja bazy danych stale generują ruch między lokalizacjami, kluczowe są pakiety z nielimitowanym transferem: u wielu wielkich dostawców chmury właśnie ten ruch jest dodatkowo płatny za każdy gigabajt. W KernelHost VPS z nielimitowanym transferem działają bez limitu ilości danych, w modelu PrePaid, bez minimalnego okresu umowy i bez opłaty aktywacyjnej.

Docker Swarm Wysoka dostępność Wiele regionów WireGuard Geo-DNS Failover Docker Chmura