Kłopotliwa migracja RabbitMQ do Kubernetes

Kłopotliwa migracja RabbitMQ do Kubernetes

RabbitMQ – to napisany w języku Erlang broker wiadomości, który pozwala na zorganizowanie odpornego na awarie klastra z pełną replikacją danych na wielu węzłach, gdzie każdy węzeł może obsługiwać zapytania do odczytu i zapisu. Posiadając wiele klastrów Kubernetes w produkcji, wspieramy dużą liczbę instalacji RabbitMQ i stanęliśmy przed koniecznością migracji danych z jednego klastra do drugiego bez przestojów.

Operacja ta była nam konieczna przynajmniej w dwóch przypadkach:

  1. Przeniesienie danych z klastra RabbitMQ, który nie działa w Kubernetes, do nowego — już „skonfigurowanego pod K8s” (tj. funkcjonującego w podach K8s) — klastra.
  2. Migracja RabbitMQ w ramach Kubernetes z jednego namespace do drugiego (na przykład, jeśli obszary są rozgraniczone przez przestrzenie nazw, to w celu przeniesienia infrastruktury z jednego obszaru do innego).

Proponowany w artykule przepis jest skierowany na sytuacje (ale wcale ich nie ogranicza), w których istnieje stary klaster RabbitMQ (na przykład składający się z 3 węzłów), który znajduje się albo już w K8s, albo na jakichś starych serwerach. Z nim współpracuje aplikacja, umieszczona w Kubernetes (już tam lub w perspektywie):

Kłopotliwa migracja RabbitMQ do Kubernetes

… i przed nami stoi zadanie migracji do nowej produkcji w Kubernetes.

Na początku zostanie opisane ogólne podejście do samej migracji, a dopiero później — szczegóły techniczne dotyczące jej realizacji.

Algorytm migracji

Pierwszy, wstępny etap przed jakimikolwiek działaniami — sprawdzenie, czy w starej instalacji RabbitMQ włączony jest tryb wysokiej dostępności (HA). Powód jest oczywisty — nie chcemy przecież stracić żadnych danych. Aby to sprawdzić, można wejść do panelu administracyjnego RabbitMQ i w zakładce Admin → Policies upewnić się, że ustawiona jest wartość ha-mode: all:

Kłopotliwa migracja RabbitMQ do Kubernetes

Następny krok — uruchamiamy nowy klaster RabbitMQ w podach Kubernetes (w naszym przypadku, na przykład, składający się z 3 węzłów, ale ich liczba może być inna).

Po tym łączymy stary i nowy klaster RabbitMQ, uzyskując jeden wspólny klaster (z 6 węzłów):

Kłopotliwa migracja RabbitMQ do Kubernetes

Inicjowany jest proces synchronizacji danych między starym a nowym klastrem RabbitMQ. Po tym, jak wszystkie dane zostaną zsynchronizowane między wszystkimi węzłami w klastrze, możemy przełączyć aplikację na korzystanie z nowego klastra:

Kłopotliwa migracja RabbitMQ do Kubernetes

Po tych operacjach wystarczy wyłączyć stare węzły z klastra RabbitMQ, a migrację można uznać za zakończoną:

Kłopotliwa migracja RabbitMQ do Kubernetes

Ten schemat wielokrotnie stosowaliśmy w naszej produkcji. Jednak dla własnej wygody zaimplementowaliśmy go w ramach wyspecjalizowanego systemu, który rozprowadza typowe konfiguracje RMQ na wielu klastrach Kubernetes. (dla ciekawskich: mowa o addon-operator, o którym niedawno opowiadaliśmy. Poniżej zostaną przedstawione oddzielne instrukcje, które każdy może zastosować w swoich instalacjach, aby sprawdzić proponowane rozwiązanie w działaniu.)Sprawdzamy w praktyce

Rekwizyty są bardzo proste:

Wymagania

Klaster Kubernetes (może być także minikube);

  1. Klaster RabbitMQ (może być zainstalowany na bare metal lub stworzony jako zwykły klaster w Kubernetes za pomocą oficjalnego Helm-chart).
  2. Dla opisanego poniżej przykładu założyłem RMQ w Kubernetes i nazwałem go

rmq-old Przygotowanie stanowiska.

1. Pobieramy Helm-chart i nieco go edytujemy:

helm fetch --untar stable/rabbitmq-ha

Dla wygody ustawiamy hasło,

ErlangCookie i tworzymy politykę ha-all , aby domyślnie kolejki synchronizowały się między wszystkimi węzłami klastra RMQ:rabbitmqPassword: guest rabbitmqErlangCookie: mae9joopaol7aiVu3eechei2waiGa2we definitions: policies: |- { "name": "ha-all", "pattern": ".*", "vhost": "\/", "definition": { "ha-mode": "all", "ha-sync-mode": "automatic", "ha-sync-batch-size": 81920 } }

2. Instalujemy chart:

helm install . --name rmq-old --namespace rmq-old

3. Wchodzimy do panelu administracyjnego RabbitMQ, tworzymy nową kolejkę i dodajemy kilka wiadomości. Będą one potrzebne, aby po migracji upewnić się, że wszystkie dane zostały zachowane i nic nie zostało utracone:

Testowe stanowisko gotowe: mamy „stary” RabbitMQ z danymi, które należy przenieść.

Kłopotliwa migracja RabbitMQ do Kubernetes

Migracja klastra RabbitMQ

1. Na początek uruchomimy nowy RabbitMQ w

innym przestrzeni nazw z takim samym i hasłem dla użytkownika. W tym celu wykonamy opisane powyżej operacje, zmieniając końcową komendę do instalacji RMQ na następującą: i tworzymy politykę helm install . --name rmq-new --namespace rmq-new

2. Teraz musimy połączyć nowy klaster ze starym. W tym celu wchodzimy do każdego z podów

nowego RabbitMQ i wykonujemy polecenia: export OLD_RMQ=rabbit@rmq-old-rabbitmq-ha-0.rmq-old-rabbitmq-ha-discovery.rmq-old.svc.cluster.local && rabbitmqctl stop_app && rabbitmqctl join_cluster $OLD_RMQ && rabbitmqctl start_app

OLD_RMQ

W zmiennej to adres jednego z węzłów starego klastra RMQ. Te polecenia zatrzymają bieżący węzeł

klastra RMQ, dołączą go do starego klastra i ponownie uruchomią. RabbitMQ i wykonujemy polecenia: 3. Klaster RMQ z 6 węzłami gotowy:

3. Klaster RMQ z 6 węzłami gotowy:

Kłopotliwa migracja RabbitMQ do Kubernetes

Musisz poczekać, aż wiadomości zsynchronizują się między wszystkimi węzłami. Nie trudno się domyślić, że czas synchronizacji wiadomości zależy od mocy sprzętu, na którym uruchomiony jest klaster, oraz od liczby wiadomości. W opisanym scenariuszu jest ich zaledwie 10, więc dane zsynchronizowały się natychmiast, ale przy wystarczająco dużej liczbie wiadomości synchronizacja może trwać godzinami.

Status synchronizacji:

Kłopotliwa migracja RabbitMQ do Kubernetes

Tutaj +5 oznacza, że wiadomości są już jeszcze na 5 węzłach (oprócz tego, który jest wskazany w polu Węzeł). W ten sposób synchronizacja przebiegła pomyślnie.

4. Pozostaje tylko przełączyć w aplikacji adres RMQ na nowy klaster (konkretne działania tutaj zależą od używanego przez Ciebie stosu technologicznego i innych specyfik aplikacji), po czym można pożegnać się ze starą wersją.

Aby wykonać ostatnią operację (tj. już po przełączenia aplikacji na nowy klaster), wchodzimy na każdy węzeł klastra RMQ. klastra i wykonujemy polecenia:

rabbitmqctl stop_app
rabbitmqctl reset

Klaster „zapomniał” o starych węzłach: można usunąć stary RMQ, co zakończy migrację.

Uwaga: Jeśli używasz RMQ z certyfikatami, to zasadniczo nic się nie zmienia — proces migracji będzie przebiegał dokładnie tak samo.

Wnioski

Opisana schemat pasuje praktycznie do wszystkich przypadków, gdy musimy przenieść RabbitMQ lub po prostu przeprowadzić się do nowego klastra.

W naszym przypadku trudności wystąpiły tylko raz, gdy do RMQ zwracano się z wielu miejsc, a nie mieliśmy możliwości zmiany adresu RMQ wszędzie. Wtedy uruchomiliśmy nowy RMQ w tej samej przestrzeni nazw z identycznymi etykietami, aby pasował do już istniejących usług i Ingressów, a przy uruchamianiu pod'a ręcznie manipulowaliśmy etykietami, usuwając je na początku, aby żadne zapytania nie trafiały na pusty RMQ i dodając je z powrotem po synchronizacji wiadomości.

Tę samą strategię zastosowaliśmy podczas aktualizacji RabbitMQ do nowej wersji z zmienioną konfiguracją — wszystko działało jak w zegarku.

P.S.

Jako logiczne rozwinięcie tego materiału przygotowujemy artykuły na temat MongoDB (migracja z serwera fizycznego do Kubernetes) i MySQL (jak przygotowujemy tę bazę danych w Kubernetes). Zostaną one opublikowane w najbliższych miesiącach.

P.P.S.

Przeczytaj także na naszym blogu:

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster