Безпроблемна миграция RabbitMQ в Kubernetes

Безпроблемна миграция RabbitMQ в Kubernetes

RabbitMQ – създаден на езика Erlang брокер за съобщения, който позволява организирането на отказоустойчив клъстер с пълна репликация на данни на няколко възли, където всеки възел може да обслужва заявки за четене и запис. Има многобройни клъстери Kubernetes в продукция, ние поддържаме голям брой инсталации на RabbitMQ и срещнахме необходимостта от миграция на данни от един клъстер в друг без време на просто.

Тази операция бе необходима поне в два случая:

  1. Прехвърляне на данни от RabbitMQ клъстер, който не се намира в Kubernetes, в нов – вече "кубернетизиран" (т.е. функциониращ в pod-ове K8s) – клъстер.
  2. Миграция на RabbitMQ в рамките на Kubernetes от едно пространство на имена в друго (например, ако контурите са ограничени с пространства на имена, за прехвърляне на инфраструктура от един контур в друг).

Предложената в статията рецепта е ориентирана към ситуации (но не се ограничава до тях), в които има стар RabbitMQ клъстер (например, състоящ се от 3 възли), който се намира или вече в K8s, или на някакви стари сървъри. С него работи приложение, разположено в Kubernetes (или вече там, или в перспектива):

Безпроблемна миграция RabbitMQ в Kubernetes

… и пред нас стои задачата за неговата миграция в нова продукция в Kubernetes.

Първо ще бъде описан общият подход към самата миграция, а след това – технически детайли за нейното реализиране.

Алгоритъм за миграция

Първият, предварителен етап преди каквито и да било действия – проверка, че в старата инсталация на RabbitMQ е включен режим на висока наличност (HA). Причината е очевидна – ние не искаме да загубим никакви данни. За да извършим тази проверка, можем да влезем в админ панела на RabbitMQ и на таба Admin → Policies да се уверим, че е зададена стойност ha-mode: all:

Безпроблемна миграция RabbitMQ в Kubernetes

Следващата стъпка е да стартираме нов RabbitMQ клъстер в pod-ове Kubernetes (в нашия случай, например, състоящ се от 3 възли, но броят им може да бъде и друг).

След това свързваме стария и новия RabbitMQ клъстер, получавайки единен клъстер (от 6 възли):

Безпроблемна миграция RabbitMQ в Kubernetes

Иницира се процес на синхронизация на данни между стария и новия RabbitMQ клъстер. След като всички данни се синхронизират между всички възли в клъстера, можем да превключим приложението да използва новия клъстер:

Безпроблемна миграция RabbitMQ в Kubernetes

След тези операции е достатъчно да изключим старите възли от RabbitMQ клъстера, и миграцията може да се счита за завършена:

Безпроблемна миграция RabbitMQ в Kubernetes

Тази схема я неведнъж сме прилагали в нашето продукционно среда. Въпреки това, за собствено удобство, я реализирахме в рамките на специализирана система, разпространяваща стандартни конфигурации RMQ на множество клъстери Kubernetes. (за тези, които са любопитни: става дума за addon-operator, за което вече съвсем наскоро разказвахме). По-долу ще бъдат представени отделни инструкции, които всеки може да приложи на своите инсталации, за да опита предложеното решение в действие.

Изпробваме на практика

Изисквания

Реквизитите са много прости:

  1. Клъстер Kubernetes (подходящ е и minikube);
  2. Клъстер RabbitMQ (може да бъде инсталиран както на bare metal, така и като обикновен клъстер в Kubernetes от официалния Helm чарт).

За описания по-долу пример, инсталирах RMQ в Kubernetes и го нарекох rmq-old.

Подготовка на стенда

1. Сваляме Helm чарт и малко го редактираме:

helm fetch --untar stable/rabbitmq-ha

За удобство задаваме паролата, ErlangCookie и правим политиката ha-all, за да се синхронизират по подразбиране опашките между всички възли на клъстера 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. Инсталираме чарта:

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

3. Влизаме в админ интерфейса на RabbitMQ, създаваме нова опашка и добавяме няколко съобщения. Те ще са необходими, за да можем след миграцията да се уверим, че всички данни са запазени и не сме загубили нищо:

Безпроблемна миграция RabbitMQ в Kubernetes

Тестовият стенд е готов: имаме „стар“ RabbitMQ с данните, които трябва да пренесем.

Миграция на клъстера RabbitMQ

1. Първо ще инсталираме нов RabbitMQ в другом пространството с същите ErlangCookie и паролата за потребителя. За целта извършваме описаните по-горе операции, променяйки крайната команда за инсталация на RMQ на следната:

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

2. Сега е необходимо да обединим новия клъстер със стария. За това влизаме в всеки от pod-овете на нови RabbitMQ и изпълняваме следните команди:

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 е адресът на един от възлите на стария клъстер RMQ.

Тези команди ще спрат текущия възел на нови на клъстера RMQ, ще го присъединят към стария клъстер и ще го стартират отново.

3. Клъстерът RMQ с 6 възли е готов:

Безпроблемна миграция RabbitMQ в Kubernetes

Трябва да изчакаме, докато съобщенията се синхронизират между всички възли. Не е трудно да се предположи, че времето за синхронизиране на съобщенията зависи от мощността на хардуера, на който е разположен кластерът, и от количеството съобщения. В описания сценарий има само 10, така че данните се синхронизираха моментално, но при достатъчно голямо количество съобщения синхронизацията може да отнеме часове.

И така, статус на синхронизацията:

Безпроблемна миграция RabbitMQ в Kubernetes

Тук +5 означава, че съобщенията вече са още на 5 възли (без да се брои този, който е указан в полето Узел). По този начин синхронизацията премина успешно.

4. Остава само да сменим адреса на RMQ в приложението на новия кластер (конкретните действия тук зависят от използваната от вас технологична стека и други специфики на приложението), след което можем да се сбогуваме със стария.

За последната операция (т.е. вече след сменянето на приложението на новия кластер) влизаме на всеки възел стария на клъстера и изпълняваме командите:

rabbitmqctl stop_app
rabbitmqctl reset

Клъстерът „забрави“ за старите възли: можем да премахнем стария RMQ, с което миграцията ще бъде завършена.

Забележка: Ако използвате RMQ със сертификати, принципно нищо не се променя — процесът на миграция ще се осъществи точно така.

Изводи

Описаната схема подхожда практически за всички случаи, когато трябва да преместим RabbitMQ или просто да се преместим в нов кластер.

В нашия случай трудности възникнаха само веднъж, когато към RMQ се обръщаха от много места, а ние нямахме възможност навсякъде да сменим адреса на RMQ на новия. Тогава стартирахме нов RMQ в същото пространство с идентични лейбли, за да попада под вече съществуващите услуги и Ingress'и, а при стартирането на pod'а ръчно манипулирахме лейблите, премахвайки ги в началото, за да не получават запитвания на празния RMQ, и добавяйки ги обратно след синхронизацията на съобщенията.

Същата стратегия приложихме и при обновлението на RabbitMQ до нова версия с променена конфигурация — всичко работеше безупречно.

P.S.

Като логично продължение на този материал подготвяме статии за MongoDB (миграция от железен сървър в Kubernetes) и MySQL (как подготвяме тази СУБД вътре в Kubernetes). Те ще бъдат публикувани в близките месеци.

P.P.S.

Прочетете също в нашия блог:

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster