
Cet article continue notre
récent matériel de migration RabbitMQ et est dédié à MongoDB. Étant donné que nous desservons de nombreux clusters Kubernetes et MongoDB, nous en sommes venus au besoin naturel de migrer les données d'une installation à une autre et de le faire sans interruption. Les principaux scénarios sont les mêmes: le portage de MongoDB d'un serveur virtuel / iron vers Kubernetes ou le portage de MongoDB au sein d'un cluster Kubernetes (d'un espace de noms à un autre).
Notre recette est destinée aux cas où l'ancien cluster MongoDB fonctionne (par exemple, de 3 nœuds et se trouve déjà dans K8s ou sur d'anciens serveurs) avec lesquels une application hébergée dans Kubernetes fonctionne:

Comment allons-nous transférer un tel cluster vers une nouvelle production à Kubernetes?
Théorie
L'algorithme de migration général est similaire à celui décrit dans la situation avec RabbitMQ.
Il est important de noter que la possibilité de se déplacer nécessite que les serveurs avec MongoDB et Kubernetes soient sur le même réseau. Les nœuds du cluster MongoDB communiqueront entre eux via l'IP des anciens serveurs (où se trouvent les anciennes installations MongoDB) et les noms DNS des pods de MongoDB dans K8s. Par conséquent, sur les serveurs Iron (avec les anciennes installations), il sera nécessaire de transférer les routes vers les pods, puis de les configurer pour utiliser le serveur DNS fonctionnant dans Kubernetes (ou d'enregistrer les noms nécessaires dans
/etc/hosts
, bien que dans le cas général, il vaut mieux éviter cette possibilité )
L'étape suivante consiste à augmenter le cluster MongoDB dans les pods Kubernetes. Dans notre cas, le cluster de base de données se compose de 3 nœuds et chaque nœud est situé dans un pod'8 K8 séparé - cependant, leur nombre peut être différent. Dans ConfigMap, vous devez spécifier l'adresse du maître MongoDB de l'ancienne installation: les nœuds MongoDB situés dans les pods dans K8 commenceront immédiatement la synchronisation avec lui.
Une fois tous les pods montés, un cluster MongoDB à 6 nœuds est formé:

Veuillez noter que les pods augmenteront pendant longtemps, car chaque pod démarre à son tour et, au moment du lancement, il synchronise les données de l'assistant.
Après cela, vous pouvez basculer l'application pour utiliser les nouveaux serveurs MongoDB:

Et il ne reste plus qu'à supprimer les anciens nœuds du cluster MongoDB, après quoi le déplacement peut être considéré comme terminé:

Nous utilisons souvent ce schéma en production et, pour la commodité de son utilisation, nous l'avons implémenté au sein du module
addon-operator (nous avons
récemment annoncé cet utilitaire), ce qui nous permet de distribuer des configurations MongoDB typiques sur de nombreux clusters. Nous prévoyons de publier nos modules dans un avenir proche, mais pour l'instant nous présentons des instructions distinctes avec lesquelles vous pouvez essayer la solution proposée en action et sans utiliser l'opérateur d'addon.
Nous essayons en pratique
Prérequis
Détails:
- Cluster Kubernetes (le minikube convient également);
- Cluster MongoDB (peut être déployé sur du métal nu et créé en tant que cluster régulier dans Kubernetes à partir du graphique Helm officiel).
Dans l'exemple décrit ci-dessous, l'ancien cluster avec MongoDB sera appelé
mongo-old
et installé dans le même cluster Kubernetes, où à l'avenir nous installerons le nouveau (
mongo-new
).
Préparation de l'ancien cluster
1. Pour un exemple qui illustre le schéma décrit en action, nous allons créer un «ancien» cluster MongoDB (c'est-à-dire sujet à migration) directement dans Kubernetes (en réalité, il peut également être situé sur des serveurs distincts en dehors des K8). Pour ce faire, téléchargez le tableau Helm:
helm fetch --untar stable/mongodb-replicaset
... et modifiez-le un peu en configurant l'autorisation:
auth: enabled: true adminUser: mongo adminPassword: pa33w0rd # metricsUser: metrics # metricsPassword: password # key: keycontent # existingKeySecret: # existingAdminSecret: # exisitingMetricsSecret:
Dans
values.yaml
vous pouvez également configurer des certificats et bien plus encore.
2. Définissez le graphique:
helm install . --name mongo-old --namespace mongo-old
Après cela, la "vieille" installation de test de MongoDB sera lancée:
kubectl --namespace=mongo-old get pods

Allons au pod avec son maître et créons une base de test:
kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo use admin db.auth('mongo','password') use music db.artists.insert({ artistname: "The Tea Party" }) show dbs

En entrant dans différents pods, j'ai découvert que le maître est
mongo-old-mongodb-replicaset-0
. Cependant, pour une solution plus pratique à ce problème, après avoir installé le Helm-chart, une commande s'affiche sur la façon de déterminer
MASTER_POD
. Dans mon cas (pour
mongo-old
de 3 nœuds), cela ressemble à ceci:
for ((i = 0; i < 3; ++i)); do kubectl exec --namespace mongo-old mongo-old-mongodb-replicaset-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; done
Sur ce point, la préparation de l'ancienne installation MongoDB, dont les données seront transférées, est prête.
Migration de cluster MongoDB
Nous allons maintenant déployer la nouvelle installation MongoDB, qui sera située à Kubernetes et utilisée par l'application en production.
NB : Veuillez noter que la même version de MongoDB doit être utilisée comme auparavant. Sinon, il existe un risque de problèmes de compatibilité.Par analogie avec la section précédente (où nous avons imité la «vieille» installation de MongoDB), nous prenons le Helm-chart déjà mentionné (en utilisant la
helm fetch
) et configurons l'autorisation, ainsi que d'autres paramètres, s'ils sont utilisés. De plus, nous corrigerons le fichier
init/on-start.sh
en lui ajoutant temporairement à la ligne 165 l'adresse de l'assistant obtenue à l'étape précédente (ou connue de vous en installant MongoDB sur des serveurs séparés):
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'
Nous sommes prêts à créer une nouvelle installation MongoDB:
helm install . --name mongo-new --namespace mongo-new
Nous attendons le démarrage de tous les pods (s'il y a beaucoup de données, leur lancement peut prendre des heures):

Maintenant, nous faisons
exec
dans un nouveau pod et regardons la liste des bases:
kubectl --namespace=mongo-new exec -ti mongo-new-mongodb-replicaset-0 mongo

Deux clusters MongoDB sont combinés en un seul, composé de 6 nœuds.
Pour le moment, vous pouvez déjà basculer l'application vers un nouveau cluster, mais il reste quelques étapes pour terminer la migration.
Du
init/on-start.sh
dans la nouvelle installation, nous
init/on-start.sh
la ligne que nous avons ajoutée:
peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'
Passons maintenant à l'ancien maître du cluster et «le renversons» - puis un nouveau maître sera affecté dans le cluster. Nous entrons dans le pod avec le maître MongoDB:
kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo use admin db.auth('mongo','password')
Après cela, nous changeons les priorités des nœuds et changeons l'assistant:
cfg = rs.conf() cfg.members[5].priority = 2 rs.reconfig(cfg) rs.stepDown(120)
Le nœud actuel a cessé d'être un maître - une nouvelle élection aura lieu. Comme nous avons changé de priorité, le nœud dont nous avons besoin deviendra le maître.
NB : Par défaut, tous les nœuds MongoDB ont une priorité de 1. Ci-dessus, nous élevons à 2 la priorité du nœud dont nous avons besoin. Ainsi, un membre d'un nouveau cluster deviendra certainement un maître commun. Vous pouvez en savoir plus sur le fonctionnement de ces mécanismes dans MongoDB dans la documentation .Désactivez l'ancienne installation MongoDB, puis accédez au nouvel assistant et supprimez les anciens nœuds:
rs.remove("mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017") rs.remove("mongo-old-mongodb-replicaset-1.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017") rs.remove("mongo-old-mongodb-replicaset-2.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")
Après cela, la migration peut être considérée comme terminée: nous sommes passés avec succès de l'ancien cluster MongoDB au nouveau!
Résumé
Le schéma décrit convient à presque tous les cas lorsque vous devez transférer MongoDB ou simplement passer à un nouveau cluster.
La principale nuance pendant le transfert est peut-être la nécessité de transmettre les adresses IP des nouveaux pods aux serveurs de l'ancienne installation MongoDB, si elle est en dehors des K8, et de les nommer correctement dans DNS (ou
/etc/hosts
). Dans l'exemple, ces étapes n'étaient pas requises, car la migration s'est produite entre différents espaces de noms du même cluster Kubernetes.
PS
Lisez aussi dans notre blog: