RabbitMQ je zprostředkovatel zpráv napsaný v Erlangu, který vám umožňuje organizovat cluster s podporou převzetí služeb při selhání s plnou replikací dat napříč více uzly, kde každý uzel může obsluhovat požadavky na čtení a zápis. Díky mnoha clusterům Kubernetes v produkčním provozu podporujeme velké množství instalací RabbitMQ a museli jsme čelit potřebě migrovat data z jednoho clusteru do druhého bez prostojů.
Tuto operaci jsme potřebovali minimálně ve dvou případech:
Přenos dat z RabbitMQ clusteru, který se nenachází v Kubernetes, do nového – již „kubernetizovaného“ (tj. fungujícího v K8s podech) – clusteru.
Migrace RabbitMQ v rámci Kubernetes z jednoho jmenného prostoru do druhého (například pokud jsou okruhy vymezeny jmennými prostory, pak k přenosu infrastruktury z jednoho okruhu do druhého).
Recept navržený v článku je zaměřen na situace (ale není na ně vůbec omezen), ve kterých existuje starý cluster RabbitMQ (například se 3 uzly), umístěný buď již v K8 nebo na některých starých serverech. Aplikace hostovaná na Kubernetes (již tam nebo v budoucnu) s ním pracuje:
... a stojíme před úkolem migrovat to do nové produkce v Kubernetes.
Nejprve bude popsán obecný přístup k samotné migraci a poté budou popsány technické detaily její implementace.
Migrační algoritmus
První, předběžnou fází před jakoukoli akcí je zkontrolovat, zda je ve staré instalaci RabbitMQ povolen režim vysoké dostupnosti (HA). Důvod je zřejmý – nechceme přijít o žádná data. Chcete-li provést tuto kontrolu, přejděte na panel správce RabbitMQ a na kartě Správce → Zásady se ujistěte, že je nastavena hodnota ha-mode: all:
Dalším krokem je vytvoření nového RabbitMQ clusteru v Kubernetes podech (v našem případě se například skládá ze 3 uzlů, ale jejich počet se může lišit).
Poté sloučíme staré a nové klastry RabbitMQ a získáme jeden klastr (se 6 uzly):
Je zahájen proces synchronizace dat mezi starým a novým clusterem RabbitMQ. Jakmile jsou všechna data synchronizována mezi všemi uzly v clusteru, můžeme přepnout aplikaci, aby používala nový cluster:
Po těchto operacích stačí odstranit staré uzly z clusteru RabbitMQ a přesun lze považovat za dokončený:
Toto schéma jsme ve výrobě použili mnohokrát. Pro naše vlastní pohodlí jsme jej však implementovali v rámci specializovaného systému, který distribuuje standardní konfigurace RMQ napříč několika clustery Kubernetes. (pro ty, kteří jsou zvědaví: mluvíme o addon-operátoro kterých my nedávno řekl). Níže představíme jednotlivé pokyny, které může kdokoli aplikovat na své instalace a vyzkoušet si navrhované řešení v akci.
Pojďme si to vyzkoušet v praxi
Požadavky
Podrobnosti jsou velmi jednoduché:
cluster Kubernetes (bude také fungovat minikube);
Cluster RabbitMQ (lze nasadit na holý kov a vytvořit jako běžný cluster v Kubernetes z oficiálního grafu Helm).
Pro příklad níže jsem nasadil RMQ do Kubernetes a zavolal jsem to rmq-old.
Příprava stojanu
1. Stáhněte si tabulku Helm a trochu ji upravte:
helm fetch --untar stable/rabbitmq-ha
Pro pohodlí jsme nastavili heslo, ErlangCookie a dělat politiku ha-alltakže ve výchozím nastavení jsou fronty synchronizovány mezi všemi uzly clusteru RMQ:
3. Přejděte do administračního panelu RabbitMQ, vytvořte novou frontu a přidejte několik zpráv. Budou potřeba, abychom se po migraci mohli ujistit, že všechna data jsou zachována a nic jsme neztratili:
Testovací stolice je připravena: máme „starý“ RabbitMQ s daty, která je třeba přenést.
Migrace clusteru RabbitMQ
1. Nejprve nasadíme nový RabbitMQ příteli jmenný prostor s stejnýErlangCookie a heslo pro uživatele. Za tímto účelem provedeme operace popsané výše a změníme konečný příkaz pro instalaci RMQ na následující:
helm install . --name rmq-new --namespace rmq-new
2. Nyní musíte sloučit nový cluster se starým. Chcete-li to provést, přejděte ke každému z podů nové RabbitMQ a spusťte příkazy:
V proměnné OLD_RMQ je nalezena adresa jednoho z uzlů starý RMQ cluster.
Tyto příkazy zastaví aktuální uzel nové Cluster RMQ, připojte jej ke starému clusteru a znovu jej spusťte.
3. Cluster RMQ 6 uzlů je připraven:
Musíte počkat, než se zprávy synchronizují mezi všemi uzly. Není těžké uhodnout, že doba synchronizace zpráv závisí na kapacitě hardwaru, na kterém je cluster nasazen, a na počtu zpráv. V popsaném scénáři je jich pouze 10, takže data byla synchronizována okamžitě, ale při dostatečně velkém počtu zpráv může synchronizace trvat hodiny.
Takže stav synchronizace:
Zde +5 znamená, že zprávy již jsou více na 5 uzlech (kromě toho, co je uvedeno v poli Node). Synchronizace tedy proběhla úspěšně.
4. Zbývá pouze přepnout adresu RMQ v aplikaci na nový cluster (konkrétní akce zde závisí na technologickém zásobníku, který používáte, a dalších specifikách aplikace), načež se můžete se starým rozloučit.
Na poslední operaci (tj po přepnutí aplikace do nového clusteru) přejděte do každého uzlu starý cluster a spusťte příkazy:
rabbitmqctl stop_app
rabbitmqctl reset
Cluster „zapomněl“ na staré uzly: můžete odstranit staré RMQ, v tomto okamžiku bude přesun dokončen.
Poznámka: Pokud používáte RMQ s certifikáty, pak se nic zásadně nemění - proces přesunu bude probíhat úplně stejně.
Závěry
Popsané schéma je vhodné téměř pro všechny případy, kdy potřebujeme migrovat RabbitMQ nebo jednoduše přejít do nového clusteru.
V našem případě nastaly potíže pouze jednou, kdy se k RMQ přistupovalo z mnoha míst a ne všude jsme měli možnost změnit adresu RMQ na novou. Poté jsme spustili nové RMQ ve stejném jmenném prostoru se stejnými štítky, aby spadalo pod stávající služby a Ingresses, a při spouštění modulu jsme ručně manipulovali štítky a odstranili je na začátku, aby požadavky nepadaly na prázdné RMQ a jejich přidání zpět po synchronizaci zpráv.
Stejnou strategii jsme použili při aktualizaci RabbitMQ na novou verzi se změněnou konfigurací – vše fungovalo jako hodinky.
PS
Jako logické pokračování tohoto materiálu připravujeme články o MongoDB (migrace z hardwarového serveru na Kubernetes) a MySQL (jak tento DBMS připravujeme uvnitř Kubernetes). Budou zveřejněny v následujících měsících.