Migration transparente de RabbitMQ vers Kubernetes
RabbitMQ est un courtier de messages écrit en Erlang qui vous permet d'organiser un cluster de basculement avec une réplication complète des données sur plusieurs nœuds, où chaque nœud peut répondre aux demandes de lecture et d'écriture. Ayant de nombreux clusters Kubernetes en production, nous prenons en charge un grand nombre d'installations RabbitMQ et avons été confrontés à la nécessité de migrer les données d'un cluster à un autre sans temps d'arrêt.
Nous avons eu besoin de cette opération dans au moins deux cas :
Transfert de données d'un cluster RabbitMQ qui n'est pas situé dans Kubernetes vers un nouveau cluster – déjà « kubernetisé » (c'est-à-dire fonctionnant dans les pods K8s).
Migration de RabbitMQ au sein de Kubernetes d'un espace de noms à un autre (par exemple, si les circuits sont délimités par des espaces de noms, alors pour transférer l'infrastructure d'un circuit à un autre).
La recette proposée dans l'article se concentre sur les situations (mais ne s'y limite pas du tout) dans lesquelles il existe un ancien cluster RabbitMQ (par exemple, de 3 nœuds), situé soit déjà dans les K8, soit sur certains anciens serveurs. Une application hébergée sur Kubernetes (déjà là ou dans le futur) fonctionne avec :
... et nous sommes confrontés à la tâche de le migrer vers la nouvelle production dans Kubernetes.
Tout d’abord, l’approche générale de la migration elle-même sera décrite, puis les détails techniques de sa mise en œuvre seront décrits.
Algorithme de migration
La première étape, préliminaire, avant toute action consiste à vérifier que le mode haute disponibilité est activé dans l'ancienne installation de RabbitMQ (HA). La raison est évidente : nous ne voulons perdre aucune donnée. Pour effectuer cette vérification, vous pouvez accéder au panneau d'administration de RabbitMQ et dans l'onglet Admin → Politiques, assurez-vous que la valeur est définie ha-mode: all:
L'étape suivante consiste à créer un nouveau cluster RabbitMQ dans des pods Kubernetes (dans notre cas, par exemple, composé de 3 nœuds, mais leur nombre peut être différent).
Après cela, nous fusionnons l'ancien et le nouveau cluster RabbitMQ, obtenant un seul cluster (de 6 nœuds) :
Le processus de synchronisation des données entre l'ancien et le nouveau cluster RabbitMQ est lancé. Une fois toutes les données synchronisées entre tous les nœuds du cluster, nous pouvons changer l'application pour utiliser le nouveau cluster :
Après ces opérations, il suffit de supprimer les anciens nœuds du cluster RabbitMQ, et le déplacement peut être considéré comme terminé :
Nous avons utilisé ce schéma à plusieurs reprises en production. Cependant, pour notre propre commodité, nous l'avons implémenté dans un système spécialisé qui distribue les configurations RMQ standard sur plusieurs clusters Kubernetes. (pour les curieux : on parle de opérateur complémentairedont nous je viens de le dire récemment). Nous présenterons ci-dessous des instructions individuelles que chacun peut appliquer sur ses installations pour essayer la solution proposée en action.
Cluster RabbitMQ (peut être déployé sur du métal nu et créé comme un cluster standard dans Kubernetes à partir de la charte Helm officielle).
Pour l'exemple ci-dessous, j'ai déployé RMQ sur Kubernetes et je l'ai appelé rmq-old.
Préparation des stands
1. Téléchargez la charte Helm et modifiez-la un peu :
helm fetch --untar stable/rabbitmq-ha
Pour plus de commodité, nous définissons un mot de passe, ErlangCookie et faire de la politique ha-allafin que par défaut les files d'attente soient synchronisées entre tous les nœuds du cluster RMQ :
3. Accédez au panneau d'administration RabbitMQ, créez une nouvelle file d'attente et ajoutez plusieurs messages. Ils seront nécessaires pour qu'après la migration, nous puissions nous assurer que toutes les données sont préservées et que nous n'avons rien perdu :
Le banc de test est prêt : nous avons le « vieux » RabbitMQ avec les données à transférer.
Migration d'un cluster RabbitMQ
1. Tout d’abord, déployons le nouveau RabbitMQ dans autre espace de noms avec le mêmeErlangCookie et le mot de passe de l'utilisateur. Pour ce faire, nous effectuerons les opérations décrites ci-dessus, en modifiant la commande finale d'installation de RMQ comme suit :
helm install . --name rmq-new --namespace rmq-new
2. Vous devez maintenant fusionner le nouveau cluster avec l'ancien. Pour cela, rendez-vous sur chacun des pods nouveau RabbitMQ et exécutez les commandes :
En variable OLD_RMQ l'adresse d'un des nœuds est trouvée vieux Grappe RMQ.
Ces commandes arrêteront le nœud actuel nouveau Cluster RMQ, attachez-le à l'ancien cluster et relancez-le.
3. Le cluster RMQ de 6 nœuds est prêt :
Vous devez attendre que les messages soient synchronisés entre tous les nœuds. Il n'est pas difficile de deviner que le temps de synchronisation des messages dépend de la capacité du matériel sur lequel le cluster est déployé et du nombre de messages. Dans le scénario décrit, il n'y en a que 10, les données ont donc été synchronisées instantanément, mais avec un nombre de messages suffisamment important, la synchronisation peut durer des heures.
Donc, l'état de synchronisation :
il est +5 signifie que les messages sont déjà arrivés ещё sur 5 nœuds (sauf ce qui est indiqué dans le champ Node). La synchronisation a donc réussi.
4. Il ne reste plus qu'à basculer l'adresse RMQ de l'application vers le nouveau cluster (les actions spécifiques ici dépendent de la pile technologique que vous utilisez et d'autres spécificités de l'application), après quoi vous pourrez dire au revoir à l'ancienne.
Pour la dernière opération (c'est-à-dire déjà après basculer l'application vers un nouveau cluster) accédez à chaque nœud vieux cluster et exécutez les commandes :
rabbitmqctl stop_app
rabbitmqctl reset
Le cluster a « oublié » les anciens nœuds : vous pouvez supprimer l'ancien RMQ, auquel cas le déplacement sera terminé.
Noter: Si vous utilisez RMQ avec des certificats, rien ne change fondamentalement - le processus de déplacement sera effectué exactement de la même manière.
résultats
Le schéma décrit convient à presque tous les cas où nous devons migrer RabbitMQ ou simplement passer à un nouveau cluster.
Dans notre cas, les difficultés ne sont survenues qu'une seule fois, lorsque RMQ était accessible depuis de nombreux endroits, et nous n'avons pas eu la possibilité de changer l'adresse RMQ pour une nouvelle partout. Ensuite, nous avons lancé un nouveau RMQ dans le même espace de noms avec les mêmes étiquettes afin qu'il relève des services et entrées existants, et lors du lancement du pod, nous avons manipulé les étiquettes à la main, en les supprimant au début afin que les requêtes ne tombent pas sur le RMQ vide, et les rajouter une fois les messages synchronisés.
Nous avons utilisé la même stratégie lors de la mise à jour de RabbitMQ vers une nouvelle version avec une configuration modifiée : tout a fonctionné comme une horloge.
PS
Dans la continuité logique de ce matériel, nous préparons des articles sur MongoDB (migration d'un serveur matériel vers Kubernetes) et MySQL (comment nous préparons ce SGBD dans Kubernetes). Ils seront publiés dans les prochains mois.