RabbitMQ je broker poruka napisan u Erlangu koji vam omogućuje organiziranje failover klastera s potpunom replikacijom podataka na više čvorova, gdje svaki čvor može servisirati zahtjeve za čitanje i pisanje. Budući da imamo mnogo Kubernetes klastera u proizvodnom radu, podržavamo veliki broj RabbitMQ instalacija i bili smo suočeni s potrebom da migriramo podatke s jednog klastera na drugi bez prekida rada.
Ova nam je operacija bila potrebna u najmanje dva slučaja:
Prijenos podataka iz RabbitMQ klastera koji se ne nalazi u Kubernetesu u novi – već “kubernetiziran” (tj. koji radi u K8s podovima) – klaster.
Migracija RabbitMQ-a unutar Kubernetesa iz jednog prostora imena u drugi (na primjer, ako su krugovi razgraničeni prostorima imena, tada za prijenos infrastrukture iz jednog kruga u drugi).
Recept predložen u članku fokusiran je na situacije (ali nije uopće ograničen na njih) u kojima postoji stari RabbitMQ klaster (na primjer, od 3 čvora), koji se već nalazi u K8s ili na nekim starim poslužiteljima. Aplikacija koja se nalazi na Kubernetesu (već tamo ili u budućnosti) radi s njim:
... i suočeni smo sa zadatkom da ga preselimo u novu proizvodnju u Kubernetesu.
Najprije će biti opisan opći pristup samoj migraciji, a nakon toga će biti opisani tehnički detalji njezine provedbe.
Algoritam migracije
Prva, preliminarna faza prije bilo kakve akcije je provjeriti je li način visoke dostupnosti omogućen u staroj RabbitMQ instalaciji (HA). Razlog je očit - ne želimo izgubiti podatke. Da biste izvršili ovu provjeru, možete otići na RabbitMQ administratorsku ploču i na kartici Admin → Pravila provjeriti je li vrijednost postavljena ha-mode: all:
Sljedeći korak je podizanje novog RabbitMQ klastera u Kubernetes podovima (u našem slučaju, na primjer, sastoji se od 3 čvora, ali njihov broj može biti drugačiji).
Nakon toga spajamo stare i nove RabbitMQ klastere, dobivajući jedan klaster (od 6 čvorova):
Pokrenut je proces sinkronizacije podataka između starog i novog RabbitMQ klastera. Nakon što su svi podaci sinkronizirani između svih čvorova u klasteru, možemo prebaciti aplikaciju da koristi novi klaster:
Nakon ovih operacija dovoljno je ukloniti stare čvorove iz RabbitMQ klastera i premještanje se može smatrati završenim:
Ovu shemu koristili smo mnogo puta u proizvodnji. Međutim, radi vlastite udobnosti, implementirali smo ga unutar specijaliziranog sustava koji distribuira standardne RMQ konfiguracije na više Kubernetes klastera (za one koji su znatiželjni: govorimo o addon-operatoro kojoj mi tek nedavno rečeno). U nastavku ćemo predstaviti pojedinačne upute koje svatko može primijeniti na svojim instalacijama kako bi isprobao predloženo rješenje na djelu.
Probajmo to u praksi
Zahtjevi
Detalji su vrlo jednostavni:
Kubernetes klaster (minikube će također raditi);
RabbitMQ klaster (može se implementirati na goli metal i napraviti kao obični klaster u Kubernetesu iz službene karte Helm).
Za primjer u nastavku, implementirao sam RMQ u Kubernetes i nazvao ga rmq-old.
Priprema postolja
1. Skinite Helm grafikon i malo ga uredite:
helm fetch --untar stable/rabbitmq-ha
Radi praktičnosti postavili smo lozinku, ErlangCookie i praviti politiku ha-alltako da su prema zadanim postavkama redovi čekanja sinkronizirani između svih čvorova RMQ klastera:
3. Idite na RabbitMQ administratorsku ploču, kreirajte novi red i dodajte nekoliko poruka. Bit će nam potrebni kako bismo nakon migracije bili sigurni da su svi podaci sačuvani i da nismo ništa izgubili:
Testni stol je spreman: imamo “stari” RabbitMQ s podacima koje je potrebno prenijeti.
Migracija RabbitMQ klastera
1. Prvo, implementirajmo novi RabbitMQ prijatelju imenski prostor sa istiErlangCookie i lozinku za korisnika. Da bismo to učinili, izvršit ćemo gore opisane operacije, mijenjajući konačnu naredbu za instalaciju RMQ-a u sljedeće:
helm install . --name rmq-new --namespace rmq-new
2. Sada morate spojiti novi klaster sa starim. Da biste to učinili, idite na svaku od mahuna novi RabbitMQ i izvršite naredbe:
U varijabli OLD_RMQ pronađena je adresa jednog od čvorova star RMQ klaster.
Ove naredbe će zaustaviti trenutni čvor novi RMQ klaster, priključite ga na stari klaster i ponovno ga pokrenite.
3. RMQ klaster od 6 čvorova je spreman:
Morate pričekati dok se poruke sinkroniziraju između svih čvorova. Nije teško pogoditi da vrijeme sinkronizacije poruka ovisi o kapacitetu hardvera na kojem je klaster raspoređen te o broju poruka. U opisanom scenariju ima ih samo 10, pa su podaci sinkronizirani trenutno, ali uz dovoljno velik broj poruka sinkronizacija može trajati satima.
Dakle, status sinkronizacije:
Ovdje +5 znači da su poruke već stigle više na 5 čvorova (osim onoga što je naznačeno u polju Node). Dakle, sinkronizacija je uspjela.
4. Sve što preostaje je prebaciti RMQ adresu u aplikaciji na novi klaster (konkretne radnje ovdje ovise o tehnološkom nizu koji koristite i drugim specifičnostima aplikacije), nakon čega se možete pozdraviti sa starom.
Za posljednju operaciju (tj. već nakon prebacivanje aplikacije na novi klaster) idite na svaki čvor star klasterirati i izvršiti naredbe:
rabbitmqctl stop_app
rabbitmqctl reset
Klaster je "zaboravio" na stare čvorove: možete izbrisati stari RMQ i tada će premještanje biti dovršeno.
Primijetiti: Ako koristite RMQ s certifikatima, tada se ništa suštinski ne mijenja - proces premještanja će se provesti potpuno isto.
Zaključci
Opisana shema je prikladna za gotovo sve slučajeve kada trebamo migrirati RabbitMQ ili se jednostavno preseliti na novi klaster.
U našem slučaju, poteškoće su se pojavile samo jednom, kada se RMQ-u pristupilo s mnogo mjesta, a nismo svugdje imali priliku promijeniti RMQ adresu u novu. Zatim smo pokrenuli novi RMQ u istom prostoru imena s istim oznakama kako bi potpao pod postojeće servise i ulaze, a prilikom pokretanja pod-a ručno smo manipulirali oznakama uklanjajući ih na početku kako zahtjevi ne bi padali na prazan RMQ i njihovo ponovno dodavanje nakon što se poruke sinkroniziraju.
Istu smo strategiju koristili prilikom ažuriranja RabbitMQ-a na novu verziju s promijenjenom konfiguracijom - sve je radilo kao sat.
PS
Kao logičan nastavak ovog materijala, pripremamo članke o MongoDB (migracija s hardverskog poslužitelja na Kubernetes) i MySQL (kako pripremamo ovaj DBMS unutar Kubernetesa). Oni će biti objavljeni u narednim mjesecima.