Les clones ZFS sont le type de fonctionnalité qui fait passer les ingénieurs stockage pour des magiciens : créer une « copie » d’un système de fichiers ou d’un volume instantanément, sans déplacer les données, et commencer à écrire dessus comme si elle avait toujours existé. La première fois que vous l’utilisez pour un modèle de VM, un environnement CI ou une copie judiciaire, on a l’impression d’avoir trompé la physique.
Puis vous tentez de nettoyer des snapshots, récupérer de l’espace ou répliquer le dataset… et vous découvrez l’autre moitié du tour : les clones sont instantanés parce qu’ils ne sont pas indépendants. Un clone est un enfant modifiable d’un snapshot, et cette dépendance cachée finira par se manifester sur un pager quelque part. Cet article vise à faire en sorte qu’elle apparaisse plutôt dans un ticket.
Ce qu’est réellement un clone ZFS
Un snapshot ZFS est une vue en lecture seule à un instant donné d’un dataset (système de fichiers) ou d’un volume (zvol). Il coûte presque rien à créer car il n’enregistre que des métadonnées ; les blocs sont partagés tant qu’ils ne divergent pas.
Un clone ZFS est un dataset ou un zvol modifiable créé à partir d’un snapshot. Ce « à partir d’un snapshot » n’est pas un détail ; c’est tout le contrat. Un clone commence sa vie en partageant des blocs avec le snapshot d’origine. Quand vous écrivez dans le clone, ZFS utilise le copy-on-write (CoW) : il écrit de nouveaux blocs ailleurs, met à jour les métadonnées, et le clone diverge du snapshot.
Les clones ont deux propriétés que les opérateurs devraient se tatouer sur leur runbook mental :
- Un clone dépend de son snapshot d’origine. Vous ne pouvez pas détruire le snapshot tant que le clone existe (sauf si vous faites une promotion, qui change l’arbre généalogique).
- La comptabilité d’espace devient « partagée ». Vous pouvez remplir un pool « sans remplir quoi que ce soit » jusqu’au moment où soudainement vous l’avez fait. Les chiffres ne mentent pas, mais ils nécessitent une interprétation.
Une blague opérationnelle trop précise pour être ignorée : les clones ZFS, c’est comme adopter un chat ; c’est instantané, mais vous héritez d’une dépendance à long terme que vous n’aviez pas budgétée.
Anatomie d’un clone : dataset vs zvol
ZFS peut cloner les deux :
- Systèmes de fichiers (datasets) : montés sur un point de montage, contiennent fichiers et répertoires.
- Volumes (zvols) : périphériques bloc, souvent utilisés pour disques VM, LUN iSCSI, périphériques bruts pour bases de données.
Le mécanisme de clone est identique. L’impact opérationnel diffère parce que les clones de zvol sont fréquemment utilisés dans des stacks de virtualisation où les modèles « template » et « linked clone » sont courants, et où l’amplification d’écriture peut apparaître rapidement sous des charges d’écriture aléatoire soutenues.
Ce que « instantané » signifie réellement
La création d’un clone est instantanée parce que ZFS ne copie pas les blocs. Il crée un nouveau dataset et pointe ses métadonnées vers les mêmes blocs référencés par le snapshot. Si vous vous attendez à ce que cela se comporte comme une copie indépendante, vous allez apprendre à propos des compteurs de référence, de usedbysnapshots, et pourquoi un snapshot que vous « n’avez pas besoin » empêche toujours la reclamation d’espace.
La dépendance cachée : « vous ne pouvez pas supprimer ce snapshot »
La surprise classique ressemble à ceci :
- Vous créez le snapshot
pool/prod@app-2025-12-25. - Vous créez le clone
pool/dev/app-testà partir de ce snapshot. - Des semaines plus tard, vous essayez de supprimer d’anciens snapshots pour récupérer de l’espace.
- ZFS refuse de détruire le snapshot parce qu’il a des clones dépendants.
Ce n’est pas ZFS qui fait l’entêté ; c’est ZFS qui évite la corruption. Le snapshot d’origine contient des références de blocs dont le clone pourrait encore dépendre. Si ZFS vous permettait de supprimer le snapshot, il pourrait libérer des blocs que le clone a encore besoin. ZFS résout cela en appliquant la dépendance.
Pourquoi cela importe au-delà du « nettoyage qui échoue »
En production, les dépendances de clone ont tendance à se manifester comme :
- Ruptures de la politique de rétention des snapshots. Votre règle « garder 14 jours » devient silencieusement « garder 14 jours sauf s’il y a un clone, alors garder indéfiniment ».
- Blocage de la récupération d’espace. Les équipes continuent de supprimer des fichiers, mais l’utilisation du pool ne baisse pas parce que des blocs sont toujours référencés par des snapshots qui ne peuvent être supprimés.
- Complexité de réplication. Les clones peuvent compliquer les workflows
zfs sendsi vous ne planifiez pas la topologie dataset/snapshot. - Chaos des promotions. Quelqu’un « promeut » un clone pour casser des dépendances et change quel dataset est considéré comme la prod, et soudainement votre modèle mental de « ce qui est prod » est faux.
Promotion : l’échappatoire (et le piège)
zfs promote fait d’un clone le dataset « principal », et son origine devient conceptuellement un enfant clone. C’est ainsi que vous cassez la dépendance à un snapshot d’origine pour pouvoir le supprimer. C’est aussi la manière d’inverser accidentellement une lignée et de perturber la réplication, la surveillance et les humains.
La promotion est légitime et souvent nécessaire. Mais elle doit être une action planifiée avec des résultats explicites, pas une commande désespérée copiée d’un forum alors que le pool est rempli à 99 %.
Faits intéressants et contexte historique
Six à dix points concis qui comptent plus que des anecdotes parce qu’ils expliquent pourquoi les clones se comportent ainsi :
- Les snapshots ZFS sont peu coûteux grâce au CoW. ZFS n’écrase jamais en place ; il écrit de nouveaux blocs et met à jour des pointeurs, ce qui rend les snapshots cohérents une conséquence naturelle du design.
- Les clones ont été conçus pour un provisionnement rapide. Les premiers adopteurs de ZFS utilisaient les clones pour le dev/test et le templating de VM bien avant que « l’infrastructure as code » ne devienne courante.
- L’espace est partagé par compteurs de référence. Un bloc peut être référencé par le système de fichiers actif, un ou plusieurs snapshots et un ou plusieurs clones ; il n’est libéré que lorsque la dernière référence disparaît.
- Le « utilisé » dans ZFS est contextuel. Il y a « used by dataset », « used by snapshots », « used by children » et « logical used » ; votre pool se remplit selon la réalité physique, pas selon le chiffre du tableau de bord que vous regardez.
- Les clones précèdent de nombreux produits modernes de « copy data management ». L’idée — copier instantanément, diverger à l’écriture — est le même principe derrière de nombreux systèmes commerciaux de snapshot/clone.
- La lignée des clones est explicite dans les propriétés. ZFS stocke la propriété
originsur les clones ; vous pouvez interroger et automatiser autour de cela (et vous devriez). - La promotion change l’ascendance, pas la validité des données. Elle réarrange quel snapshot est considéré « origine » pour les dépendances ; elle ne réécrit pas l’ensemble du dataset.
- Les clones et snapshots ne sont pas des sauvegardes. Ce sont d’excellents outils de récupération locale, mais ils partagent le même pool, le même domaine de panne et souvent le même risque « oops j’ai détruit le pool ».
- Les clones de ZVOL ont modifié l’économie VM. Les linked clones permettent de déployer des centaines de VM à partir d’une image dorée avec un stockage minimal — jusqu’à ce que les patterns d’écriture transforment « minimal » en « surprise ».
Quand utiliser les clones (et quand s’en abstenir)
Bonnes utilisations
- Modèles VM / images dorées : provisionner des disques VM instantanément ; ne payer que la divergence.
- Environnements CI : lancer rapidement des datasets de test et les détruire après l’exécution.
- Experts judiciaires (forensics) : faire une copie modifiable d’un snapshot pour reproduire des problèmes sans toucher la prod.
- Sandboxes data science : donner aux analystes un dataset modifiable à partir d’un snapshot stable sans dupliquer des téraoctets.
- Migrations risquées : cloner un dataset et répéter des changements ; si ça échoue, détruire le clone.
Mauvaises utilisations (ou du moins : qui nécessitent des garde-fous)
- Environnements « temporaires » de longue durée qui survivent aux fenêtres de rétention des snapshots. C’est ainsi qu’un clone de test hebdomadaire devient une ancre d’espace vieille de trois ans.
- « Clone comme sauvegarde ». Si le pool meurt, l’original et le clone meurent ensemble. Les clones réduisent le rayon d’erreur des erreurs humaines, pas des pannes matérielles.
- Service libre des développeurs sans limites. Les développeurs créeront des clones avec des noms créatifs, les oublieront, et votre nettoyage de snapshots deviendra une séance de thérapie.
Deuxième blague, parce que le stockage a besoin de légèreté : Les clones sont « gratuits » comme les chiots gratuits — le coût initial est zéro, mais le planning de nettoyage devient votre vie.
Trois mini-histoires du monde de l’entreprise
1) Incident causé par une mauvaise hypothèse : « Supprimer le snapshot libérera de l’espace »
L’équipe stockage d’une entreprise de taille moyenne exploitait un cluster virtualisé sur ZFS. Ils avaient une politique propre : snapshots horaires pendant 48 heures, quotidiens pendant deux semaines. Ça fonctionnait — jusqu’à ce que ça échoue. Le pool est passé de 70 % à 88 % sur un mois, puis a atteint 94 % pendant un week-end, et lundi matin est arrivé avec des VM lentes et des dashboards furieux.
Le responsable on-call a fait l’évidence : supprimer d’anciens snapshots. Les commandes destroy ont commencé à échouer avec « snapshot has dependent clones ». Ce message paraît inoffensif jusqu’à ce que vous réalisiez qu’il signifie « votre politique de rétention est maintenant de la fiction ». L’hypothèse était que les snapshots étaient le seul objet de rétention. En réalité, la pipeline de provisioning VM s’était tranquillement tournée vers des « linked clones à partir du snapshot de la nuit précédente » pour accélérer la création d’environnements. Personne n’avait prévenu le stockage, car du point de vue de la pipeline, c’était une amélioration de performance.
Ils ont essayé de supprimer les clones, mais ces clones étaient maintenant en production : quelqu’un avait reclassé des VM « test » en « production temporaire » lors d’un incident précédent. Les clones n’étaient plus jetables. Les snapshots d’origine étaient épinglés, ce qui épinglait des blocs, ce qui épinglait de l’espace.
L’incident s’est terminé par un triage forcé : identifier quels clones importaient, migrer les importants vers des datasets indépendants, promouvoir quand approprié, puis rétablir un calendrier de snapshot sain. La correction clé du postmortem n’a pas été « supprimer plus de snapshots ». C’était la gouvernance : chaque clone a eu un TTL, le système de provisioning a taggué les clones avec un propriétaire et une expiration. Le stockage a enfin obtenu un rapport quotidien des clones dépendants bloquant la suppression de snapshots.
2) Une optimisation qui s’est retournée contre eux : « ajoutons aussi la dédup »
Une autre organisation aimait l’efficacité. Ils ont découvert les clones et les ont utilisés partout : bases de données développeurs, environnements QA, rafraîchissements staging. L’utilisation du pool a chuté, le provisioning s’est accéléré, et tout le monde se félicitait.
Puis quelqu’un a prononcé la phrase qui a fini tant de bonnes semaines : « Si les clones économisent de l’espace, la dédupérentation en économisera encore plus. » Ils ont activé la dédup sur un dataset contenant des images VM clonées et des zvols de base de données. Les premiers jours, les chiffres étaient excellents. Dans les semaines suivantes, la pression mémoire s’est aggravée. Les misses ARC ont augmenté. La latence est devenue saccadée pendant les heures de pointe. Finalement, la machine a pris l’habitude de se mettre en pause sous charge comme si elle réfléchissait profondément à ses choix de vie.
Les tables de dédup consomment. Les clones partagent déjà efficacement des blocs quand ils proviennent de la même lignée de snapshot ; la dédup ajoute une surcharge mondiale de comptabilité des blocs. Pour leur charge — de nombreuses VM similaires mais divergentes avec beaucoup d’écritures aléatoires — la dédup a augmenté le churn des métadonnées et rendu chaque écriture plus coûteuse. L’« espace économisé » était réel, mais ils ont troqué la performance prévisible et la simplicité opérationnelle.
La correction a été douloureuse : migrer hors des datasets dédupliqués, reprovisionner avec seulement des clones, et accepter que « efficace » a plusieurs dimensions. Les clones étaient la bonne optimisation ; la dédup était la bonne optimisation pour une charge et un budget matériel différents.
3) Une pratique ennuyeuse mais correcte qui a sauvé la mise : « les clones ont des propriétaires et une expiration »
Une équipe de plateforme d’entreprise traitait les clones comme des ressources de production, pas des tours de magie. Leur règle était ennuyeuse : chaque clone doit avoir un propriétaire, une référence de ticket et une date d’expiration. Pas dans un tableur — stockés comme propriétés utilisateur ZFS directement sur le dataset.
Quand un pool a commencé à monter, ils n’ont pas improvisé. Ils ont lancé un script : lister tous les clones, leurs snapshots d’origine et leurs dates d’expiration. La plupart étaient légitimes. Une poignée était expirée et inutilisée. Celles-ci ont été détruites en priorité, ce qui a débloqué des snapshots, ce qui a libéré de l’espace. Aucune bataille requise.
Plus tard, une pipeline de déploiement a échoué car elle ne pouvait pas détruire d’anciens snapshots. L’on-call a suivi la sortie du script et a trouvé un seul clone de longue durée créé pour une enquête d’incident des mois plus tôt. Le propriétaire était passé dans une autre équipe. Le dataset existait encore parce que personne ne voulait supprimer « au cas où ». L’équipe a contacté le nouveau propriétaire du service, convenu d’une réplication des artefacts nécessaires, puis détruit le clone et repris les opérations normales.
C’est la vérité peu sexy : l’inventaire ennuyeux bat les fonctionnalités de stockage brillantes. Les clones sont puissants, mais la seule façon durable de les utiliser à l’échelle est de les rendre visibles, possédés et gérés dans leur cycle de vie.
Tâches pratiques : commandes, sorties, interprétation
Ci‑dessous des tâches pratiques que vous pouvez exécuter sur un système OpenZFS typique (Linux ou illumos). Les commandes supposent que vous avez les privilèges. Les sorties sont représentatives ; les vôtres différeront.
Task 1: List snapshots and clones together
cr0x@server:~$ zfs list -t filesystem,snapshot,volume -o name,type,used,refer,origin -r tank/app
NAME TYPE USED REFER ORIGIN
tank/app filesystem 12.3G 9.8G -
tank/app@daily-2025-12-20 snapshot 0B 9.8G -
tank/app@daily-2025-12-21 snapshot 0B 10.1G -
tank/app@daily-2025-12-22 snapshot 0B 10.1G -
tank/app-clone-qa filesystem 3.1G 11.0G tank/app@daily-2025-12-21
Interprétation : Le clone a une propriété origin pointant vers un snapshot. Ce snapshot d’origine est maintenant protégé contre la destruction à moins que vous ne supprimiez ou ne promouviez le clone.
Task 2: Create a snapshot (safe and fast)
cr0x@server:~$ zfs snapshot tank/app@pre-change-001
cr0x@server:~$ zfs list -t snapshot -o name,creation -r tank/app | tail -n 3
NAME CREATION
tank/app@daily-2025-12-22 Mon Dec 22 01:00 2025
tank/app@pre-change-001 Thu Dec 25 09:14 2025
Interprétation : Le snapshot est instantané et cohérent au niveau ZFS.
Task 3: Create a clone from a snapshot
cr0x@server:~$ zfs clone tank/app@pre-change-001 tank/app-clone-dev
cr0x@server:~$ zfs get origin,mountpoint tank/app-clone-dev
NAME PROPERTY VALUE SOURCE
tank/app-clone-dev origin tank/app@pre-change-001 -
tank/app-clone-dev mountpoint /tank/app-clone-dev default
Interprétation : Le clone est un dataset réel avec ses propres propriétés, point de montage, quotas, et une dépendance solide au snapshot d’origine.
Task 4: Prove the dependency: try to destroy the origin snapshot
cr0x@server:~$ zfs destroy tank/app@pre-change-001
cannot destroy snapshot tank/app@pre-change-001: snapshot has dependent clones
Interprétation : Ce snapshot est épinglé. Votre politique de rétention vient de rencontrer la réalité.
Task 5: Find dependent clones for a snapshot
cr0x@server:~$ zfs list -t filesystem,volume -o name,origin -r tank | grep 'tank/app@pre-change-001'
tank/app-clone-dev tank/app@pre-change-001
Interprétation : Un simple grep marche, mais pour de grands domaines vous voudrez des requêtes scriptées utilisant zfs get -H.
Task 6: Quantify “what’s actually using space” with used breakdown
cr0x@server:~$ zfs list -o name,used,usedbysnapshots,usedbychildren,usedbydataset -r tank/app | head
NAME USED USEDBYSNAPSHOTS USEDBYCHILDREN USEDBYDATASET
tank/app 12.3G 2.4G 3.1G 6.8G
Interprétation : Si usedbysnapshots est grand, supprimer des snapshots aiderait — sauf si des clones l’en empêchent. Si usedbychildren est élevé, des clones (ou d’autres datasets enfants) consomment de l’espace.
Task 7: Check pool health and free space headroom (because CoW needs it)
cr0x@server:~$ zpool status tank
pool: tank
state: ONLINE
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
cr0x@server:~$ zpool list tank
NAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOT
tank 7.25T 6.68T 576G - - 41% 92% 1.00x ONLINE -
Interprétation : 92 % de capacité est une zone dangereuse pour les systèmes CoW. Les environnements riches en clones peuvent dériver ici parce que « nous n’avons rien copié » devient « nous avons écrit beaucoup de données divergentes ».
Task 8: Identify clone lineage and prepare for promotion
cr0x@server:~$ zfs get -r -o name,property,value origin tank/app tank/app-clone-dev
NAME PROPERTY VALUE
tank/app origin -
tank/app@pre-change-001 origin -
tank/app-clone-dev origin tank/app@pre-change-001
Interprétation : Seuls les clones ont une propriété origin. Les snapshots n’en ont pas.
Task 9: Promote a clone to break dependency (carefully)
cr0x@server:~$ zfs promote tank/app-clone-dev
cr0x@server:~$ zfs get origin tank/app-clone-dev tank/app
NAME PROPERTY VALUE SOURCE
tank/app-clone-dev origin - -
tank/app origin tank/app-clone-dev@pre-change-001 -
Interprétation : Après promotion, le clone est maintenant la « lignée principale » ; le dataset original peut devenir un clone selon le graphe des snapshots. C’est le comportement attendu, et aussi pourquoi les promotions doivent être suivies via la gestion des changements.
Task 10: Destroy the old snapshot after promotion (if appropriate)
cr0x@server:~$ zfs destroy tank/app@pre-change-001
cr0x@server:~$ zfs list -t snapshot -r tank/app | grep pre-change-001
cr0x@server:~$ echo $?
1
Interprétation : Le snapshot a disparu. L’espace n’est libéré que si aucune autre référence n’existe.
Task 11: Create a zvol clone for a VM disk workflow
cr0x@server:~$ zfs create -V 80G -o volblocksize=16K tank/vm/golden
cr0x@server:~$ zfs snapshot tank/vm/golden@v1
cr0x@server:~$ zfs clone tank/vm/golden@v1 tank/vm/vm-123-disk0
cr0x@server:~$ ls -l /dev/zvol/tank/vm/vm-123-disk0
brw-rw---- 1 root disk 230, 128 Dec 25 09:33 /dev/zvol/tank/vm/vm-123-disk0
Interprétation : Vous avez maintenant un périphérique bloc soutenu par un clone. Parfait pour un provisionnement rapide — jusqu’au moment où vous oubliez que les snapshots ne peuvent pas être pivotés tant que des clones de disques VM en dépendent.
Task 12: Check compression and logical space vs physical
cr0x@server:~$ zfs get compressratio,logicalused,used tank/app-clone-dev
NAME PROPERTY VALUE SOURCE
tank/app-clone-dev compressratio 1.45x -
tank/app-clone-dev logicalused 14.9G -
tank/app-clone-dev used 3.1G -
Interprétation : logicalused reflète la taille logique non compressée ; used est l’espace physique consommé par ce dataset et ses descendants. Avec des clones, « used » n’est pas « unique ».
Task 13: Show unique vs shared usage for a dataset (quick estimate)
cr0x@server:~$ zfs list -o name,used,refer,logicalrefer tank/app tank/app-clone-dev
NAME USED REFER LOGICALREFER
tank/app 12.3G 9.8G 13.9G
tank/app-clone-dev 3.1G 11.0G 15.1G
Interprétation : refer est la quantité accessible depuis ce dataset ; les clones peuvent afficher un grand refer car ils référencent des blocs partagés. Cela ne signifie pas qu’ils consomment autant d’espace de façon unique.
Task 14: Use holds to intentionally pin a snapshot (controlled dependency)
cr0x@server:~$ zfs snapshot tank/app@forensics-keep
cr0x@server:~$ zfs hold case-INC123 tank/app@forensics-keep
cr0x@server:~$ zfs destroy tank/app@forensics-keep
cannot destroy 'tank/app@forensics-keep': snapshot is held
cr0x@server:~$ zfs holds tank/app@forensics-keep
NAME TAG TIMESTAMP
tank/app@forensics-keep case-INC123 Thu Dec 25 09:41 2025
Interprétation : Les holds sont un moyen délibéré d’empêcher la suppression. Par rapport aux dépendances de clone, les holds sont explicites et faciles à auditer.
Task 15: Release the hold and destroy the snapshot
cr0x@server:~$ zfs release case-INC123 tank/app@forensics-keep
cr0x@server:~$ zfs destroy tank/app@forensics-keep
Interprétation : C’est la voie de nettoyage que vous voulez : contrôle explicite du cycle de vie.
Task 16: Replication sanity check: list snapshots to send
cr0x@server:~$ zfs list -t snapshot -o name -s creation -r tank/app | tail -n 5
tank/app@daily-2025-12-21
tank/app@daily-2025-12-22
tank/app@pre-change-001
tank/app@daily-2025-12-23
tank/app@daily-2025-12-24
Interprétation : Si des clones sont impliqués, assurez-vous que votre plan send/receive correspond au graphe des snapshots que vous voulez préserver. La bonne approche dépend de si vous souhaitez répliquer des clones, promouvoir sur la cible ou ne garder que les primaires.
Guide de diagnostic rapide
Voici le playbook « c’est lent et le pool se remplit » que je veux voir chez les ingénieurs on-call. Pas parce qu’il est parfait, mais parce qu’il pose les bonnes questions dans le bon ordre.
1) D’abord : confirmer que ce n’est pas un problème de santé du pool ou de capacité
cr0x@server:~$ zpool status -x
all pools are healthy
cr0x@server:~$ zpool list -o name,size,alloc,free,cap,frag,health
NAME SIZE ALLOC FREE CAP FRAG HEALTH
tank 7.25T 6.68T 576G 92% 41% ONLINE
Interprétation : Si CAP est au-dessus d’environ 85–90 %, attendez-vous à de la fragmentation et à une amplification du coût CoW sur la latence. Les clones augmentent la probabilité de dériver ici parce qu’ils encouragent le « provisionnement rapide » sans autant d’attention au « reclamation rapide ».
2) Ensuite : trouver ce qui épingle les snapshots et bloque la suppression
cr0x@server:~$ zfs list -t snapshot -o name,used,refer -r tank/app | head
NAME USED REFER
tank/app@daily-2025-12-10 0B 8.9G
tank/app@daily-2025-12-11 0B 9.0G
cr0x@server:~$ zfs destroy tank/app@daily-2025-12-10
cannot destroy snapshot tank/app@daily-2025-12-10: snapshot has dependent clones
Interprétation : Maintenant vous savez pourquoi la rétention ne fonctionne pas. L’étape suivante est d’identifier les clones (ou holds) responsables.
3) Troisième : mesurer où va l’espace (dataset vs snapshots vs enfants)
cr0x@server:~$ zfs list -o name,used,usedbydataset,usedbysnapshots,usedbychildren -r tank/app
NAME USED USEDBYDATASET USEDBYSNAPSHOTS USEDBYCHILDREN
tank/app 12.3G 6.8G 2.4G 3.1G
Interprétation : Si usedbychildren est élevé, vous avez probablement des clones (ou d’autres datasets enfants) consommant des données divergentes. Si usedbysnapshots est élevé, des snapshots retiennent des blocs — possiblement parce que des clones forcent leur existence.
4) Quatrième : identifier quels clones sont « actifs » vs abandonnés
cr0x@server:~$ zfs list -t filesystem,volume -o name,origin,used,creation -r tank | grep -v 'origin\s*-' | head
tank/app-clone-qa tank/app@daily-2025-12-21 3.1G Mon Dec 22 02:10 2025
tank/vm/vm-123-disk0 tank/vm/golden@v1 9.4G Thu Dec 25 09:33 2025
Interprétation : Constituez rapidement une liste « qui possède ceci ? ». Si vous n’avez pas de métadonnées de propriété, vous faites de l’archéologie sous pression.
5) Cinquième : si la performance est le symptôme, vérifier la pression I/O et TXG
cr0x@server:~$ zpool iostat -v tank 1 5
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
tank 6.68T 576G 820 2400 65.2M 210M
mirror-0 6.68T 576G 820 2400 65.2M 210M
sda - - 410 1200 32.6M 105M
sdb - - 410 1200 32.6M 105M
-------------------------- ----- ----- ----- ----- ----- -----
Interprétation : Les clones ne rendent pas intrinsèquement l’I/O lente, mais les environnements riches en clones signifient souvent plus de snapshots, plus de métadonnées et plus d’écritures aléatoires (surtout avec des zvols VM). Si le pool est proche du plein, la même charge devient plus lente.
Erreurs courantes : symptômes et corrections
Mistake 1: Treating clones as independent copies
Symptôme : Vous supprimez un snapshot et ZFS refuse : « snapshot has dependent clones ». Ou pire : vous avez peur de supprimer quoi que ce soit parce que « ça pourrait casser le clone ».
Correction : Inventoriez les clones et leurs origines. Décidez si le clone est jetable. Si jetable, détruisez-le. Sinon, envisagez zfs promote (planifié) ou migrez-le vers un dataset indépendant (send/receive, ou copie complète) puis supprimez la dépendance.
Mistake 2: Clone sprawl with no TTL
Symptôme : La rétention des snapshots ne diminue jamais ; l’utilisation du pool augmente même après suppression des données. Les datasets « temporaires » sont plus vieux que certains employés.
Correction : Imposer une expiration via des propriétés utilisateur (owner, ticket, expires). Rapporter les clones chaque semaine. Détruire automatiquement les clones expirés après notification.
Mistake 3: Promoting a clone in the middle of an incident without understanding lineage
Symptôme : Les scripts de réplication échouent, les étiquettes de monitoring basculent, ou quelqu’un découvre que le « dataset original » a maintenant une propriété origin et n’est plus le primaire.
Correction : Avant de promouvoir : capturez zfs get origin sur les datasets concernés, documentez les résultats attendus et coordonnez avec les propriétaires de réplication. Après promotion : mettez à jour la documentation opérationnelle et toute automatisation qui suppose des rôles de dataset.
Mistake 4: Expecting snapshot deletion to reclaim space immediately
Symptôme : Vous détruisez des snapshots et le pool reste plein. Ou vous supprimez des fichiers et rien ne change.
Correction : Vérifiez les clones dépendants, les holds de snapshot et d’autres datasets référant les blocs. Utilisez usedbysnapshots et usedbychildren pour comprendre qui épingle réellement l’espace.
Mistake 5: Using clones for long-lived databases without watching write amplification
Symptôme : Le used du clone croît rapidement, la performance devient erratique et vous voyez une fragmentation accrue au fil du temps.
Correction : Pour des charges intensives en écriture, les clones restent utilisables, mais traitez-les comme de vrais datasets avec une croissance réelle. Appliquez des quotas, surveillez used et la marge du pool, et envisagez de rafraîchir les clones à partir de nouveaux snapshots périodiquement plutôt que de les conserver indéfiniment.
Mistake 6: Confusing “refer” with “unique space consumed”
Symptôme : Un clone affiche refer=10T et quelqu’un panique en supposant qu’il consomme 10T.
Correction : Apprenez à l’équipe que refer est des données accessibles, pas l’allocation physique unique. Utilisez la ventilation de l’utilisation et l’allocation du pool pour évaluer le risque réel de capacité.
Listes de contrôle / plan étape par étape
Checklist A: Safe workflow for creating clones in production
- Créer un snapshot nommé avec un timestamp et un objectif (par ex.
@template-v3ou@pre-change-INC123). - Créer le clone avec un nom encodant le propriétaire/service.
- Définir des propriétés utilisateur sur le clone : owner, ticket, expiry.
- Appliquer quotas/réservations quand approprié pour que les clones ne mangent pas silencieusement le pool.
- Documenter le snapshot d’origine dans le ticket ; traitez-le comme une dépendance, comme une version de schéma de base de données.
cr0x@server:~$ zfs snapshot tank/app@template-v3
cr0x@server:~$ zfs clone tank/app@template-v3 tank/app-clone-ci-4512
cr0x@server:~$ zfs set org.owner=ci-team tank/app-clone-ci-4512
cr0x@server:~$ zfs set org.ticket=CI-4512 tank/app-clone-ci-4512
cr0x@server:~$ zfs set org.expires=2026-01-05 tank/app-clone-ci-4512
cr0x@server:~$ zfs set quota=200G tank/app-clone-ci-4512
Checklist B: Safe cleanup when snapshots won’t delete
- Tenter de détruire le snapshot et confirmer que l’erreur vient bien de clones dépendants (et non de holds).
- Lister les clones ayant la même origine.
- Classer les clones : jetables, à conserver, propriétaire inconnu.
- Pour les clones jetables : les détruire en priorité.
- Pour les clones à conserver : décider entre promotion ou migration vers une nouvelle lignée.
- Après suppression de la dépendance : détruire le snapshot, confirmer la tendance de récupération d’espace.
cr0x@server:~$ zfs destroy tank/app@daily-2025-12-10
cannot destroy snapshot tank/app@daily-2025-12-10: snapshot has dependent clones
cr0x@server:~$ zfs list -t filesystem,volume -o name,origin -r tank | grep 'tank/app@daily-2025-12-10'
tank/app-clone-sandbox tank/app@daily-2025-12-10
cr0x@server:~$ zfs get org.owner,org.expires tank/app-clone-sandbox
NAME PROPERTY VALUE SOURCE
tank/app-clone-sandbox org.owner alice local
tank/app-clone-sandbox org.expires 2025-12-01 local
cr0x@server:~$ zfs destroy tank/app-clone-sandbox
cr0x@server:~$ zfs destroy tank/app@daily-2025-12-10
Checklist C: Promotion decision tree (make it explicit)
- Voulez-vous que le clone devienne la lignée principale ? Si oui, la promotion est raisonnable.
- La réplication ou l’automatisation supposera-t-elle que le dataset original est primaire ? Si oui, mettez à jour l’automatisation d’abord ou choisissez la migration.
- Devez-vous préserver l’historique des snapshots sur l’original ? Si oui, revoyez soigneusement les ensembles de snapshots et testez le comportement send/receive en staging.
- Avez-vous suffisamment d’espace libre ? Les promotions sont des opérations métadonnées, mais le nettoyage que vous essayez d’accomplir peut nécessiter de la marge pour se terminer en toute sécurité.
FAQ
1) What’s the difference between a snapshot and a clone in ZFS?
Un snapshot est en lecture seule et représente une vue à un instant T. Un clone est un dataset ou zvol modifiable créé à partir d’un snapshot. Le clone dépend du snapshot jusqu’à ce que vous détruisiez le clone ou changiez la lignée via une promotion.
2) Why can’t I delete a snapshot even though I don’t need it?
Parce qu’au moins un clone en dépend. Ce snapshot contient des références à des blocs que le clone peut encore utiliser. ZFS vous empêche de le supprimer pour éviter de libérer des blocs en cours d’utilisation.
3) How do I find which clone is blocking snapshot deletion?
Listez les datasets et volumes avec leur propriété origin et faites correspondre le nom du snapshot.
cr0x@server:~$ zfs list -t filesystem,volume -o name,origin -r tank | grep 'tank/app@daily-2025-12-10'
4) Do clones consume space?
Ils consomment de l’espace à mesure qu’ils divergent du snapshot d’origine. Initialement ils partagent des blocs, donc la création est peu coûteuse. Avec le temps, les écritures allouent de nouveaux blocs, et ces blocs sont uniques au clone (sauf s’ils sont référencés ailleurs).
5) Can I replicate clones with zfs send?
Oui, mais il faut un plan clair. Répliquer un dataset qui a des clones peut exiger de répliquer les snapshots pertinents et de préserver la lignée attendue côté réception. Si vous avez seulement besoin d’une copie indépendante, envisagez d’envoyer un flux snapshot dans un nouveau dataset plutôt que de recréer la topologie de clones.
6) Should I use clones for database environments?
Souvent oui pour des rafraîchissements rapides, mais appliquez des quotas et surveillez la croissance. Les bases de données écrivent beaucoup ; un clone peut rapidement atteindre une taille « presque pleine » par rapport à son origine selon le churn. L’avantage est la vitesse de provisionnement et la commodité de rollback, pas des économies d’espace garanties à long terme.
7) What does zfs promote actually do?
Elle change quel dataset est considéré comme origine dans la relation clone. Concrètement, elle rend le clone sélectionné indépendant de son snapshot d’origine et réarrange l’ascendance pour que vous puissiez supprimer des dépendances. Elle ne copie pas toutes les données, mais modifie absolument la façon dont les suppressions de snapshots et la réplication se comporteront.
8) Are ZFS clones safe to use in production?
Oui — si vous gérez le cycle de vie et les dépendances. Le risque n’est pas l’intégrité des données ; ZFS fait exactement ce qu’il promet. Le risque est opérationnel : rétention cachée, épinglage d’espace et promotions surprises. Traitez les clones comme des ressources de première classe avec propriétaire et expiration.
9) Why did freeing files not free pool space?
Parce que les blocs supprimés sont encore référencés par des snapshots et/ou des clones. Vérifiez usedbysnapshots, les clones dépendants et les holds sur snapshots. L’espace n’est libéré que lorsque la dernière référence disparaît.
10) Is there a safer alternative to clones for “copying” data?
Si vous avez besoin d’une copie indépendante sans dépendances, faites une copie complète ou utilisez zfs send | zfs receive dans un dataset/pool séparé. Ce n’est pas instantané, mais cela supprime la chaîne de dépendance par blocs partagés que les clones introduisent.
Conclusion
Les clones ZFS sont l’un des meilleurs outils pour « aller vite sans casser le stockage » — jusqu’au moment où vous les traitez comme des copies normales. Ils sont instantanés parce qu’ils sont liés. Ce lien est puissant quand vous le contrôlez, et coûteux quand vous l’oubliez.
Si vous ne retenez que trois choses, ce sont celles-ci : les clones épinglent les snapshots, les snapshots épinglés épinglent l’espace, et l’espace non géré finit par épingler votre week‑end. Mettez des propriétaires et des expirations sur les clones, comprenez la promotion avant d’en avoir besoin, et gardez suffisamment de marge libre pour que le CoW fasse son travail. C’est ainsi que les clones restent un super‑pouvoir plutôt qu’une scène de crime.