ZFS zfs promote : démêler les chaînes de clones sans perte de données

Cet article vous a aidé ?

Les chaînes de clones sont une de ces fonctionnalités de ZFS qui semblent relever d’un tour de magie jusqu’au jour où vous ne pouvez plus détruire un snapshot, libérer de l’espace, et que votre tâche de réplication commence à transférer de l’historique que vous jurez avoir supprimé le trimestre dernier. L’outil qui vous sort de ce nœud est zfs promote. Ce n’est pas glamour, mais c’est la différence entre « je nettoierai ça après le déjeuner » et « pourquoi le téléphone d’astreinte fond-il ? »

Cet article est écrit depuis le côté production du rack : le côté où les datasets ont des propriétaires, les SLA ont des dents, et où vous découvrez de nouvelles dépendances de clones pendant un bridge d’incident. Nous irons assez en profondeur pour être précis, mais pas si académiques que vous ne puissiez pas l’utiliser à 3 h du matin.

Ce que zfs promote fait réellement

Dans ZFS, un clone est un dataset inscriptible créé à partir d’un snapshot. Le snapshot est « l’origine » de ce clone. Sous le capot, le clone partage initialement des blocs avec son snapshot d’origine, et diverge au fur et à mesure qu’il écrit de nouvelles données (comportement classique copy-on-write).

La conséquence opérationnelle clé : un clone crée une dépendance. Tant que le clone existe, le snapshot d’origine ne peut pas être détruit, parce que ZFS en a encore besoin pour représenter l’état initial du clone. C’est pourquoi vous tombez parfois sur le mur « can’t destroy snapshot: snapshot has dependent clones ».

zfs promote est l’échappatoire : il inverse la dépendance entre un clone et son origine. Après promotion, le clone devient le dataset « principal », et l’ancien parent devient le clone dépendant (ou, plus précisément : la relation d’origine s’inverse de sorte que le dataset promu ne dépend plus du snapshot d’origine précédent).

Considérez cela comme un changement de qui est considéré comme l’ancêtre dans la relation d’origine. Vous ne copiez pas des données ; vous changez quel snapshot est pris comme point de référence pour la relation clone/origine. C’est pourquoi la promotion est rapide : c’est une chirurgie des métadonnées, pas une réécriture de données.

Une phrase à vous répéter pendant une fenêtre de maintenance : promote change qui dépend de qui ; il ne « fusionne » pas les datasets.

Première plaisanterie (courte et douloureusement exacte) : si vous n’avez jamais dit « c’est juste un clone » et l’avez immédiatement regretté, félicitations pour votre carrière de stockage paisible et étrangement courte.

Termes clés à garder en tête

  • Snapshot : vue en lecture seule d’un dataset à un instant donné.
  • Clone : dataset inscriptible créé à partir d’un snapshot.
  • Origin : le snapshot depuis lequel un clone a été créé (visible via la propriété origin).
  • Chaîne de clones : lorsqu’un clone a des snapshots, et que de nouveaux clones sont faits à partir de ces snapshots, formant un graphe de dépendance.
  • Promotion : inversion de la dépendance d’origine de sorte que le dataset promu ne soit plus bloqué par un snapshot ancêtre plus ancien.

Chaînes de clones : l’arbre généalogique que vous n’aviez pas voulu lancer

Un cas simple ressemble à ceci :

  • pool/app a le snapshot pool/app@baseline
  • pool/app_clone est créé à partir de pool/app@baseline

À ce stade, pool/app@baseline est épinglé. Vous ne pouvez pas le détruire tant que pool/app_clone existe, parce que ce snapshot est l’origine qui définit l’état initial du clone.

Ajoutez maintenant du temps et la créativité humaine. Quelqu’un prend des snapshots du clone. Quelqu’un crée un autre clone à partir du clone. Quelqu’un renomme des datasets. Quelqu’un réplique vers un pool DR. La simple dépendance à deux nœuds devient un petit écosystème.

En production, les chaînes de clones ont tendance à apparaître dans trois endroits prévisibles :

  • Templates de VM et images golden : un snapshot de base engendre des dizaines de clones (disques de VM), puis de nouveaux « templates » sont clonés à partir de ces clones par commodité.
  • Environnements CI/CD : clones éphémères créés par build, mais les snapshots de base sont conservés « au cas où », et finissent par devenir critiques pour l’entreprise.
  • Rafraîchissements de bases de données : un snapshot prod est cloné dans un environnement staging, staging devient « l’endroit où les correctifs se font », et soudain staging a des snapshots et des enfants qui doivent être conservés.

Voici le piège opérationnel : les chaînes de clones peuvent donner l’impression que le pool fuit de l’espace. Vous supprimez de vieux snapshots, mais « USED » bouge à peine. Vous détruisez ce que vous pensez être le dernier dataset dépendant, et un autre maintient encore le snapshot d’origine épinglé. Pendant ce temps, votre politique de rétention devient silencieusement « pour toujours ».

Pourquoi la promotion compte dans la vraie vie

La promotion sert à :

  • Libérer un dataset plus ancien pour suppression tout en conservant le dataset récent.
  • Recentrer la lignée d’une charge de travail sur le dataset qui compte réellement maintenant.
  • Nettoyer un arbre de snapshots où le dataset « parent » est mort, mais son snapshot bloque encore tout.
  • Rendre les flux de réplication plus sains en stabilisant quel dataset est la source faisant foi.

Faits intéressants & contexte historique

  1. Les clones ZFS précèdent le boom des conteneurs modernes : les clones étaient déjà une façon pratique de lancer des copies inscriptibles rapidement, bien avant que « couches copy-on-write » ne deviennent un mot à la mode ailleurs.
  2. La promotion existe parce que la suppression vaut plus que la création : cloner est facile ; nettoyer en toute sécurité nécessitait une commande de première classe.
  3. L’« origin » est une propriété, pas un ressenti : ZFS enregistre explicitement le snapshot d’origine, ce qui permet d’interroger et de raisonner sur les dépendances au lieu de deviner.
  4. Les chaînes de clones sont des graphes, pas des listes : un snapshot peut avoir plusieurs clones ; chaque clone peut avoir ses propres snapshots et clones. On dit « chaîne » parce que ça semble linéaire jusqu’à ce que ce ne le soit pas.
  5. L’espace est retenu par les blocs référencés, pas par votre intention : supprimer un snapshot ne libère que les blocs qui ne sont référencés nulle part ailleurs. Les clones sont « ailleurs ».
  6. La promotion est typiquement du travail sur les métadonnées : c’est rapide parce que ZFS ajuste la comptabilité de lignée, pas parce qu’il recopie des téraoctets. (Cela peut quand même prendre du temps sur des systèmes très chargés à cause des synchronisations et des groupes de transactions.)
  7. Renommer ne change pas l’ascendance : zfs rename change les noms ; il ne change pas la relation d’origine. C’est ainsi que « on l’a renommé, donc c’est nouveau » devient un incident de stockage.
  8. Les politiques de rétention de snapshots ignorent souvent les clones : les scripts de rétention bricolés détruisent souvent les snapshots du plus ancien au plus récent, puis se cognent sur un clone dépendant et s’arrêtent — ou, pire, réussissent partiellement et laissent un bazar.

Quand vous devriez promouvoir (et quand vous ne devriez pas)

Promouvoir quand…

  • Vous voulez supprimer le dataset original (ou ses vieux snapshots), mais des clones en dépendent.
  • Un clone est devenu la charge de travail réelle, et le dataset original est maintenant « juste de l’histoire ».
  • Vous avez hérité d’un pool où le dataset de production actuel est un clone d’un clone d’un snapshot de 2019, et votre rétention est en gros un musée.
  • Vous devez casser une dépendance pour que la destruction de snapshots ou l’élagage de réplication puisse avancer.

Ne pas promouvoir quand…

  • Vous n’êtes pas sûr du dataset qui est la source faisant foi et la réplication en amont attend une lignée particulière.
  • Vous avez de l’automatisation qui suppose qu’un dataset donné est le parent et utilise origin ou des conventions de nommage comme logique.
  • Vous essayez de « fusionner des changements vers le parent ». La promotion ne fusionne pas ; elle réorganise juste qui est l’origine.

Deuxième plaisanterie (parce que tout le monde a besoin d’encore une) : promouvoir le mauvais dataset, c’est comme faire « répondre à tous » dans un e-mail — techniquement impressionnant, socialement coûteux, et immédiatement irréversible dans la mémoire collective.

Tâches pratiques avec commandes (et ce que la sortie signifie)

Voici des tâches opératoires réelles : « montrer la dépendance », « prouver quel snapshot est épinglé », « promouvoir en toute sécurité », « valider après ». Les commandes partent du principe d’un pool nommé tank et de datasets comme tank/app. Adaptez à votre environnement.

Task 1: Trouver les clones et leurs origines

cr0x@server:~$ zfs list -t filesystem,volume -o name,origin
NAME                 ORIGIN
tank/app             -
tank/app-clone       tank/app@baseline
tank/db              -
tank/db-staging      tank/db@weekly-2025w51

Interprétation : Tout dataset avec une origine non-- est un clone. Ici, tank/app-clone dépend de tank/app@baseline.

Task 2: Voir quel snapshot refuse de mourir (erreur de dépendance)

cr0x@server:~$ zfs destroy tank/app@baseline
cannot destroy 'tank/app@baseline': snapshot has dependent clones
use '-R' to destroy the following datasets:
tank/app-clone

Interprétation : ZFS vous dit exactement ce qui est épinglé. Vous pouvez détruire le clone (-R détruirait récursivement), ou promouvoir le clone pour pouvoir supprimer l’historique d’origine sans supprimer la charge active.

Task 3: Afficher l’espace des snapshots et « pourquoi c’est encore utilisé ? »

cr0x@server:~$ zfs list -t snapshot -o name,used,refer,creation -s creation tank/app
NAME                   USED  REFER  CREATION
tank/app@baseline      0B    5.20G  Mon Nov 10 09:12 2025
tank/app@post-upgrade  88M   5.45G  Tue Nov 18 14:03 2025

Interprétation : Le USED d’un snapshot est l’espace attribuable uniquement à ce snapshot comparé au dataset actif, pas l’espace total épinglé par son existence. Les clones peuvent quand même forcer ce snapshot à exister même s’il « utilise 0B ».

Task 4: Vérifier la comptabilité d’espace du dataset qui pointe vers des clones/snapshots

cr0x@server:~$ zfs get -H -o name,property,value used,usedbysnapshots,usedbychildren,usedbydataset tank/app
tank/app  used             220G
tank/app  usedbysnapshots  12G
tank/app  usedbychildren   180G
tank/app  usedbydataset    28G

Interprétation : Si usedbychildren est énorme, des datasets enfants (y compris des clones montés ailleurs) conservent des blocs référencés. Si usedbysnapshots est énorme, la rétention des snapshots est la suspecte.

Task 5: Trouver où le clone est monté (pour ne pas promouvoir la mauvaise chose)

cr0x@server:~$ zfs get -H -o name,value mountpoint tank/app tank/app-clone
tank/app       /srv/app
tank/app-clone /srv/app-staging

Interprétation : C’est ainsi que vous liez un nom de dataset à une charge réelle. Avant de promouvoir, confirmez lequel la production écrit réellement.

Task 6: Promouvoir le clone (l’opération centrale)

cr0x@server:~$ sudo zfs promote tank/app-clone

Interprétation : Après cela, tank/app-clone devient indépendant de tank/app@baseline de la manière qui vous importe opérationnellement : l’ancien dataset « parent » devient le dépendant dans la relation d’origine.

Task 7: Vérifier les origines après promotion

cr0x@server:~$ zfs list -o name,origin tank/app tank/app-clone
NAME           ORIGIN
tank/app       tank/app-clone@baseline
tank/app-clone -

Interprétation : Le dataset promu n’a maintenant plus d’origine. L’ancien parent pointe maintenant vers un snapshot du dataset promu. C’est l’inversion. Cela explique aussi pourquoi la promotion peut créer/exiger une référence de snapshot correspondante dans la lignée du dataset promu.

Task 8: Maintenant détruire l’ancien historique de snapshots (le nettoyage)

cr0x@server:~$ sudo zfs destroy tank/app@baseline
cannot destroy 'tank/app@baseline': snapshot has dependent clones

Interprétation : Si vous voyez encore cette erreur, vous pouvez avoir plus d’un clone, ou un graphe plus profond. La promotion règle une relation ; elle ne dissout pas automatiquement toutes les dépendances si plusieurs clones dépendent du même snapshot.

Task 9: Énumérer tous les clones d’un snapshot (cartographie des dépendances)

cr0x@server:~$ zfs get -H -o name,value clones tank/app@baseline
tank/app@baseline  tank/app-clone,tank/app-ci-112,tank/app-ci-113

Interprétation : Cela vous dit qui épingle ce snapshot. Vous ne pourrez le détruire que lorsque aucun de ceux-ci n’existe (ou lorsque chacun aura été promu de manière appropriée et que la lignée aura été mise à jour).

Task 10: Renommer en toute sécurité après promotion (stabiliser les noms)

cr0x@server:~$ sudo zfs rename tank/app tank/app-old
cr0x@server:~$ sudo zfs rename tank/app-clone tank/app

Interprétation : La promotion change l’ascendance ; renommer change les noms utilisés par vos outils et humains. En pratique, vous promouvez souvent, puis renommez pour que la production reste sur le nom canonique du dataset.

Task 11: Confirmer que les points de montage n’ont pas changé (ou les corriger)

cr0x@server:~$ zfs get -H -o name,value mountpoint tank/app tank/app-old
tank/app      /srv/app
tank/app-old  /srv/app-staging

Interprétation : Le renommage ne fait pas toujours automatiquement ce que vous voulez avec les mountpoints s’ils ont été explicitement définis. Confirmez et définissez-les délibérément.

cr0x@server:~$ sudo zfs set mountpoint=/srv/app tank/app
cr0x@server:~$ sudo zfs set mountpoint=/srv/app-old tank/app-old

Task 12: Valider l’effet « espace épinglé » après nettoyage

cr0x@server:~$ zfs list -o name,used,usedbysnapshots,usedbychildren,usedbydataset tank/app-old
NAME         USED  USEDBYSNAPSHOTS  USEDBYCHILDREN  USEDBYDATASET
tank/app-old 28G   0B               0B             28G

Interprétation : L’ancien dataset est maintenant un dataset normal (ou un clone) sans la charge des enfants/snapshots. Si vous le retirez, il est maintenant simple à snapshotter/détruire selon la politique.

Task 13: Trouver tous les clones dans un sous-arbre (audit avant maintenance)

cr0x@server:~$ zfs list -r -o name,origin tank | awk '$2 != "-" {print}'
tank/app-ci-112 tank/app@baseline
tank/app-ci-113 tank/app@baseline
tank/db-staging tank/db@weekly-2025w51

Interprétation : C’est un inventaire rapide et sale. Dans de grands environnements, la prolifération de clones est rarement documentée ; vous la découvrez en interrogeant ZFS, pas Slack.

Task 14: Vérifier les holds qui empêchent la destruction de snapshots (problème différent, symptôme similaire)

cr0x@server:~$ zfs holds tank/app@baseline
NAME               TAG        TIMESTAMP
tank/app@baseline  keep       Wed Dec 10 10:21 2025

Interprétation : Si la destruction échoue mais que les clones ne sont pas la raison, un hold utilisateur pourrait l’être. La promotion ne vous aidera pas ici ; vous devez libérer le hold.

cr0x@server:~$ sudo zfs release keep tank/app@baseline

Task 15: Simulation d’une décision « destroy recursively » avec zfs destroy -nvp

cr0x@server:~$ sudo zfs destroy -nvp tank/app@baseline
would destroy tank/app@baseline
would destroy tank/app-ci-112
would destroy tank/app-ci-113
would reclaim 41.2G

Interprétation : C’est ainsi que vous évitez le geste qui ruinerait votre carrière consistant à effacer un environnement CI que quelqu’un a discrètement transformé en production l’année dernière.

Réplication et sauvegardes : zfs send/receive avec des clones

Les chaînes de clones ne compliquent pas seulement la suppression ; elles compliquent la réplication. Dès que vous comptez sur des envois incrémentiels, vous avez implicitement accepté la lignée comme contrat : « ce dataset sur le récepteur partage l’historique de snapshots avec l’expéditeur ». Les clones introduisent des forks dans cet historique.

Ce qui tourne généralement mal

Deux surprises classiques :

  • La réplication envoie plus que prévu parce que vous avez accidentellement répliqué la mauvaise branche ou gardé un snapshot d’origine vivant, si bien que le récepteur doit aussi le conserver.
  • La réplication échoue avec « incremental source does not match » parce que quelqu’un a promu/renommé d’un côté et pas de l’autre, brisant la lignée de snapshots attendue.

La promotion elle-même n’est pas intrinsèquement incompatible avec la réplication, mais c’est un changement structurel. Si vous promouvez un dataset qui est répliqué incrémentalement, traitez-le comme une migration de schéma : coordonnez, documentez et validez des deux côtés.

Task 16: Inspecter la lignée des snapshots pour la réplication (base commune)

cr0x@server:~$ zfs list -t snapshot -o name,creation -s creation tank/app | tail -n 5
tank/app@replica-2025-12-20  Sat Dec 20 01:00 2025
tank/app@replica-2025-12-21  Sun Dec 21 01:00 2025
tank/app@replica-2025-12-22  Mon Dec 22 01:00 2025
tank/app@replica-2025-12-23  Tue Dec 23 01:00 2025
tank/app@replica-2025-12-24  Wed Dec 24 01:00 2025

Interprétation : Un schéma de nommage de snapshots stable et prévisible est votre ami. Si vos snapshots sont ad hoc, les dépendances de clones deviennent plus difficiles à raisonner et à répliquer proprement.

Task 17: Utiliser un flux de réplication avec précaution (exemple incrémental)

cr0x@server:~$ sudo zfs send -I tank/app@replica-2025-12-23 tank/app@replica-2025-12-24 | sudo zfs receive -u backup/app

Interprétation : -I envoie tous les snapshots intermédiaires. Si les chaînes de clones et les promotions ont modifié les snapshots disponibles, le récepteur peut ne pas avoir la base attendue. Confirmez toujours que la snapshot de base existe des deux côtés avant d’exécuter des incrémentaux.

Task 18: Confirmer l’idée d’origin et d’identité de type GUID (vérification pragmatique)

cr0x@server:~$ zfs get -H -o name,property,value origin tank/app backup/app
tank/app   origin  -
backup/app origin  -

Interprétation : La réplication n’exige pas que le dataset récepteur soit un clone, mais elle nécessite des snapshots partagés pour les incrémentaux. Ne confondez pas « origin » (relation de clone) avec « histoire partagée » (ensemble de snapshots de réplication). Ils se recoupent conceptuellement, mais ce sont des mécanismes différents.

Trois mini-histoires du monde de l’entreprise

1) Incident causé par une mauvaise hypothèse : « Supprimer le snapshot libérera de l’espace »

Dans une grande entreprise très normale, une équipe applicative gérait son propre pool ZFS pour les artefacts de build et les environnements « temporaires ». Leur script de rétention était simple : détruire les snapshots de plus de 30 jours. Quand le pool a approché 90 % d’utilisation, ils ont fait ce que tout le monde fait sous pression : supprimer plus de snapshots.

Ça n’a rien fait. zfs list montrait moins de snapshots, mais zpool list n’a pas bougé. L’ingénieur d’astreinte a supposé que ZFS était « lent à récupérer l’espace », et a planifié un reboot parce que — eh bien — parfois ça marche sur d’autres choses.

Le reboot n’a pas récupéré d’espace. Le pool a atteint un seuil supérieur, les allocations ont commencé à échouer, et quelques jobs ont commencé à produire des sorties corrompues (pas parce que ZFS les avait corrompues, mais parce que les outils en amont ne géraient pas ENOSPC). Le bridge d’incident s’est rempli du son de personnes découvrant que « disque plein » est un hobby inter-fonctionnel.

La correction a été embarrassante de simplicité : les snapshots qu’ils supprimaient étaient épinglés par des clones créés pour des jobs CI. Ces clones ont été conservés plus de 30 jours parce que quelqu’un aimait avoir des « builds anciens reproductibles ». Le script de rétention ne vérifiait jamais les dépendances de clones et passait silencieusement sur les snapshots qu’il ne pouvait pas détruire. C’était le pire type de défaillance : une défaillance silencieuse.

Ils ont audité les origins, promu les quelques clones devenus des environnements permanents, et supprimé les datasets clones vraiment éphémères. L’espace a chuté immédiatement, et l’incident s’est terminé avec les leçons habituelles : ZFS a fait exactement ce qu’il promettait ; les humains ne l’ont pas fait.

2) Une optimisation qui s’est retournée contre eux : « clonons tout pour gagner du temps »

Une équipe plateforme voulait accélérer les rafraîchissements de base de données pour le QA. Ils avaient un processus propre : snapshotter la production la nuit, la répliquer, restaurer en QA. C’était lent, et l’équipe subissait la pression de la performance. Quelqu’un a proposé une idée astucieuse : arrêter de restaurer ; cloner simplement le dernier snapshot et le donner au QA comme dataset inscriptible. Les rafraîchissements seraient instantanés.

Ça a brillamment fonctionné pendant un mois. Le QA a adoré. L’équipe plateforme a goûté la rare sensation d’avoir résolu le temps. Puis le stockage a commencé à avoir un aspect étrange : la rétention des snapshots ne libérait pas d’espace, les flux de réplication augmentaient, et le pool DR conservait l’historique bien au-delà de la politique. Tout le monde a blâmé « l’overhead ZFS ». Personne n’a dit « dépendance de clone » à voix haute jusqu’à ce que quelqu’un essaie de supprimer un ancien snapshot et tombe sur l’erreur dependent-clone.

Le vrai problème était organisationnel, pas technique. L’optimisation a transformé des datasets QA éphémères en environnements longue durée de type production avec leurs propres habitudes de snapshots. Les ingénieurs ont commencé à créer des clones à partir de clones pour exécuter des tests parallèles. Le graphe résultant a épinglé des mois de snapshots prod. L’astuce « rafraîchissement instantané » avait silencieusement réécrit le contrat de rétention pour tout le système.

Ils se sont rétablis en traçant une frontière stricte : les clones éphémères ont eu un TTL appliqué par l’automatisation, et les environnements QA longue durée ont été promus pour ne plus ancrer l’historique prod. Ils ont gardé l’optimisation, mais seulement après avoir ajouté des garde-fous : inventaire des origins de clones, points de promotion explicites, et une politique disant « les clones sont du bétail sauf s’ils sont explicitement promus ».

3) Une pratique ennuyeuse mais correcte qui a sauvé la mise : « Nommez les snapshots sérieusement, et répétez la promotion »

Une équipe proche des finances gérait une ferme de VM basée sur ZFS. Ils avaient la complexité habituelle : templates, clones pour VMs, et une petite armée de snapshots pour patch et rollback. Rien de spécial — juste assez de pièces mobiles pour rendre une panne épicée.

Leur pratique ennuyeuse était la suivante : chaque clone de disque VM avait une étiquette dans ses propriétés ZFS pour propriétaire et environnement, chaque snapshot de template avait un nom stable, et une fois par trimestre ils exécutaient une répétition de maintenance où ils promouvaient délibérément un clone dans un pool labo et validaient que leur sauvegarde/réplication se comportait toujours.

Un jour, un ingénieur a tenté de retirer un ancien dataset template. La suppression de ses snapshots a échoué parce que des clones dépendants existaient. C’est là que les équipes paniquent habituellement. Mais l’inventaire de cette équipe leur a dit exactement quels clones étaient longue durée et lesquels étaient éphémères. Ils ont promu les clones longue durée, puis détruit le reste, et finalement supprimé l’ancien historique du template.

La meilleure partie n’était pas la promotion — c’était à quel point c’était inintéressant. Pas de downtime surprenant. Pas d’archéologie « qui possède ce dataset ? ». Pas de meltdown de réplication. Le ticket de changement avait l’air ennuyeux, ce qui est le plus grand compliment que vous puissiez faire au travail de stockage.

Playbook de diagnostic rapide

Ceci est la séquence « j’ai 15 minutes avant que le pool n’atteigne 95 % et que mon pager commence à composer de la poésie ». L’objectif est d’identifier si votre goulot est des clones épinglant des snapshots, de la rétention de snapshots, des datasets enfants, ou autre chose entièrement.

Premier : confirmer le problème au niveau du pool et sa nature

cr0x@server:~$ zpool list
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  7.25T  6.71T   560G        -         -    38%    92%  1.00x  ONLINE  -

Interprétation : Un CAP élevé est l’urgence. La fragmentation peut compter, mais ce n’est généralement pas la cause première de « pourquoi la suppression n’a pas libéré d’espace ».

Second : trouver les gros consommateurs et s’il s’agit de snapshots ou d’enfants

cr0x@server:~$ zfs list -o name,used,usedbysnapshots,usedbychildren,usedbydataset -S used | head -n 10
NAME           USED  USEDBYSNAPSHOTS  USEDBYCHILDREN  USEDBYDATASET
tank/vm        4.90T 900G             3.80T          200G
tank/app       220G  12G              180G           28G
tank/db        140G  60G              0B             80G

Interprétation : Si usedbychildren domine, votre espace est dans les enfants (souvent des clones). Si usedbysnapshots domine, la rétention est suspecte. Si usedbydataset domine, les données vivantes sont volumineuses et vous ne supprimez pas la bonne chose.

Troisième : vérifier les dépendances de clones qui épinglent de vieux snapshots

cr0x@server:~$ zfs list -t filesystem,volume -o name,origin -r tank/vm | awk '$2 != "-" {print}' | head
tank/vm/qa-01     tank/vm/template@golden
tank/vm/qa-02     tank/vm/template@golden
tank/vm/prod-17   tank/vm/template@2025q3

Interprétation : Cela vous dit si des clones existent et ce qu’ils épinglent. Si vous ne pouvez pas supprimer un snapshot, c’est généralement la raison.

Quatrième : pour un snapshot épinglé spécifique, lister ses clones

cr0x@server:~$ zfs get -H -o value clones tank/vm/template@golden
tank/vm/qa-01,tank/vm/qa-02,tank/vm/ci-881,tank/vm/ci-882

Interprétation : Vous avez maintenant la liste des actions : détruire les clones éphémères, promouvoir ceux qui doivent survivre, puis supprimer l’ancien historique de snapshots.

Cinquième : vérification de sanity de la pression I/O avant d’effectuer des opérations lourdes

cr0x@server:~$ zpool iostat -v 1 3
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        6.71T   560G    380    520   42.1M  88.3M
  mirror-0                  3.35T   280G    190    260   21.0M  44.1M
    sda                         -      -     95    130   10.5M  22.1M
    sdb                         -      -     95    130   10.5M  22.0M
  mirror-1                  3.36T   280G    190    260   21.1M  44.2M
    sdc                         -      -     95    130   10.6M  22.1M
    sdd                         -      -     95    130   10.5M  22.1M

Interprétation : Les promotions sont généralement rapides, mais les opérations de nettoyage qui déclenchent beaucoup de frees peuvent coïncider avec de fortes écritures et augmenter les latences. Si vous êtes déjà à la limite, planifiez le nettoyage ou limitez les charges.

Erreurs courantes, symptômes et corrections

Mistake 1: Essayer de détruire le snapshot d’origine sans traiter les clones

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

Correction : Identifiez les clones dépendants avec zfs get clones pool/ds@snap. Décidez : détruire les clones (éphémères) ou promouvoir les clones (longue durée), puis retentez la destruction du snapshot.

Mistake 2: Promouvoir le dataset que vous aviez l’intention de supprimer

Symptôme : Après promotion, le « mauvais » dataset a origin=- et votre automatisation pointe vers le mauvais point de montage.

Correction : Avant la promotion, confirmez les mountpoints et les écrivains actifs. Utilisez zfs get mountpoint et des vérifications au niveau OS (quel processus écrit où). Si vous avez déjà promu, vous pouvez toujours récupérer en renommant les datasets et en corrigeant les mountpoints ; les données ne sont pas perdues, mais votre lignée a changé, donc mettez à jour les runbooks et les hypothèses de réplication.

Mistake 3: Supposer que la promotion libérera immédiatement de l’espace

Symptôme : Vous avez promu un clone mais l’utilisation du pool n’a pas diminué.

Correction : La promotion ne supprime rien. Elle vous permet seulement de détruire les snapshots/datasets anciens qui étaient auparavant épinglés. Faites le suivi : détruisez les snapshots/datasets obsolètes après avoir vérifié que les dépendances ont disparu.

Mistake 4: Confondre « snapshot USED » avec « espace épinglé par le snapshot »

Symptôme : Un snapshot affiche USED=0B, mais sa destruction est bloquée et/ou il semble épingler beaucoup d’espace.

Correction : Utilisez zfs get clones et les propriétés usedby* au niveau du dataset pour comprendre l’espace. USED sur un snapshot n’est pas un comptage complet de ce qu’il permet ailleurs.

Mistake 5: Laisser la prolifération de clones devenir une politique par accident

Symptôme : D’anciens snapshots « baseline » ne peuvent pas être supprimés des années plus tard ; la réplication conserve d’énormes historiques ; personne ne sait ce qu’on peut supprimer.

Correction : Ajoutez des métadonnées (propriétés comme owner/env), un TTL automatisé pour les clones éphémères, et un audit trimestriel : lister les clones et leurs origins, identifier lesquels devraient être promus pour devenir des lignées indépendantes.

Mistake 6: Casser la réplication incrémentale en modifiant unilatéralement la lignée

Symptôme : L’envoi incrémental échoue parce que le récepteur n’a pas le snapshot de base attendu ; après promotion, les noms et l’ascendance des snapshots ne correspondent plus.

Correction : Coordonnez la promotion avec la réplication. Validez les snapshots communs des deux côtés. Dans certains cas, vous devrez reseeder avec un envoi complet, ou ajuster la réplication vers de nouvelles bases.

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

Checklist A: « Je dois supprimer un ancien dataset, mais ses snapshots sont épinglés »

  1. Identifiez le dataset et les snapshots précis que vous voulez supprimer.
  2. Listez les clones de ces snapshots avec zfs get clones.
  3. Classifiez chaque clone : éphémère (sécuritaire à détruire) vs longue durée (à conserver).
  4. Pour chaque clone longue durée, confirmez que c’est bien le dataset à préserver (mountpoint, propriétaire, écrivains actifs).
  5. Promouvez les clones longue durée (zfs promote).
  6. Détruisez les clones éphémères (préférez zfs destroy -nvp d’abord).
  7. Détruisez les snapshots désormais désépinglés.
  8. Détruisez ou archivez le dataset retraité (après un snapshot de sécurité final si la politique l’exige).

Checklist B: « Je promeus un clone qui est (ou pourrait être) en production »

  1. Geler la fenêtre de changement ; annoncer le changement de lignée aux propriétaires applicatifs et sauvegarde.
  2. Vérifier le dataset et le mountpoint ; vérifier que la charge utilise bien ce mount.
  3. Prendre un snapshot de sécurité du parent et du clone.
  4. Enregistrer la sortie de zfs list -o name,origin avant le changement.
  5. Exécuter zfs promote.
  6. Vérifier l’inversion d’origine avec zfs list -o name,origin.
  7. Si souhaité, renommer les datasets pour restaurer le nom canonique.
  8. Valider l’I/O applicative, les montages et les jobs de réplication.
  9. Ce n’est qu’ensuite que vous procédez à la suppression des anciens snapshots/datasets parents.

Checklist C: « Nous devons empêcher que les chaînes de clones deviennent une surprise trimestrielle »

  1. Définir quels datasets sont autorisés à être des origines de clones (templates, baselines).
  2. Tagger les datasets clones avec owner/environnement en utilisant des propriétés utilisateur ZFS.
  3. Automatiser le nettoyage TTL pour les clones éphémères et leurs snapshots.
  4. Exécuter un audit hebdomadaire : lister tous les datasets avec origin non vide.
  5. Revoir les « snapshots épinglés » : snapshots avec beaucoup de clones.
  6. Promouvoir intentionnellement les clones longue durée, pas par accident.

FAQ

1) zfs promote copie-t-il des données ?

Non. La promotion est principalement une opération sur les métadonnées qui change la relation d’origine. Vos blocs restent là où ils sont ; ZFS change la façon dont il comptabilise l’ascendance et les dépendances.

2) Promouvoir un clone libérera-t-il immédiatement de l’espace ?

Non. La promotion vous permet de supprimer des snapshots/datasets qui étaient auparavant épinglés. L’espace est libéré lorsque vous détruisez les snapshots/datasets désormais inutiles et que ces blocs ne sont plus référencés.

3) Puis-je promouvoir un dataset ayant des enfants ?

En pratique, oui, mais il faut être prudent : les datasets enfants, snapshots et clones peuvent élargir le graphe de dépendance plus que prévu. Auditez d’abord le sous-arbre (zfs list -r -o name,origin) pour ne pas promouvoir dans une situation encore plus embrouillée.

4) Que devient la propriété origin après la promotion ?

Le dataset promu affichera origin=-. Le dataset qui était l’ancien parent gagnera généralement une origin pointant vers un snapshot du dataset promu (la relation s’inverse).

5) La promotion est-elle sûre sur un système en production ?

Cela se fait couramment sur des systèmes en live, mais la « sécurité » dépend de ce qui se passe d’autre : forte I/O, runs de réplication et automatisation réagissant aux changements de dataset peuvent rendre une opération simple bruyante. Promouvez pendant une fenêtre contrôlée et validez les montages et outils ensuite.

6) Pourquoi ne puis-je pas détruire un snapshot même s’il n’y a pas de clones ?

Deux raisons fréquentes : un hold utilisateur existe (zfs holds), ou le snapshot est nécessaire pour l’historique de réplication incrémentale (pas un « bloqueur » au sens ZFS, mais votre processus peut en dépendre). ZFS vous dira si des clones bloquent la destruction ; les holds sont séparés.

7) Renommer un dataset aide-t-il pour les dépendances de clones ?

Non. Le renommage change le nom, pas l’ascendance. Si un snapshot est épinglé par des clones, renommer ne le libérera pas. La promotion ou la destruction des clones est ce qui modifie la dépendance.

8) Comment trouver tous les snapshots qui ont des clones ?

Vous pouvez itérer les snapshots et vérifier la propriété clones. Pratiquement, commencez par les datasets où l’espace est coincé et interrogez leurs anciens snapshots pour des clones. Dans de nombreux environnements, il est plus rapide de lister d’abord tous les datasets avec origin défini, puis de les mapper aux snapshots d’origine.

9) La promotion peut-elle casser ma réplication incrémentale ?

Ça peut, si votre workflow de réplication suppose une lignée particulière et que vous la changez sur l’expéditeur sans coordonner le récepteur. Traitez la promotion comme un changement de lignée : vérifiez les snapshots partagés et soyez prêt à reseeder ou ajuster les baselines.

10) Quelle est la façon la plus sûre d’expérimenter la promotion ?

Faites-le sur un pool de test avec un petit dataset qui imite votre structure : créez un snapshot, clonez-le, ajoutez des snapshots des deux côtés, créez un clone-d’un-clone, puis promouvez et observez les inversions d’origine. La mémoire musculaire paie quand vous le faites sous pression.

Conclusion

zfs promote est une de ces commandes qui paraît un coin niche de ZFS jusqu’à ce que vous réalisiez que c’est la clé pour supprimer des choses en toute sécurité dans un monde plein de clones. La promotion ne déplace pas les données ; elle déplace la responsabilité. Elle vous permet de déclarer « ce dataset est la nouvelle vérité », puis de retirer proprement l’ancienne vérité sans écraser le présent par accident.

L’approche de niveau production est cohérente : inventoriez les origins de clones, promouvez intentionnellement, validez ensuite, et seulement alors détruisez les snapshots et datasets que vous aviez l’intention de retirer. Si vous faites cela, les chaînes de clones cessent d’être effrayantes. Elles deviennent juste un autre outil que vous pouvez utiliser — en toute confiance — sans payer d’intérêts cachés plus tard.

← Précédent
Proxmox PBS « datastore not found » : pourquoi PVE ne le voit pas et comment le réparer
Suivant →
Shaders programmables : quand le « graphisme » est devenu logiciel

Laisser un commentaire