L’enfer des snapshots n’arrive pas avec des sirènes. Il se manifeste par des questions du type « pourquoi le pool est-il à 94 % plein à nouveau ? » et « pourquoi la suppression d’anciens snapshots ne libère rien ? ».
Puis la fenêtre de sauvegarde s’allonge, la réplication prend du retard, et une restauration de routine se transforme en excavation médico-légale.
Les snapshots ZFS sont l’une des meilleures idées qu’ait apportées le stockage. Ils sont aussi la manière la plus simple de créer silencieusement une machine à remonter le temps que vous ne pouvez pas vous permettre de faire fonctionner.
La solution n’est pas « prendre moins de snapshots » ni « acheter plus de disques ». C’est une politique de rétention qui traite les snapshots comme des données de production : budgétisées, observables,
et régulièrement collectées avec des preuves.
Ce qu’est vraiment « l’enfer des snapshots »
L’enfer des snapshots n’est pas « trop de snapshots ». C’est des snapshots sans gouvernance.
Vous pouvez avoir des dizaines de milliers de snapshots et vous en sortir si vous comprenez comment l’espace est retenu, comment fonctionnent la réplication et les holds,
et si vous supprimez en connaissance de cause plutôt qu’au feeling.
Voici à quoi cela ressemble en production :
- Panne de capacité : l’utilisation du pool monte même si « nous avons supprimé les anciennes données ».
- Incertaines des restaurations : personne ne sait quel snapshot est sûr, cohérent ou pertinent.
- Réplication ralentie : les envois incrémentiels grossissent parce que les snapshots sont mal alignés, ou parce que vous avez conservé les mauvais.
- Peur opérationnelle : « ne supprimez rien, ça pourrait être nécessaire. » Félicitations, vous gérez maintenant un musée.
Le problème central est que les snapshots préservent d’anciens blocs. Si vous modifiez des données de façon intensive (VM, bases de données, caches CI),
les snapshots conservent ces anciennes versions. Vos données « supprimées » ne le sont pas ; elles sont commémorées.
Blague n°1 : Les snapshots sont comme des tickets de caisse — utiles jusqu’à ce que vous les conserviez sept ans et découvriez que vous avez acheté 300 câbles USB identiques.
Faits et historique utiles
- ZFS a été conçu autour du copy-on-write (CoW), ce qui signifie qu’il n’écrase jamais les blocs en place ; les snapshots en sont une conséquence naturelle, pas une fonctionnalité ajoutée.
- Les snapshots sont presque gratuits à créer (travail sur les métadonnées), d’où la facilité à en abuser ; le coût apparaît plus tard sous forme de blocs retenus.
- Les snapshots ZFS sont cohérents au niveau du système de fichiers ; pour la cohérence applicative (bases de données), vous avez toujours besoin d’une coordination (freeze, flush ou outils de réplication).
- La comptabilité d’espace pour les snapshots n’est pas la « taille du snapshot » ; c’est « les blocs uniques référencés uniquement par ce snapshot ». Cela embrouille presque tout le monde au moins une fois.
- Les clones sont des snapshots réinscriptibles — et ils créent des chaînes de dépendance où vous ne pouvez pas supprimer « l’ancien truc » parce qu’un clone l’utilise encore.
- Les holds existent parce que les humains suppriment la mauvaise chose ; ZFS a rendu la suppression de snapshot réversible en esprit (préventive), pas en fait (elle reste destructive).
- Les envois incrémentiels reposent sur la lignée des snapshots ; supprimer des snapshots « intermédiaires » peut casser les incrémentiels sauf si vous planifiez en conséquence.
- Les outils d’auto-snapshot sont devenus populaires parce que la sauvegarde manuelle échoue en silence : ça marche jusqu’à la semaine où vous oubliez — juste avant d’en avoir besoin.
Modèle mental : snapshots, blocs et pourquoi la suppression déçoit
Les snapshots sous ZFS sont des pointeurs vers une vue cohérente d’un dataset à un instant donné. Ils ne « contiennent pas de fichiers ».
Ils contiennent des références aux blocs qui existaient au moment de leur création.
Quand les données changent après un snapshot, ZFS écrit de nouveaux blocs (CoW). Les anciens blocs restent car le snapshot y fait toujours référence.
Le coût d’un snapshot est donc proportionnel à la quantité modifiée depuis sa création, pas à la taille nominale du dataset.
Trois comportements qui rendent les opérateurs misérables
- L’espace libre revient tard : supprimer un fichier ne libère pas les blocs si un snapshot y fait toujours référence.
- « Used » est contextuel : le champ « used » d’un snapshot correspond à la propriété unique de blocs ; il peut augmenter à mesure que le dataset churn.
- Les dépendances sont invisibles sauf si vous les vérifiez : clones et holds empêcheront les suppressions et troubleront les scripts de nettoyage.
Ce que la politique de rétention doit résoudre
Une politique de rétention n’est pas un simple calendrier. C’est un contrat entre risque et coût :
« Nous serons toujours capables de restaurer dans une fenêtre temporelle X et avec une granularité Y, et nous ne dépasserons jamais Z % d’utilisation du pool à cause des snapshots. »
Il vous faut :
- Des classes de snapshots claires (horaire/journalier/hebdo/mensuel).
- Un schéma de nommage qui encode l’intention.
- Un algorithme d’élagage qui conserve des points représentatifs dans le temps.
- Des garde-fous : holds pour les snapshots spéciaux, et des alertes quand la rétention viole le budget de capacité.
- Des runbooks pour le jour « le pool se remplit » — parce que ça arrivera.
Une idée paraphrasée, souvent citée car elle a façonné la culture ops :
Vous devriez construire des systèmes qui supposent que les humains feront des erreurs, puis en contraindre le périmètre d’impact.
— James Hamilton (ingénierie de fiabilité)
La politique de rétention qui fonctionne réellement
La politique ci-dessous est ennuyeuse. C’est pourquoi elle survit au contact de la production.
Elle est conçue autour de trois vérités : la plupart des restaurations sont récentes, la conformité exige des horizons longs, et la capacité est finie.
1) Choisissez un objectif de récupération, puis payez-le avec des snapshots
Décidez votre RPO (combien de données vous pouvez perdre) et votre RTO (à quelle vitesse vous devez restaurer). Puis mappez-les à la fréquence des snapshots.
Si votre activité dit « nous pouvons tolérer 1 heure de perte », ne prenez pas que des snapshots journaliers en espérant que ça suffira.
Par défaut pratique qui convient à beaucoup d’équipes :
- Horaire : conserver 48 (2 jours)
- Journalier : conserver 35 (5 semaines)
- Hebdomadaire : conserver 12 (3 mois)
- Mensuel : conserver 18 (18 mois)
Ça peut sembler beaucoup. Ce n’est pas le cas si vous élaguez selon le planning et que vous séparez vos datasets les plus volatils (VM, caches de build, WAL de base de données).
2) Séparez les datasets par churn et par valeur
La rétention des snapshots doit être par classe de dataset, pas « une règle pour tout le pool ».
Placez les éléments à fort churn dans leur propre dataset pour qu’ils ne contaminent pas l’économie de rétention des autres.
- Bases de données : snapshots cohérents coordonnés avec la DB ; rétention courte localement, plus longue sur les réplica/sauvegardes.
- Disques VM : snapshots fréquents et courts ; élagage agressif ; envisagez la réplication pour des horizons plus longs.
- Répertoires personnels : rétention longue, churn plus faible, bon candidat pour des horizons étendus.
- Scratch / CI : rétention minimale ou inexistante ; les snapshots ici font lentement brûler de l’argent.
3) Budgétez les snapshots en pourcentage de la capacité du pool
Choisissez un plafond strict, par exemple : « les snapshots ne doivent pas faire dépasser le pool 80 % d’utilisation en conditions normales. »
Votre budget est une contrainte de politique, pas une suggestion.
Quand le plafond est franchi, l’élagage devient automatiquement plus agressif (supprimer les mensuels d’abord ? ou les horaires d’abord ?).
Mon opinion : supprimez d’abord les couches à haute fréquence (horaire), car elles coûtent le plus dans les datasets churn et apportent le moins en récupération à long terme.
4) Exigez des holds pour les snapshots spéciaux, mais jamais pour les snapshots routine
Les holds sont pour des moments exceptionnels : points de contrôle pré-upgrade, holds juridiques, « nous allons faire une migration destructive ».
La rétention de routine doit être entièrement automatisée et entièrement supprimable.
Si vous laissez les holds s’infiltrer dans l’ensemble de snapshots par défaut, votre politique de rétention devient une fiction polie.
5) Alignez la rétention avec la réplication
Si vous utilisez la réplication ZFS send/receive, décidez quel côté est l’autorité pour la rétention long terme.
Schéma gagnant courant :
- Source : rétention courte, snapshots fréquents pour restauration locale rapide et incrémentiels petits.
- Destination : rétention plus longue, moins de snapshots retenus, plus des « ancres » périodiques (hebdo/mensuel) pour conformité.
Cela évite l’erreur classique « nous avons tout retenu partout ». Le disque est moins cher que le temps — jusqu’à ce qu’il ne le soit plus.
Nommage et métadonnées : votre futur vous remerciera
Les noms de snapshots font partie de votre plan de contrôle. Ce n’est pas de la décoration.
Si vous n’encodez pas l’intention, vous vous retrouverez avec des noms comme auto-2025-thing et un humain devinant lesquels comptent.
Un schéma de nommage qui tient la route
Utilisez : <dataset>@<classe>-<utc timestamp> plus des suffixes optionnels pour la coordination applicative.
Exemples :
tank/vmstore@hourly-2026-02-04T00:00Ztank/home@daily-2026-02-04T00:00Ztank/db@hourly-2026-02-04T00:00Z-pgfreeze
Utilisez des propriétés pour taguer l’intention
Les propriétés utilisateur ZFS peuvent porter des métadonnées de politique. Par exemple :
com.example:retention=hourlycom.example:owner=paymentscom.example:tier=gold
Les noms aident les humains. Les propriétés aident les outils.
Tâches pratiques (commandes, sorties, décisions)
Ce ne sont pas des commandes « jouet ». Ce sont celles que vous exécutez quand quelqu’un demande pourquoi le pool est plein et que votre agenda va être annulé par la physique.
Chaque tâche inclut : la commande, ce que signifie la sortie, et la décision que vous en tirez.
Task 1: See pool capacity pressure and fragmentation
cr0x@server:~$ zpool list -o name,size,alloc,free,cap,health,frag
NAME SIZE ALLOC FREE CAP HEALTH FRAG
tank 10.9T 9.2T 1.7T 84% ONLINE 38%
Signification : CAP à 84 % est déjà dans la zone de danger pour les performances et le comportement d’allocation ; FRAG indique à quel point l’espace libre est morcelé.
La fragmentation n’est pas « mauvaise » en soi, mais CAP élevé + FRAG en hausse, c’est là que la latence devient problématique.
Décision : Si CAP > 80%, arrêtez de créer de nouveaux snapshots à longue rétention, priorisez l’élagage et identifiez qui retient l’espace (snapshots, clones ou données actives).
Task 2: Identify which datasets are actually consuming space
cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint -S used
NAME USED AVAIL REFER MOUNTPOINT
tank/vmstore 4.3T 820G 1.1T /tank/vmstore
tank/home 2.7T 820G 2.2T /tank/home
tank/db 1.6T 820G 540G /tank/db
Signification : USED inclut les snapshots et les enfants ; REFER est ce que le système de fichiers vivant référence actuellement.
De grands écarts entre USED et REFER sont votre taxe snapshot (ou des enfants).
Décision : Concentrez-vous sur les datasets où USED ≫ REFER. Ce sont des suspects prioritaires pour la surcharge de snapshots.
Task 3: Quantify snapshot overhead per dataset
cr0x@server:~$ zfs get -H -o name,property,value used,usedbysnapshots,usedbydataset tank/vmstore
tank/vmstore used 4.30T
tank/vmstore usedbysnapshots 3.10T
tank/vmstore usedbydataset 1.10T
Signification : 3.10T est bloqué par les snapshots. Ce n’est pas le « nombre de snapshots », c’est les blocs retenus.
Décision : Ce dataset nécessite une révision immédiate de la rétention. Réduisez la fréquence/la durée des snapshots ou séparez les sous-chemins volatils en datasets distincts.
Task 4: List snapshots with space impact, sorted
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -S used tank/vmstore | head
NAME USED REFER CREATION
tank/vmstore@hourly-2026-02-02T10:00Z 120G 1.05T Sun Feb 2 10:00 2026
tank/vmstore@hourly-2026-02-02T11:00Z 118G 1.06T Sun Feb 2 11:00 2026
tank/vmstore@daily-2026-01-28T00:00Z 90G 1.02T Tue Jan 28 00:00 2026
Signification : La colonne USED pour les snapshots représente « les données uniques détenues par ce snapshot ». Les valeurs élevées sont votre levier de nettoyage.
Décision : Commencez par élaguer les gros snapshots horaires en premier — sauf s’ils font partie d’une chaîne de réplication dont vous avez encore besoin.
Task 5: Check if snapshots are blocked by holds
cr0x@server:~$ zfs holds tank/vmstore@hourly-2026-02-02T10:00Z
NAME TAG TIMESTAMP
tank/vmstore@hourly-2026-02-02T10:00Z pre-upgrade Mon Feb 3 09:12 2026
Signification : Ce snapshot ne peut pas être détruit tant que le hold n’est pas libéré.
Décision : Confirmez que l’événement « pre-upgrade » est terminé et approuvé. Puis libérez le hold ; sinon conservez-le et élaguer d’autres snapshots.
Task 6: Release a hold (safely) and delete a snapshot
cr0x@server:~$ zfs release pre-upgrade tank/vmstore@hourly-2026-02-02T10:00Z
cr0x@server:~$ zfs destroy tank/vmstore@hourly-2026-02-02T10:00Z
cr0x@server:~$ zfs list -t snapshot -o name,used -S used tank/vmstore | head -3
NAME USED
tank/vmstore@hourly-2026-02-02T11:00Z 118G
tank/vmstore@daily-2026-01-28T00:00Z 90G
Signification : Le snapshot a disparu ; l’ordre a changé. L’espace peut ne pas apparaître immédiatement comme « libre » si d’autres snapshots référencent encore ces blocs.
Décision : Si l’espace libre ne bouge pas, continuez à supprimer dans la chaîne (ou identifiez clones/autres snapshots retenant les mêmes blocs).
Task 7: Detect clones that block snapshot deletion
cr0x@server:~$ zfs get -H -o name,property,value origin -r tank/vmstore
tank/vmstore origin -
tank/vmstore/clone-win11 origin tank/vmstore@daily-2026-01-28T00:00Z
Signification : tank/vmstore/clone-win11 dépend de ce snapshot journalier. Supprimer le snapshot échouera tant que le clone n’est pas retiré ou promu.
Décision : Détruisez le clone (s’il est jetable) ou zfs promote le clone pour rompre la dépendance avant l’élagage.
Task 8: Promote a clone to unblock retention
cr0x@server:~$ zfs promote tank/vmstore/clone-win11
cr0x@server:~$ zfs get -H -o name,property,value origin tank/vmstore/clone-win11
tank/vmstore/clone-win11 origin -
Signification : Le clone est maintenant indépendant ; son origin est effacé.
Décision : Vous pouvez maintenant détruire d’anciens snapshots qui agissaient auparavant comme origin — après vérification de la nouvelle lignée de snapshots du clone et du plan de réplication.
Task 9: Check snapshot count and distribution by class
cr0x@server:~$ zfs list -t snapshot -o name -r tank/home | awk -F@ '{print $2}' | cut -d- -f1 | sort | uniq -c
48 hourly
35 daily
12 weekly
18 monthly
Signification : Cela correspond à la politique. Une augmentation des comptes constitue un échec d’automatisation ou une suppression bloquée (holds/clones).
Décision : Si les comptes dépassent la politique, inspectez d’abord les holds et les clones ; puis vérifiez si votre job d’élagage s’exécute bien et a les permissions nécessaires.
Task 10: Inspect what’s preventing incremental replication
cr0x@server:~$ zfs list -t snapshot -o name,creation tank/db | tail -5
tank/db@hourly-2026-02-03T20:00Z Mon Feb 3 20:00 2026
tank/db@hourly-2026-02-03T21:00Z Mon Feb 3 21:00 2026
tank/db@hourly-2026-02-03T22:00Z Mon Feb 3 22:00 2026
tank/db@hourly-2026-02-03T23:00Z Mon Feb 3 23:00 2026
tank/db@hourly-2026-02-04T00:00Z Tue Feb 4 00:00 2026
Signification : Les incrémentiels de réplication exigent un snapshot commun sur les deux côtés. Si la destination manque d’anciens horaires parce que vous les avez élagués là-bas,
la source ne pourra pas faire d’incrémentiel depuis ce point.
Décision : Définissez quels snapshots sont des « ancres de réplication » (souvent des dailies ou hebdos) et assurez-vous que les deux côtés les conservent suffisamment longtemps.
Task 11: Estimate send size before you commit
cr0x@server:~$ zfs send -nvP -I tank/db@hourly-2026-02-03T20:00Z tank/db@hourly-2026-02-04T00:00Z
send from @hourly-2026-02-03T20:00Z to tank/db@hourly-2026-02-04T00:00Z estimated size is 36.2G
total estimated size is 36.2G
Signification : C’est ce que votre réplication pousserait. Si c’est étonnamment énorme, votre dataset churn est élevé ou votre intervalle est trop large.
Décision : Si la taille estimée est trop grande pour votre fenêtre, augmentez la fréquence des snapshots (deltas plus petits), réduisez le churn (séparez WAL/temp),
ou modifiez le calendrier de réplication.
Task 12: Confirm compression and recordsize choices that affect snapshot churn
cr0x@server:~$ zfs get -o name,property,value compression,recordsize,atime tank/vmstore
NAME PROPERTY VALUE
tank/vmstore compression zstd
tank/vmstore recordsize 128K
tank/vmstore atime off
Signification : Recordsize influence combien de données changent quand de petits écrits surviennent ; atime=on peut créer un churn de métadonnées inutile (et donc une croissance des snapshots).
Décision : Pour les images VM et les bases de données, considérez recordsize et la disposition des datasets de manière intentionnelle. Désactivez atime sauf si vous en avez besoin réellement.
Task 13: Find “space that won’t free” due to deletes under snapshots
cr0x@server:~$ zfs list -o name,used,refer,usedbysnapshots -r tank/vmstore
NAME USED REFER USEDBYSNAPSHOTS
tank/vmstore 4.3T 1.1T 3.1T
tank/vmstore/images 3.9T 820G 3.0T
tank/vmstore/iso 120G 115G 2G
Signification : Le churn est concentré sous images. C’est là que des suppressions/réécritures ont eu lieu alors que des snapshots existaient.
Décision : Ajustez la rétention spécifiquement pour tank/vmstore/images ou isolez davantage (datasets par VM) pour limiter le périmètre d’impact.
Task 14: Dry-run a destructive cleanup by listing what would be deleted
cr0x@server:~$ zfs list -t snapshot -o name,creation -S creation tank/home | awk 'NR==1 || /@hourly-/' | head -5
NAME CREATION
tank/home@hourly-2026-02-04T00:00Z Tue Feb 4 00:00 2026
tank/home@hourly-2026-02-03T23:00Z Mon Feb 3 23:00 2026
tank/home@hourly-2026-02-03T22:00Z Mon Feb 3 22:00 2026
tank/home@hourly-2026-02-03T21:00Z Mon Feb 3 21:00 2026
Signification : Vous avez confirmé le motif de nommage et les timestamps de création. Les scripts de nettoyage doivent opérer sur ces motifs, pas sur « ce qui a l’air vieux ».
Décision : Si les snapshots ne correspondent pas aux motifs, arrêtez et corrigez le nommage d’abord. La collecte des ordures sans noms cohérents n’est que suppression créative.
Task 15: Observe I/O pressure when snapshots are heavy
cr0x@server:~$ zpool iostat -v tank 2 3
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 9.2T 1.7T 420 1150 62.1M 210M
raidz2-0 9.2T 1.7T 420 1150 62.1M 210M
sda - - 52 140 7.8M 26.5M
sdb - - 50 138 7.5M 25.9M
sdc - - 54 145 8.0M 27.1M
Signification : Un grand nombre d’opérations d’écriture plus une utilisation élevée du pool coïncident souvent avec des workloads lourds en snapshots (plus de churn de métadonnées, plus de fragmentation).
Décision : Si votre workload est sensible à la latence et que CAP est élevé, élaguer les snapshots et réduire le churn aide. Si vous êtes à court d’espace, planifiez une expansion — ne négociez pas avec l’entropie.
Playbook de diagnostic rapide
Quand quelqu’un dit « les snapshots nous tuent », il a peut-être raison — ou il peut blâmer la seule fonctionnalité visible.
Ce playbook trouve le goulot rapidement, dans l’ordre qui rapporte habituellement.
Premièrement : êtes-vous réellement contraint par la capacité ?
-
Vérifiez l’utilisation et la santé du pool :
cr0x@server:~$ zpool list -o name,cap,health,frag NAME CAP HEALTH FRAG tank 84% ONLINE 38%Décision : Si CAP > 80%, traitez cela comme un incident. Vos options se réduisent rapidement au-delà de ce seuil.
-
Trouvez la contribution des snapshots :
cr0x@server:~$ zfs get -H -o name,value usedbysnapshots -r tank | sort -h -k2 | tail -5 tank/vmstore 3.10T tank/home 420G tank/db 310GDécision : Attaquez d’abord le principal contributeur. Les efforts héroïques ailleurs sont performatifs.
Deuxièmement : la suppression est-elle bloquée par des dépendances (holds/clones/réplication) ?
-
Vérifiez les holds sur les snapshots « supprimables » :
cr0x@server:~$ zfs holds -r tank/vmstore | head NAME TAG TIMESTAMP tank/vmstore@daily-2026-01-28T00:00Z legal Thu Jan 30 14:10 2026Décision : Les holds impliquent un processus. Confirmez la propriété, puis relâchez ou acceptez le coût de capacité.
-
Vérifiez les clones et origins :
cr0x@server:~$ zfs get -H -o name,value origin -r tank/vmstore | grep -v '^-' tank/vmstore/clone-win11 tank/vmstore@daily-2026-01-28T00:00ZDécision : S’il existe des clones, promouvez-les ou détruisez-les avant d’élaguer leurs origin snapshots.
Troisièmement : la plainte concerne-t-elle les performances, pas la capacité ?
-
Vérifiez les symptômes d’E/S et de latence :
cr0x@server:~$ zpool iostat -v tank 1 5 capacity operations bandwidth pool alloc free read write read write -------------------------- ----- ----- ----- ----- ----- ----- tank 9.2T 1.7T 380 1320 58.0M 225MDécision : Si les écritures sont nombreuses et que CAP est élevé, l’élagage aide. Si CAP est correct, examinez recordsize, les réglages sync et la forme du workload.
-
Vérifiez les propriétés des datasets qui créent du churn (atime, recordsize) :
cr0x@server:~$ zfs get -o name,property,value atime,recordsize -r tank/vmstore NAME PROPERTY VALUE tank/vmstore atime off tank/vmstore recordsize 128K tank/vmstore/images atime off tank/vmstore/images recordsize 128KDécision : Ajustez par dataset. N’« optimisez » pas tout le pool parce qu’un workload crie le plus fort.
Trois mini-récits d’entreprise issus du terrain
Mini-récit 1 : L’incident causé par une fausse hypothèse
Une entreprise SaaS de taille moyenne utilisait ZFS pour le stockage des VM et des répertoires personnels. Ils avaient un job nocturne qui « supprimait les anciennes sauvegardes » dans le système invité.
L’équipe stockage s’attendait à ce que le pool décroisse après chaque nettoyage. Ce ne fut jamais le cas.
Quand le pool est passé dans la haute tranche des 80 %, la latence a grimpé. Les tickets sont arrivés : « Les VM sont lentes », « la sauvegarde prend plus de temps », « les déploiements sont bloqués ».
L’ingénieur d’astreinte a fait l’évidence : supprimer plus de fichiers. Le pool est devenu… encore plus rempli. C’est là que la panique développe un sens de l’humour.
La mauvaise hypothèse était simple : « Supprimer des fichiers libère de l’espace. » Sur ZFS avec snapshots, ce n’est vrai que si aucun snapshot ne référence les blocs supprimés.
Leur dataset VM avait des snapshots horaires pendant 30 jours. Chaque nettoyage nocturne supprimait de gros fichiers de log et faisait tourner des images VM. Les snapshots retenaient tous les anciens blocs.
La solution n’était pas mystique. Ils ont mesuré usedbysnapshots, constaté que c’était la majorité du dataset, et réduit la rétention horaire de 30 jours à 2 jours.
Ils ont conservé des dailies et hebdos plus longs pour la récupération point-in-time. Ils ont aussi séparé les images VM volatiles en datasets par VM pour qu’un locataire bruyant ne bloque pas l’espace pour tous.
Le meilleur : les restaurations se sont améliorées. Au lieu de scroller à travers un mois d’horaires, ils avaient une fenêtre récente claire pour un rollback rapide et une fenêtre plus longue pour les besoins d’audit.
Moins de snapshots. Meilleurs résultats. L’univers récompense parfois la comptabilité basique.
Mini-récit 2 : L’optimisation qui a échoué
Une organisation financière voulait « plus de sécurité » et a décidé de snapshotter toutes les cinq minutes. Ils l’ont fait sur un dataset de base de données occupé sans coordination applicative.
Le job de snapshot était rapide. La réplication ne l’était pas. Le pool s’est rempli plus vite que leur cycle d’approvisionnement, qui est le plus lent des niveaux de stockage connus.
Ils ont ensuite « optimisé » : « conservons les snapshots de cinq minutes seulement 24 heures, et gardons des dailies pendant un an. »
Raisonnable sur le papier. En pratique, leur script d’élagage supprimait des snapshots « intermédiaires » nécessaires pour les chaînes d’envoi incrémentiel vers le site DR,
forçant des envois complets fréquents. La bande passante a augmenté, le retard de réplication aussi, et le dataset DR a commencé à manquer des points de récupération que tout le monde croyait avoir.
La subtilité était qu’ils optimisaient le mauvais métrique. La fréquence des snapshots n’était pas le problème ; c’était l’alignement.
La source créait des snapshots à :00, :05, :10. La destination élaguait selon son heure locale et sa charge, supprimant les ancres de façon imprévisible.
La correction : ils ont défini des ancres de réplication explicites (horaire et journalier) et les ont conservées sur les deux côtés. Les snapshots de cinq minutes sont restés locaux et éphémères.
Le DR a conservé des hourlies pendant quelques jours et des dailies pendant des mois. La réplication est redevenue incrémentielle, prévisible et ennuyeuse — exactement ce qu’on veut pour le DR.
Blague n°2 : Rien ne dit « haute disponibilité » comme découvrir que votre plan DR dépend de l’humeur d’un cron.
Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise
Une entreprise de santé avait un contrôle de changement strict. Avant toute mise à jour majeure, ils prenaient un snapshot manuel et appliquaient un hold avec l’ID de ticket dans le tag.
C’était procédural, légèrement pénible et universellement moqué jusqu’au moment où ça a servi.
Lors d’un déploiement de firmware stockage, un paramétrage multipath incorrect a causé des erreurs I/O intermittentes sur un sous-ensemble d’hôtes.
L’équipe applicative est revenue au code précédent. Les erreurs ont persisté. Le problème n’était pas logiciel ; c’était le routage du stockage.
Ils ont eu besoin de restaurer un ensemble d’annuaires de configuration et une petite base de données qui avaient été « nettoyés » pendant le dépannage.
Parce que le snapshot pré-upgrade était en hold, il a survécu au cycle d’élagage régulier. La restauration a été chirurgicale : cloner le snapshot, extraire les fichiers nécessaires,
et maintenir les opérations pendant qu’ils corrigeaient le multipath.
Cela n’a pas demandé de génie. Cela a demandé une discipline ennuyeuse : snapshot + hold + propriétaire documenté. Le hold a empêché le « nettoyage utile » de détruire la sortie de secours.
Ils ont ensuite supprimé le hold une fois l’incident clos, et le système est revenu à sa politique de rétention normale sans accumuler de barnacles permanents.
Erreurs courantes : symptôme → cause → correction
1) « Nous avons supprimé de vieilles données mais l’espace n’est pas revenu »
Symptôme : REFER du dataset diminue, CAP du pool ne bouge pas.
Cause : Les snapshots référencent toujours les blocs supprimés.
Correction : Mesurez usedbysnapshots, puis élaguer les snapshots selon la politique. Si vous avez besoin des snapshots, séparez les datasets pour isoler le churn.
2) « La destruction de snapshots échoue avec ‘dataset is busy’ ou erreur de dépendance »
Symptôme : zfs destroy refuse, ou le script saute des snapshots.
Cause : Des holds ou des clones existent ; le snapshot est une origin.
Correction : Utilisez zfs holds et zfs get origin. Libérez les holds si autorisé ; détruisez ou promouvez les clones.
3) « La réplication est soudain devenue énorme ou lente »
Symptôme : Les envois incrémentiels gonflent ; le retard de réplication augmente.
Cause : Des snapshots communs manquent à cause d’une rétention ou d’un élagage décalés sur un côté.
Correction : Établissez des ancres de réplication conservées sur les deux côtés. Validez avec zfs list -t snapshot sur source et destination.
4) « Nous avons des milliers de snapshots et personne ne sait ce que c’est »
Symptôme : Noms inconsistants, propriété inconnue.
Cause : Pas de convention de nommage ; pas de métadonnées ; plusieurs outils créent des snapshots.
Correction : Standardisez les noms par classe + timestamp UTC. Ajoutez des propriétés utilisateur pour propriétaire et classe de rétention. Stoppez les créateurs de snapshots non autorisés.
5) « Les performances ont empiré à mesure que nous ajoutions des snapshots »
Symptôme : Latence en hausse ; le pool semble « lourd » sous charge.
Cause : Utilisation élevée du pool + fragmentation + churn dû aux snapshots fréquents amplifient les coûts de métadonnées CoW et d’allocation.
Correction : Gardez CAP sous contrôle (objectif < 80%). Réduisez la rétention haute fréquence sur les datasets churn. Envisagez une refonte des datasets et une expansion de capacité.
6) « L’élagage s’exécute, mais le nombre de snapshots n’arrête pas d’augmenter »
Symptôme : L’automatisation rapporte un succès, mais les anciens snapshots restent.
Cause : Les filtres du script ne correspondent pas aux noms ; snapshots en hold ; permissions ; ou l’élagage opère sur le mauvais périmètre de dataset.
Correction : Validez en listant les snapshots ciblés pour suppression avant de supprimer. Ajoutez du monitoring sur le nombre de snapshots par classe et le nombre de holds.
7) « Les restaurations sont peu fiables ou incohérentes pour les bases de données »
Symptôme : La restauration démarre mais la DB a besoin d’une récupération, ou les données sont logiquement corrompues.
Cause : Snapshot du système de fichiers sans coordination applicative.
Correction : Utilisez des mécanismes natifs DB (freeze/flush, checkpoints cohérents) autour du timing des snapshots, ou répliquez avec des outils DB et snapshottez les réplicas.
Listes de contrôle / plan pas à pas
Pas à pas : implémenter une politique de rétention sans créer un nouvel incident
-
Inventairez les datasets et classez par churn/valeur.
Regroupez en : bases de données, images VM, données utilisateurs, logs, scratch. Si tout est dans un seul dataset, vous avez déjà trouvé le problème n°1. -
Définissez RPO/RTO par classe.
N’autorisez pas « on veut tout pour toujours » à moins qu’ils aient apporté un bon de commande. - Choisissez des paliers de rétention (horaire/journalier/hebdo/mensuel) et des comptes par classe.
- Adoptez un schéma de nommage utilisant des timestamps UTC et le préfixe de classe.
- Implémentez l’automatisation pour la création des snapshots avec le périmètre correct et un nommage cohérent.
-
Implémentez l’automatisation pour l’élagage qui :
- conserve les N plus récents par classe
- ne supprime jamais les snapshots en hold
- est conscient des clones (ou au moins signale les clones bloquants)
- journalise ce qu’il a supprimé et ce qu’il n’a pas pu supprimer
- Mettez en place des garde-fous de capacité : alertez à 75 % et 80 % d’utilisation du pool ; traitez 85 % comme critique selon la charge.
-
Testez les restaurations trimestriellement, pas pendant les incidents.
La restauration est une fonctionnalité produit. Si vous ne la testez pas, vous ne l’avez pas. - Alignez la réplication avec des ancres et une autorité de rétention (source vs destination).
- Documentez la procédure pour les « snapshots spéciaux » : prendre snapshot, appliquer un tag de hold avec l’ID du ticket, définir un propriétaire/expiration, et exiger la suppression quand c’est clos.
Checklist opérationnelle : le jour où « le pool se remplit »
- Confirmez CAP et identifiez les principaux datasets par
usedbysnapshots. - Listez les plus gros snapshots par USED et vérifiez holds/clones.
- Élaguer d’abord les snapshots haute fréquence sur les datasets churn (horaire), tout en préservant les ancres de réplication.
- Si l’espace ne se libère toujours pas, chassez les clones et les holds de longue durée.
- Si vous êtes proche de 90% CAP, planifiez un soulagement d’urgence de capacité (déplacer des données, étendre le pool) tout en élaguant — ne choisissez pas l’un et espérez pour l’autre.
Checklist de conception : prévenir structurellement l’enfer des snapshots
- Séparez les chemins à fort churn en datasets dédiés.
- Désactivez atime là où ce n’est pas requis.
- Décidez quel système est le magasin de « longue rétention » (souvent la cible de réplication).
- N’utilisez les holds qu’avec un propriétaire et une date d’expiration.
- Surveillez le nombre de snapshots et l’espace occupé par les snapshots, pas seulement le CAP du pool.
- Gardez le nommage cohérent entre hôtes pour simplifier les outils.
FAQ
Les snapshots ralentissent-ils ZFS ?
Pas intrinsèquement. Ils vous ralentissent indirectement en augmentant les blocs retenus, ce qui pousse l’utilisation du pool, augmente le travail d’allocation et peut amplifier la fragmentation.
Aussi, plus de métadonnées et un partage de blocs plus complexe peuvent rendre certaines opérations plus lourdes.
Pourquoi le chiffre USED d’un snapshot change-t-il avec le temps ?
Parce que USED est « les blocs uniques qui seraient libérés si ce snapshot était détruit ». À mesure que le dataset vivant change, le snapshot devient la dernière référence pour des blocs plus anciens,
donc sa propriété unique peut augmenter.
Combien de snapshots est-ce trop ?
Mauvaise question. La bonne question est : combien d’espace les snapshots retiennent-ils, et pouvez-vous restaurer ce dont vous avez besoin dans votre RPO/RTO ?
Vous pouvez avoir des milliers de snapshots avec peu de churn et être tranquille ; vous pouvez avoir 200 snapshots sur un dataset VM à fort churn et être fauché.
Faut-il conserver une longue rétention sur la source ou la cible de réplication ?
Préférez la longue rétention sur la cible de réplication. Gardez la source légère pour la performance et pour des envois incrémentiels petits.
Conservez des ancres explicites sur les deux côtés pour préserver la réplication incrémentielle.
Quelle est la manière la plus sûre de supprimer des snapshots ?
La plus sûre signifie : vous savez pourquoi le snapshot existe, vous savez ce qui dépend de lui (holds/clones/réplication), et vous supprimez selon une politique.
Commencez par lister les snapshots par USED, vérifiez les holds, vérifiez les relations origin/clone, puis supprimez du plus ancien au plus récent dans la classe que vous élaguez.
Puis-je snapshotter une base de données en toute sécurité sans coordination ?
La cohérence du système de fichiers n’est pas équivalente à la cohérence applicative. Certaines bases récupèrent proprement ; d’autres nécessitent une récupération longue ou souffrent de problèmes logiques.
Coordonnez les snapshots avec la base (flush/freeze), ou snapshottez un réplica conçu pour les sauvegardes.
Pourquoi l’élagage n’a-t-il pas libéré autant d’espace que prévu ?
Parce que les snapshots que vous avez supprimés ne détenaient pas de façon unique les blocs que vous imaginiez, ou d’autres snapshots référencent encore ces blocs.
Vérifiez aussi les clones : un clone peut retenir des blocs même après l’élagage des snapshots.
Les holds sont-ils un bon mécanisme de rétention à long terme ?
Non. Les holds sont un garde-fou pour des snapshots exceptionnels, pas un moteur de politique. Si vous utilisez des holds comme rétention, vous accumulerez des snapshots permanents sans propriétaire clair,
et votre système d’élagage deviendra mensonger.
Quelle politique de rétention devrais-je démarrer si je suis dépassé ?
Commencez par : hourly 48, daily 35, weekly 12, monthly 18 — puis ajustez selon le churn des datasets. Placez images VM et bases de données dans des datasets séparés et raccourcissez leur rétention locale.
Faites de la cible de réplication votre magasin de longue durée.
Comment empêcher des outils de créer des snapshots aléatoires ?
Standardisez l’automatisation des snapshots en un seul endroit, limitez les accès administratifs, et surveillez les taux de création et la conformité du nommage.
Si des snapshots apparaissent avec des préfixes inconnus, considérez cela comme un problème de dérive de configuration, pas comme une curiosité.
Conclusion : étapes pratiques suivantes
L’enfer des snapshots est une défaillance de politique déguisée en costume de stockage. ZFS vous a donné le mécanisme ; vous lui devez encore de la gouvernance.
Si vous voulez arrêter de vivre dans la peur de zfs destroy, faites le travail une fois et gardez-le ennuyeux.
- Mesurer : collectez
usedbysnapshotspar dataset et alertez sur les tendances de croissance. - Classer : séparez les datasets par churn et valeur pour qu’un workload ne puisse pas ruiner le pool.
- Standardiser : adoptez un schéma de nommage et ajoutez des propriétés utilisateur pour la propriété et la classe de rétention.
- Automatiser : créez et élaguez les snapshots selon un planning, en tenant compte des clones/holds et avec un vrai logging.
- Aligner la réplication : conservez des ancres sur les deux côtés ; poussez la longue rétention vers la cible.
- Pratiquer les restaurations : testez le chemin important avant d’en avoir besoin à 3 h du matin.
Faites cela et les snapshots deviendront ce qu’ils ont toujours été destinés à être : un bouton d’annulation rapide et fiable — pas un site archéologique.