
RabbitMQ – un broker de mesaje scris în Erlang, care permite organizarea unui cluster rezistent la defecte, cu replicarea completă a datelor pe mai multe noduri, fiecare dintre acestea putând gestiona cereri de citire și scriere. Având numeroase clustere Kubernetes în exploatare în producție, susținem un număr mare de instalări RabbitMQ și ne-am confruntat cu necesitatea de a migra date dintr-un cluster în altul fără a avea întreruperi.
Această operațiune a fost necesară în cel puțin două situații:
- Transferul datelor dintr-un cluster RabbitMQ care nu este în Kubernetes într-un nou – deja «kubernetizat» (adică funcționând în poduri K8s) – cluster.
- Migrarea RabbitMQ în cadrul Kubernetes dintr-un namespace în altul (de exemplu, dacă contururile sunt delimitate de spații de nume, atunci pentru a transfera infrastructura dintr-un contur în altul).
Rețeta propusă în acest articol este orientată spre situații (dar nu se limitează doar la acestea) în care există un vechi cluster RabbitMQ (de exemplu, format din 3 noduri), care este fie deja în K8s, fie pe unele servere vechi. Acesta este folosit de o aplicație plasată în Kubernetes (fie deja acolo sau în perspectivă):

… și ne confruntăm cu sarcina de a-l migra în noul mediu de producție în Kubernetes.
La început, va fi descrisă abordarea generală a migrației, iar ulterior detaliile tehnice ale implementării acesteia.
Algoritmul de migrare
Primul pas, preliminar, înainte de orice acțiune – verificarea dacă în vechea instalare RabbitMQ este activat modul de înaltă disponibilitate (). Motivația este evidentă – nu dorim să pierdem date. Pentru a efectua această verificare, putem accesa interfața de administrare a RabbitMQ și, în tab-ul Admin → Policies, ne asigurăm că este setată valoarea ha-mode: all:

Următorul pas – ridicăm un nou cluster RabbitMQ în podurile Kubernetes (în cazul nostru, de exemplu, format din 3 noduri, dar numărul lor poate fi diferit).
După aceasta, combinăm vechiul și noul cluster RabbitMQ, obținând un singur cluster (format din 6 noduri):

Se inițiază procesul de sincronizare a datelor între vechiul și noul cluster RabbitMQ. După ce toate datele sunt sincronizate între toate nodurile din cluster, putem comuta aplicația pentru a folosi noul cluster:

După aceste operațiuni, este suficient să eliminăm din clusterul RabbitMQ vechile noduri, iar mutarea poate fi considerată finalizată:

Această schemă a fost aplicată de mai multe ori în producția noastră. Totuși, pentru confortul propriu, am implementat-o în cadrul unui sistem specializat, care distribuie configurații standard RMQ pe un număr mare de clustere Kubernetes. (pentru cei curioși: este vorba despre , despre care noi ). Mai jos vor fi prezentate instrucțiuni separate, pe care fiecare le poate aplica în instalările proprii pentru a testa propunerea în acțiune.
Să încercăm în practică
Cerințe
Ceriuile sunt foarte simple:
- Cluster Kubernetes (poate fi și minikube);
- Cluster RabbitMQ (poate fi implementat pe bare metal sau creat ca un cluster obișnuit în Kubernetes din graficul oficial Helm).
Pentru exemplul descris mai jos, am implementat RMQ în Kubernetes și l-am numit rmq-old.
Pregătirea standului
1. Vom descărca graficul Helm și îl vom edita puțin:
helm fetch --untar stable/rabbitmq-ha Pentru comoditate, stabilim parola, ErlangCookie și facem politica ha-all, astfel încât, implicit, coșurile să se sincronizeze între toate nodurile clusterului 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. Instalăm graficul:
helm install . --name rmq-old --namespace rmq-old3. Accesăm interfața de administrare RabbitMQ, creăm un nou coș și adăugăm câteva mesaje. Acestea vor fi necesare pentru a ne asigura că, după migrare, toate datele au fost păstrate și nu am pierdut nimic:
![]()
Standul de testare este gata: avem un RabbitMQ „vechi” cu datele care trebuie migrate.
Migrarea clusterului RabbitMQ
1. În primul rând, vom implementa un nou RabbitMQ în alt spațiu de nume cu aceleași ErlangCookie și parolă pentru utilizator. Pentru aceasta, vom efectua operațiile descrise mai sus, modificând comanda finală de instalare RMQ la următoarea:
helm install . --name rmq-new --namespace rmq-new2. Acum trebuie să unim noul cluster cu cel vechi. Pentru aceasta, accesăm fiecare dintre podurile noului RabbitMQ și executăm comenzile:
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 În variabila OLD_RMQ reprezintă adresa unuia dintre nodurile vechiului cluster RMQ.
Aceste comenzi vor opri nodul curent noului al clusterului RMQ, îl vor alătura vechiului cluster și îl vor reporni.
3. Clusterul RMQ din 6 noduri este gata:

Trebuie să așteptați până când mesajele se sincronizează între toate nodurile. Nu e greu de intuit că timpul de sincronizare a mesajelor depinde de puterea hardware-ului pe care este desfășurat clusterul și de numărul de mesaje. În cazul descris, sunt doar 10, așa că datele s-au sincronizat instantaneu, dar cu un număr suficient de mare de mesaje, sincronizarea poate dura ore întregi.
Așadar, starea sincronizării:

Aici +5 înseamnă că mesajele sunt deja încă pe 5 noduri (în afară de cel menționat în câmpul Node). Astfel, sincronizarea a avut loc cu succes.
4. Rămâne doar să schimbăm în aplicație adresa RMQ pe noul cluster (acțiunile specifice aici depind de tehnologia pe care o utilizați și de alte particularități ale aplicației), după care putem lua la revedere de la cel vechi.
Pentru ultima operațiune (adică deja după schimbarea aplicației pe noul cluster) intrăm pe fiecare nod vechiului al clusterului și executăm comenzile:
rabbitmqctl stop_app
rabbitmqctl resetClusterul a "uitat" de nodurile vechi: se poate șterge RMQ-ul vechi, iar migrarea va fi completă.
Notă: Dacă utilizați RMQ cu certificate, principial nimic nu se schimbă — procesul de migrare se va desfășura exact la fel.
Conclusions
Schema descrisă se potrivește practic pentru toate cazurile în care trebuie să mutăm RabbitMQ sau pur și simplu să ne transferăm într-un nou cluster.
În cazul nostru, dificultățile au apărut doar o dată, când RMQ-ul era accesat din multe locuri, iar noi nu aveam posibilitatea să schimbăm adresa RMQ la noua locație peste tot. Atunci am pornit un nou RMQ în același spațiu de nume cu etichete identice, astfel încât să intre sub serviciile și Ingress-urile deja existente, iar la pornirea podului am manipulat manual etichetele, eliminându-le la început pentru ca cererile să nu ajungă la RMQ-ul gol, și adăugându-le înapoi după sincronizarea mesajelor.
Am aplicat aceeași strategie și la actualizarea RabbitMQ la o nouă versiune cu o configurație modificată — totul a funcționat ca un ceas.
P.S.
Ca o continuare logică a acestui material, pregătim articole despre MongoDB (migrarea de pe un server fizic în Kubernetes) și MySQL (cum pregătim această SGBD în Kubernetes). Acestea vor fi publicate în lunile următoare.
P.P.S.
Citiți și în blogul nostru:
- «»;
- «».
Sursa: habr.com
