ZFS : le système de nommage des snapshots qui rend les rollbacks sereins

Cet article vous a aidé ?

Les rollbacks sont censés être ennuyeux. Vous appuyez sur le bouton, votre rythme cardiaque reste stable, et le compte rendu post-incident se limite à une phrase : « Restauré depuis un snapshot. »

En pratique, la panique arrive plus tôt — au moment où vous devez choisir quel snapshot est « le bon ». Si vos noms de snapshots ressemblent à un tiroir où tout est jeté, vous ne faites pas des sauvegardes ; vous collectionnez des surprises.

Pourquoi le nommage est un contrôle de production (pas une lubie)

Le nommage des snapshots attire deux types de personnes : celles qui pensent que c’est une question d’esthétique, et celles qui ont dû revenir en arrière sur un dataset pendant qu’un VP regardait le canal d’incident se rafraîchir. Le second groupe a raison.

Un snapshot ZFS est une vue à un instant donné. Il est peu coûteux à créer, rapide à lister, et terriblement littéral : il capture des blocs, pas votre intention. Le seul endroit où votre intention vit de façon fiable est le nom du snapshot et les métadonnées qui l’entourent (propriétés, holds, bookmarks). C’est pourquoi le nommage est un contrôle opérationnel — comme étiqueter des disjoncteurs dans une salle serveur. Bien sûr, vous pouvez deviner. Mais vous ne pouvez pas vous le permettre.

Voici la réalité opérationnelle :

  • Vous prendrez plus de snapshots que prévu.
  • Vous oublierez pourquoi vous en avez pris au moins 30 %.
  • Vous aurez besoin du bon snapshot sous pression.
  • Au moins un snapshot sera pris pendant une panne partielle (et il paraîtra « récent »).

Le but n’est donc pas d’avoir des « jolis » noms. Le but est de faire en sorte que la restauration correcte soit le chemin de moindre résistance, et que la restauration incorrecte soit pénible.

Une vérité sèche : si votre liste de snapshots ne vous dit pas instantanément quand, pourquoi, qui/quoi et si c’est sûr, vous ne gérez pas un système de snapshots. Vous gérez un dossier de captures d’écran.

Blague #1 : Un snapshot sans schéma de nommage, c’est comme un gestionnaire de mots de passe rempli de « password123 » — techniquement fonctionnel, spirituellement voué à l’échec.

Faits intéressants et contexte historique

Un peu de contexte aide, parce que le nommage ZFS se situe à l’intersection des systèmes de fichiers, de la gestion de volumes et de la culture opérationnelle. Quelques faits concrets :

  1. ZFS a été conçu comme un système de bout en bout : système de fichiers + gestionnaire de volumes + sommes de contrôle + snapshots, développé à l’origine chez Sun Microsystems au début des années 2000.
  2. Les noms de snapshots ne sont pas globaux : ils sont limités à un dataset ou zvol (par ex. pool/app@name). Deux datasets peuvent chacun avoir @daily sans que ZFS s’en préoccupe.
  3. Les snapshots ne sont modifiables qu’à travers des clones : un snapshot est en lecture seule ; vous pouvez zfs clone pour obtenir un dataset modifiable. Ce workflow influence la façon dont vous nommez les points de restauration « candidats ».
  4. L’envoi de snapshots dépend des noms : un zfs send -i incrémental dépend d’un snapshot ancêtre commun. Un nommage désordonné rend l’ascendance ambiguë pour les humains même quand ZFS peut la calculer.
  5. Les snapshots sont bon marché, jusqu’à ce qu’ils ne le soient plus : ils ne dupliquent pas immédiatement les blocs, mais ils retiennent les anciens blocs. Une politique de snapshots peut silencieusement devenir votre plus grand consommateur d’espace.
  6. ZFS supporte les « holds » : vous pouvez appliquer un tag de hold pour empêcher la destruction d’un snapshot. C’est essentiellement votre mécanisme « legal hold » / « ne supprimez pas, vraiment ».
  7. Les bookmarks existent : ce sont des références légères à des points de snapshot pour les workflows de réplication, et ils peuvent réduire la charge de rétention quand il faut des « ancres de réplication » sans conserver de snapshots complets.
  8. Les noms font partie de votre piste d’audit : ZFS n’enregistrera pas votre numéro de ticket ou la raison à moins que vous ne le mettiez dans le nom ou les propriétés. Les équipes d’opérations utilisent généralement les deux.
  9. Il existe plusieurs branches ZFS : OpenZFS est l’implémentation communautaire utilisée sur illumos, FreeBSD, Linux et autres. Les conventions de nommage sont votre couche de portabilité entre différences d’outillage.

Ce qu’un bon nom de snapshot fait dans le monde réel

Un bon nom de snapshot est une entrée d’index. Il doit vous permettre de répondre à ces questions sans faire défiler :

  • Quand a-t-il été pris (avec fuseau horaire ou en UTC non ambigu) ?
  • Qu’est-ce qui l’a généré (tâche planifiée, job CI, opérateur manuel, runbook de mise à niveau) ?
  • Pourquoi (pré-mise à niveau, pré-migration, post-sauvegarde, capture d’incident) ?
  • Niveau de sécurité (peut-il être supprimé ; doit-il être mis en hold ; est-il « golden ») ?
  • À quel workflow il appartient (réplication, gestion VM, quiesce DB, déploiement applicatif) ?

Le système de nommage doit aussi être :

  • Triable en ordre chronologique.
  • Stable entre les équipes et les outils d’automatisation.
  • Sûr à taper en situation de stress (pas d’espaces, pas de pièges shell, pas de ponctuation « créative »).
  • Compatible avec la façon dont vous sélectionnez les snapshots dans des scripts (grep, awk, ou filtres de propriétés ZFS).

Et il doit anticiper les modes de défaillance. Le principal : vous aurez plusieurs snapshots pris autour du même événement, mais tous ne sont pas des points de restauration équivalents. Exemple : les datasets de base de données. Un snapshot « crash-consistent » peut suffire, ou il peut nécessiter une lecture des journaux pendant 20 minutes et faire paniquer tout le monde. Votre nommage doit distinguer « quiesced » de « non quiesced », sinon l’astreinte fera l’apprentissage en direct.

Une idée paraphrasée de Werner Vogels (CTO d’Amazon) : Tout échoue tout le temps ; concevez et opérez comme si l’échec était normal. (idée paraphrasée)

Le système de nommage des snapshots : conventions évolutives

Règle 0 : Utilisez l’UTC dans les noms de snapshot

L’heure locale est pour les calendriers. Les opérations de restauration sont des problèmes de systèmes distribués : équipes dans plusieurs fuseaux, serveurs aux horloges qui dérivent, et logs déjà en UTC. Mettez l’UTC dans le nom du snapshot et vous éliminez tout un ensemble de discussions « attends, c’était avant le déploiement ? ».

Format recommandé : YYYYMMDDThhmmssZ (ISO-ish, sans deux-points). Il se trie lexicographiquement et est évident pour les humains.

Règle 1 : Séparez « cadence » et « intention »

Beaucoup d’équipes commencent avec @daily, @hourly, @weekly. C’est mignon jusqu’au moment où vous devez restaurer « le snapshot juste avant la migration de schéma ». Là vous comptez les dailies. Ne faites pas ça.

Au lieu de ça, encodez :

  • cadence (hourly/daily/adhoc)
  • intention (predeploy, preupgrade, postbackup, incident)
  • créateur (auto/manual/ci)

Règle 2 : Utilisez un ordre de tokens prévisible

Choisissez un ordre canonique et ne déviez jamais. Les humains balayent de gauche à droite. Les scripts analysent de gauche à droite. Votre vous futur sera fatigué et peu impressionné par la créativité.

Un schéma pratique et adapté à la production :

<prefix>.<cadence>.<creator>.<intent>.<ts>[.<ticket>][.<flags>]

Exemples de noms :

  • snap.hourly.auto.base.20260204T010000Z
  • snap.daily.auto.base.20260204T000000Z
  • snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
  • snap.adhoc.ci.predeploy.20260204T015912Z.PR4812
  • snap.adhoc.manual.incident.20260204T021100Z.INC7781.hold
  • snap.adhoc.auto.quiesced-db.20260204T020000Z

Remarques :

  • Prefix (snap) vous permet de filtrer vos snapshots des outils fournisseurs.
  • Les points sont banals et shell-friendly. Évitez les espaces. Évitez les deux-points. Évitez « @prod:good ».
  • IDs de ticket sont optionnels mais précieux. N’y mettez pas d’informations sensibles ; ils apparaissent dans les logs, la supervision et les flux de réplication.
  • Flags sont de petits mots comme hold, gold, quiesced. Évitez d’en faire de la prose.

Règle 3 : Mettez la « spécialité » à la fin, mais gardez le timestamp avant

Les gens veulent ajouter « -final » ou « -good ». Si vous le placez avant le timestamp, le tri casse. Si vous le placez après, l’ordre reste chronologique et vous conservez votre indice.

Bon : snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345.gold
Mauvais : snap.adhoc.manual.gold.preupgrade.CHG12345.20260203T221530Z

Règle 4 : Encodez explicitement la quiescence pour les applis concernées

Il existe des datasets où la crash-consistency suffit (contenu statique, la plupart des disques VM si le journaling invité est sain). Puis il y a des datasets où c’est la roulette russe (bases de données actives, certaines queues, applis legacy). Pour ceux-là, votre nommage doit inclure un token comme :

  • quiesced-db (appli a confirmé flush / fsfreeze / coordination)
  • crash (aucune coordination ; la restauration peut nécessiter une récupération)

Ceci n’est pas un jugement moral. C’est une étiquette de risque.

Règle 5 : Utilisez les propriétés ZFS pour des métadonnées lisibles par machine (et les noms pour les humains)

Les noms de snapshot sont visibles. Les propriétés sont interrogeables. Utilisez les deux. Un schéma pratique :

  • Le nom porte cadence/intent/timestamp et éventuellement un ticket.
  • Les propriétés portent des métadonnées structurées comme com.company:reason, com.company:owner, com.company:expiry.

Pourquoi les deux ? Parce que les humains choisissent les snapshots par le nom pendant les incidents, et l’automatisation a besoin de sélecteurs fiables qui ne dépendent pas du parsing d’une chaîne que vous « améliorerez » un jour.

Règle 6 : Prévoyez la réplication et la rétention dès le premier jour

Si vous répliquez des snapshots, vos noms font partie du protocole entre sites. Un système de nommage instable devient une panne de réplication déguisée en « nettoyage ».

Recommandation pratique :

  • Gardez les snapshots de cadence automatisée sur un motif strict : facile à matcher, facile à expirer.
  • Gardez les snapshots « événement » (preupgrade/incident) sur un motif différent et protégez-les par des holds.
  • Utilisez des bookmarks comme ancres de réplication quand approprié, mais nommez-les avec la même discipline de timestamp.

Tâches pratiques : commandes, sorties et décisions (12+)

Task 1: List snapshots in a dataset, sorted by creation time

cr0x@server:~$ zfs list -t snapshot -o name,creation -s creation tank/app
NAME                                   CREATION
tank/app@snap.daily.auto.base.20260203T000000Z   Mon Feb  3 00:00 2026
tank/app@snap.hourly.auto.base.20260203T230000Z Mon Feb  3 23:00 2026
tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345 Tue Feb  3 22:15 2026

Ce que signifie la sortie : Vous avez les timestamps de création depuis ZFS lui-même, pas déduits du nom. Cela compte quand les horloges dérivent ou quand quelqu’un renomme manuellement des patterns.

Décision : Si le temps de création ZFS n’aligne pas avec le token timestamp dans le nom, vous avez un problème de processus (ou de synchronisation temporelle). Réparez NTP et votre automatisation avant de faire confiance aux timestamps pour le travail d’incident.

Task 2: Show space held by snapshots (why “cheap” becomes “expensive”)

cr0x@server:~$ zfs list -o name,used,refer,usedbysnapshots tank/app
NAME      USED  REFER  USEDBYSNAPSHOTS
tank/app  850G  620G   210G

Ce que signifie la sortie : USEDBYSNAPSHOTS est l’espace retenu parce que les snapshots référencent d’anciens blocs.

Décision : Si USEDBYSNAPSHOTS est élevé et que votre pool manque d’espace libre, vous devriez expirer des snapshots (de préférence via une politique et non par panique). Si c’est élevé sur un dataset à fort churn, revisitez cadence et rétention immédiatement.

Task 3: Find the largest snapshots (useful for targeted cleanup)

cr0x@server:~$ zfs list -t snapshot -o name,used,refer -s used tank/app
NAME                                                   USED  REFER
tank/app@snap.hourly.auto.base.20260203T230000Z        18G   620G
tank/app@snap.hourly.auto.base.20260203T220000Z        14G   615G
tank/app@snap.adhoc.manual.incident.20260203T210100Z.INC7781.hold 9G  610G

Ce que signifie la sortie : USED du snapshot est la quantité d’espace unique que le snapshot maintient en vie par rapport au dataset actif.

Décision : De gros snapshots horaires impliquent un fort churn. Envisagez de réduire la fréquence, de fractionner les datasets pour isoler le churn, ou de faire en sorte que l’appli écrive dans un dataset dédié avec une politique de rétention différente.

Task 4: Verify a snapshot exists before you do something irreversible

cr0x@server:~$ zfs list -t snapshot tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
NAME
tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345

Ce que signifie la sortie : Si le nom s’affiche, il existe. Si une erreur apparaît, votre plan de restauration est déjà incorrect.

Décision : Si vous ne pouvez pas identifier positivement le snapshot, arrêtez-vous. Ne « approximiez » pas avec le daily le plus proche. C’est comme ça qu’on restaure vers le mauvais schéma.

Task 5: Create an “event snapshot” with a disciplined name

cr0x@server:~$ ts=$(date -u +%Y%m%dT%H%M%SZ); zfs snapshot tank/app@snap.adhoc.manual.preupgrade.${ts}.CHG12345

Ce que signifie la sortie : L’absence de sortie signifie succès. ZFS fonctionne comme ça.

Décision : Suivez immédiatement par un hold pour les changements à haut risque (tâche suivante). Sans ça, un job de nettoyage peut supprimer le seul snapshot qui compte.

Task 6: Protect a snapshot with a hold tag (make deletion fail on purpose)

cr0x@server:~$ zfs hold keep tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
cr0x@server:~$ zfs holds tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
NAME                                                    TAG   TIMESTAMP
tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345  keep  Tue Feb  3 22:16 2026

Ce que signifie la sortie : Le snapshot a un tag de hold keep. Il ne peut pas être détruit tant que les holds ne sont pas libérés.

Décision : Pour les snapshots d’incident et de pré-mise à niveau, les holds sont une assurance peu coûteuse. Utilisez-les. Puis créez un processus pour les libérer quand le changement est validé comme sûr.

Task 7: Attach structured metadata via user properties (queryable later)

cr0x@server:~$ zfs set com.acme:reason="preupgrade app 7.4" tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
cr0x@server:~$ zfs set com.acme:ticket="CHG12345" tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
cr0x@server:~$ zfs get -H -o property,value com.acme:reason,com.acme:ticket tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
com.acme:reason	preupgrade app 7.4
com.acme:ticket	CHG12345

Ce que signifie la sortie : Le snapshot porte maintenant des métadonnées lisibles par machine que vous pouvez filtrer sans parser le nom.

Décision : Si vous exécutez de l’automatisation, orientez vos scripts vers les propriétés pour la sélection et gardez les noms lisibles par les humains. Cela réduit la logique fragile de parsing.

Task 8: Roll back a dataset (and understand what you’re overwriting)

cr0x@server:~$ zfs rollback -n tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
would rollback tank/app to tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
would destroy the following snapshots:
  tank/app@snap.hourly.auto.base.20260203T230000Z
  tank/app@snap.daily.auto.base.20260204T000000Z

Ce que signifie la sortie : -n est un dry run. Le rollback supprimera les snapshots plus récents à moins d’utiliser -r avec précaution ou de les préserver par clonage.

Décision : Si le rollback détruirait des snapshots nécessaires à la réplication ou à l’audit, arrêtez-vous et envisagez plutôt le clonage (Tâche 9). Le dry-run est non négociable en production.

Task 9: Clone a snapshot instead of rolling back (safer for forensics)

cr0x@server:~$ zfs clone tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345 tank/app-restore
cr0x@server:~$ zfs list -o name,used,refer,mountpoint tank/app-restore
NAME            USED  REFER  MOUNTPOINT
tank/app-restore  1G   620G   /tank/app-restore

Ce que signifie la sortie : Le clone est modifiable et initialement petit (USED) car il partage des blocs avec le snapshot.

Décision : Pour la réponse aux incidents, le clonage est souvent la première action correcte. Vous pouvez valider les données, extraire des fichiers ou exécuter des contrôles applicatifs sans détruire l’état courant.

Task 10: Send/receive with clear ancestry (replication that doesn’t guess)

cr0x@server:~$ zfs send -nvP -i tank/app@snap.daily.auto.base.20260203T000000Z tank/app@snap.daily.auto.base.20260204T000000Z
send from @snap.daily.auto.base.20260203T000000Z to tank/app@snap.daily.auto.base.20260204T000000Z estimated size is 12.3G
total estimated size is 12.3G
TIME        SENT   SNAPSHOT

Ce que signifie la sortie : Envoi en mode dry-run (-n) avec estimation de progression (-P). Cela confirme que le snapshot de base incrémental existe et la taille du delta.

Décision : Si la taille estimée est étonnamment grande, c’est un signal de churn (ou de changement de compression/chiffrement). Vérifiez ce qui a changé entre les snapshots avant de saturer un lien WAN.

Task 11: Use bookmarks to keep replication anchors lightweight

cr0x@server:~$ zfs bookmark tank/app@snap.daily.auto.base.20260204T000000Z tank/app#bmark.daily.20260204T000000Z
cr0x@server:~$ zfs list -t bookmark -o name,creation tank/app
NAME                                   CREATION
tank/app#bmark.daily.20260204T000000Z  Tue Feb  4 00:00 2026

Ce que signifie la sortie : Un bookmark référence un point dans l’historique du dataset sans conserver les mêmes sémantiques de rétention qu’un snapshot complet.

Décision : Si la pression de rétention est élevée, les bookmarks peuvent aider les workflows de réplication tout en permettant de supprimer d’anciens snapshots. Mais ne considérez pas les bookmarks comme des points de restauration pour les humains ; ce ne sont pas des montages.

Task 12: Verify holds before cleanup (why destroy sometimes “fails”)

cr0x@server:~$ zfs destroy tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
cannot destroy snapshot tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345: snapshot has holds
cr0x@server:~$ zfs holds tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
NAME                                                    TAG   TIMESTAMP
tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345  keep  Tue Feb  3 22:16 2026

Ce que signifie la sortie : Les holds font leur travail : empêcher la suppression.

Décision : Si ce snapshot est toujours requis, laissez-le. Si sa suppression est sûre, libérez le hold explicitement avec un enregistrement de changement (Tâche 13).

Task 13: Release a hold and then destroy (make it deliberate)

cr0x@server:~$ zfs release keep tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345
cr0x@server:~$ zfs destroy tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345

Ce que signifie la sortie : Pas de sortie : succès.

Décision : La libération des holds doit être plus rare que leur mise. Si vous libérez les holds à la légère, vous finirez par supprimer le snapshot dont vous aviez besoin. Traitez les holds comme des contrôles « casse-glace ».

Task 14: Find snapshots by intent using name patterns (human triage)

cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | grep preupgrade | tail -5
tank/app@snap.adhoc.manual.preupgrade.20260110T210002Z.CHG12111
tank/app@snap.adhoc.manual.preupgrade.20260124T210011Z.CHG12202
tank/app@snap.adhoc.manual.preupgrade.20260203T221530Z.CHG12345

Ce que signifie la sortie : Votre système de nommage rend l’intention searchable sous pression.

Décision : Si vous avez besoin d’expressions régulières compliquées pour trouver « le dernier snapshot preupgrade », vos noms sont trop astucieux. Simplifiez les tokens.

Task 15: Confirm dataset mountpoints before restore actions

cr0x@server:~$ zfs get -o name,property,value mountpoint,canmount tank/app tank/app-restore
NAME            PROPERTY    VALUE
tank/app        mountpoint  /srv/app
tank/app        canmount    on
tank/app-restore mountpoint /tank/app-restore
tank/app-restore canmount   on

Ce que signifie la sortie : Vous voyez où les choses seront montées et si elles seront auto-montées.

Décision : Avant un rollback, vérifiez que vous n’allez pas monter un clone par-dessus des chemins de production. Pour des restaurations de test, définissez un mountpoint sûr ou canmount=noauto.

Task 16: Check pool health before blaming snapshots for slowness

cr0x@server:~$ zpool status -x
all pools are healthy

Ce que signifie la sortie : ZFS ne voit pas d’erreurs ni de vdevs dégradés. C’est la base.

Décision : Si le pool n’est pas sain, les opérations sur snapshots peuvent être lentes parce que le système est déjà en difficulté. Réparez le matériel ou terminez le resilver d’abord ; ne faites pas du tuning pour compenser un pool dégradé.

Blague #2 : La seule chose plus effrayante que « nous n’avons pas de snapshots » est « nous avons 40 000 snapshots et personne ne sait lesquels sont réels ».

Trois mini-récits d’entreprise depuis le terrain

Mini-récit 1 : L’incident causé par une mauvaise hypothèse (« @daily veut dire sûr »)

Dans une entreprise SaaS de taille moyenne, l’équipe stockage avait une politique simple : snapshots horaires pour les datasets critiques, quotidiens pour le reste. Les noms étaient courts : @hourly, @daily. L’automatisation ne conservait qu’une semaine d’horaires et un mois de quotidiens. L’équipe se sentait responsable. Ils l’étaient. Pas pour la bonne chose.

Un déploiement backend a mal tourné et corrompu un sous-ensemble de métadonnées utilisateur. Le responsable d’incident a demandé une restauration « hier à minuit ». L’astreinte a trouvé le snapshot @daily, a rollbacké le dataset et a regardé l’application redémarrer. Elle est remontée. Puis elle a commencé à émettre un nouveau type d’erreur : des enregistrements manquants référencés par des fichiers plus récents. Le rollback avait restauré le dataset, mais pas le système.

La mauvaise hypothèse était que « daily » impliquait « connu comme bon ». En réalité, le snapshot était crash-consistent et avait capturé un état en pleine ingestion. L’application attendait un checkpoint coordonné entre deux datasets : un contenant les métadonnées, un contenant les blobs. Le dataset des blobs avait son propre @daily, pris quelques minutes plus tard. Le rollback a restauré un côté de la relation, pas les deux. Félicitations, vous avez inventé l’incohérence de données avec une grande confiance.

La correction n’a pas été un nouvel outil héroïque. Ce fut un changement de nommage et de politique : les snapshots pour applications multi-dataset furent pris en lot orchestré avec un token timestamp partagé, et le nom incluait quiesced seulement quand l’appli le confirmait. Le runbook fut mis à jour pour restaurer un ensemble cohérent en faisant correspondre le timestamp entre datasets. Soudain, « quel snapshot ? » a cessé d’être un débat et est devenu un filtre.

Mini-récit 2 : L’optimisation qui s’est retournée contre l’équipe (fréquence de snapshots amplifiant la latence)

Une équipe de services financiers utilisait ZFS pour des disques VM. Ils avaient une exigence de conformité pour conserver des points de restauration fréquents. Quelqu’un s’est montré ambitieux : « Si les snapshots sont peu coûteux, prenons-les toutes les cinq minutes. » L’automatisation fut mise à jour. Ça a marché. Pendant un temps.

Deux mois plus tard, les plaintes de performance devinrent régulières. Pas catastrophiques, mais constantes : pics de latence périodiques, surtout pendant les heures de pointe en écriture. Tout le monde accusa « l’hyperviseur » ou « le réseau ». Les graphiques de stockage montraient quelque chose de plus prosaïque : des rafales de travail métadonnées autour des temps de snapshot, une amplification d’écriture due aux blocs retenus, et des pools proches du plein car la rétention s’était silencieusement étendue.

Le retour de bâton fut subtil : l’équipe avait optimisé le RPO en ignorant la courbe de coût du churn. Des snapshots haute-fréquence sur des datasets à forte écriture ne créent pas seulement plus d’entrées ; ils retiennent plus d’historiques de blocs divergents. Combiné à un pool proche d’un seuil élevé d’utilisation, l’allocation devient plus difficile, la fragmentation augmente, et le système a moins d’options saines. La politique des cinq minutes n’ajoutait pas seulement du travail ; elle amplifiait le pire comportement d’un pool stressé.

Le plan de rétablissement fut pragmatique : réduire la fréquence pour les datasets à fort churn, séparer les « disques OS » et les « disques données » en datasets distincts avec des rétentions différentes, et imposer un plancher d’espace libre. Le nommage des snapshots a aidé : l’équipe a pu identifier et expirer précisément la cadence cinq-minutes (snap.5min.auto.base...) sans toucher aux snapshots d’événement ou aux ancres de réplication.

Ils respectaient toujours la conformité. Ils ont juste arrêté de prétendre que le sous-système de stockage exauçait tous les souhaits.

Mini-récit 3 : La pratique ennuyeuse mais correcte qui a sauvé la situation (dry runs + holds)

Une plateforme de santé avait une culture du « faisons d’abord la chose ennuyeuse ». Leurs runbooks ZFS exigeaient deux étapes avant tout rollback : zfs rollback -n en dry run, et confirmer les holds sur tout snapshot associé à un ticket de changement. Les ingénieurs râlaient. Ça ressemblait à de la paperasserie avec des frappes en plus.

Pendant une fenêtre de mise à niveau, un ingénieur dut restaurer un dataset après qu’un outil de migration ait écrit des valeurs inattendues. Ils ont choisi ce qui semblait être le bon snapshot : même jour, timestamp proche. Le dry-run a averti que le rollback détruirait plusieurs snapshots plus récents utilisés comme incrémentaux de réplication. Ce n’est pas juste une perte de données ; c’est un backlog de réplication qui devient un week-end de travail.

L’ingénieur a pris une pause. Il a cloné à la place, validé l’état applicatif du dataset cloné, puis choisi un autre snapshot qui préservait la chaîne de réplication. L’étape ennuyeuse a évité un second incident : réplication cassée suivie d’un reseed paniqué.

Plus tard, l’automatisation de nettoyage a tenté de supprimer les snapshots « adhoc » plus anciens qu’un seuil. Elle n’a pas pu supprimer ceux de pré-mise à niveau parce que des holds avaient été posés avec un tag standard. Personne n’a dû s’en souvenir. Le système l’a fait. La mise à niveau a été menée correctement, les holds libérés après vérification, et le ticket d’incident fermé sans drame.

La maturité opérationnelle ressemble souvent à ça : moins de moments héroïques, plus de résultats prévisibles.

Méthode de diagnostic rapide : trouver rapidement le goulot d’étranglement

Quand les opérations sur snapshots sont lentes — ou que la réplication traîne — les gens ont tendance à pointer du doigt « les snapshots ZFS » comme si c’était un démon. Ne faites pas du folklore. Faites du triage. Voici une séquence rapide et à fort signal.

Première étape : le pool est-il malade ?

  • Vérifier : zpool status -x
  • Pourquoi : vdevs dégradés, resilvers, erreurs de checksum ou périphériques hors ligne domineront tout le reste.
  • Décision : Si ce n’est pas sain, réparez ça d’abord. Le tuning est inutile tant que votre pool boîte.

Deuxième étape : le pool est-il trop plein ?

  • Vérifier : zpool list et usedbysnapshots des datasets
  • Pourquoi : une forte utilisation réduit la flexibilité d’allocation ; les snapshots retiennent des blocs ; les deux peuvent provoquer des pics de latence.
  • Décision : Si vous approchez du plancher d’espace libre opérationnel, expirez des snapshots (en sécurité), ajoutez de la capacité, ou réduisez le churn. Choisissez au moins une action aujourd’hui.

Troisième étape : le churn vient-il d’un dataset en particulier ?

  • Vérifier : zfs list -o name,used,usedbysnapshots sur les datasets ; trouvez les coupables.
  • Pourquoi : un dataset de logs peut dominer les deltas de snapshot et le volume de réplication.
  • Décision : Séparez les datasets par profil d’écriture. Arrêtez de snapshotter des logs éphémères à haute fréquence, sauf si vous aimez payer pour des déchets retenus.

Quatrième étape : la réplication est-elle lente parce que les deltas sont énormes ?

  • Vérifier : zfs send -nvP -i entre snapshots.
  • Pourquoi : vous ne pouvez pas optimiser un delta 10x à moins de changer ce qui écrit.
  • Décision : Si les deltas sont incompréhensiblement grands, enquêtez sur le comportement applicatif, les mismatch de recordsize, les changements de compression et la fréquence des snapshots.

Cinquième étape : souffrez-vous d’un « entassement de snapshots » ?

  • Vérifier : nombre de snapshots : zfs list -t snapshot | wc -l (approximatif, mais rapide)
  • Pourquoi : un très grand nombre de snapshots augmente la surcharge de gestion et la probabilité d’erreurs humaines.
  • Décision : Si les comptes sont hors de contrôle, corrigez l’automatisation de rétention et les patterns de nommage pour pouvoir expirer en sécurité sans roulette regex.

Erreurs courantes : symptômes → cause racine → correctif

Mistake 1: “We can’t tell which snapshot is safe to restore”

Symptômes : longs fils d’incident argumentant sur les timestamps ; restaurations partielles multiples ; peur du rollback.

Cause racine : les noms n’encodent que la cadence (@daily) mais pas l’intention, la quiescence ou le regroupement par workflow.

Correctif : Adoptez un schéma de nommage tokenisé avec timestamps UTC et marqueurs d’intention (preupgrade, predeploy, incident, quiesced-db). Pour les applis multi-dataset, prenez des snapshots coordonnés partageant le même token timestamp sur tous les datasets.

Mistake 2: “Cleanup deleted the one snapshot we needed”

Symptômes : les snapshots d’événement disparaissent ; le postmortem contient « on pensait qu’il serait là ».

Cause racine : pas de holds ; scripts de nettoyage matchent « adhoc » trop largement ; pas de séparation entre classes de rétention.

Correctif : Appliquez des holds par défaut aux snapshots de changement/incident. Séparez les rétentions : snap.hourly.auto.base expire agressivement ; snap.adhoc.manual.preupgrade est en hold jusqu’à libération explicite.

Mistake 3: “Rollback would destroy newer snapshots and replication breaks”

Symptômes : le dry-run montre destruction de snapshots ; pipelines de réplication cassent après rollback ; nécessité de reseed.

Cause racine : rollback au lieu de clonage ; méconnaissance que rollback recule l’historique du dataset et supprime les snapshots plus récents.

Correctif : Utilisez zfs rollback -n systématiquement. Préférez le clonage pour validation et forensique. Si vous devez rollbacker, planifiez explicitement le ré-ancrage de la réplication et préservez les snapshots requis.

Mistake 4: “Snapshot space usage keeps growing even when we delete files”

Symptômes : USED du dataset ne baisse pas ; le pool reste plein ; supprimer des données ne libère pas d’espace.

Cause racine : les snapshots retiennent les anciens blocs, donc les suppressions dans le dataset actif ne libèrent pas l’espace tant que les snapshots existent.

Correctif : Identifiez les gros snapshots (zfs list -t snapshot -s used). Réduisez la rétention sur les datasets à fort churn. Envisagez de modifier la disposition des datasets pour isoler les sources de churn.

Mistake 5: “Names are inconsistent across tools; scripts miss snapshots”

Symptômes : certains snapshots utilisent des underscores, d’autres des traits d’union ; les timestamps diffèrent ; les scripts de rétention en sautent ; les snapshots d’incident ne sont pas trouvés par grep.

Cause racine : plusieurs créateurs de snapshots (cron, CI, admins) sans convention imposée.

Correctif : Définissez un ordre de tokens et des séparateurs canoniques ; appliquez via scripts wrapper ou politique. Ajoutez des propriétés pour des métadonnées structurées afin que l’automatisation puisse sélectionner par propriété plutôt que par parsing de chaîne.

Mistake 6: “We snapshot too often and performance gets spiky”

Symptômes : pics de latence aux moments de snapshot ; deltas de réplication énormes ; utilisation du pool qui grimpe.

Cause racine : snapshots haute-fréquence sur datasets à fort churn ; rétention mal ajustée ; pool trop plein.

Correctif : Réduisez la fréquence pour les datasets à fort churn ; séparez les datasets par profil d’écriture ; imposez un plancher d’espace libre ; vérifiez les deltas avec zfs send -nvP avant de propager les changements globalement.

Checklists / plan pas-à-pas

Checklist A: Adopt a naming system without breaking everything

  1. Inventoriez les créateurs de snapshots : cron jobs, pipelines CI, outils fournisseurs, humains. Si vous ne savez pas qui crée des snapshots, vous ne contrôlez pas le nommage.
  2. Choisissez un pattern de nom canonique : ex. snap.<cadence>.<creator>.<intent>.<ts>.
  3. Standardisez le format timestamp UTC : YYYYMMDDThhmmssZ. Pas d’exception.
  4. Définissez des classes de rétention :
    • hourly.auto.base (court)
    • daily.auto.base (moyen)
    • adhoc.*.preupgrade et adhoc.*.incident (tenus)
  5. Décidez des tokens de quiescence : au minimum, quiesced-db vs crash.
  6. Ajoutez des propriétés pour les métadonnées : reason, ticket, expiry, owner.
  7. Mettez à jour les runbooks : restaurer par groupe de timestamps pour les applis multi-dataset ; politique clone-first pour les restaurations à haut risque.
  8. Déployez progressivement : commencez par les nouveaux snapshots. Ne renommez pas les anciens en place sauf si vous êtes sûr que l’outillage ne cassera pas.

Checklist B: “I need to restore now” (operator steps)

  1. Confirmez la santé du pool : zpool status -x. Si non sain, attendez-vous à des retards et des risques.
  2. Identifiez les dataset(s) exacts impliqués. Ne restaurez pas un parent si seul un enfant est impacté.
  3. Listez les snapshots triés par création et trouvez le token d’intention (predeploy/preupgrade/incident).
  4. Vérifiez la quiescence pour les datasets type DB. Choisissez quiesced-db quand disponible.
  5. Dry-run rollback : zfs rollback -n. Lisez ce qu’il détruirait.
  6. Privilégiez le clone-first pour validation. Montez-le en sécurité et vérifiez les contrôles applicatifs.
  7. Rollback uniquement quand vous comprenez le blast radius et que vous l’avez communiqué (réplication, snapshots plus récents, services dépendants).
  8. Après la restauration : prenez un nouveau snapshot avec l’intention postrestore et mettez-le en hold brièvement. Il vous donne un état stable connu si des changements ultérieurs tournent mal.

Checklist C: Snapshot hygiene (weekly housekeeping)

  1. Revoyez l’usage d’espace des snapshots : trouvez les top datasets par usedbysnapshots.
  2. Repérez les cadences incontrôlées : trop de snapshots par dataset signifie souvent une dérive d’automatisation.
  3. Expirez par classe : supprimez d’abord les hourly.auto.base anciens ; ne touchez pas aux snapshots d’événement en hold.
  4. Auditez les holds : si les holds ne sont jamais libérés, votre « temporaire » devient permanent. Ajoutez une propriété d’expiration et une boucle de revue.
  5. Testez les restaurations : pas seulement « peut-on lister les snapshots ? » — clonez et validez réellement les données. Votre système de nommage n’est prouvé que lorsqu’il aide une restauration.

FAQ

1) Les noms de snapshot doivent-ils inclure le nom du dataset ?

Non. Le dataset fait déjà partie du nom complet du snapshot (tank/app@...). Le dupliquer rallonge le nom et le rend moins lisible. Encodez plutôt l’intention et l’heure.

2) Puis-je renommer un snapshot ZFS ?

Oui, ZFS supporte le renommage de snapshot dans de nombreuses implémentations, mais cela peut avoir des conséquences opérationnelles (attentes de réplication, scripts, monitoring). Traitez les renommages comme une tâche de migration avec tests, pas comme un nettoyage casual.

3) Pourquoi ne pas utiliser simplement @hourly et garder ça simple ?

Parce que « hourly » ne répond qu’à une de vos vraies questions. Sous pression d’incident, vous avez besoin de « hourly de quelle intention, pris par quel système, et est-il quiesced ? » La simplicité qui supprime du sens n’est pas de la simplicité ; c’est une douleur différée.

4) Comment regrouper des snapshots sur plusieurs datasets pour une restauration cohérente ?

Utilisez un token timestamp partagé sur tous les datasets lors de la capture coordonnée. Ensuite restaurez en faisant correspondre ce timestamp. Exemple : tous les datasets impliqués obtiennent ...20260204T020000Z.... C’est là que la discipline UTC rapporte.

5) Les noms de snapshots sont-ils utilisés par zfs send pour la correction ?

La justesse ZFS dépend de l’ascendance des snapshots, pas de la signification lisible du nom. Mais les humains opèrent le système. Un bon nommage vous évite d’envoyer les mauvais incrementals ou de choisir la mauvaise base sous stress.

6) Devrait-on mettre des numéros de ticket dans les noms de snapshot ?

En général oui, pour les snapshots de changement et d’incident. C’est une traçabilité légère. Gardez-les courts et non sensibles. Si les IDs de ticket sont mal propres, stockez-les dans les propriétés et gardez les noms propres.

7) Combien de snapshots est « trop » ?

Il n’y a pas de nombre magique. La limite pratique est celle où la surcharge de gestion, l’espace de rétention et l’erreur humaine deviennent problématiques. Si lister les snapshots est lent, si le nettoyage est risqué, ou si les opérateurs choisissent systématiquement le mauvais snapshot, vous avez déjà dépassé la ligne.

8) Quelle est la différence entre un hold et « ne pas le supprimer » ?

Un hold fait échouer la suppression au niveau du filesystem, même si un script de nettoyage tourne avec de bonnes intentions. « Ne pas le supprimer » est un espoir. Les holds sont un contrôle.

9) Devrait-on garder des snapshots « golden » indéfiniment ?

Rarement. Les snapshots de longue durée peuvent accumuler des blocs retenus et augmenter la pression d’espace, surtout sur des datasets à fort churn. Si vous avez besoin d’une rétention long terme, répliquez vers une cible de sauvegarde et gardez moins de snapshots locaux, ou déplacez les archives vers un dataset conçu pour ça.

10) Les noms de snapshots doivent-ils être identiques entre environnements (dev/stage/prod) ?

Le pattern devrait être identique. Les chemins des datasets vont différer. Des patterns de nommage cohérents aident à réutiliser les runbooks et l’automatisation et réduisent les surprises « ça marche en staging ».

Conclusion : prochaines étapes qui réduisent vraiment le stress

Si vous voulez des rollbacks sereins, arrêtez de traiter les snapshots comme une pile de points dans le temps et commencez à les gérer comme un système : nommage, métadonnées, rétention et workflows opérateurs. La meilleure convention de nommage est celle que votre astreinte peut utiliser à moitié endormie sans improviser.

Prochaines étapes pratiques :

  1. Choisissez l’ordre des tokens (snap.cadence.creator.intent.ts) et imposez les timestamps UTC.
  2. Séparez les classes de rétention : cadence de base vs snapshots d’événement. Utilisez des holds pour les événements.
  3. Ajoutez des propriétés pour reason/ticket/expiry afin que l’automatisation soit robuste.
  4. Mettez à jour le runbook de restauration : lister → dry-run → clone-first → valider → rollback seulement quand tout est compris.
  5. Faites un exercice de restauration ce mois-ci en utilisant vos nouveaux noms. Si l’exercice est confus, le système de nommage vous ment.

Les snapshots sont l’une des superpuissances de ZFS. Le nommage est la manière dont vous les visez.

← Précédent
WooCommerce : la correction du paiement qui améliore les conversions sans redesign
Suivant →
Récupération WordPress : Écran blanc de la mort — La réparation en 5 étapes qui fonctionne

Laisser un commentaire