Concept
Compte tenu de l'architecture mise en place et du nombre élevé de démons qui entrent en compte dans le fonctionnement d'un cluster MongoDB, la maintenance et la résolution des problèmes peut être complexe.
Cette page recense et détaille les opérations de maintenance et des recherches/résolutions de problèmes courants.
Vérification de l'état d'un cluster MongoDB
La vérification de l'état d'un cluster MongoDB peut se faire de plusieurs manières :
- En vérifiant l'état des services Linux et les logs.
- Directement via la console MongoDB.
- Par les checks MongoDB livrés avec Shinken Entreprise.
Services Linux
Avant de vérifier l'état détaillé du cluster MongoDB avec la console MongoDB ou les checks Shinken, on peut d'abord commencer par vérifier, sur chaque nœud, l'état des services Linux associés aux différents démons MongoDB.
$ systemctl status mongod
● mongod.service - SYSV: Mongo is a scalable, document-oriented database.
Loaded: loaded (/etc/rc.d/init.d/mongod; bad; vendor preset: disabled)
Active: active (running) since Tue 2019-10-22 16:39:52 CEST; 6min ago
Docs: man:systemd-sysv-generator(8)
Process: 908 ExecStart=/etc/rc.d/init.d/mongod start (code=exited, status=0/SUCCESS)
Main PID: 1037 (mongod)
CGroup: /system.slice/mongod.service
└─1037 /usr/bin/mongod -f /etc/mongod.conf --smallfiles
Oct 22 16:39:48 lab-mongo1 systemd[1]: Starting SYSV: Mongo is a scalable, document-oriented database....
Oct 22 16:39:48 lab-mongo1 runuser[979]: pam_unix(runuser:session): session opened for user mongod by (uid=0)
Oct 22 16:39:52 lab-mongo1 runuser[979]: pam_unix(runuser:session): session closed for user mongod
Oct 22 16:39:52 lab-mongo1 mongod[908]: Starting mongod: [ OK ]
Oct 22 16:39:52 lab-mongo1 systemd[1]: Started SYSV: Mongo is a scalable, document-oriented database..
$ systemctl status mongo-configsrv
● mongo-configsrv.service - SYSV: Mongo is a scalable, document-oriented database.
Loaded: loaded (/etc/rc.d/init.d/mongo-configsrv; bad; vendor preset: disabled)
Active: active (running) since Tue 2019-10-22 16:39:51 CEST; 6min ago
Docs: man:systemd-sysv-generator(8)
Process: 906 ExecStart=/etc/rc.d/init.d/mongo-configsrv start (code=exited, status=0/SUCCESS)
Main PID: 1034 (mongod)
CGroup: /system.slice/mongo-configsrv.service
└─1034 /usr/bin/mongod -f /etc/mongo-configsrv.conf --smallfiles
Oct 22 16:39:48 lab-mongo1 systemd[1]: Starting SYSV: Mongo is a scalable, document-oriented database....
Oct 22 16:39:48 lab-mongo1 runuser[975]: pam_unix(runuser:session): session opened for user mongod by (uid=0)
Oct 22 16:39:51 lab-mongo1 runuser[975]: pam_unix(runuser:session): session closed for user mongod
Oct 22 16:39:51 lab-mongo1 mongo-configsrv[906]: Starting mongod: [ OK ]
Oct 22 16:39:51 lab-mongo1 systemd[1]: Started SYSV: Mongo is a scalable, document-oriented database..
$ systemctl status mongos
● mongos.service - SYSV: Mongo is a scalable, document-oriented database.
Loaded: loaded (/etc/rc.d/init.d/mongos; bad; vendor preset: disabled)
Active: active (running) since Tue 2019-10-22 16:47:29 CEST; 28s ago
Docs: man:systemd-sysv-generator(8)
Process: 2110 ExecStart=/etc/rc.d/init.d/mongos start (code=exited, status=0/SUCCESS)
Main PID: 2127 (mongos)
CGroup: /system.slice/mongos.service
└─2127 /usr/bin/mongos -f /etc/mongos.conf
Oct 22 16:46:47 lab-mongo1 systemd[1]: Starting SYSV: Mongo is a scalable, document-oriented database....
Oct 22 16:46:47 lab-mongo1 runuser[2123]: pam_unix(runuser:session): session opened for user mongod by (uid=0)
Oct 22 16:47:29 lab-mongo1 mongos[2110]: Starting mongos: [ OK ]
Oct 22 16:47:29 lab-mongo1 systemd[1]: Started SYSV: Mongo is a scalable, document-oriented database..
Lorsqu'un démon du cluster n'est pas correctement démarré, on peut commencer les recherches en analysant les logs de chaque démon du cluster MongoDB.
Sur chaque nœud du cluster, on trouve les logs suivants :
- Démon mongod: /var/log/mongodb/mongod.log.
- Démon mongo-configsrv: /var/log/mongodb/mongo-configsrv.log.
- Démon mongos: /var/log/mongodb/mongos.log.
Console MongoDB
La console MongoDB permet de récupérer des informations détaillées sur l'état de chaque démon ainsi que leur statut au sein du cluster ( primaire, secondaire, en récupération, injoignable … ).
Pour accéder à la console MongoDB, il faut se connecter depuis n'importe quel nœud du cluster sur le démon "mongod" avec la commande suivante :
mongo --port 27018
En fonction de la configuration du MongoDB ( cluster, mot de passe, port ... ) il peut être nécessaire de fournir des options de connexion supplémentaire à cette commande ( voir la page MongoDB - options de connexion à la base des commandes MongoDB ).
Pour vérifier l'état du cluster, exécuter la commande :
rs.status()
On obtient le résultat suivant :
rs-shinken:SECONDARY> rs.status();
{
"set" : "rs-shinken",
"date" : ISODate("2018-05-04T07:29:15Z"),
"myState" : 2,
"syncingTo" : "node2:27018",
"members" : [
{
"_id" : 0,
"name" : "node1:27018",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : Timestamp(0, 0),
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2018-05-04T07:29:13Z"),
"lastHeartbeatRecv" : ISODate("1970-01-01T00:00:00Z"),
"pingMs" : 0
},
{
"_id" : 1,
"name" : "node2:27018",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 81988,
"optime" : Timestamp(1525250222, 106),
"optimeDate" : ISODate("2018-05-02T08:37:02Z"),
"lastHeartbeat" : ISODate("2018-05-04T07:29:14Z"),
"lastHeartbeatRecv" : ISODate("2018-05-04T07:29:14Z"),
"pingMs" : 1,
"electionTime" : Timestamp(1525336975, 1),
"electionDate" : ISODate("2018-05-03T08:42:55Z")
},
{
"_id" : 2,
"name" : "node3:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 81988,
"optime" : Timestamp(1525250222, 106),
"optimeDate" : ISODate("2018-05-02T08:37:02Z"),
"self" : true
}
],
"ok" : 1
}
Avec l'affichage ci-dessus, on tire par exemple les informations suivantes sur notre cluster :
- Le cluster comporte 3 nœuds ( node1, node2, node3 ).
- Le nœud node2 est le nœud primaire, et le nœud node3 est un nœud secondaire.
- Le nœud node1 n'est pas joignable.
- Le nœud node2 a été élu comme nœud primaire le à 07h29 (GMT).
Checks Shinken
Un cluster MongoDB peut être supervisé avec Shinken. Shinken Entreprise met à disposition un pack MongoDB ( voir la page Pack MongoDB ).
Le modèle d'hôte "mongodb" prend également en compte les aspects de réplication de la base avec les checks "Mongodb-replicaset" et "Mongodb-replication-lag".
En pratique, pour superviser un cluster MongoDB avec Shinken Entreprise, on associe un hôte Shinken à un nœud du cluster. Chaque hôte aura le modèle "mongodb" accroché, ce qui permet de superviser ces 3 nœuds de manière indépendante. On effectue par ailleurs la supervision sur le port 27018 au lieu du port 27017 utilisé par défaut.
Voici un aperçu du résultat des checks concernant la réplication de MongoDB, pour un nœud primaire et pour un nœud secondaire :
Le modèle mongodb permet d'utiliser un tunnel SSH pour la connexion aux serveurs et l'exécution des checks. L'utilisation du tunnel SSH se fait en modifiant la donnée MONGO_CONNECTION_METHOD en lui donnant la valeur "ssh" au lieu de "direct".
L'utilisateur et la clé SSH utilisés pour créer ce tunnel peuvent se configurer en modifiant les données MONGO_SSH_USER et MONGO_SSH_KEY sur l'hôte.
Le modèle mongodb se connecte aux démons mongod pour effectuer les vérifications sur le cluster MongoDB.
Dans une installation classique, ce démon utilise le port 27017.
Dans le cas du cluster, il est configuré pour utiliser le port 27018.
Il faut donc également modifier la donnée MONGO_PORT en 27018 sur l'hôte pour que Shinken utilise le bon port lors du check .
La configuration et le fonctionnement du pack MongoDB sont décrits en détail sur la page de documentation du pack MongoDB ( voir la page Pack MongoDB ).
Manipulation d'un cluster MongoDB
Redémarrage du cluster
Les démons du cluster MongoDB sont dépendants les uns des autres et doivent être démarrés dans un ordre particulier pour pouvoir fonctionner.
Pour rappel, chaque nœud du cluster contient les démons MongoDB suivants :
- mongod: responsable du stockage des données
- mongo-configsrv: gère la configuration des éléments du cluster
- mongos: sert d'interface à Shinken et route les requêtes reçues à l'intérieur du cluster Mongo
L'ordre de démarrage des démons est le suivant : mongod → mongo-configsrv → mongos
- On démarre le démon mongod en premier, qui s'occupe de stocker les données.
- On démarre ensuite le démon mongo-configsrv.
- On démarre enfin le démon mongos, qui a besoin du démon mongo-configsrv pour pouvoir démarrer.
La séquence de démarrage est donc la suivante :
Sur tous les nœuds du cluster, on démarre mongod:
systemctl start mongod
Sur tous les nœuds du cluster, on démarre ensuite mongo-configsrv:
systemctl start mongo-configsrv
Enfin, sur les machines clientes ( serveur Shinken ) on démarre le démon mongos:
systemctl start mongos
L'extinction des démons du cluster peut se faire dans n'importe quel ordre. Le redémarrage des démons sur un seul nœud suit également le même ordre de démarrage.
Résolution des problèmes
Erreurs lors du redémarrage des démons
Lorsqu'un démon MongoDB démarre, il écrit dans :
- /var/run sous Debian 13
- /var/run/mongodb sous RHEL / CentOS / Alma / Rocky
Un fichier .pid qui contient le PID du processus associé ( mongod.pid pour le démon mongod, mongos.pid pour le démon mongos et mongo-configsrv.pid pour le démon mongo-configsrv ). Les scripts de démarrage des démons MongoDB appelés lors de la gestion des démons avec "service" ou "systemctl" se basent sur ces fichiers PID pour la manipulation du démon.
Ce mécanisme permet aux scripts d'initialisation livrés avec MongoDB de redémarrer ou d'arrêter les démons MongoDB concernés.
Cependant, ce mécanisme a quelques failles :
- Lorsqu'un démon refuse de démarrer ou qu'il s'arrête de manière imprévue ( suite à un plantage ou tué par le système ), le fichier PID associé peut ne pas être nettoyé et être toujours présent alors que le démon n'est plus en fonctionnement
- Lors du démarrage d'un démon via les scripts d'initialisation ( ou commandes service/systemctl ), la présence d'un fichier PID empêche le démarrage du démon ( sous RHEL / CentOS / Alma / Rocky ).
Dans ce cas, on voit dans les logs donnés par journalctl le message suivant ( on prend ici mongos pour l'exemple ) :
-- Unit mongos.service has begun starting up. Oct 23 10:22:34 mongo-primaire mongos[5174]: Error starting mongos. /var/run/mongodb/mongos.pid exists. Oct 23 10:22:34 mongo-primaire systemd[1]: mongos.service: control process exited, code=exited status=1 Oct 23 10:22:34 mongo-primaire systemd[1]: Failed to start SYSV: Mongo is a scalable, document-oriented database.. -- Subject: Unit mongos.service has failed -- Defined-By: systemd -- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel -- -- Unit mongos.service has failed. -- -- The result is failed. Oct 23 10:22:34 mongo-primaire systemd[1]: Unit mongos.service entered failed state. Oct 23 10:22:34 mongo-primaire systemd[1]: mongos.service failed. Oct 23 10:22:34 mongo-primaire polkitd[631]: Unregistered Authentication Agent for unix-process:5168:1290264 (system bus name :1.1560, object path /org/freedesktop/PolicyKit1/AuthenticationA
La résolution de ce problème se fait en 2 temps :
- La présence d'un fichier PID alors que le démon n'est pas démarré témoigne d'un problème au niveau du démon concerné. Il faut avant de pouvoir redémarrer le démon enquêter sur la cause d'extinction du démon. Pour cette recherche, on peut regarder aux endroits suivants :
- Logs du démon, localisés dans /var/log/mongodb
- Logs du système : /var/log/messages ou bien avec la commande 'dmesg -T'
- Une fois le problème identifié et géré, on peut supprimer le fichier correspondant ( dans /var/run/mongodb ou /var/run selon la distribution ) et redémarrer le démon MongoDB.
Cette procédure est identique pour l'ensemble des démons qui constituent le cluster ( mongod, mongos, mongo-configsrv ).
Un fichier PID est également créé et non supprimé par MongoDB lorsqu'un démon refuse de démarrer correctement, par exemple dans le cas d'une configuration incorrecte. On a dans ce cas le comportement suivant :
- Le démon MongoDB en question démarre. Il écrit un fichier PID et commence son processus de démarrage.
- Il détecte une erreur ( configuration incorrecte par exemple ) et s'arrête sans supprimer le fichier PID
Dans ce cas, il faudra supprimer le fichier PID généré par le démon pour pouvoir le redémarrer.
Resynchronisation manuelle d'un noeud Mongodb
Symptômes
Suite à une interruption sur un des nœuds du cluster, on peut observer les erreurs suivantes.
La première est qu'un des nœuds reste bloqué dans un état "RECOVERING". Cette information peut être obtenue via les checks du pack Mongodb, ou bien via la console MongoDB avec la commande "rs.status()'.
la sortie de la commande rs.status() ressemble à ceci pour le nœud en erreur :
{
"_id" : 4,
"name" : "55.55.55.55:27017",
"health" : 1,
"state" : 3,
"stateStr" : "RECOVERING",
"uptime" : 502511,
"optime" : {
"t" : 1340841938000,
"i" : 5028
},
"optimeDate" : ISODate("2012-06-28T00:05:38Z"),
"lastHeartbeat" : ISODate("2012-08-22T22:47:00Z"),
"pingMs" : 0,
"errmsg" : "error RS102 too stale to catch up"
},
On peut également observer une erreur similaire dans les logs du démon mongod ( /var/log/mongodb/mongod.log ) sur le nœud en état RECOVERING:
replSet error RS102 too stale to catch up
Explications
Lors de l'utilisation de la réplication de données dans un cluster MongoDB, MongoDB enregistre dans un log d'opérations ( oplog ) les différentes requêtes effectuées dans le cluster. Pour s'assurer que les données enregistrées soient bien synchronisées, chaque entrée du log d'opération est rejoué sur tous les autres nœuds. De cette manière, on s'assure que chaque nœud possède bien les mêmes données.
Lors d'une interruption sur un des nœuds du cluster, ce log d'opérations s'agrandit jusqu'à atteindre sa taille maximale. À ce moment-là, les nouvelles requêtes effectuées sur le cluster sont écrites dans le log d'opérations, mais en écrasant les requêtes les plus anciennes.
Quand le nœud en erreur est remis en état et redémarre correctement, il ne peut pas se resynchroniser au niveau des données stockées puisqu'une partie des requêtes les plus anciennes a été écrasée. On observe dans ce cas l'erreur et les logs mentionnés précédemment :
- Le nœud démarre correctement, mais reste bloqué en état "RECOVERING"
- L'erreur "too stale to catch up" apparaît dans les logs du démon mongod du nœud Mongo en question
Il faut donc arriver à resynchroniser manuellement les données stockées sur le nœud Mongo en erreur.
Pour cela il faut purger les données sur ce nœud. MongoDB va le considérer comme un nouveau nœud venant d'être ajouté au cluster et il va procéder automatiquement à la resynchronisation intégrale des données stockées sur ce nœud.
Resynchronisation automatique par réinitialisation du nœud
Cette méthode resynchronise entièrement le nœud. Elle peut générer du trafic réseau et une utilisation de ressources systèmes plus importantes pendant la resynchronisation.
Les commandes doivent toutes être exécutées sur le nœud noeud_recovery
Arrêt de mongod
systemctl stop mongod
Purge des données
Durant cette procédure, il ne faut pas toucher aux données de mongo-configsrv.
RHEL / CentOS 7 ou RHEL / Alma / Rocky 8 ou RHEL / Alma / Rocky 9
find /var/lib/mongo/ \! -path '*/configdb*' -exec rm -fr \{\} \;
Debian 13
find /var/lib/mongodb/ \! -path '*/configdb*' -exec rm -fr \{\} \;
Démarrer mongod
Une fois les données supprimées, le redémarrage du démon mongod va initier la resynchronisation
systemctl start mongod
Suivre l'état de la synchronisation
On peut maintenant vérifier l'état du cluster MongoDB via la console MongoDB ( mongo --port 27018 ) avec la commande suivante :
rs.status()
Le nœud va commencer sa resynchronisation. Il devrait à terme repasser dans son état habituel (PRIMARY ou SECONDARY).
Erreur d'enregistrement SLA
Si le message d'erreur suivant apparait dans les logs du Broker, les données de SLA ne se sont pas enregistrés :
ERROR : [broker-master ] [SLA} update active fail not master and slaveOk=false: WARNING: [broker-master ] The instance sla raised an exception not master and slaveOk=false. I disabled it, and set it to restart later ERROR : [broker-master ] The instance sla raised an exception not master and slaveOk=false.
- Il s'agit d'un problème de configuration du port de communication de mongos. Mongos est le point d'entrée de toute communication avec la base de données MongoDB. Il n'est pas possible d'envoyer de requête directement sur le port ( 27018 ) de la base de données, il faut passer par le port de mongos ( 27017 ).
- Pour corriger, il faut vérifier la configuration du fichier /etc/mongos.conf.

