Няпростая міграцыя RabbitMQ у Kubernetes

Няпростая міграцыя RabbitMQ у Kubernetes

RabbitMQ – напісаны на мове Erlang брокер паведамленняў, які дазваляе арганізаваць адмоваўстойлівасць кластар з поўнай рэплікацыяй дадзеных на некалькі вузлоў, дзе кожны вузел можа абслугоўваць запыты на чытанне і запіс. Маючы ў production-эксплуатацыі мноства кластараў Kubernetes, мы падтрымліваем вялікую колькасць усталёвак RabbitMQ і сутыкнуліся з неабходнасцю міграцыі дадзеных з аднаго кластара ў іншы без прастою.

Дадзеная аперацыя была неабходна нам як мінімум у двух выпадках:

  1. Перанос дадзеных з кластара RabbitMQ, які знаходзіцца не ў Kubernetes, у новы – ужо «кубернетэзаваны» (г.зн. які функцыянуе ў pod'ах K8s) – кластар.
  2. Міграцыя RabbitMQ у рамках Kubernetes з аднаго namespace ў іншы (напрыклад, калі контуры размежаваны прасторамі імёнаў, то для пераносу інфраструктуры з аднаго контуру ў іншы).

Прапанаваны ў артыкуле рэцэпт арыентаваны на сітуацыі (але зусім не абмежаваны імі), у якіх ёсць стары кластар RabbitMQ (напрыклад, з 3 вузлоў), які знаходзіцца альбо ўжо ў K8s, альбо на нейкіх старых серверах. З ім працуе дадатак, размешчанае ў Kubernetes (ужо там ці ў перспектыве):

Няпростая міграцыя RabbitMQ у Kubernetes

… і перад намі стаіць задача яго міграцыі ў новы production у 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

Гэтую схему мы неаднаразова ўжывалі ў нас у production. Аднак для ўласнай выгоды рэалізавалі яе ў рамках спецыялізаванай сістэмы, якая распаўсюджвае тыпавыя канфігурацыі 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 вузлах (акрамя таго, што пазначаны ў полі Node). Такім чынам, сінхранізацыя прайшла паспяхова.

4. Застаецца толькі пераключыць у дадатку адрас RMQ на новы кластар (канкрэтныя дзеянні тут залежаць ад выкарыстоўванага вамі тэхналагічнага стэка і іншай спецыфікі прыкладання), пасля чаго можна развітацца са старым.

Для апошняй аперацыі (г.зн. ужо пасля пераключэння прыкладання на новы кластар) заходзім на кожны вузел старога кластара і выконваем каманды:

rabbitmqctl stop_app
rabbitmqctl reset

Кластар "забыўся" аб старых вузлах: можна выдаляць стары RMQ, на чым пераезд будзе скончаны.

Заўвага: Калі вы выкарыстоўваеце RMQ з сертыфікатамі, то прынцыпова нічога не мяняецца - працэс пераезду будзе ажыццяўляцца сапраўды гэтак жа.

Высновы

Апісаная схема падыходзіць практычна для ўсіх выпадкаў, калі нам трэба перанесці RabbitMQ ці проста пераехаць у новы кластар.

У нашым выпадку складанасці ўзнікалі толькі адзін раз, калі да RMQ звярталіся са мноства месцаў, а ў нас не было магчымасці ўсюды памяняць адрас RMQ на новы. Тады мы запускалі новы RMQ у той жа прасторы імёнаў з аднолькавымі лэйбламі, каб ён пападаў пад ужо існыя сэрвісы і Ingress'ы, а пры запуску pod'а рукамі маніпулявалі лэйбламі, выдаляючы іх у пачатку, каб на пусты RMQ не пападалі запыты, і дадаючы іх назад пасля сінхранізацыі паведамленняў.

Такую ж стратэгію мы ўжывалі пры абнаўленні RabbitMQ на новую версію са змененай канфігурацыяй – усё працавала як гадзіннік.

PS

У якасці лагічнага працягу гэтага матэрыялу мы рыхтуем артыкулы пра MongoDB (міграцыя з жалезнага сервера ў Kubernetes) і MySQL (як мы рыхтуем гэтую СКБД усярэдзіне Kubernetes). Яны будуць апублікаваны ў бліжэйшыя месяцы.

PPS

Чытайце таксама ў нашым блогу:

Крыніца: habr.com

Дадаць каментар