Supprimer un snapshot ZFS devrait être ennuyeux : zfs destroy pool/fs@snap, et c’est fini. Mais dans les systèmes réels, c’est souvent une scène de série policière : le snapshot est « disparu » et pourtant l’espace ne revient pas, ou la destruction échoue parce que quelque chose—quelque part—en a encore « besoin ».
Ce guide de terrain couvre ces moments. Ce n’est pas une brochure. Nous verrons les raisons techniques pour lesquelles les snapshots refusent de disparaître (holds, clones, datasets occupés, destructions différées, réplication, comptabilité de l’espace) et les correctifs opérationnels qui fonctionnent quand votre pager est déjà chaud.
Ce qu’est vraiment un snapshot ZFS (et pourquoi la suppression n’est pas « gratuite »)
Un snapshot ZFS n’est pas une copie de vos fichiers. C’est une vue figée d’un dataset à une frontière de groupe de transactions : un ensemble de pointeurs de blocs qui dit « ces blocs définissent le système de fichiers à ce moment ». Quand vous modifiez les données actives, ZFS écrit de nouveaux blocs ailleurs (copy-on-write). Les anciens blocs restent référencés par le snapshot. Si vous supprimez le snapshot, ces anciens blocs peuvent devenir non référencés et être éligibles à la libération—si rien d’autre ne les pointe.
C’est pour cela que la suppression d’un snapshot a deux modes d’échec différents :
- L’opération de destroy est bloquée (holds, clones, « dataset is busy »). Vous ne pouvez même pas retirer les métadonnées du snapshot.
- L’opération de destroy réussit mais l’espace ne revient pas (parce que les blocs sont encore référencés par d’autres snapshots, clones, ou parce que la comptabilité d’espace est mal comprise).
Cela veut aussi dire que la suppression peut être coûteuse. ZFS peut devoir parcourir les métadonnées pour déterminer quels blocs deviennent libres. De grands arbres de snapshots avec des années de modifications peuvent rendre les destructions longues—de minutes, voire d’heures—selon la charge du pool, la latence du stockage et les flags de fonctionnalités.
Une vérité opérationnelle : quand on dit « les snapshots sont bon marché », on entend « créer des snapshots est bon marché ». C’est à la suppression que la facture arrive.
Faits intéressants et contexte historique (vous le ressentirez en production)
- Les snapshots ZFS remontent à Sun Microsystems et ont été conçus comme primitive pour le clonage, le rollback et la réplication—bien avant que « sauvegardes immuables » devienne un argument marketing.
- Le copy-on-write explique pourquoi on peut prendre des snapshots sans arrêter les écritures : vous pouvez prendre un snapshot d’un dataset de base de données en activité sans geler les I/O, parce que les nouvelles écritures vont dans de nouveaux blocs.
- Les noms de snapshot font partie de l’espace de noms du dataset :
pool/fs@snapn’est pas un type d’objet séparé comme les snapshots LVM ; il est intimement lié à la comptabilité du dataset. - Les clones sont des snapshots réinscriptibles : un clone est un dataset qui partage initialement tous les blocs avec un snapshot ; cette dépendance est ce qui rend certains snapshots « indestructibles ».
- Les « holds » ont été introduits pour empêcher les suppressions accidentelles lors de workflows comme la réplication, la vérification des sauvegardes, et le provisioning basé sur snapshots.
- La destruction différée existe parce que la suppression peut être lente : ZFS peut marquer un snapshot pour nettoyage ultérieur afin que la commande retourne rapidement tandis que la libération se fait en arrière-plan.
- L’espace n’est pas un seul nombre dans ZFS : « used », « refer », « logicalused », « written »,
usedbysnapshots, etusedbychildrenrépondent à des questions différentes. Les gens choisissent couramment la mauvaise métrique sous pression. - La compression change l’intuition : un snapshot peut « retenir » des blocs qui paraissent énormes logiquement mais minimes physiquement—ou l’inverse avec des changements de recordsize et des réécritures.
Et une petite blague, parce qu’on l’a méritée : les snapshots ZFS sont comme des chaises de bureau—faciles à ajouter, étrangement difficiles à enlever, et vous ne remarquez le coût que quand le couloir est encombré.
Méthode de diagnostic rapide (vérifiez ceci en premier)
Voici la séquence que j’utilise quand quelqu’un dit « nous avons supprimé des snapshots mais l’espace n’est pas revenu », ou « la destruction échoue et on ne sait pas pourquoi ». L’objectif est d’identifier rapidement le goulot d’étranglement, pas d’admirer la complexité philosophique du pool.
1) Le snapshot a-t-il vraiment disparu, ou est-ce différé ?
Vérifiez d’abord si vous êtes face à une situation de destruction différée. ZFS peut accepter la destruction mais libérer les blocs plus tard.
2) Y a-t-il des holds ?
Les holds sont le premier coupable quand on dit « ça refuse de mourir » dans des environnements disciplinés (les outils de sauvegarde/réplication les adorent). Ils sont aussi le premier coupable « personne ne se souvient les avoir posés ».
3) Y a-t-il une dépendance de clone ?
Si un clone a été créé à partir d’un snapshot, vous ne pouvez pas détruire ce snapshot tant que le clone n’est pas promu ou détruit. Dans beaucoup d’équipes, un développeur a « temporairement » cloné des données de production pour un test et a transformé le nettoyage des snapshots en une prise d’otage.
4) Si le snapshot est détruit, pourquoi l’espace ne revient-il pas ?
Vérifiez usedbysnapshots, et vérifiez si d’autres snapshots référencent encore les mêmes blocs écrasés. Vérifiez aussi que vous observez le bon dataset et que vous ne confondez pas l’usage au niveau pool et dataset.
5) Le pool est-il en mauvaise santé ou sous forte charge ?
Un pool dégradé, une forte fragmentation ou des IOPS saturées peuvent ralentir les destructions. La suppression de snapshots est gourmande en métadonnées ; elle concurrence vos workloads réels.
6) Avez-vous supprimé des snapshots du mauvais côté de la réplication ?
Les topologies de réplication peuvent maintenir des snapshots vivants : l’émetteur les conserve pour satisfaire les chaînes incrémentales, le récepteur les garde parce que vous les avez épinglés, et les deux côtés se rejettent la faute.
Pourquoi les snapshots refusent de disparaître : causes réelles
Cause A : Holds (holds utilisateur, holds d’outil, « c’est pour votre bien »)
Un hold est une étiquette attachée à un snapshot qui empêche sa destruction. Vous le verrez quand zfs destroy échoue avec un message au sujet des holds, ou quand un outil de suppression « saute les snapshots protégés ». Les holds sont excellents—jusqu’à ce qu’ils soient orphelins suite à un job planté, un système de sauvegarde à moitié migré, ou un script qui tagge des snapshots sans jamais les détager.
Dans la réalité, les holds apparaissent comme :
- Des pipelines de réplication qui retiennent des snapshots jusqu’à ce que la réception soit terminée.
- Des jobs de vérification de sauvegarde qui gardent des snapshots jusqu’à la fin des checksums.
- Des holds « de sécurité » ajoutés par des admins pendant un incident et oubliés.
Cause B : Dépendances de clones (le bloqueur le plus silencieux)
Si un snapshot a un clone, ce snapshot fait partie de l’ascendance du clone. ZFS refusera de le détruire car cela briserait les références de blocs du clone. Vous pouvez l’identifier en regardant la propriété clones du snapshot. La solution est de détruire le clone, ou de promouvoir le clone pour qu’il devienne la nouvelle origine et que la dépendance bascule.
Il s’agit du cas le plus courant de « on ne comprend pas pourquoi ça échoue » dans les équipes mixtes, car la personne qui supprime les snapshots ne sait souvent pas que quelqu’un a créé un clone des mois auparavant.
Cause C : Erreurs « dataset busy » (monté, en cours d’utilisation, ou cas spéciaux)
La plupart du temps, vous pouvez détruire des snapshots de datasets montés sans problème. Mais « dataset is busy » peut survenir quand vous détruisez un filesystem ou un volume avec des références actives, ou quand vous essayez de détruire des snapshots pendant certaines opérations (comme une réception en cours selon la plateforme et les flags).
Méfiez-vous aussi de zfs destroy -r ou -R : vous pourriez détruire des datasets (pas seulement des snapshots) et rencontrer l’usage des points de montage, des exports NFS, des jails/zones, ou des runtimes de conteneurs qui épinglent des mountpoints.
Cause D : Destruction différée (il a « disparu », mais le pool n’a pas respiré)
La destruction différée permet à ZFS de retirer rapidement le snapshot de l’espace de noms tout en reportant le travail réel de libération des blocs. Ce n’est pas magique ; c’est une décision d’ordonnancement. Si le pool est sous charge, le nettoyage peut prendre du retard. Les opérateurs voient « le snapshot a disparu » et supposent que l’espace devrait revenir instantanément. Ce n’est pas forcément le cas.
La destruction différée est souvent déclenchée via zfs destroy -d, mais elle peut aussi apparaître quand le système choisit de ne pas bloquer trop longtemps la commande (l’implémentation dépend de la plateforme et des flags).
Cause E : Méprises sur la comptabilité de l’espace (vous avez libéré de l’espace—pas là où vous regardez)
ZFS rapporte l’espace à plusieurs niveaux :
- niveau pool d’espace libre : ce que le pool peut allouer.
- niveau dataset « used » : inclut les enfants et les snapshots selon les propriétés et le point de vue.
usedbysnapshots: blocs tenus uniquement par des snapshots pour ce dataset.- referenced : ce à quoi le dataset lui-même pointe à cet instant (hors snapshots).
Une réalité fréquente : vous supprimez une série de snapshots, et zfs list montre encore un « used » à peine changé parce que le dataset actif (ou d’autres snapshots) référence toujours la plupart des blocs. Ceci est particulièrement courant quand la charge est à ajout (logs) plutôt qu’à réécriture (overwrites).
Cause F : Chaînes de réplication et dépendances incrémentales
Un zfs send incrémental a besoin d’un snapshot commun entre source et destination. Si vous supprimez le « mauvais » snapshot de l’un ou l’autre côté, vous cassez la chaîne et forcez un envoi complet la fois suivante. Pour éviter cela, beaucoup d’outils de réplication conservent ou retiennent des snapshots. Si vous outrepasser la rétention manuellement, vous pouvez gagner quelques gigaoctets et perdre un week-end à re-seeder.
Cause G : Vous supprimez trop, trop vite (opérationnellement correct mais physiquement douloureux)
Détruire des milliers de snapshots en une fois peut créer une poussée désagréable de travail métadonnées. Sur des pools occupés—surtout sur disques magnétiques—cela peut ressembler à un incident de performance. ZFS n’est pas rancunier ; il fait la comptabilité que vous avez demandée. La solution est de réguler, traiter par lots, ou différer.
Deuxième blague (et dernière) : les politiques de rétention des snapshots sont comme des régimes—faciles à commencer, difficiles à maintenir, et tout le monde ment sur le nombre qu’il garde.
Tâches pratiques : commandes, sorties et ce qu’elles signifient
Ci-dessous des tâches concrètes que j’ai exécutées en urgence. Les commandes sont des outils ZFS standard ; les sorties sont représentatives. Votre plateforme (OpenZFS sur Linux, FreeBSD, illumos) peut différer légèrement, mais le workflow tient.
Tâche 1 : Confirmer que le snapshot existe (et que vous l’épelez correctement)
cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -s creation pool/app
NAME USED REFER CREATION
pool/app@auto-2025-12-24 12G 1.20T Wed Dec 24 02:00 2025
pool/app@auto-2025-12-25 14G 1.21T Thu Dec 25 02:00 2025
Interprétation : Vous avez deux snapshots. USED est l’espace que ce snapshot consomme de façon unique par rapport au head du dataset et aux autres snapshots.
Tâche 2 : Tenter une destruction normale et lire l’erreur littéralement
cr0x@server:~$ sudo zfs destroy pool/app@auto-2025-12-24
cannot destroy snapshot pool/app@auto-2025-12-24: snapshot has holds
Interprétation : Ce n’est pas un mystère. Il y a des holds. Ne commencez pas à deviner « busy ». Allez vérifier les holds.
Tâche 3 : Lister les holds sur un snapshot
cr0x@server:~$ sudo zfs holds pool/app@auto-2025-12-24
NAME TAG TIMESTAMP
pool/app@auto-2025-12-24 repl-inflight Thu Dec 25 02:05 2025
pool/app@auto-2025-12-24 backup-verify Thu Dec 25 02:10 2025
Interprétation : Deux systèmes différents pensent avoir encore besoin de ce snapshot. C’est une bonne nouvelle : vous avez des noms à suivre.
Tâche 4 : Libérer un hold (en toute sécurité, avec intention)
cr0x@server:~$ sudo zfs release backup-verify pool/app@auto-2025-12-24
cr0x@server:~$ sudo zfs holds pool/app@auto-2025-12-24
NAME TAG TIMESTAMP
pool/app@auto-2025-12-24 repl-inflight Thu Dec 25 02:05 2025
Interprétation : Vous avez retiré une étiquette. Si un hold est possédé par un job de réplication ou de sauvegarde, le relâcher prématurément peut briser des garanties. Coordonnez-vous ou confirmez que le job est mort/bloqué.
Tâche 5 : Forcer la destruction (à éviter, mais savoir ce que ça fait)
cr0x@server:~$ sudo zfs destroy -f pool/app@auto-2025-12-24
cannot destroy snapshot pool/app@auto-2025-12-24: snapshot has holds
Interprétation : -f n’est pas « ignorer les holds ». Les holds existent précisément pour empêcher cela. Vous devez release les holds ou éliminer les conditions dépendantes.
Tâche 6 : Vérifier si un snapshot a des clones
cr0x@server:~$ zfs get -H -o value clones pool/app@auto-2025-12-24
pool/dev/app-clone
Interprétation : Ce snapshot est l’origine d’un dataset clone. Vous ne pouvez pas détruire le snapshot tant que le clone existe.
Tâche 7 : Inspecter le clone et son origine
cr0x@server:~$ zfs get -o name,property,value origin pool/dev/app-clone
NAME PROPERTY VALUE
pool/dev/app-clone origin pool/app@auto-2025-12-24
Interprétation : Lignée claire. Si ce clone est encore nécessaire, envisagez de le promouvoir. S’il est jetable, détruisez-le.
Tâche 8 : Promouvoir un clone pour casser la dépendance (quand vous avez besoin du clone, pas de l’origine)
cr0x@server:~$ sudo zfs promote pool/dev/app-clone
cr0x@server:~$ zfs get -o name,property,value origin pool/dev/app-clone
NAME PROPERTY VALUE
pool/dev/app-clone origin -
Interprétation : Après promotion, le clone devient un dataset indépendant (son origin est effacé). L’ancienne origine peut maintenant pointer en retour, selon la lignée. Re-vérifiez la liste des clones sur le snapshot que vous voulez supprimer.
Tâche 9 : Détruire un snapshot une fois holds/clones résolus
cr0x@server:~$ sudo zfs release repl-inflight pool/app@auto-2025-12-24
cr0x@server:~$ sudo zfs destroy pool/app@auto-2025-12-24
Interprétation : Si cela réussit et que le snapshot disparaît de zfs list -t snapshot, vous avez retiré l’entrée de l’espace de noms. La récupération d’espace peut encore prendre du temps.
Tâche 10 : Vérifier si l’espace est réellement retenu par des snapshots
cr0x@server:~$ zfs get -o name,property,value -s local,default used,usedbysnapshots,usedbydataset,referenced pool/app
NAME PROPERTY VALUE
pool/app used 3.10T
pool/app usedbysnapshots 420G
pool/app usedbydataset 2.68T
pool/app referenced 2.68T
Interprétation : Si usedbysnapshots est important, supprimer des snapshots peut aider. S’il est faible, la suppression de snapshots ne vous sauvera pas ; c’est le dataset actif qui occupe l’espace.
Tâche 11 : Identifier quels snapshots consomment le plus d’espace
cr0x@server:~$ zfs list -t snapshot -o name,used,refer -s used pool/app | tail -n 5
pool/app@auto-2025-10-01 85G 1.05T
pool/app@auto-2025-11-01 92G 1.10T
pool/app@auto-2025-11-15 97G 1.12T
pool/app@auto-2025-12-01 110G 1.18T
pool/app@auto-2025-12-15 140G 1.20T
Interprétation : Ce sont de bons candidats pour l’élagage si la politique le permet. D’habitude les pics USED corrèlent avec de grosses réécritures, compactions, churn d’images VM, ou maintenance de bases de données.
Tâche 12 : Supprimer par lots des snapshots selon un motif (avec prudence)
cr0x@server:~$ zfs list -H -t snapshot -o name -s creation pool/app | grep '@auto-2025-10' | head
pool/app@auto-2025-10-01
pool/app@auto-2025-10-02
pool/app@auto-2025-10-03
pool/app@auto-2025-10-04
pool/app@auto-2025-10-05
cr0x@server:~$ zfs list -H -t snapshot -o name -s creation pool/app | grep '@auto-2025-10' | xargs -n 1 sudo zfs destroy
Interprétation : Cela supprime les snapshots un par un (moins de rafales qu’un seul destroy récursif sur de nombreux datasets). Si un snapshot échoue à cause de holds/clones, vous verrez lequel et pourquoi. Dans de grands environnements, ajoutez une régulation entre les destructions.
Tâche 13 : Utiliser la destruction différée quand la commande doit revenir vite
cr0x@server:~$ sudo zfs destroy -d pool/app@auto-2025-12-15
cr0x@server:~$ zfs list -t snapshot pool/app | grep auto-2025-12-15
# (no output)
Interprétation : Le snapshot est retiré rapidement de l’espace de noms, mais le pool peut encore libérer des blocs en arrière-plan. Surveillez l’I/O du pool et l’espace dans le temps.
Tâche 14 : Vérifier l’état du pool et les signes évidents avant de blâmer la logique de suppression ZFS
cr0x@server:~$ zpool status -x
all pools are healthy
cr0x@server:~$ zpool status pool
pool: pool
state: ONLINE
scan: scrub repaired 0B in 03:21:10 with 0 errors on Sun Dec 22 03:00:11 2025
config:
NAME STATE READ WRITE CKSUM
pool ONLINE 0 0 0
raidz2-0 ONLINE 0 0 0
sda ONLINE 0 0 0
sdb ONLINE 0 0 0
sdc ONLINE 0 0 0
sdd ONLINE 0 0 0
errors: No known data errors
Interprétation : Si le pool est dégradé ou en résilver, les suppressions de snapshots peuvent traîner, et vous pourriez vouloir reporter un nettoyage massif jusqu’après la récupération.
Tâche 15 : Confirmer que vous n’êtes pas piégé par des attentes de réplication
cr0x@server:~$ zfs list -t snapshot -o name,creation pool/app | tail -n 3
pool/app@repl-2025-12-24-0200 Wed Dec 24 02:00 2025
pool/app@repl-2025-12-25-0200 Thu Dec 25 02:00 2025
pool/app@repl-2025-12-25-1400 Thu Dec 25 14:00 2025
cr0x@server:~$ zfs holds pool/app@repl-2025-12-24-0200
NAME TAG TIMESTAMP
pool/app@repl-2025-12-24-0200 zfs-send-chain Thu Dec 25 14:05 2025
Interprétation : Un outil de réplication maintient volontairement ce snapshot. Si vous le retirez, le prochain incrémental peut échouer ou retomber sur un transfert complet.
Tâche 16 : Voir le nombre de snapshots et détecter une « explosion » de snapshots
cr0x@server:~$ zfs list -H -t snapshot -o name pool/app | wc -l
1827
Interprétation : Un dataset avec des milliers de snapshots n’est pas automatiquement erroné, mais cela change le modèle de coût des suppressions et des rollbacks. Planifiez le nettoyage comme vous planifiez une reconstruction d’index : programmez, régulez, et surveillez.
Trois mini-histoires du monde de l’entreprise
1) Incident causé par une mauvaise hypothèse : « Supprimer des snapshots libérera instantanément des téraoctets »
Dans un grand cluster de VM d’entreprise, une équipe stockage a reçu une alerte inquiétante : le pool principal était passé sous le seuil d’espace libre. Un ingénieur a fait ce que beaucoup d’entre nous ont fait : il a supprimé des « vieux snapshots » sur le dataset le plus actif, en s’attendant à une baisse rapide de l’utilisation. La suppression s’est terminée, mais l’espace libre du pool a à peine bougé. Dans l’heure suivante, la latence d’écriture a augmenté, et certaines VM ont commencé à timeout.
La mauvaise hypothèse n’était pas que les snapshots coûtent de l’espace ; c’était que ces snapshots étaient la cause. Le dataset avait une charge à forte churn : les images VM étaient compactées et réécrites quotidiennement, mais de nouveaux snapshots étaient aussi pris toutes les heures. Supprimer une poignée d’anciens snapshots n’a pas aidé parce que les blocs écrasés étaient encore référencés par des snapshots plus récents.
L’équipe a doublé la mise : plus de suppressions, plus rapides. C’est comme ça qu’ils ont déclenché l’effet de second ordre : la destruction massive de snapshots a généré une pression métadonnées. ZFS n’a pas « cassé », mais cela a concurrencé les I/O VM et empiré une situation déjà marginale. Ils se sont retrouvés avec peu d’espace libre et des performances dégradées.
La solution a été un mélange d’humilité et d’arithmétique. Ils ont mesuré usedbysnapshots, identifié les pires plages de snapshots via USED, et supprimé par lots contrôlés. Ils ont aussi ajusté la planification des snapshots pour ce dataset : moins de snapshots horaires, plus de quotidiens, et une fenêtre de rétention plus courte pour les images à fort churn. Le pool s’est stabilisé, et les performances ont récupéré—lentement, comme tout système qui a dû faire beaucoup de tenue de livres en urgence.
2) Optimisation qui a mal tourné : « Transformons tout en clones pour accélérer le dev »
Une entreprise avec une forte équipe plateforme voulait accélérer les environnements développeurs. L’idée était élégante : prendre un snapshot nocturne de datasets proches de la prod, puis créer des clones par équipe en quelques secondes. Ça a marché. Les devs étaient contents. L’équipe plateforme a reçu des louanges pour « tirer parti des primitives de stockage ».
Des mois plus tard, le pool de stockage a atteint ses limites. La suppression des snapshots a commencé à échouer à cause des dépendances de clones. Pire, ces clones n’étaient plus « temporaires ». Les équipes avaient installé des paquets, vidé des données de test et construit des workflows autour de leurs clones. Les détruire n’était plus une tâche de nettoyage ; c’était un processus politique.
Le retour de bâton était subtil : l’optimisation a déplacé la complexité du cycle de vie dans la couche de stockage. Les snapshots sont devenus indestructibles non pas parce que ZFS est têtu, mais parce que l’organisation avait fait des snapshots une partie d’un contrat implicite. Chaque clone ancrant un snapshot ; chaque snapshot ancré conservant de l’historique ; et l’historique conservant de l’espace.
Le plan de rétablissement n’était pas un one-liner héroïque. Ils ont introduit une politique : les clones dev doivent être promus dans un délai (ou reconstruits depuis un snapshot plus récent). Ils ont aussi mis en place du tagging et des rapports : âge des clones, âge du snapshot d’origine, et exceptions de rétention. Le gain a été autant culturel que technique : le coût des « clones instantanés » est devenu visible, et l’équipe plateforme a cessé de traiter le nettoyage des snapshots comme une après-pensée.
3) Pratique ennuyeuse mais correcte qui a sauvé la situation : « Holds avec tag propriétaire, et contrat de nettoyage »
Un autre environnement avait deux systèmes de réplication pendant une migration—ancien et nouveau—fonctionnant en parallèle pendant un certain temps. C’est le genre de situation où les snapshots s’accumulent discrètement, parce que personne ne veut supprimer quelque chose qui pourrait être nécessaire pour des envois incrémentaux.
La pratique de l’équipe était peu glamour : chaque tag de hold incluait le nom du système propriétaire et un identifiant d’exécution, et les holds étaient limités dans le temps par la politique. Un job quotidien rapportait les snapshots avec des holds plus vieux qu’un seuil, ventilés par tag. Quand un pipeline mourait, il laissait une preuve au lieu d’un mystère.
Pendant la migration, un des jobs de réplication a commencé à échouer de façon intermittente. Des snapshots s’accumulaient, mais ils ne devenaient pas « immortels ». Le rapport montrait un seul tag de hold qui vieillissait. L’ingénieur d’astreinte n’a pas eu à deviner quel système le possédait ; le tag le disait.
Ils ont mis le pipeline fautif en pause, confirmé un snapshot de base sûr, relâché les holds obsolètes, et repris avec une chaîne mise à jour. Pas de drame, pas de suppressions spéculatives. Le pool n’a jamais plongé dans la zone dangereuse, et la migration a été menée à bien sans l’incident habituel « pourquoi la rétention ne fonctionne pas ? ». La pratique était ennuyeuse. Elle a aussi fonctionné—ce qui, en production, est le compliment le plus élevé.
Erreurs fréquentes (symptômes précis et corrections)
Erreur 1 : Confondre « snapshot détruit » et « espace immédiatement récupéré »
Symptôme : Le snapshot n’apparaît plus dans zfs list -t snapshot, mais l’espace libre du pool n’augmente pas.
Correction : Vérifiez usedbysnapshots et si d’autres snapshots existent encore. Considérez le délai de destruction différée et la charge du pool. Mesurez dans le temps, pas en secondes.
Erreur 2 : Supprimer des snapshots en ignorant les dépendances de clones
Symptôme : cannot destroy snapshot ...: snapshot has dependent clones ou la propriété clones du snapshot n’est pas vide.
Correction : Identifiez les clones via zfs get clones. Détruisez les clones inutiles ou zfs promote le clone s’il doit survivre.
Erreur 3 : Relâcher des holds sans comprendre qui les a posés
Symptôme : Les jobs de réplication ou de sauvegarde commencent à échouer après le « nettoyage ». Les envois incrémentaux se plaignent de snapshots manquants.
Correction : Avant de relâcher des holds, identifiez le processus/outils propriétaire et confirmez que c’est sûr. Si vous devez casser la chaîne, planifiez un re-seed complet et estimez le coût en bande passante/temps.
Erreur 4 : Utiliser des destructions récursives trop largement
Symptôme : Vous lancez zfs destroy -r pool/fs@snap et vous touchez par erreur un énorme sous-arbre ; les suppressions prennent une éternité ou échouent à des endroits surprenants.
Correction : Listez d’abord ce qui sera affecté. Préférez une suppression par lots avec des noms de snapshots explicites quand le rayon d’impact compte.
Erreur 5 : Mesurer le mauvais dataset ou la mauvaise propriété
Symptôme : Vous supprimez des snapshots sur pool/app mais le pool reste plein ; plus tard vous réalisez que l’espace est dans pool/app/logs ou un dataset différent.
Correction : Utilisez des vues de type zfs list -o space (ou des requêtes de propriétés explicites) sur l’arbre de datasets. Vérifiez que le dataset contribue effectivement à la pression du pool.
Erreur 6 : Supprimer d’abord les snapshots à gros USED sans considérer les incrémentaux
Symptôme : Après la suppression d’un gros snapshot, votre prochaine réplication devient un envoi complet ou échoue.
Correction : Comprenez quels snapshots sont des points d’ancrage pour les chaînes incrémentales. Coordonnez les suppressions avec le planning de réplication et l’état de la destination.
Erreur 7 : Lancer des destructions massives pendant les pics d’I/O
Symptôme : Les latences grimpent, l’iowait augmente, les utilisateurs signalent des lenteurs, sans qu’il y ait de service « down ».
Correction : Régulez les suppressions, faites-les par lots, planifiez-les en périodes creuses, ou utilisez la destruction différée. La suppression de snapshots est lourde en métadonnées ; traitez-la comme une opération de maintenance.
Checklists / plan pas à pas
Checklist A : « Destroy échoue » étape par étape
- Confirmez le nom exact du snapshot avec
zfs list -t snapshot. - Tentez une destruction une fois et capturez le texte d’erreur.
- Si le message mentionne des holds : lancez
zfs holds, identifiez les tags, décidez de les relâcher ou non. - Si le message mentionne des clones : lancez
zfs get clones, puis inspectez et détruisez ou promouvez les clones. - Si le message mentionne « busy » : confirmez si vous détruisez seulement des snapshots ou aussi des datasets (
-r/-R) ; vérifiez montages, exports, conteneurs et réceptions en cours. - Relancez la destruction pour un seul snapshot afin de vérifier que vous avez levé le blocage avant de monter en charge.
Checklist B : « Snapshots supprimés mais l’espace n’est pas revenu » étape par étape
- Vérifiez que le nombre de snapshots a effectivement diminué :
zfs list -t snapshot | wc -l(ou scope dataset). - Vérifiez la répartition de l’espace du dataset :
zfs get used,usedbysnapshots,usedbydataset,referenced. - Listez les snapshots restants et triez par
USEDpour voir qui retient encore des blocs. - Considérez que le head du dataset peut encore référencer les blocs : la suppression de snapshots n’aidera pas si les données live représentent la majorité.
- Si vous utilisez la destruction différée, laissez du temps et surveillez la tendance de l’espace libre du pool.
- Vérifiez si un dataset différent est la vraie source de pression du pool.
Checklist C : Plan de nettoyage massif sûr (quand il faut supprimer des centaines/milliers)
- Choisissez une fenêtre de suppression (période hors pic). Annoncez-la comme toute autre maintenance.
- Exécutez un dry-run de la sélection : listez les noms de snapshots que vous voulez supprimer, vérifiez les motifs (ancres de réplication, fins de mois).
- Vérifiez les holds et les dépendances de clones avant de commencer.
- Supprimez par lots ; surveillez la latence et l’activité du pool entre les lots.
- Consignez ce que vous avez supprimé et ce qui a échoué (et pourquoi). « On a exécuté une commande » n’est pas une piste d’audit.
- Après le nettoyage, vérifiez que la réplication/les sauvegardes disposent toujours des snapshots de base requis.
FAQ
1) Pourquoi zfs destroy affiche « snapshot has holds » ?
Parce qu’une ou plusieurs étiquettes de hold sont posées sur le snapshot. Les holds sont des protections explicites. Utilisez zfs holds pool/fs@snap pour les lister, puis zfs release TAG pool/fs@snap pour retirer une étiquette spécifique quand c’est sûr.
2) Pourquoi ne puis-je pas détruire un snapshot qui a des clones dépendants ?
Un clone est un dataset qui utilise ce snapshot comme origine. Détruire le snapshot briserait le graphe de références du clone. Détruisez le clone, ou zfs promote le clone pour inverser la dépendance.
3) J’ai détruit des snapshots et df affiche encore le filesystem plein. ZFS ment-il ?
En général non ; vous comparez des systèmes de comptabilité différents. df montre ce que le filesystem monté pense être disponible, ce qui peut être influencé par des réservations, quotas, refreservations, et la pression d’allocation au niveau du pool. Utilisez zfs get used,available,usedbysnapshots et zpool list pour voir ce qui se passe réellement.
4) Les snapshots ralentissent-ils ma charge ?
Pas simplement en existant. Le coût vient du churn : si vous réécrivez beaucoup de données en conservant beaucoup de snapshots, le pool retient plus de vieux blocs, augmentant la pression d’espace et potentiellement la fragmentation. Supprimer beaucoup de snapshots peut aussi créer une rafale de travail métadonnées.
5) Quelle est la différence entre USED sur un snapshot et usedbysnapshots sur un dataset ?
USED sur un snapshot est ce que ce snapshot contribue de façon unique par rapport aux autres. usedbysnapshots sur un dataset est l’espace total consommé par les snapshots associés à ce dataset. Ils répondent à des questions différentes : « quel snapshot est cher ? » versus « combien coûtent les snapshots ici au total ? »
6) La destruction différée est-elle sûre ?
Oui, dans le sens où c’est un mécanisme supporté : le snapshot est retiré et la libération des blocs se fait plus tard. Le compromis est la visibilité opérationnelle—les gens s’attendent à un retour d’espace instantané. Utilisez-la quand vous avez besoin de réactivité et pouvez tolérer une récupération différée.
7) Pourquoi détruire des snapshots prend-il parfois une éternité ?
ZFS peut avoir besoin de traverser des métadonnées pour libérer des blocs, et cela concurrence les I/O normales. Les pools avec beaucoup de snapshots, un fort churn, des disques lents, ou des workloads concurrents lourds ressentent cela davantage. Supprimez par lots et planifiez pendant des périodes plus calmes.
8) Puis-je supprimer des snapshots côté source sans toucher la destination (ou vice versa) ?
Vous pouvez, mais les incrémentaux de réplication dépendent d’avoir des snapshots communs. Supprimer un snapshot « ancre » sur l’un ou l’autre côté peut forcer un re-seed complet ou casser l’automatisation. Si vous n’êtes pas sûr, inspectez quels snapshots sont utilisés pour la réplication et s’ils sont tenus/épinglés.
9) Comment empêcher que les snapshots deviennent « immortels » à nouveau ?
Utilisez des conventions de nommage explicites, taggez les holds avec le propriétaire, surveillez les snapshots avec holds plus vieux que prévu, et évitez les clones longue durée sauf si vous avez une politique de cycle de vie (fenêtre de promotion, TTL, ou nettoyage automatique).
Conclusion
Les snapshots ZFS ne « refusent pas de mourir » par méchanceté. Ils persistent parce que ZFS fait exactement ce pour quoi vous l’avez engagé : préserver la cohérence, respecter les dépendances, et empêcher les suppressions dangereuses. Quand un snapshot ne se supprime pas, c’est presque toujours l’une des trois choses—holds, clones, ou une mauvaise compréhension de la comptabilité d’espace—et la solution est d’identifier laquelle avant de lancer des commandes à tout-va.
Quand vous traitez la suppression de snapshots comme une maintenance (ciblée, surveillée, et coordonnée avec les réalités de réplication/sauvegarde), cela redevient ennuyeux. Et un stockage ennuyeux est celui dont on ne parle que pour se vanter de l’uptime plutôt que pour l’expliquer.