Snapshots ZFS : la superpuissance qui peut aussi remplir votre pool

Cet article vous a aidé ?

Les snapshots ZFS sont la chose la plus proche que les ingénieurs stockage ont du voyage dans le temps. Ils permettent de revenir à l’état d’un dataset, récupérer un fichier que quelqu’un « n’a pas supprimé », et transférer des données cohérentes vers une autre machine sans arrêter les services. Vous pouvez en prendre toutes les minutes et mieux dormir — jusqu’à ce que vous vous réveilliez avec un pool à 98% et un cluster qui soudain traite fsync() comme une suggestion.

Ce texte s’adresse aux personnes qui gèrent des systèmes de production, pas aux démonstrations de laboratoire. Nous couvrirons ce que les snapshots coûtent réellement, comment la comptabilité d’espace vous induit en erreur (sincèrement), et comment appliquer une rétention sans transformer votre planning de snapshots en un déni de service au ralenti. En chemin : des commandes à exécuter aujourd’hui, trois histoires du monde de l’entreprise que vous reconnaitrez, et un guide de diagnostic rapide pour quand le pool se remplit plus vite que la batterie de votre pager.

Ce qu’un snapshot ZFS est réellement (et n’est pas)

Un snapshot ZFS est une référence en lecture seule à l’état d’un dataset à un instant donné. ZFS utilise le copy-on-write : lorsque des données changent, ZFS écrit de nouveaux blocs puis met à jour les métadonnées pour y pointer. Les anciens blocs restent jusqu’à ce qu’aucune référence ne les désigne. Un snapshot est simplement « quelque chose d’autre qui référence encore les anciens blocs ».

C’est pourquoi les snapshots sont rapides à créer : ZFS ne copie pas votre dataset ; il fixe des références. Et c’est aussi pourquoi les snapshots peuvent « utiliser » beaucoup d’espace plus tard : ce n’est pas parce qu’ils grossissent d’eux‑mêmes, mais parce qu’ils empêchent la libération des anciens blocs lorsque le dataset actif change.

Le modèle mental qui évite les pannes

Pensez à votre dataset comme une playlist, pas un dossier. Les blocs sont les chansons. Quand vous « éditez » la playlist, ZFS n’édite pas les chansons en place ; il écrit de nouvelles chansons et pointe la playlist vers elles. Un snapshot est une version sauvegardée de la playlist qui continue de pointer vers les anciennes chansons. Si vous continuez d’éditer, vous accumulez de vieilles chansons que les snapshots référencent encore.

Si cette métaphore paraît trop douce pour la production : les snapshots sont des « racines du ramasse-miettes ». Ils maintiennent les blocs en vie. Si vous créez beaucoup de racines et que vous modifiez fortement le tas, vous remplirez la mémoire. Ici, la mémoire, c’est votre pool.

Les snapshots ne sont pas des sauvegardes (la plupart du temps)

Les snapshots vous protègent contre des problèmes logiques : suppressions accidentelles, mauvais déploiements, ransomware que vous détectez rapidement, ou ce script qui « ne supprime que les vieux fichiers » mais a un off-by-one dans le chemin. Les sauvegardes vous protègent contre des problèmes physiques et existentiels : perte de pool, erreur d’opérateur qui détruit des snapshots, incendie, vol, et « nous avons migré le mauvais dataset et ne l’avons pas remarqué pendant un mois ».

Vous pouvez transformer des snapshots en sauvegardes en les répliquant ailleurs (par exemple zfs send/receive) avec une rétention indépendante. Tant que vous ne le faites pas, les snapshots sont un filet de sécurité attaché à la même trapeze.

Blague #1 : Un snapshot, c’est comme « annuler », sauf qu’il n’oublie jamais et il vous facture en térabytes.

Faits & contexte : pourquoi les snapshots sont devenus importants

Un peu de contexte historique et technique aide à expliquer pourquoi la prise de snapshots ZFS semble magique — et pourquoi elle peut surprendre des équipes venant de systèmes de fichiers traditionnels ou de LVM.

  1. ZFS a livré les snapshots en tant que fonctionnalité de première classe alors que beaucoup de systèmes de fichiers traitaient les snapshots comme un ajout (gestionnaire de volumes, fonctionnalité d’array, ou outil propriétaire).
  2. Le copy-on-write est l’enabler : ZFS peut snapshotter à faible coût parce qu’il n’écrase jamais les blocs en place ; il écrit de nouveaux blocs et bascule les pointeurs.
  3. La comptabilité d’espace a évolué dans le temps : les implémentations initiales et les anciens outils confondaient souvent « référencé », « utilisé » et tailles « logiques », ce qui menait à des tableaux de bord incohérents dans des environnements mixtes.
  4. Les environnements Solaris ont standardisé des politiques agressives bien avant que les conteneurs rendent l’« infrastructure immuable » à la mode ; des schémas quotidiens/horaire/minutés étaient courants dans les workflows NAS d’entreprise.
  5. Les snapshots sont scopiés par dataset, pas par pool. Cela a de l’importance quand des gens supposent « une seule politique de rétention pour tout le pool » se comportera de la même façon partout.
  6. Les clones ont rendu les snapshots plus dangereux (dans le bon sens) : un clone dépend de son snapshot. Les suppressions sont bloquées, et votre job « élaguer les vieux snaps » devient soudain un menteur.
  7. Les images VM et les bases de données ont changé la donne : les charges d’écriture aléatoire modifient rapidement les blocs, faisant accumuler des blocs référencés beaucoup plus vite qu’une charge majoritairement append-only.
  8. « Pool plein » est devenu une classe d’incident opérationnel car les performances et le comportement d’allocation de ZFS se dégradent fortement en haute utilisation ; ce n’est pas juste « plus d’espace », c’est « tout devient lent puis des erreurs apparaissent ».
  9. Les snapshots peu coûteux ont rendu la politique de rétention plus politique : une fois que les équipes savent qu’on peut garder 30 jours « gratuitement », quelqu’un demandera 365 jours « pour la conformité ».

La vérité inconfortable : comment les snapshots « utilisent » l’espace

La mauvaise hypothèse la plus courante est : « Les snapshots sont bon marché, donc ils sont petits. » La création est peu coûteuse. L’espace, lui, n’est pas garanti.

Trois types de « taille » que vous verrez

ZFS rapporte plusieurs métriques qui répondent à des questions différentes :

  • logicalused : combien de données sont stockées logiquement (ignore la compression, les copies, etc.).
  • used : combien d’espace est utilisé sur disque du point de vue de ce dataset (inclut des choses comme des snapshots selon les flags/propriétés affichés).
  • referenced : l’espace qui serait libéré si le dataset était détruit (la vue « unique » live, excluant l’espace tenu uniquement par des snapshots).
  • usedbysnapshots / usedbydataset / usedbychildren : une ventilation qui met fin aux discussions en réunion.

Les snapshots « utilisent » l’espace des blocs qui ne sont plus référencés par le dataset live mais qui sont toujours référencés par un ou plusieurs snapshots. Cela signifie que l’utilisation liée aux snapshots est proportionnelle au taux de changement, pas à la taille totale du dataset. Un dataset de 10 To avec peu de churn peut avoir des années de snapshots avec un surcoût modéré ; un datastore VM de 500 Go avec un fort churn peut dévorer un pool en un week-end.

Pourquoi la suppression de fichiers ne libère pas l’espace (parfois)

Vous supprimez un répertoire de 200 Go. Les utilisateurs applaudissent. Le monitoring ne bouge pas. Ce sont les snapshots qui font leur travail : ils référencent encore les blocs, donc le pool ne peut pas les libérer. C’est aussi pourquoi les « scripts de nettoyage » peuvent être trompeurs dans des systèmes riches en snapshots : ils réduisent l’espace référencé par le live, mais pas l’allocation du pool, tant que les vieux snapshots ne sont pas supprimés.

« Mais nous ne snapshottons que /var/log, jusqu’où ça peut aller ? »

Les schémas append-only sont amicaux pour les snapshots. Mais beaucoup de systèmes ne sont pas append-only :

  • Images VM : métadonnées de système de fichiers invité qui churnent, petites écritures aléatoires, rotation de logs à l’intérieur des invités.
  • Bases de données : checkpointing et compactage peuvent réécrire de larges régions.
  • Caches de build et espaces CI : schémas supprimer-et-recréer qui modifient tout.
  • Couches de conteneurs : rebuilds fréquents ; beaucoup de petits fichiers changent.

La falaise « pool plein » est réelle

Beaucoup d’équipes traitent 95% d’utilisation comme « il reste encore 5% ». Dans ZFS, ces derniers 5% sont souvent l’endroit où les performances meurent, surtout sur des pools avec fragmentation, petite recordsize, ou écriture aléatoire élevée. Les allocations de métadonnées deviennent plus difficiles, l’espace libre devient fragmenté, et des charges de travail qui étaient correctes à 70% commencent à timeout à 92%.

Blague #2 : ZFS à 98% c’est comme une valise à l’aéroport : elle se ferme encore, mais tout le monde transpire et la fermeture éclair est sur le point de lâcher.

La suppression de snapshots ne libère pas toujours l’espace immédiatement

La destruction de snapshots libère généralement de l’espace rapidement, mais pas toujours instantanément comme les humains l’attendent :

  • Frees en attente peuvent différer la reclamation effective ; vous pourriez voir un décalage « en cours de libération ».
  • Holds peuvent bloquer totalement la suppression.
  • Clones peuvent garder des blocs référencés même après des tentatives de suppression de snapshot (ou empêcher leur suppression).
  • Périphériques spéciaux / métadonnées peuvent compliquer l’endroit où la pression se manifeste (par exemple, un special vdev se remplissant alors que le vdev principal semble correct).

Tâches pratiques (commandes + interprétation)

Voici des tâches opérationnelles réelles que vous pouvez exécuter pendant un jour calme pour comprendre l’empreinte de vos snapshots — ou pendant une journée bruyante pour arrêter l’hémorragie. Les commandes supposent un prompt de type Linux et les outils OpenZFS.

Tâche 1 : Obtenir la vérité sur la capacité et la santé du pool

cr0x@server:~$ zpool status -v
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 00:12:31 with 0 errors on Sun Dec 22 01:10:03 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          mirror-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0

errors: No known data errors

Interprétation : Si le pool n’est pas sain, nettoyer les snapshots n’est pas la première action à mener. Un vdev dégradé, un resilver en cours ou des erreurs de checksum peuvent changer les symptômes de performance et le seuil de tolérance. Les résultats du scrub vous indiquent aussi si vous avez affaire à une « pression d’espace » ou à une « pression d’intégrité des données ».

cr0x@server:~$ zpool list -o name,size,alloc,free,capacity,health,fragmentation
NAME  SIZE  ALLOC   FREE  CAPACITY  HEALTH  FRAG
tank  20T   17.8T   2.2T      89%  ONLINE    43%

Interprétation : La capacité et la fragmentation importent ensemble. 89% et 43% de fragmentation sur un pool à écritures aléatoires est une bête différente que 89% et 5% sur un pool append-only.

Tâche 2 : Lister les datasets avec une ventilation sensible aux snapshots

cr0x@server:~$ zfs list -o name,used,avail,refer,usedbysnapshots,usedbydataset,usedbychildren -r tank
NAME              USED  AVAIL  REFER  USEDSNAP  USEDDS  USEDCHILD
tank              17.8T  2.2T   256K   0B       256K    17.8T
tank/home         1.2T   2.2T   980G   220G     980G    0B
tank/vm           12.9T  2.2T   3.1T   9.8T     3.1T    0B
tank/db           3.4T   2.2T   1.9T   1.5T     1.9T    0B

Interprétation : Ceci est votre manchette. tank/vm a 9.8T « used by snapshots ». Cela ne signifie pas que les snapshots sont des copies de 9.8T ; cela signifie que tant de données anciennes sont épinglées par les snapshots. L’empreinte live référencée n’est que de 3.1T.

Tâche 3 : Compter les snapshots par dataset (détecteur de dérive de rétention)

cr0x@server:~$ zfs list -H -t snapshot -o name | awk -F@ '{print $1}' | sort | uniq -c | sort -nr | head
  4320 tank/vm
   720 tank/db
   120 tank/home

Interprétation : 4320 snapshots signifie souvent « toutes les 10 minutes pendant 30 jours » ou « chaque minute pendant 3 jours », selon le schéma de nommage. Dans tous les cas : c’est beaucoup de métadonnées et beaucoup d’historique épinglé si le churn est élevé.

Tâche 4 : Trouver les snapshots les plus lourds (par used)

cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -s used | tail -n 10
tank/vm@auto-2025-12-24-2300   48G   3.1T  Wed Dec 24 23:00 2025
tank/vm@auto-2025-12-24-2200   47G   3.1T  Wed Dec 24 22:00 2025
tank/vm@auto-2025-12-24-2100   46G   3.1T  Wed Dec 24 21:00 2025
tank/db@auto-2025-12-24-2300   18G   1.9T  Wed Dec 24 23:00 2025
tank/vm@auto-2025-12-24-2000   44G   3.1T  Wed Dec 24 20:00 2025
tank/vm@auto-2025-12-24-1900   44G   3.1T  Wed Dec 24 19:00 2025
tank/vm@auto-2025-12-24-1800   43G   3.1T  Wed Dec 24 18:00 2025
tank/vm@auto-2025-12-24-1700   42G   3.1T  Wed Dec 24 17:00 2025
tank/db@auto-2025-12-24-2200   16G   1.9T  Wed Dec 24 22:00 2025
tank/vm@auto-2025-12-24-1600   41G   3.1T  Wed Dec 24 16:00 2025

Interprétation : Le used d’un snapshot est « l’espace détenu de façon unique par ce snapshot ». Les grands nombres indiquent en général un fort churn entre snapshots. Si vous voyez des dizaines de deltas horaires de 40–50G, votre politique de rétention doit être conservatrice sur le temps, pas sur le compte.

Tâche 5 : Voir rapidement quels datasets sont des monstres de churn

cr0x@server:~$ zfs list -o name,refer,usedbysnapshots,compression,recordsize,primarycache -r tank/vm
NAME      REFER  USEDSNAP  COMPRESS  RECSIZE  PRICACHE
tank/vm   3.1T   9.8T      lz4       128K     all

Interprétation : La compression et la recordsize influencent la dynamique du churn. Un mauvais choix de recordsize pour des images VM (souvent mieux entre 16K–64K selon le cas) peut augmenter l’amplification d’écriture et les deltas de snapshot.

Tâche 6 : Confirmer si des holds bloquent la suppression

cr0x@server:~$ zfs holds tank/vm@auto-2025-12-01-0000
NAME                         TAG        TIMESTAMP
tank/vm@auto-2025-12-01-0000 backup     Wed Dec  1 00:00 2025

Interprétation : Un hold est une épingle explicite « ne pas supprimer ». Si votre job de purge prétend avoir supprimé des snapshots mais qu’ils restent, les holds sont un suspect de premier plan.

Tâche 7 : Relâcher un hold (avec précaution) pour permettre la purge

cr0x@server:~$ sudo zfs release backup tank/vm@auto-2025-12-01-0000

Interprétation : Cela ne supprime rien. Cela retire le dispositif de sécurité. Si un job de réplication utilise des holds pour protéger des snapshots « pas encore répliqués », coordonnez-vous avant de relâcher. Le workflow correct : confirmer l’état de réplication, puis relâcher, puis détruire.

Tâche 8 : Détecter les clones qui dépendent des snapshots

cr0x@server:~$ zfs get -H -o name,value origin -r tank | grep -v -- '-'
tank/vm/dev-clone-01    tank/vm@auto-2025-12-15-0000
tank/vm/dev-clone-02    tank/vm@auto-2025-12-20-0000

Interprétation : Si un clone existe, le snapshot d’origine ne peut pas être détruit tant que le clone n’est pas promu ou détruit. Les équipes oublient souvent des clones dev/test puis se demandent pourquoi la rétention « a cessé de fonctionner ».

Tâche 9 : Identifier exactement ce qui empêche la destruction d’un snapshot

cr0x@server:~$ sudo zfs destroy tank/vm@auto-2025-12-15-0000
cannot destroy 'tank/vm@auto-2025-12-15-0000': snapshot has dependent clones

Interprétation : ZFS vous dit la vérité. Votre politique de rétention est maintenant un problème de graphe de dépendances. Soit supprimez les clones, soit promouvez-les, soit ajustez la politique pour conserver les origines plus longtemps.

Tâche 10 : Supprimer des snapshots pendant une fenêtre contrôlée

cr0x@server:~$ sudo zfs destroy tank/vm@auto-2025-12-01-0000

Interprétation : Détruire un snapshot à la fois est plus lent mais plus sûr quand vous découvrez l’environnement. Une fois que vous faites confiance à votre nommage et aux règles de dépendance, vous pouvez supprimer des plages ou utiliser des scripts — mais uniquement après avoir prouvé les sorties.

Tâche 11 : Supprimer une plage de snapshots par motif (surgical, pas casual)

cr0x@server:~$ zfs list -H -t snapshot -o name -s creation | grep '^tank/vm@auto-2025-11' | head -n 5
tank/vm@auto-2025-11-01-0000
tank/vm@auto-2025-11-01-0100
tank/vm@auto-2025-11-01-0200
tank/vm@auto-2025-11-01-0300
tank/vm@auto-2025-11-01-0400

cr0x@server:~$ zfs list -H -t snapshot -o name -s creation | grep '^tank/vm@auto-2025-11' | wc -l
720

cr0x@server:~$ zfs list -H -t snapshot -o name -s creation | grep '^tank/vm@auto-2025-11' | sudo xargs -n 50 zfs destroy

Interprétation : D’abord afficher, puis compter, puis détruire. Le découpage -n 50 évite « argument list too long ». Si un snapshot dans la liste a des holds ou des clones, la commande échouera pour ceux-ci ; vous devez inspecter les échecs et ne pas supposer que tout le lot a réussi.

Tâche 12 : Surveiller la reclamation d’espace après des suppressions (et ne pas paniquer)

cr0x@server:~$ zpool list -o name,alloc,free,capacity
NAME  ALLOC   FREE  CAPACITY
tank  17.8T   2.2T      89%

cr0x@server:~$ sudo zfs destroy tank/vm@auto-2025-11-01-0000

cr0x@server:~$ zpool list -o name,alloc,free,capacity
NAME  ALLOC   FREE  CAPACITY
tank  17.7T   2.3T      88%

Interprétation : La reclamation peut être graduelle. Si vous êtes sous pression, supprimez assez pour retrouver un espace sécurité (souvent 15–20% libres selon la charge), pas « juste un snapshot ».

Tâche 13 : Trouver des datasets avec des réservations inattendues (espace inutilisable)

cr0x@server:~$ zfs get -o name,property,value -r tank | egrep 'refreservation|reservation' | grep -v '0$'
tank/vm  refreservation  2T

Interprétation : Une refreservation peut faire paraître un pool « plus plein » car c’est un espace garanti. Ce n’est pas un problème de snapshot, mais cela apparaît souvent pendant un incident lié aux snapshots parce que tout le monde se demande « où est passé mon espace libre ? »

Tâche 14 : Mesurer le taux de création de snapshots et la santé send/receive (environnements de réplication)

cr0x@server:~$ zfs list -t snapshot -o name,creation -s creation | tail -n 5
tank/vm@auto-2025-12-24-2000  Wed Dec 24 20:00 2025
tank/vm@auto-2025-12-24-2100  Wed Dec 24 21:00 2025
tank/vm@auto-2025-12-24-2200  Wed Dec 24 22:00 2025
tank/vm@auto-2025-12-24-2300  Wed Dec 24 23:00 2025
tank/vm@auto-2025-12-25-0000  Thu Dec 25 00:00 2025

Interprétation : Si les snapshots arrivent mais que la réplication ne suit pas, vous accumulerez des holds « à garder jusqu’à réplication » (manuels ou gérés par outil), et la rétention se bloquera. Opérationnellement, « explosion de snapshots » est souvent un problème de retard de réplication déguisé en incident stockage.

Playbook de diagnostic rapide : goulots et consommation incontrôlée

Ceci est la séquence « le pager sonne ». L’objectif est d’identifier si vous êtes face à (a) une vraie exhaustion d’espace, (b) un échec de rétention de snapshots, (c) des réservations/pression sur special vdev, ou (d) un effondrement de performance parce que vous êtes proche du plein et fragmenté.

Première étape : confirmer le rayon d’impact

  1. Capacité et santé du pool : vérifier zpool list et zpool status.
  2. Est‑ce un dataset ou plusieurs ? vérifier zfs list -o name,usedbysnapshots,refer -r POOL.
  3. Y a‑t‑il une pression sur un vdev spécial ? si vous utilisez un périphérique spécial, cherchez‑le dans zpool status et comparez les symptômes à des charges orientées métadonnées.

Seconde étape : décider si c’est « blocs épinglés par snapshots » ou « autre chose »

  1. Empreinte des snapshots : les datasets avec un haut usedbysnapshots sont généralement les coupables.
  2. Dérive du nombre de snapshots : compter les snapshots par dataset ; des pics soudains indiquent souvent un job de rétention en échec, un changement de nommage, ou un doublement d’ordonnancement.
  3. Réservations : vérifier refreservation/reservation ; ne supprimez pas des snapshots pour compenser une réservation définie par quelqu’un il y a des mois.

Troisième étape : identifier ce qui empêche le nettoyage

  1. Holds : exécuter zfs holds sur les snapshots les plus anciens que vous souhaitez supprimer.
  2. Clones : vérifier origin sur les descendants ; les clones bloquent la destruction.
  3. Retard de réplication : si des snapshots sont gardés pour la réplication, vérifiez que le pipeline de réplication est sain avant de relâcher les holds.

Quatrième étape : stabiliser, puis optimiser

  1. Stabiliser : libérer assez d’espace pour éviter la falaise near-full. Si vous êtes au‑dessus de ~90%, visez à redescendre rapidement en dessous.
  2. Arrêter l’hémorragie : suspendre les tâches de création de snapshots ou réduire la fréquence pour les datasets à fort churn pendant l’investigation.
  3. Puis optimiser : revoir recordsize, emplacement des workloads, fréquence/rétention des snapshots et architecture de réplication.

Trois mini-histoires du monde de l’entreprise

1) L’incident causé par une mauvaise hypothèse : « Les snapshots sont à peu près gratuits »

Tout a commencé comme un projet de modernisation sensé : migrer un cluster de virtualisation legacy sur un stockage basé ZFS pour bénéficier du checksumming, de la compression et — le mot favori de tout le monde — des snapshots. L’équipe a mis des snapshots horaires sur le dataset VM et a gardé 30 jours. Cette politique avait fonctionné sur un serveur de fichiers pendant des années, donc cela paraissait sûr.

La mauvaise hypothèse n’était pas sur la justesse de ZFS ; elle portait sur le churn de la charge. Un datastore VM n’est pas un serveur de fichiers. Les OS invités effectuent des petites écritures constantes, mettent à jour des métadonnées, pivotent des logs, et réécrivent des parties de disques virtuels qui « semblent inactives » au niveau applicatif. Le dataset ZFS n’était pas énorme, mais il changeait partout, tout le temps.

Deux semaines plus tard, le pool est monté dans les hauts 80s. Puis dans les hauts 90s. La latence a grimpé en premier — de petites écritures synchrones bloquées par la pression d’allocation et la fragmentation. Les temps de boot des VM sont devenus étranges. Des VM de bases de données ont commencé à lancer des timeouts. Les graphes de stockage ressemblaient à un moniteur cardiaque après un espresso.

La première réaction de l’équipe a été de chasser « le gros fichier » et de le supprimer. Cela n’a presque rien libéré, parce que de vieux blocs étaient épinglés dans des centaines de snapshots horaires. Ce n’est qu’après avoir exécuté une ventilation consciente des snapshots que le schéma est devenu évident : usedbysnapshots portait le pool.

La solution n’a pas été héroïque. Ce fut un nettoyage contrôlé et une réinitialisation de politique : moins de snapshots sur les datasets à fort churn, rétention courte pour les snapshots haute fréquence, et réplication vers une autre machine pour des points de récupération à plus long terme. La leçon retenue : les snapshots sont bon marché à créer, coûteux à conserver sous churn — et votre charge décide de la facture.

2) L’optimisation qui s’est retournée contre eux : « Snapshoter chaque minute »

Une autre organisation avait un vrai problème métier : les développeurs réinitialisaient fréquemment des environnements de test, et l’équipe infra voulait une récupération plus rapide sans restaurer depuis des sauvegardes. Quelqu’un a proposé des snapshots à la minute pour quelques datasets. Sur le papier, c’était élégant : plus de snapshots, granularité de rollback réduite, temps de rebuild réduit.

Pendant un temps, ça a fonctionné. L’équipe a célébré la première grosse sauvegarde : une migration de schéma cassée en staging, restaurée en secondes. Ce succès a créé une incitation subtile : « Si des snapshots à la minute sont bons, pourquoi pas partout ? » Plus de datasets ont rejoint le planning. Personne ne voulait être l’équipe sans filet de sécurité.

Puis le retour de bâton : surcharge de métadonnées de snapshots et complexité opérationnelle. Lister les snapshots est devenu lent sur des datasets fortement snapshottés ; des scripts supposant « quelques dizaines de snapshots » ont commencé à timeout. Le retard de réplication a augmenté car les flux incrémentaux devaient traverser plus de bornes de snapshot, et le côté récepteur a commencé à prendre du retard pendant les heures de pointe.

Et voici la partie qui les a le plus surpris : la fréquence des snapshots n’a pas réduit l’utilisation d’espace comme ils l’espéraient. Avec une charge à fort churn, des snapshots à la minute peuvent en réalité augmenter la diversité des blocs retenus : plus de versions intermédiaires sont épinglées, moins de blocs deviennent « totalement obsolètes » jusqu’à ce que vous supprimiez une tranche beaucoup plus large d’historique. Les deltas étaient petits, mais il y en avait tellement que l’ensemble épinglé restait large.

La solution a été contre-intuitive : moins de snapshots, mais des niveaux plus intelligents. Garder les snapshots minutés sur une fenêtre courte (heures), horaires pour une fenêtre moyenne (jours), quotidiens pour plus long (semaines). Et pour les datasets nécessitant une récupération « oups », déplacer les workflows les plus dangereux (comme les rafraîchissements de BD de test) vers des datasets séparés pour que le churn ne pollue pas tout le reste.

3) La pratique ennuyeuse mais correcte qui a sauvé la mise : « Rétention avec garde-fous »

Cette histoire est presque décevante parce qu’elle n’est pas dramatique. Une société proche de la finance utilisait ZFS sur des serveurs hébergeant à la fois des homes d’utilisateurs et des données applicatives. Leur politique de snapshots était conservatrice et franchement peu sexy : snapshots horaires conservés 48 heures, quotidiens 30 jours, mensuels 12 mois. Ils avaient aussi deux règles ennuyeuses : les snapshots sont nommés de façon prévisible, et la suppression est toujours précédée d’un rapport d’inventaire.

Un vendredi, un bug de déploiement a corrompu l’état applicatif d’une façon qui n’était pas immédiatement évidente. L’application a continué de tourner, mais la qualité des données a décliné. Lundi, le business a remarqué. C’est exactement le scénario où « restaurer depuis la nuit dernière » ne suffit pas — il vous faut plusieurs points dans le temps pour encadrer le moment où la corruption a commencé.

L’équipe infra n’a pas discuté de l’existence des snapshots ni de l’exécution du planning. Ils avaient déjà des points horaires et quotidiens, et des scripts capables de lister et comparer les candidats. Ils ont monté un snapshot, validé des invariants au niveau applicatif, et avancé pas à pas jusqu’à trouver le dernier état sain.

Ils ont récupéré sans remplir le pool, sans inventer un nouveau processus en plein incident, et sans le chaos classique « on a des snapshots mais on ne sait pas ce qu’il y a dedans ». La partie peu glamour qui a compté : ils avaient aussi un garde-fou de capacité strict — alertes à 75/80/85% avec un runbook explicite — donc le pool ne s’est jamais approché de la falaise while they were doing forensic restores.

Les gens aiment acheter de la fiabilité avec des fonctionnalités. Ils ont sauvé la situation grâce à des habitudes.

Erreurs courantes : symptômes et corrections

Erreur 1 : Confondre « referenced » et « used » et déclarer victoire trop tôt

Symptôme : Vous supprimez de grands répertoires, zfs list montre un refer plus bas, mais zpool list change à peine.

Cause : Les snapshots tiennent des blocs anciens. Le dataset live a réduit ; l’allocation du pool non.

Correction : Vérifiez usedbysnapshots et élaguez les snapshots selon la politique de rétention. Validez qu’aucun hold/clone ne bloque la suppression.

Erreur 2 : Élagage aveugle via un motif de nom que vous n’avez pas vérifié

Symptôme : Le job de rétention supprime les mauvais snapshots (ou aucun), ou supprime les plus récents et garde les anciens.

Cause : Format de nommage changé, fuseaux horaires modifiés, plusieurs outils écrivant des préfixes différents, ou l’ordre lexicographique ne correspond pas à l’ordre temporel.

Correction : Triez par creation et non par nom ; validez avec un dry-run avant destruction. Préférez zfs list -s creation comme source de vérité.

Erreur 3 : Ignorer les clones et se demander pourquoi la destruction échoue

Symptôme : cannot destroy ... snapshot has dependent clones

Cause : Quelqu’un a créé un clone pour dev/test ou analyse et l’a oublié.

Correction : Trouvez les clones via zfs get origin. Décidez : détruire le clone, ou le promouvoir s’il doit vivre indépendamment, puis revoir la rétention.

Erreur 4 : Des holds utilisés par la réplication, mais personne ne surveille le retard de réplication

Symptôme : Le nombre de snapshots croît ; les suppressions échouent silencieusement ; l’âge du « plus ancien snapshot » augmente.

Cause : L’outil de réplication applique des holds jusqu’à ce qu’un snapshot soit transféré en toute sécurité ; la réplication prend du retard et l’ensemble des holds grossit.

Correction : Surveillez la réplication de bout en bout. Lors de la réponse à l’incident, confirmez le dernier snapshot répliqué avant de relâcher les holds. Réparez le pipeline plutôt que de lutter contre les symptômes.

Erreur 5 : Faire chauffer le pool

Symptôme : Pics de latence, ralentissements d’allocation, parfois des erreurs proches d’ENOSPC alors que « df montre de l’espace ».

Cause : Forte utilisation du pool et fragmentation provoquent un effondrement de performance, surtout sur les écritures aléatoires.

Correction : Restaurez une marge de sécurité. Définissez des SLO opérationnels pour la capacité (alertez tôt). Réévaluez la rétention des snapshots et le placement des workloads.

Erreur 6 : Traiter un special vdev de métadonnées comme une amélioration magique

Symptôme : Le pool principal montre de l’espace libre, mais le système échoue encore à écrire ou les performances s’effondrent ; le special vdev est plein.

Cause : Le special vdev est rempli (métadonnées/petits blocs). Les snapshots et le churn de petits fichiers peuvent amplifier la pression sur les métadonnées.

Correction : Surveillez l’allocation du special vdev. Conservez une marge de sécurité aussi là‑dessus. Envisagez d’ajuster special_small_blocks et les politiques de snapshot, et planifiez la capacité pour la croissance des métadonnées.

Listes de contrôle / plan étape par étape

Étape par étape : construire une politique de rétention de snapshots qui n’engloutit pas votre pool

  1. Classifiez les datasets par churn : images VM, bases de données, caches CI, homes utilisateurs, logs. N’appliquez pas un seul planning à tous.
  2. Définissez les objectifs de récupération : « Je veux un rollback horaire sur deux jours » est un besoin. « Tout garder indéfiniment » est un souhait.
  3. Utilisez une rétention tierée : fenêtre courte à haute fréquence + fenêtre longue à basse fréquence. C’est ainsi que vous obtenez de la granularité sans épingler indéfiniment.
  4. Séparez les workloads risqués : placez les caches CI et les espaces scratch dans leurs propres datasets avec des politiques de purge agressives.
  5. Rendez les noms de snapshots prévisibles : préfixe cohérent + timestamp de type ISO. La prévisibilité évite les bugs de suppression.
  6. Décidez comment gérer holds/clones : documentez qui peut cloner, combien de temps les clones vivent, et comment les origines sont protégées.
  7. Ajoutez des garde-fous de capacité : alertes à 75/80/85% et une politique « arrêter la création de snapshots à X% » pour les datasets non critiques.
  8. Répétez les restaurations : monter un snapshot et restaurer un fichier doit être routinier, pas un art de minuit.

Étape par étape : récupérer l’espace en toute sécurité lors d’un incident de capacité lié aux snapshots

  1. Geler les changements : suspendre les plannings de création de snapshots s’ils empirent la situation (surtout les jobs à la minute).
  2. Trouver les principaux consommateurs de snapshots : zfs list -o name,usedbysnapshots -r POOL.
  3. Identifier les bloqueurs : holds et clones sur les snapshots les plus anciens que vous voulez retirer.
  4. Supprimer d’abord les snapshots les plus anciens : ils épinglent généralement l’histoire la plus large. Évitez de supprimer des « points de récupération récents » sauf si nécessaire.
  5. Recontrôler la capacité du pool : ne vous arrêtez pas à « c’est passé de 98% à 96% ». Revenez à une marge de sécurité.
  6. Correction post-incident : ajuster les niveaux de rétention, affiner la fréquence des snapshots par classe de dataset, et réparer le retard de réplication si applicable.

Étape par étape : audit hebdomadaire de routine (la pratique ennuyeuse)

  1. Revoir zpool list et les tendances de fragmentation.
  2. Revoir les principaux datasets par usedbysnapshots.
  3. Vérifier le nombre de snapshots par dataset ; signaler les outliers.
  4. Rechercher les vieux snapshots avec des holds inattendus.
  5. Scanner les clones oubliés et décider s’ils doivent être promus ou supprimés.

FAQ

1) Les snapshots ZFS copient-ils tout le dataset ?

Non. Ils fixent des références aux blocs existants. L’impact sur l’espace vient des modifications ultérieures : les vieux blocs ne peuvent pas être libérés tant que des snapshots les référencent.

2) Pourquoi zfs list montre une énorme utilisation des snapshots sur un dataset qui « n’a pas beaucoup changé » ?

Quelque chose a changé plus que vous ne le pensez. Les images VM, les bases de données et les charges de petits fichiers peuvent churner des blocs même si les données applicatives semblent stables. Vérifiez aussi que vous lisez usedbysnapshots et que vous ne confondez pas avec refer.

3) Si je supprime un gros répertoire, quand récupère‑t‑on l’espace ?

Vous le récupérez quand aucun snapshot ne référence ces blocs. Si des snapshots datant d’avant la suppression existent, les blocs restent épinglés tant que ces snapshots ne sont pas détruits (ou jusqu’à ce qu’ils expirent selon la rétention).

4) Pourquoi ne puis‑je pas détruire un snapshot ?

Raisons communes : il a des clones dépendants, ou il a des holds. Vérifiez avec zfs holds SNAP et trouvez les clones avec zfs get origin -r.

5) Supprimer des snapshots nuira‑t‑il aux performances ?

La suppression de nombreux snapshots peut générer des E/S et une charge CPU, surtout sur des systèmes occupés, et peut entrer en concurrence avec la charge. Mais l’alternative — fonctionner near-full — est souvent pire. Faites des suppressions en lots contrôlés et observez la latence.

6) Des snapshots plus fréquents sont‑ils toujours mieux ?

Non. Des snapshots plus fréquents améliorent la granularité de récupération, mais peuvent augmenter la surcharge de métadonnées et garder plus de versions intermédiaires épinglées. La rétention en tiers bat généralement « snapshots à la minute pour toujours ».

7) Combien d’espace libre dois‑je garder dans un pool ZFS ?

Il n’y a pas un chiffre unique, mais beaucoup d’équipes de production traitent ~80–85% comme un plafond « soft » pour des charges mixtes, et moins encore pour des pools à écriture aléatoire lourde. L’important est de laisser assez d’espace libre contigu-ish pour éviter la douleur d’allocation et les spirales de fragmentation.

8) Les snapshots protègent‑ils contre les ransomwares ?

Les snapshots peuvent protéger contre un ransomware qui chiffrement des fichiers — si l’attaquant ne peut pas supprimer les snapshots. Si un attaquant obtient des accès privilégiés, il peut aussi détruire les snapshots. Répliquez les snapshots vers un système séparé avec des identifiants restreints et une rétention indépendante si vous voulez une vraie résilience.

9) Pourquoi l’affichage de l’utilisation des snapshots diffère‑t‑il entre serveurs ?

Les différences peuvent venir des valeurs par défaut de reporting des propriétés, des feature flags, de la compression, de la recordsize et du churn de la charge. Comparez toujours en utilisant des colonnes explicites (par ex. usedbysnapshots) et des commandes cohérentes.

10) Est‑il acceptable de snapshotter des bases de données ?

Oui, avec précaution. Pour des snapshots crash‑consistents, vous pouvez avoir besoin d’une coordination applicative (flush/checkpoint) selon la base et les attentes de récupération. Attendez‑vous aussi à un churn plus élevé et planifiez la rétention en conséquence.

Conclusion

Les snapshots ZFS sont une superpuissance parce qu’ils transforment le temps en un primitif opérationnel : vous pouvez créer rapidement des points de restauration cohérents, souvent sans interrompre les workloads. Le piège est que le temps n’est pas gratuit. Chaque snapshot est une promesse de se souvenir d’anciens blocs, et les datasets à fort churn collecteront ces promesses comme des intérêts.

Gérez les snapshots comme toute autre fonctionnalité de production : mesurez le taux de changement, classez les datasets, définissez une rétention tierée, surveillez la capacité tôt, et traitez holds/clones comme des dépendances de première classe. Faites cela, et les snapshots resteront ce qu’ils étaient censés être : le « undo » le plus rapide que vous ayez jamais utilisé — sans transformer votre pool en décharge.

← Précédent
Debian 13 : AppArmor bloque votre service — autorisez ce dont vous avez besoin sans désactiver la sécurité
Suivant →
MySQL vs PostgreSQL : réplicas de lecture — quand ils aident et quand ils mentent

Laisser un commentaire