La protection des données MongoDB n'est réelle que lorsque vous prouvez régulièrement que vous pouvez les restaurer. Ce guide vous donne des étapes pratiques, prêtes à copier-coller, pour les sauvegardes, restaurations, validations, planification de rollback et reprise après sinistre. Vous terminerez avec un pilote local testé et un chemin clair vers la production.
Pour qui ce guide
- Développeurs, consultants DevOps et équipes de startups qui ont besoin d'un plan fiable et sans drame
- Toute personne souhaitant un workflow répétable testable d'abord en local
Ce que vous allez faire
- Effectuer des sauvegardes MongoDB cohérentes (mongodump et snapshots filesystem)
- Restaurer vers une cible sûre, valider minutieusement et planifier une bascule propre
- Répéter des scénarios de sinistre et mesurer RTO/RPO
Aperçu du workflow
Un workflow de production fiable est simple et explicite :
- Choisir votre méthode de sauvegarde
- mongodump pour les sauvegardes logiques ; utilisez
--oplogpour les replica sets - Snapshots filesystem pour les charges de travail à haut débit et les clusters shardés
- Planifier et stocker les sauvegardes
- Exécuter sur un secondaire quand possible, compresser et chiffrer au repos, conserver plusieurs générations
- Tester les restaurations régulièrement
- Restaurer vers un namespace de staging, jamais directement en production
- Valider les résultats
- Comptages, hachages, requêtes d'échantillon, index, utilisateurs/rôles, fCV
- Planifier le rollback et la bascule
- Restaurer vers des collections parallèles, puis permuter atomiquement
- Répéter la reprise après sinistre
- Chronométrer chaque étape, corriger les goulots d'étranglement et documenter le runbook
Exemples de sauvegarde (Replica Set)
Créez des utilisateurs aux privilèges minimaux pour la sauvegarde et la restauration.
// Dans mongosh sur le primaire
use admin
// Utilisateur de sauvegarde
db.createUser({
user: "backup",
pwd: "REDACTED_STRONG_PW",
roles: [{ role: "backup", db: "admin" }]
})
// Utilisateur de restauration (utiliser seulement en non-prod ou cible DR)
db.createUser({
user: "restore",
pwd: "REDACTED_STRONG_PW",
roles: [{ role: "restore", db: "admin" }]
})
Variables d'environnement utiles :
export RS_URI='mongodb://backup:REDACTED_STRONG_PW@rs0/yourdb?replicaSet=rs0&authSource=admin'
export TS=$(date -u +%Y%m%dT%H%M%SZ)
mkdir -p backups
Vidage complet de la base depuis un secondaire avec oplog pour la sécurité point-in-time :
mongodump \
--uri "$RS_URI" \
--readPreference secondaryPreferred \
--db yourdb \
--archive "backups/yourdb-$TS.archive" \
--gzip \
--oplog
Vidage d'une seule collection (filtrer un sous-ensemble actif pour réduire la taille) :
mongodump \
--uri "$RS_URI" \
--db yourdb \
--collection orders \
--archive "backups/yourdb-orders-$TS.archive" \
--gzip
Chiffrer l'archive au repos (exemple avec GnuPG) :
gpg --symmetric --cipher-algo AES256 "backups/yourdb-$TS.archive"
shred -u "backups/yourdb-$TS.archive" # supprimer le texte en clair proprement
Idée de rétention :
- Conserver N archives quotidiennes, W hebdomadaires, M mensuelles
- Stocker des copies hors site et tester les restaurations depuis hors site aussi
Exemples de sauvegarde (Snapshots)
mongod standalone : verrouiller, snapshot, déverrouiller.
// Dans mongosh sur le nœud
use admin
db.adminCommand({ fsync: 1, lock: true })
Effectuez un snapshot LVM, EBS ou autre au niveau filesystem, puis :
// De retour dans mongosh
db.fsyncUnlock()
Clusters shardés : désactiver le balancer et snapshots chaque shard et config server de façon cohérente.
sh.stopBalancer()
// Vérifier l'état : sh.getBalancerState() doit être false
Après avoir pris des snapshots filesystem synchronisés sur tous les shards et config servers, réactiver le balancer :
sh.startBalancer()
Notes :
- mongodump
--oplogfonctionne pour les replica sets, pas pour un cluster shardé via mongos - Pour la cohérence cross-shard, préférez les snapshots filesystem coordonnés ou une solution de sauvegarde gérée
Exemples de restauration
Restaurez toujours vers une cible sûre d'abord (DB de staging ou nouveau namespace) et validez avant la bascule.
Restauration de base d'une archive de base complète :
export RESTORE_URI='mongodb://restore:REDACTED_STRONG_PW@primary/yourdb?authSource=admin'
mongorestore \
--uri "$RESTORE_URI" \
--archive "backups/yourdb-$TS.archive" \
--gzip \
--nsFrom 'yourdb.*' \
--nsTo 'yourdb_restored.*' \
--drop \
--writeConcern '{"w":"majority","wtimeout":60000}'
Restauration sélective d'une seule collection :
mongorestore \
--uri "$RESTORE_URI" \
--archive "backups/yourdb-orders-$TS.archive" \
--gzip \
--nsInclude 'yourdb.orders' \
--drop
Récupération point-in-time (PITR) avec un dump incluant l'oplog :
- La commande mongodump ci-dessus a écrit un segment d'oplog dans l'archive
- Vous pouvez rejouer cet oplog pendant la restauration, en limitant optionnellement par un timestamp
# Restaurer la base plus rejouer l'oplog jusqu'au dernier dans l'archive
mongorestore \
--uri "$RESTORE_URI" \
--archive "backups/yourdb-$TS.archive" \
--gzip \
--oplogReplay
Limiter l'oplog à un timestamp (format : secondes[:ordinal]) :
# Exemple : arrêter à l'epoch UNIX 1719931200
mongorestore \
--uri "$RESTORE_URI" \
--archive "backups/yourdb-$TS.archive" \
--gzip \
--oplogReplay \
--oplogLimit 1719931200
Astuce : restaurer dans un namespace différent (yourdb_pitr.*) pour pouvoir comparer avant tout échange.
Vérifications de validation après restauration
Exécutez des vérifications rapides et déterministes avant de considérer la restauration comme bonne.
- Comptages
// Comparer source vs restauré (exécuter sur chaque)
use yourdb
const expected = db.orders.countDocuments({})
// Sur le namespace restauré
use yourdb_restored
const actual = db.orders.countDocuments({})
printjson({ expected, actual, ok: expected === actual })
- Hachages (par collection)
// Sur chaque environnement
db.adminCommand({ dbHash: 1, collections: ["orders" ] })
- Index
db.orders.getIndexes()
- Requêtes représentatives
db.orders.find({ status: "open" }).limit(5).toArray()
db.orders.aggregate([{ $match: { createdAt: { $gte: ISODate("2026-01-01" ) } } }, { $count: "n" }])
- Utilisateurs et rôles
use admin
db.getUsers()
- Version de compatibilité des fonctionnalités (fCV)
use admin
db.adminCommand({ getParameter: 1, featureCompatibilityVersion: 1 })
Script Node.js de vérification automatisé (optionnel) :
// verify.js
const { MongoClient } = require('mongodb');
(async () => {
const srcUri = process.env.SRC_URI; // e.g. mongodb://.../yourdb
const dstUri = process.env.DST_URI; // e.g. mongodb://.../yourdb_restored
const coll = 'orders';
const src = new MongoClient(srcUri);
const dst = new MongoClient(dstUri);
try {
await src.connect();
await dst.connect();
const srcCount = await src.db().collection(coll).countDocuments();
const dstCount = await dst.db().collection(coll).countDocuments();
console.log({ srcCount, dstCount, match: srcCount === dstCount });
process.exit(srcCount === dstCount ? 0 : 2);
} catch (e) {
console.error(e);
process.exit(1);
} finally {
await src.close();
await dst.close();
}
})();
Planification du rollback et bascules
Évitez de restaurer directement en production. Préférez :
- Restaurer vers des collections parallèles dans la même base (suffixe
_new) - Réchauffer les caches avec des requêtes de lecture
- Permuter les noms de collections atomiquement
- Conserver les anciennes collections pour un revert rapide, puis nettoyer
Exemple de plan de renommage (privilèges admin requis) :
use admin
// Échanger orders_new -> orders avec sauvegarde de l'ancienne
// Étape 1 : archiver l'ancien nom de collection
db.adminCommand({ renameCollection: 'yourdb.orders', to: 'yourdb.orders_old', dropTarget: true })
// Étape 2 : promouvoir la nouvelle collection
db.adminCommand({ renameCollection: 'yourdb.orders_new', to: 'yourdb.orders', dropTarget: true })
Notes :
- renameCollection fonctionne dans la même base de données
- Faire une collection à la fois pour des rollbacks clairs
- Si rollback nécessaire, inverser les étapes de renommage
Planification de la reprise après sinistre
Définir les cibles :
- RTO (Recovery Time Objective, objectif de temps de reprise) : temps maximal acceptable pour une restauration
- RPO (Recovery Point Objective, objectif de point de reprise) : quantité maximale de données qu'on peut se permettre de perdre
Pratiques recommandées :
- Réplication : exécuter des replica sets across failure domains (domaines de panne)
- Sauvegardes : conserver des copies chiffrées, versionnées, hors site
- PITR : combiner des dumps de base réguliers ou snapshots avec archivage d'oplog
- Runbooks : documenter noms d'hôtes, URIs, gestion des credentials, commandes et critères de succès
- Répétitions : exécuter des exercices de restauration trimestriels, enregistrer les temps, corriger les goulots
- Surveillance : alerter sur échecs de jobs de sauvegarde, dérive de données et capacité de stockage
Plan de pilote local
Commencez petit et mesurable avant de déployer à grande échelle :
Périmètre
- Une base de données (
yourdb), une collection critique (orders), taille cible sous quelques Go
Étapes
- Faire un mongodump avec
--oplogdepuis un secondaire de replica set - Restaurer dans
yourdb_restoredsur un cluster de dev - Exécuter le script de validation (comptages, hachages, requêtes d'échantillon)
- Enregistrer taille du dump, temps de dump, temps de restauration, résultats de validation
- Documenter les constats et optimiser si nécessaire (compression, parallélisme, index)
Critères de sortie
- La restauration passe tous les contrôles
- Le temps de bout en bout est sous votre budget RTO pour la taille du pilote
- Les membres de l'équipe peuvent répéter le processus sans aide
Erreurs courantes et correctifs
| Erreur | Correctif |
|---|---|
| Ne pas tester les restaurations | Planifier des exercices de restauration mensuels ou trimestriels avec validation |
Omettre --oplog pour les replica sets | Toujours ajouter --oplog avec mongodump sur un replica set |
| Sauvegarder un cluster shardé via mongos en espérant une cohérence cross-shard | Utiliser des snapshots filesystem coordonnés avec le balancer arrêté, ou une solution gérée |
| Restaurer directement en production | Restaurer dans un namespace de staging, valider, puis basculer avec renommage |
| Oublier index ou utilisateurs dans la validation | Comparer les sorties de getIndexes et db.getUsers |
| Surcharger le primaire pendant la sauvegarde | Lire depuis un secondaire avec --readPreference secondaryPreferred |
| Artefacts de sauvegarde non sécurisés | Chiffrer au repos, restreindre l'accès et faire tourner les clés |
Conclusion
Vous disposez maintenant d'un workflow pratique de sauvegarde et restauration MongoDB :
- Pour les replica sets, utilisez mongodump avec
--oploget restaurez avec validation - Pour les clusters shardés, préférez les snapshots filesystem coordonnés
- Validez comptages, hachages, requêtes d'échantillon, index et utilisateurs
- Planifiez les rollbacks avec renommage de collections, et répétez la DR pour prouver RTO/RPO
Prochaines étapes
- Implémenter le Plan de pilote local cette semaine
- Automatiser la validation et ajouter la surveillance des échecs
- Étendre le périmètre et la fréquence une fois le pilote validé