Intro
Cette version française explique MongoDB upgrade and migration with practical examples avec le même objectif pratique que l article source : aider le lecteur à comprendre le contexte, les décisions à prendre et les points à vérifier avant de passer à l action.
Mettre à niveau ou migrer MongoDB devrait être ennuyeux : des plans prévisibles, des vérifications répétables et des filets de sécurité solides. Ce guide vous propose une voie pratique pour :
- Planifier une mise à niveau de version (MongoDB version upgrade) ou une migration de données avec un risque minimal
- Sauvegarder et répéter des restaurations
- Valider les changements par le code et les requêtes (MongoDB validation)
- Revenir en arrière proprement si quelque chose échoue (MongoDB rollback)
Vous verrez un workflow orienté production et un pilote local exécutable avec Docker, Node.js et une API Express minimale.
Vue d'ensemble du workflow
La voie la plus sûre consiste à découper l'opération en étapes claires et vérifiables. Traitez chaque étape comme un point de passage/échec et n'avancez que lorsque l'étape précédente est au vert.
1) Définir périmètre et réussite
- Cible : versions serveur, versions de drivers, et tout changement de schéma ou d'index
- Contraintes : temps d'arrêt autorisé (idéalement nul ou quasi nul pour les replica sets), fenêtre de maintenance, volume de données
- Succès : checks de santé mesurables, smoke tests applicatifs et seuils de performance
Exemples de critères de succès :
- Tous les nœuds sur la nouvelle version
- Feature compatibility positionnée sur la nouvelle version
- Les smoke tests de l'app passent (connexion, lecture, écriture, usage d'index)
- Les erreurs et requêtes lentes ne dépassent pas la ligne de base
2) Inventaire et compatibilité
Dressez l'état des lieux actuel :
- Topologie : standalone, replica set ou sharded cluster
- Versions : MongoDB, feature compatibility et drivers
- Stockage et marge disque
- Opérations critiques : collections volumineuses, capped collections, index TTL, index texte et géo
Vérifications utiles dans mongosh :
// Version actuelle de la feature compatibility
db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })
// Informations de build serveur
db.version()
db.serverBuildInfo()
Préparation du driver (exemple Node.js) :
- Utilisez un driver compatible avec la version cible du serveur
- Activez retryable writes lorsque pertinent
- Réglez des délais (timeouts) et tailles de pool de connexions raisonnables
3) Sauvegardes et répétition de restauration
Prenez une sauvegarde cohérente et prouvez que vous pouvez la restaurer avant de toucher la production.
# Sauvegarde logique (portable entre versions)
mongodump --uri 'mongodb://user: pass@host:27017/dbname' \
--out ./backup-$(date +%Y%m%d-%H%M)
# Répétition de restauration dans une base jetable
mongorestore --uri 'mongodb://user: pass@staging:27017/rehearsal' \
./backup-YYYYMMDD-HHMM
Envisagez aussi des snapshots système de fichiers si votre plateforme de stockage les supporte. Conservez au moins un snapshot vérifié par nœud.
4) Environnement de staging
Miroitez la production aussi fidèlement que possible :
- Même version majeure MongoDB que la base
- Même mode d'auth, paramètres TLS et index
- Volume de données représentatif (un sous-ensemble suffit)
Chargez des données de départ via mongorestore ou laissez l'application les générer.
5) Préparation de l'application (Node.js + Express)
Préparez l'app pour des changements progressifs et des erreurs transitoires.
// app.js
const express = require('express');
const { MongoClient } = require('mongodb');
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/appdb';
async function start() {
const client = new MongoClient(MONGODB_URI, {
maxPoolSize: 20,
serverSelectionTimeoutMS: 5000,
retryWrites: true
});
await client.connect();
const db = client.db();
// Vérification simple de disponibilité via ping
async function dbReady() {
try {
await db.command({ ping: 1 });
return true;
} catch (e) {
return false;
}
}
const app = express();
app.get('/healthz', async (req, res) => {
res.json({ ok: await dbReady() });
});
app.get('/smoke', async (req, res) => {
const col = db.collection('items');
await col.insertOne({ t: new Date(), v: Math.random() });
const count = await col.countDocuments();
res.json({ count });
});
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`HTTP on ${port}`));
}
start().catch((e) => {
console.error('Fatal:', e);
process.exit(1);
});
Conservez la configuration en variables d'environnement. En staging, simulez une courte panne en redémarrant des primaires et observez la récupération de l'app.
6) Plan d'exécution
Choisissez le bon déroulé selon votre topologie.
Nœud unique
- Stoppez les écritures de l'application (mode maintenance ou arrêt du service)
- Sauvegarde : snapshot et mongodump
- Arrêtez mongod
- Installez ou basculez sur le nouveau binaire/image de MongoDB
- Redémarrez mongod et surveillez les logs jusqu'au succès
- Exécutez les vérifications de base et les smoke tests
- Si tout est bon, réactivez les écritures
Replica set (rolling, quasi zéro-downtime)
- Assurez-vous d'avoir des sauvegardes et des snapshots récents pour tous les nœuds
- Mettez à niveau les secondaires un par un :
- Arrêtez un secondaire
- Installez ou basculez sur le nouveau binaire/image
- Redémarrez et attendez l'état SECONDARY à jour
- Déclassez le primaire depuis mongosh :
rs.stepDown(60)
- Mettez à niveau l'ancien primaire avec les mêmes étapes
- Lorsque tous les nœuds tournent sur la nouvelle version, définissez la feature compatibility depuis le primaire :
db.adminCommand({ setFeatureCompatibilityVersion: 'X.Y' })
- Lancez les smoke tests et validations approfondies
Notes :
- Laissez l'application connectée avec retryWrites et des timeouts raisonnables
- Attendez-vous à de brefs failovers ; le driver doit se reconnecter automatiquement
Cluster shardé (vue d'ensemble)
- Mettez à niveau les serveurs de config d'abord, puis les routeurs mongos, puis les replica sets de shards
- Traitez chaque shard comme une mise à niveau rolling indépendante
7) Liste de validation
Effectuez d'abord les vérifs rapides, puis des contrôles plus profonds dans la même fenêtre.
Immédiat :
- Connexion et ping
- Lecture/écriture d'un petit document
- Santé du replica set : rôles PRIMARY/SECONDARY comme attendu
rs.status()
- Confirmation de la version attendue :
db.version()
db.serverBuildInfo().version
Approfondi :
- Comparez les lenteurs et le taux d'erreurs à la ligne de base
- Vérifiez l'existence et l'usage des index critiques sur vos parcours chauds
// Exemple de création d'index pendant une migration
const col = db.getSiblingDB('appdb').items;
col.createIndex({ userId: 1, createdAt: -1 }, { name: 'ix_user_createdAt' })
- Exécutez des smoke tests métier (login, création de commande, etc.)
8) Plan de rollback
Ayez un chemin clair et répété vers l'état précédent.
- Nœud unique : stoppez les écritures, arrêtez mongod, restaurez depuis snapshot ou mongorestore vers un répertoire de données vierge, redémarrez l'ancien binaire/image, validez
- Replica sets : revenez en arrière nœud par nœud vers l'ancien binaire/image, ne restaurez les données que si le nœud ne démarre pas proprement
- Si vous avez changé la feature compatibility, évitez d'utiliser de nouvelles fonctionnalités avant la fin de la fenêtre de validation, pour garder le rollback simple
- Gardez l'app capable de se connecter à la version précédente sans changement de code
Liste de smoke pour rollback :
- L'app se connecte et le /smoke passe
- La forme des données et les index clés sont conformes
- L'élection du primaire et la réplication sont saines
9) Supervision et sécurité
Supervision :
- Suivez les connexions, latences d'opérations, retard de réplication, CPU/mémoire
- Surveillez les logs pour les warnings et requêtes lentes
Sécurité :
- Exigez l'authentification et des rôles de moindre privilège pour l'utilisateur applicatif
- Stockez les chaînes de connexion dans des secrets, pas dans le code
- Utilisez TLS quand approprié et testez la rotation de certificats en staging
Plan pilote local
Gardez le premier pilote petit, rapide et facile à déboguer. Objectif : faire tourner les étapes critiques de bout en bout sur votre laptop.
Périmètre :
- MongoDB mono-nœud
- Amorcer un minuscule jeu de données
- Mettre à niveau vers une nouvelle version (MongoDB upgrade)
- Valider avec une app Express Node.js
- Pratiquer le rollback
1) Docker Compose pour un nœud unique
docker-compose.yml :
version: '3.8'
services:
mongo:
image: mongo:6.0
container_name: mongo-old
ports:
- '27017:27017'
volumes:
- ./data:/data/db
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
Démarrez :
docker compose up -d
Initialisez un utilisateur pour l'app (mongosh dans le conteneur ou depuis l'hôte) :
mongosh 'mongodb://root: example@localhost:27017/admin' --eval 'db.getSiblingDB("appdb").createUser({ user: "app", pwd: "appsecret", roles: [ { role: "readWrite", db: "appdb" } ] })'
2) Amorcer des données
export MONGODB_URI='mongodb://app: appsecret@localhost:27017/appdb'
mongosh "$MONGODB_URI" --eval 'db.items.insertMany([{name:"alpha"},{name:"beta"}])'
3) Lancer l'app Express
Créez app.js depuis l'extrait plus haut puis exécutez :
export MONGODB_URI='mongodb://app: appsecret@localhost:27017/appdb'
node app.js
Vérifiez santé et smoke :
curl http://localhost:3000/healthz
curl http://localhost:3000/smoke
4) Sauvegarde
mongodump --uri "$MONGODB_URI" --out ./backup-preupgrade
Optionnel : prenez un snapshot du répertoire ./data.
5) Mise à niveau locale
Arrêtez l'ancien conteneur et redémarrez avec la même data directory :
docker compose down
Remplacez le tag d'image par une version plus récente dans docker-compose.yml, par exemple :
image: mongo:7.0
Démarrez :
docker compose up -d
Surveillez les logs jusqu'au démarrage propre :
docker logs -f mongo-old
Exécutez la validation :
mongosh "$MONGODB_URI" --eval 'db.version()'
curl http://localhost:3000/healthz
curl http://localhost:3000/smoke
Optionnel : définissez la feature compatibility si nécessaire :
mongosh 'mongodb://root: example@localhost:27017/admin' --eval 'db.adminCommand({ setFeatureCompatibilityVersion: "X.Y" })'
6) Exemple simple de migration
Créez un index et remplissez un champ :
mongosh "$MONGODB_URI" --eval '
db.items.createIndex({ name: 1 }, { name: "ix_name" });
db.items.updateMany({ migrated: { $exists: false } }, { $set: { migrated: true } });
'
Vérifiez :
mongosh "$MONGODB_URI" --eval 'db.items.getIndexes()'
7) Exercice de rollback
Arrêtez le nouveau conteneur, restaurez le dump dans un répertoire neuf et relancez l'ancienne image.
# Arrêt et suppression des conteneurs
docker compose down
# Mettre de côté les données actuelles et recréer un répertoire propre
mv ./data ./data-new && mkdir ./data
# Restaurer la sauvegarde dans un mongod standalone
mongod --dbpath ./data --bind_ip 127.0.0.1 --port 27018 --fork --logpath ./mongod.log
mongorestore --uri 'mongodb://localhost:27018/appdb' ./backup-preupgrade/appdb
# Arrêter le mongod temporaire
mongosh 'mongodb://localhost:27018/admin' --eval 'db.shutdownServer()'
# Repasser l'image à mongo:6.0 dans docker-compose.yml et démarrer
docker compose up -d
# Revérifier les smoke tests
echo 'health:' && curl http://localhost:3000/healthz
echo 'smoke:' && curl http://localhost:3000/smoke
Résultat : vous pouvez réaliser une MongoDB migration, valider et revenir en arrière localement en quelques minutes.
Conclusion
Vous disposez maintenant d'un chemin pratique pour une MongoDB upgrade à faible risque :
- Séparez planification, sauvegardes, staging, exécution, validation et rollback
- Utilisez une approche rolling pour les replica sets afin de minimiser l'arrêt
- Validez via checks ciblés, smoke tests Node.js et vérification d'index
- Conservez un rollback testé avec snapshots et mongodump
- Intégrez supervision et sécurité de moindre privilège dès le départ
Prochaines étapes :
- Étendez le pilote local en un replica set de staging et répétez les exercices
- Automatisez les smoke tests et les checks dans vos scripts de déploiement
- Documentez précisément vos commandes de bascule et de rollback pour la production
Astuce finale : traitez chaque MongoDB version upgrade comme une opération d'ingénierie répétable, pilotée par des métriques et des validations observables, afin de réduire le risque et les surprises.