Bezproblemowa migracja RabbitMQ do Kubernetes

Bezproblemowa migracja RabbitMQ do Kubernetes

RabbitMQ to broker komunikatów napisany w języku Erlang, który pozwala zorganizować klaster pracy awaryjnej z pełną replikacją danych w wielu węzłach, gdzie każdy węzeł może obsługiwać żądania odczytu i zapisu. Mając wiele klastrów Kubernetes w pracy produkcyjnej, wspieraliśmy dużą liczbę instalacji RabbitMQ i stanęliśmy przed koniecznością migracji danych z jednego klastra do drugiego bez przestojów.

Operację tę potrzebowaliśmy co najmniej w dwóch przypadkach:

  1. Przeniesienie danych z klastra RabbitMQ, który nie jest zlokalizowany w Kubernetesie do nowego – już „kubernetyzowanego” (czyli działającego w podach K8s) – klastra.
  2. Migracja RabbitMQ w ramach Kubernetes z jednej przestrzeni nazw do drugiej (na przykład, jeśli obwody są oddzielone przestrzeniami nazw, to w celu przeniesienia infrastruktury z jednego obwodu do drugiego).

Przepis zaproponowany w artykule skupia się na sytuacjach (ale nie ogranicza się do nich), w których znajduje się stary klaster RabbitMQ (na przykład składający się z 3 węzłów), zlokalizowany już albo w K8, albo na niektórych starych serwerach. Współpracuje z nim aplikacja hostowana na Kubernetesie (już tam lub w przyszłości):

Bezproblemowa migracja RabbitMQ do Kubernetes

…i stajemy przed zadaniem migracji go na nową produkcję w Kubernetesie.

Najpierw zostanie opisane ogólne podejście do samej migracji, a następnie omówione zostaną szczegóły techniczne jej realizacji.

Algorytm migracji

Pierwszym, wstępnym etapem przed jakąkolwiek akcją jest sprawdzenie, czy w starej instalacji RabbitMQ włączony jest tryb wysokiej dostępności (HA). Powód jest oczywisty – nie chcemy stracić żadnych danych. Aby przeprowadzić tę kontrolę, możesz przejść do panelu administracyjnego RabbitMQ i w zakładce Administrator → Polityki upewnić się, że wartość jest ustawiona ha-mode: all:

Bezproblemowa migracja RabbitMQ do Kubernetes

Kolejnym krokiem jest podniesienie nowego klastra RabbitMQ w podach Kubernetes (w naszym przypadku składających się np. z 3 węzłów, ale ich liczba może być inna).

Następnie łączymy stare i nowe klastry RabbitMQ, uzyskując pojedynczy klaster (6 węzłów):

Bezproblemowa migracja RabbitMQ do Kubernetes

Rozpoczyna się proces synchronizacji danych pomiędzy starym i nowym klastrem RabbitMQ. Po zsynchronizowaniu wszystkich danych pomiędzy wszystkimi węzłami w klastrze możemy przełączyć aplikację tak, aby korzystała z nowego klastra:

Bezproblemowa migracja RabbitMQ do Kubernetes

Po tych operacjach wystarczy usunąć stare węzły z klastra RabbitMQ i przeprowadzkę można uznać za zakończoną:

Bezproblemowa migracja RabbitMQ do Kubernetes

Wielokrotnie korzystaliśmy z tego schematu w produkcji. Jednak dla własnej wygody zaimplementowaliśmy go w ramach specjalizowanego systemu, który dystrybuuje standardowe konfiguracje RMQ na wiele klastrów Kubernetes (dla ciekawskich: mowa o operator dodatkówo którym my niedawno powiedziano). Poniżej przedstawiamy indywidualną instrukcję, którą każdy może zastosować na swojej instalacji, aby wypróbować proponowane rozwiązanie w działaniu.

Spróbujmy tego w praktyce

Wymagania

Szczegóły są bardzo proste:

  1. Klaster Kubernetes (minikube też będzie działać);
  2. Klaster RabbitMQ (można wdrożyć na platformie Bare Metal i utworzyć jak zwykły klaster w Kubernetesie na podstawie oficjalnego wykresu Helm).

W poniższym przykładzie wdrożyłem RMQ w Kubernetes i nazwałem go rmq-old.

Przygotowanie stoiska

1. Pobierz wykres Helma i trochę go zmodyfikuj:

helm fetch --untar stable/rabbitmq-ha

Dla wygody ustalamy hasło, ErlangCookie i uprawiać politykę ha-alltak aby domyślnie kolejki były synchronizowane pomię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. Zainstaluj wykres:

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

3. Przejdź do panelu administracyjnego RabbitMQ, utwórz nową kolejkę i dodaj kilka wiadomości. Będą potrzebne, abyśmy po migracji mogli mieć pewność, że wszystkie dane zostały zachowane i niczego nie straciliśmy:

Bezproblemowa migracja RabbitMQ do Kubernetes

Stanowisko testowe gotowe: mamy „stary” RabbitMQ z danymi do przeniesienia.

Migracja klastra RabbitMQ

1. Najpierw wdróżmy nowy RabbitMQ w другом przestrzeń nazw z to samo ErlangCookie i hasło dla użytkownika. Aby to zrobić, wykonamy operacje opisane powyżej, zmieniając końcowe polecenie instalacji RMQ na następujące:

helm install . --name rmq-new --namespace rmq-new

2. Teraz musisz połączyć nowy klaster ze starym. W tym celu udaj się do każdego z kapsuł nowy RabbitMQ i wykonaj 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

W zmiennej OLD_RMQ znaleziono adres jednego z węzłów stary Klaster RMQ.

Te polecenia zatrzymają bieżący węzeł nowy Klaster RMQ, podłącz go do starego klastra i uruchom go ponownie.

3. Klaster RMQ składający się z 6 węzłów jest gotowy:

Bezproblemowa migracja RabbitMQ do Kubernetes

Musisz poczekać, aż wiadomości zostaną zsynchronizowane pomiędzy wszystkimi węzłami. Nietrudno się domyślić, że czas synchronizacji komunikatów zależy od wydajności sprzętu, na którym zbudowany jest klaster oraz od liczby komunikatów. W opisywanym scenariuszu jest ich tylko 10, więc dane zostały zsynchronizowane błyskawicznie, ale przy odpowiednio dużej liczbie wiadomości synchronizacja może trwać godzinami.

A więc stan synchronizacji:

Bezproblemowa migracja RabbitMQ do Kubernetes

Tutaj +5 oznacza, że ​​wiadomości już dotarły więcej w 5 węzłach (z wyjątkiem wskazanych w polu Node). Zatem synchronizacja przebiegła pomyślnie.

4. Pozostało jedynie przełączyć adres RMQ w aplikacji na nowy klaster (konkretne działania zależą tutaj od stosu technologii, z którego korzystasz oraz innych specyfiki aplikacji), po czym będziesz mógł pożegnać się ze starym.

Dla ostatniej operacji (tj. już później przełączanie aplikacji do nowego klastra) przejdź do każdego węzła stary klaster i wykonaj polecenia:

rabbitmqctl stop_app
rabbitmqctl reset

Klaster „zapomniał” o starych węzłach: możesz usunąć stare RMQ, po czym przenoszenie zostanie zakończone.

Operacja: Jeśli korzystasz z RMQ z certyfikatami, zasadniczo nic się nie zmienia - proces przenoszenia zostanie przeprowadzony dokładnie tak samo.

odkrycia

Opisany schemat sprawdza się niemal we wszystkich przypadkach, kiedy potrzebujemy dokonać migracji RabbitMQ lub po prostu przenieść się do nowego klastra.

W naszym przypadku trudności pojawiły się tylko raz, gdy dostęp do RMQ był z wielu miejsc i nie wszędzie mieliśmy możliwość zmiany adresu RMQ na nowy. Następnie uruchomiliśmy nowy RMQ w tej samej przestrzeni nazw z tymi samymi etykietami tak, aby mieścił się w istniejących usługach i Ingressach, a przy uruchamianiu poda ręcznie manipulowaliśmy etykietami, usuwając je na początku, aby żądania nie spadały na puste RMQ i dodawanie ich ponownie po zsynchronizowaniu wiadomości.

Tę samą strategię zastosowaliśmy przy aktualizacji RabbitMQ do nowej wersji ze zmienioną konfiguracją – wszystko działało jak zegar.

PS

Jako logiczną kontynuację tego materiału, przygotowujemy artykuły o MongoDB (migracja z serwera sprzętowego do Kubernetes) i MySQL (jak przygotowujemy ten DBMS w Kubernetes). Zostaną opublikowane w nadchodzących miesiącach.

PPS

Przeczytaj także na naszym blogu:

Źródło: www.habr.com

Dodaj komentarz