Restauration ZFS : la manière sûre d’annuler des erreurs sans dégâts collatéraux

Cet article vous a aidé ?

Certaines pannes ne commencent pas par une défaillance de disque ou un kernel panic. Elles commencent avec un système parfaitement sain et une commande bien intentionnée : un réglage de configuration, une mise à jour de paquet, un « nettoyage » qui supprime le mauvais répertoire. Soudainement votre application est cassée, vos données sont bizarres, et vos parties prenantes émettent ce genre de sons que font les gens quand ils réalisent que leurs plans de week-end sont annulés.

Le zfs rollback est l’un des rares outils en production qui peuvent faire reculer le temps avec une précision chirurgicale. C’est aussi l’un des moyens les plus simples de vaporiser les mauvais snapshots, de casser des chaînes de réplication, ou de restaurer un dataset tout en laissant des systèmes dépendants dans un état subtilement corrompu. Voici la manière sûre : minimiser le rayon d’impact, préserver les preuves, et éviter de traumatiser votre futur vous.

Ce que fait réellement le rollback (et ce qu’il détruit)

zfs rollback replace le dataset « live » exactement au contenu d’un snapshot. Il ne « fusionne » pas et n’« annule » pas en douceur. Il recule le pointeur de tête du dataset, ce qui entraîne implicitement l’abandon des modifications effectuées après ce snapshot.

Voici la partie qui surprend : par défaut, ZFS ne vous laissera pas revenir en arrière au-delà d’un snapshot qui a des snapshots plus récents à moins que vous ne le lui demandiez. Si vous utilisez -r (récursif) ou -R (récursif plus destructeur), vous demandez explicitement à ZFS de détruire les snapshots et les clones dépendants qui sont « plus récents » que le snapshot cible. Cela peut être la bonne action. Cela peut aussi être le moment exact où vous coupez votre historique de réplication et où l’équipe de sauvegarde cesse de répondre à vos appels.

Opérationnellement, le rollback doit être traité comme une démolition contrôlée : vous pouvez le faire en sécurité, mais seulement si vous avez déjà vérifié ce qui est attaché à la chose que vous allez déplacer.

L’arbre familial des snapshots compte

Les snapshots forment une chronologie. Le rollback fait revenir en arrière. Si vous avez des snapshots après ce point, ces snapshots référencent des blocs qui représentent de l’histoire postérieure au snapshot cible. Quand vous faites un rollback avec des indicateurs de destruction, ZFS efface le futur que vous ne voulez plus. Ce n’est pas « dangereux », c’est juste définitif.

Rollback n’est pas une restauration de fichier

Si vous avez seulement besoin de quelques fichiers ou d’un répertoire, monter ou parcourir un snapshot est plus sûr que de rollbacker l’ensemble du dataset. Le rollback sert quand « le dataset est maintenant incorrect, et nous voulons qu’il redevienne exactement comme avant ». La récupération au niveau fichier sert quand « je regrette une commande, pas ma personnalité entière ».

Une citation à coller au-dessus de votre terminal

Idée paraphrasée (Gene Kim, auteur sur la fiabilité/DevOps) : « L’amélioration vient de la mise en visibilité du travail et de la réduction du coût de récupération. » Le rollback réduit le coût de récupération — si vous le gardez visible et contrôlé.

Faits intéressants et contexte historique

  • ZFS a été livré avec les snapshots dès le départ (début des années 2000 dans le développement Solaris), à une époque où beaucoup de systèmes de fichiers considéraient la « sauvegarde » comme le problème de quelqu’un d’autre.
  • Les snapshots sont essentiellement gratuits à la création (seulement des métadonnées au moment de la création). Ils deviennent « coûteux » ultérieurement uniquement lorsque des blocs divergents sont conservés.
  • Le rollback est instantané pour les métadonnées, mais l’impact opérationnel ne l’est pas : les services voient un changement d’état soudain, les caches deviennent faux, et les applications peuvent nécessiter des étapes de récupération.
  • Les clones existent parce que le rollback est trop brutal : un clone est une branche modifiable à partir d’un snapshot, conçue pour des tests sûrs et des récupérations sélectives.
  • La réplication ZFS (send/receive) est basée sur les snapshots, ce qui signifie que les décisions de rollback peuvent casser les chaînes incrémentales si vous supprimez des snapshots attendus par le récepteur.
  • « Used by snapshots » embrouille presque tout le monde au début : ce n’est pas la « taille du snapshot », c’est « combien d’espace serait libéré si ce snapshot disparaissait ».
  • Les holds ZFS ont été introduits pour empêcher la suppression accidentelle de snapshots critiques, surtout dans des environnements automatisés où des scripts de « nettoyage » circulent.
  • Les bookmarks existent pour l’hygiène de la réplication : ils enregistrent un point d’envoi sans conserver tous les blocs épinglés comme un snapshot complet.
  • Le rollback du pool racine est devenu une pratique opérationnelle courante avec les boot environments (notamment sur illumos et certaines configurations Linux), rendant les « upgrade puis revert » moins terrifiants.

Un modèle mental pour éviter la panique

Quand vous êtes en plein incident, vous ne voulez pas de poésie. Vous voulez un modèle que vous pouvez exécuter.

Pensez en trois couches :

  1. Couche données (ZFS) : datasets, snapshots, clones, holds, bookmarks.
  2. Couche cohérence (apps) : bases de données, files de messages, fichiers qui doivent correspondre entre eux, WAL/redo logs, sémantique de récupération après crash.
  3. Couche dépendances (ops) : réplication, sauvegardes, attentes de monitoring, consommateurs de chemins montés.

Le rollback concerne uniquement la couche 1. Votre incident est généralement causé par la couche 2 ou 3. C’est pourquoi « le rollback a corrigé les fichiers » laisse parfois le système cassé : le monde de l’application inclut caches, états externes et invariants transactionnels.

Règle pratique : si une application ne tolère pas une coupure d’alimentation à tout moment, elle ne tolère pas non plus un rollback sans coordination explicite. ZFS reculera volontiers ; votre base de données expliquera volontiers pourquoi elle est fâchée.

Valeurs par défaut sûres : cloner d’abord, rollback plus tard

Si vous ne retenez rien d’autre : ne faites pas de rollback en premier si vous n’êtes pas 100 % sûr. Clonez le snapshot, montez-le dans un endroit sans risque, comparez, extrayez, et ensuite seulement envisagez le rollback.

Le rollback est excellent pour :

  • Revenir d’une mauvaise mise à jour de paquet ou d’un changement de configuration sur un dataset dédié ou un boot environment.
  • Annuler des opérations destructrices de fichiers quand l’état actuel du dataset ne mérite pas d’être conservé.
  • Restaurer une image de service connue comme saine quand l’application est sans état ou possède sa propre récupération par journalisation.

Le rollback est risqué pour :

  • Bases de données avec dépendances externes (réplicas, PITR, envoi de binlog/WAL).
  • Datasets utilisés par plusieurs services dont un seul est « cassé ».
  • Systèmes avec des chaînes de réplication serrées où la suppression de snapshots casse les incrémentaux.

Blague #1 : Le rollback, c’est comme une machine à voyager dans le temps : ça marche très bien jusqu’à ce que vous réalisiez que vous avez aussi supprimé la timeline où vous aviez noté ce que vous aviez changé.

Tâches pratiques avec commandes, sorties et décisions

Voici des actions opérationnelles réelles que vous pouvez exécuter sous pression. Chaque tâche inclut : la commande, ce que signifie la sortie, et la décision à prendre.

Task 1: Confirm pool health before you touch anything

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

Signification : pas d’erreurs de périphérique connues ni de vdevs dégradés. Si vous voyez « DEGRADED » ou des erreurs de checksum, votre problème peut être matériel ou de corruption, pas « oups on a changé un fichier ».

Décision : Si le pool n’est pas sain, arrêtez-vous et stabilisez : scrub, remplacez des disques, ou au moins capturez la sortie de statut pour les notes d’incident avant tout rollback.

Task 2: Identify the exact dataset behind the mountpoint

cr0x@server:~$ zfs list -o name,mountpoint -S mountpoint
NAME                 MOUNTPOINT
tank                 /tank
tank/app             /srv/app
tank/app/logs        /srv/app/logs
tank/db              /var/lib/postgresql

Signification : Vous savez maintenant quel dataset correspond à un chemin. Les gens rollbackent « tank » alors qu’ils voulaient « tank/app ». C’est comme ça qu’on crée de nouveaux incidents.

Décision : Ciblez le plus petit dataset qui contient l’état cassé.

Task 3: Enumerate snapshots for the dataset and find your candidate

cr0x@server:~$ zfs list -t snapshot -o name,creation,used -s creation tank/app
NAME                          CREATION                USED
tank/app@autosnap_2025-12-26  Fri Dec 26 01:00 2025   120M
tank/app@autosnap_2025-12-26_02-00  Fri Dec 26 02:00 2025   8M
tank/app@pre_upgrade          Fri Dec 26 02:12 2025   0B
tank/app@post_upgrade         Fri Dec 26 02:20 2025   35M

Signification : Noms des snapshots et heures de création. USED indique combien d’espace unique serait libéré si le snapshot était supprimé (pas la « taille du contenu du snapshot »).

Décision : Choisissez le snapshot qui correspond à votre « dernier point connu bon ». Préférez des snapshots explicites comme @pre_upgrade aux snapshots périodiques quand possible.

Task 4: Check for dependent clones (rollback may be blocked or destructive)

cr0x@server:~$ zfs list -t snapshot -o name,clones tank/app@pre_upgrade
NAME                    CLONES
tank/app@pre_upgrade    tank/app-test

Signification : Il existe un clone tank/app-test basé sur ce snapshot. Certaines opérations de rollback qui détruisent des snapshots peuvent exiger la destruction des clones dépendants.

Décision : Si des clones existent, préférez « cloner et restaurer des fichiers » plutôt que le rollback, ou planifiez explicitement le sort du clone.

Task 5: Verify whether newer snapshots exist that would be destroyed

cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | tail -n 5
tank/app@autosnap_2025-12-26_02-00
tank/app@pre_upgrade
tank/app@post_upgrade
tank/app@autosnap_2025-12-26_03-00
tank/app@autosnap_2025-12-26_04-00

Signification : Si vous faites un rollback vers @pre_upgrade avec des flags de suppression récursive, tout ce qui suit est sur la table.

Décision : Si ces snapshots ultérieurs sont nécessaires pour la réplication ou l’audit, ne les supprimez pas ; clonez plutôt.

Task 6: Create a safety snapshot right now (yes, even if things are broken)

cr0x@server:~$ zfs snapshot tank/app@before_rollback_2025-12-26T0235
cr0x@server:~$ zfs list -t snapshot -o name,creation | grep before_rollback
tank/app@before_rollback_2025-12-26T0235  Fri Dec 26 02:35 2025

Signification : Vous avez préservé l’état cassé actuel. C’est votre forensic et votre « annuler l’annulation ».

Décision : Si le rollback tourne mal, vous pouvez revenir à ce point ou extraire des preuves.

Task 7: Put a hold on critical snapshots so automation can’t delete them mid-incident

cr0x@server:~$ zfs hold incident tank/app@before_rollback_2025-12-26T0235
cr0x@server:~$ zfs holds tank/app@before_rollback_2025-12-26T0235
NAME                                      TAG       TIMESTAMP
tank/app@before_rollback_2025-12-26T0235  incident  Fri Dec 26 02:36 2025

Signification : Le snapshot ne peut pas être détruit tant que la hold n’est pas libérée.

Décision : Utilisez les holds chaque fois que des jobs de nettoyage existent, ou lorsque plusieurs personnes sont « en train d’aider ». C’est moins coûteux que de se disputer.

Task 8: Clone the snapshot to inspect and recover without changing prod

cr0x@server:~$ zfs clone tank/app@pre_upgrade tank/app_recover
cr0x@server:~$ zfs set mountpoint=/mnt/app_recover tank/app_recover
cr0x@server:~$ zfs mount tank/app_recover
cr0x@server:~$ zfs list -o name,mountpoint,mounted tank/app_recover
NAME              MOUNTPOINT        MOUNTED
tank/app_recover  /mnt/app_recover  yes

Signification : Vous disposez maintenant d’une branche modifiable avec l’ancien contenu. Vous pouvez diff, copier, ou exécuter des vérifications sans risquer le dataset en production.

Décision : Si vous pouvez réparer la prod en copiant quelques fichiers depuis le clone, faites-le et évitez le rollback intégral.

Task 9: Compare dataset properties that might affect behavior after rollback

cr0x@server:~$ zfs get -H -o property,value compression,recordsize,atime,xattr,acltype tank/app
compression  lz4
recordsize   128K
atime        off
xattr        sa
acltype      posixacl

Signification : Les propriétés impactent les performances et la sémantique. Le rollback ne change pas les propriétés (elles ne sont pas par snapshot), mais si quelqu’un « a corrigé » quelque chose en modifiant une propriété après le snapshot, le rollback ne l’annulera pas.

Décision : Si l’incident a été causé par un changement de propriété, corrigez la propriété au lieu de rollbacker les données. Ou snapshottez les propriétés séparément via la gestion de configuration.

Task 10: Check space pressure (snapshots can block frees; rollback can amplify it)

cr0x@server:~$ zfs list -o name,used,avail,refer,mounted tank
NAME  USED  AVAIL  REFER  MOUNTED
tank  8.21T  640G  96K    yes

Signification : Seulement 640G disponibles. Si vous créez des clones, recevez des streams, ou conservez beaucoup de snapshots, vous pourriez atteindre 100% et déclencher un effondrement des performances ou des échecs d’allocation.

Décision : Si l’espace libre est limité, évitez les opérations qui augmentent l’espace référencé (gros clones, gros receives). Envisagez de supprimer des snapshots non critiques (avec précaution) ou d’ajouter de la capacité avant de faire une récupération « intelligente ».

Task 11: See what’s pinning space via snapshots

cr0x@server:~$ zfs list -t snapshot -o name,used,refer -S used tank/app | head
NAME                                   USED  REFER
tank/app@autosnap_2025-12-25_23-00     88G   612G
tank/app@autosnap_2025-12-26_00-00     74G   618G
tank/app@autosnap_2025-12-26_01-00     120M  620G
tank/app@before_rollback_2025-12-26T0235 0B  621G

Signification : Les anciens snapshots avec des valeurs USED élevées retiennent beaucoup de blocs. C’est généralement « attendu », mais c’est ainsi que l’on obtient « df dit libre, ZFS dit non ».

Décision : Si la capacité est le goulot d’étranglement, supprimez ou externalisez les snapshots qui retiennent le plus d’espace — après avoir vérifié qu’ils ne sont pas requis pour la réplication ou la conformité.

Task 12: Dry-run your rollback impact by listing what would be destroyed

cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | awk '/@pre_upgrade/{flag=1}flag{print}'
tank/app@pre_upgrade
tank/app@post_upgrade
tank/app@autosnap_2025-12-26_03-00
tank/app@autosnap_2025-12-26_04-00
tank/app@before_rollback_2025-12-26T0235

Signification : C’est le « futur » par rapport à @pre_upgrade. Si vous rollbackez avec des flags destructeurs, ceux-ci sont concernés.

Décision : Si un snapshot listé est nécessaire (base de réplication, point d’audit, « before_rollback »), ne le détruisez pas. Utilisez la récupération basée sur clone ou une approche plus chirurgicale.

Task 13: Perform the rollback (single dataset), only after you’ve made it boring

cr0x@server:~$ sudo systemctl stop app.service
cr0x@server:~$ zfs rollback tank/app@pre_upgrade
cr0x@server:~$ sudo systemctl start app.service
cr0x@server:~$ systemctl status --no-pager app.service
● app.service - Example App
     Loaded: loaded (/etc/systemd/system/app.service; enabled)
     Active: active (running)

Signification : Le service a été arrêté pour éviter les écritures pendant le rollback. Le rollback a réussi et le service est relancé.

Décision : Si le service échoue toujours, vous êtes maintenant en territoire de cohérence applicative (migrations, caches, dérive de schéma). Passez à la récupération au niveau applicatif, pas à davantage de manipulations ZFS.

Task 14: If you must destroy newer snapshots during rollback, do it explicitly and understand the blast radius

cr0x@server:~$ zfs rollback -r tank/app@pre_upgrade
cr0x@server:~$ zfs list -t snapshot -o name -s creation tank/app | tail -n 3
tank/app@autosnap_2025-12-26_01-00
tank/app@autosnap_2025-12-26_02-00
tank/app@pre_upgrade

Signification : Les snapshots plus récents ont disparu. Cela peut inclure les ancres de réplication. Voilà pourquoi vous vérifiez avant.

Décision : N’acceptez cela que si vous avez confirmé que vous pouvez re-seeder la réplication, et que vous disposez d’un snapshot « before_rollback » préservé (éventuellement sur un autre système) si vous en avez besoin plus tard.

Task 15: Validate replication implications by checking bookmarks (if used)

cr0x@server:~$ zfs list -t bookmark -o name,creation tank/app
NAME                         CREATION
tank/app#replica_base_01      Fri Dec 20 03:00 2025
tank/app#replica_base_02      Wed Dec 25 03:00 2025

Signification : Les bookmarks peuvent préserver des points d’envoi même si des snapshots sont supprimés. Si votre stratégie de réplication s’appuie sur des bookmarks, vous avez plus de flexibilité.

Décision : Si vous avez un bookmark adapté, vous pouvez peut-être maintenir les incrémentaux. Sinon, planifiez un re-seed complet après un rollback destructeur.

Task 16: Check encryption-related constraints before cloning or sending

cr0x@server:~$ zfs get -H -o property,value encryption,keylocation,keystatus tank/app
encryption   aes-256-gcm
keylocation  file:///etc/zfs/keys/tank_app.key
keystatus    available

Signification : Les datasets chiffrés nécessitent des clés chargées pour les opérations de montage/receive selon votre conception. Le rollback en lui-même ne « nécessite » pas les clés de la même manière, mais le montage des clones en a besoin.

Décision : Assurez-vous que le matériel de clés est disponible avant de cloner/monter pour la récupération. Si les clés manquent, corrigez d’abord la gestion des clés — rollbacker à l’aveugle ne ramènera pas les clés.

Mode opératoire de diagnostic rapide

Quand le rollback est envisagé, vous posez généralement l’une des deux questions : « Puis-je revenir en arrière en toute sécurité ? » et « Si je reviens en arrière, est-ce que ça réparera réellement le système ? » Ce playbook est optimisé pour la vitesse et un minimum de dégâts collatéraux.

First: Confirm you’re fixing the right layer

  1. Le problème est-il purement sur le disque ? Fichiers manquants, mauvaise config, artefact de déploiement corrompu. Si oui, ZFS peut aider directement.
  2. Le problème est-il dans le monde externe de l’application ? Incompatibilité de schéma, secrets en cache, API en aval incompatible, messages en file. Si oui, le rollback peut être hors sujet ou nuisible.
  3. Est-ce réellement un problème matériel ou d’état du pool ? Si des lectures échouent ou que la latence est énorme, le rollback ne changera pas la physique.

Second: Identify the smallest safe rollback unit

  1. Mappez les mountpoints aux datasets (zfs list -o name,mountpoint).
  2. Choisissez le dataset le plus spécifique qui contient le problème.
  3. Vérifiez si des datasets enfants existent ; ne restaurez pas accidentellement des enfants qui ne doivent pas bouger.

Third: Check the “don’t break the future” constraints

  1. Chaîne de réplication : La suppression de snapshots cassera-t-elle les envois incrémentaux ?
  2. Clones : Y a-t-il des clones dépendants qui bloqueront ou seront détruits ?
  3. Espace : Êtes-vous dans une marge d’espace libre suffisante pour cloner/migrer si nécessaire ?
  4. Coordination : Pouvez-vous arrêter proprement les écrivains ? Sinon, vous faites un rollback sur une cible mouvante.

Quick bottleneck check if things are slow (common during snapshot-heavy incidents)

cr0x@server:~$ zpool iostat -v 1 5
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        8.21T   640G    120    980  32.1M  210M
  raidz2-0                  8.21T   640G    120    980  32.1M  210M
    sda                         -      -     15    130  4.0M   28.0M
    sdb                         -      -     14    126  3.9M   27.5M
    sdc                         -      -     46    340  12.2M  72.1M
    sdd                         -      -     45    340  12.0M  72.0M
--------------------------  -----  -----  -----  -----  -----  -----

Signification : Une charge inégale par disque peut suggérer un disque en fin de vie, un vdev chaud, ou des motifs IO pathologiques. L’afflux de snapshots et l’espace libre bas peuvent aussi transformer les écritures en misère.

Décision : Si l’IO est le goulot d’étranglement, stabilisez les performances (espace libre, pause des jobs lourds, planification des scrub) avant de faire de grosses opérations sur les snapshots.

Trois mini-histoires d’entreprise issues du terrain

Mini-histoire 1 : L’incident causé par une fausse hypothèse

Une entreprise de taille moyenne exploitait une flotte de serveurs applicatifs avec ZFS pour l’état local : configurations, petits fichiers de données et quelques artefacts « temporaires » qui n’ont jamais été temporaires. Ils avaient pour habitude de snapshotter l’ensemble du pool tank toutes les heures parce que c’était facile. Et pour être justes, ça a fonctionné pendant des mois.

Puis un ingénieur a essayé de revenir en arrière après un déploiement raté. Il a vu tank@pre_deploy et a supposé que rollbacker tank annulerait proprement le changement. Ça a annulé le changement. Ça a aussi rollbacké des datasets sans rapport : le répertoire spool d’une file de messages et l’état d’un agent de supervision. Le spool contenait maintenant des messages déjà traités. L’agent de supervision a oublié ce qu’il avait vu. Le système n’a pas planté. Il a menti.

La partie vraiment coûteuse a été le décalage : l’incident ne s’est pas annoncé par un bruit. Il est apparu sous forme de travail dupliqué, de métriques incohérentes, et de questions « pourquoi la file rejoue ? » trois heures plus tard. Tout le monde a dû reconstruire ce qui s’était passé à partir des logs — logs qui étaient également sur ZFS et avaient été rollbackés.

La solution n’a pas été magique. Ils ont séparé les datasets afin que l’unité de rollback corresponde à l’unité de propriété : tank/app, tank/queue, tank/monitoring. Ils ont aussi arrêté de considérer le rollback au niveau du pool comme un outil normal. Désormais, « rollback » nécessite de nommer explicitement le dataset dans le plan de changement.

Mini-histoire 2 : L’optimisation qui s’est retournée contre eux

Une autre organisation voulait des récupérations plus rapides. Leur idée : conserver des snapshots plus fréquents, les garder plus longtemps, et compter sur le rollback pour la plupart des « oups ». Ils ont configuré leur autosnap pour garder de nombreux snapshots par jour. Les managers étaient contents parce que ça sonnait résilient.

Ce qu’ils n’avaient pas modélisé, c’est l’amplification d’écriture sous pression d’espace. Les snapshots retiennent des blocs anciens ; les suppressions ne libèrent pas l’espace tant que les snapshots existent ; l’espace libre du pool a diminué ; les allocations se sont fragmentées ; les performances ont dégradé. L’équipe plateforme a remarqué une latence accrue pendant les pics d’écriture, mais cela ressemblait à un problème applicatif parce que le pool était « sain ».

Puis un vrai incident est survenu : une migration de schéma ratée. Ils ont voulu rollbacker le dataset de la base. Mais ils ne pouvaient pas facilement, car le récepteur de réplication attendait une chaîne de snapshots qui couvrait une grande période, et le pool était trop juste en espace pour cloner pour l’investigation. Leur design de « récupérations plus rapides » les a forcés dans la récupération la plus lente possible : un re-seed complet plus la réconciliation au niveau applicatif.

Après coup, ils ont conservé les snapshots fréquents, mais réduit la rétention sur les datasets les plus chauds, introduit des holds seulement pour les snapshots pré-changement, et imposé une politique d’espace libre minimum. Leur meilleure optimisation est devenue une alerte ennuyeuse : « pool < 20% free. »

Mini-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Un service adjacent aux paiements (sans nom, sans drame) tournait sur ZFS avec un contrôle strict des changements. Avant chaque déploiement, leur pipeline prenait un snapshot nommé @pre_change_$ticket. Le snapshot était maintenu avec un tag et automatiquement répliqué vers un système secondaire. Rien de fancy. Juste de la consistance.

Un soir, une mise à jour de dépendance a livré un changement subtil de valeur par défaut. Le service a commencé à rejeter des requêtes valides. Le SRE a été appelé, et en quelques minutes ils ont pris une décision claire : le problème a commencé au moment du déploiement, leur snapshot pré-changement existait, était en hold, et avait déjà été répliqué hors site.

Ils n’ont même pas rollbacké immédiatement. Ils ont cloné @pre_change, comparé les configs, et trouvé le changement de valeur par défaut. Ils ont appliqué un hotfix dans la config en place. Aucun rollback nécessaire, aucune chaîne de réplication cassée, et le rapport d’incident avait une chronologie claire parce que le snapshot de l’état cassé existait aussi.

Ce n’était pas glamour. C’était l’équivalent systèmes de se brosser les dents. Et ça a marché.

Erreurs courantes : symptômes → cause racine → correctif

1) « Rollback failed: dataset has dependent clones »

Symptômes : Erreurs de commande rollback mentionnant des clones ou « dataset is busy » ou des dépendances de clone.

Cause racine : Un snapshot que vous tentez de dépasser est l’origine d’un clone, ou le dataset est actuellement monté et en cours d’utilisation.

Correctif : Listez les clones du snapshot, décidez si vous voulez les conserver, et pivotez vers une récupération basée sur clone si vous ne pouvez pas les détruire. Arrêtez les services et démontez si c’est juste « busy ». Utilisez zfs list -t snapshot -o name,clones et lsof/fuser sur le point de montage si nécessaire.

2) « We rolled back and the app is still broken »

Symptômes : Les fichiers semblent corrects, mais les erreurs applicatives persistent ; la base de données se plaint ; les caches ne correspondent pas.

Cause racine : État applicatif hors du dataset : changements de schéma, files externes, dépendances distantes, ou attentes de journalisation.

Correctif : Considérez le rollback comme seulement la première étape. Coordonnez la récupération applicative : récupération après crash de la base, journaux undo/redo, vérifications de version de schéma, vidage des caches, ou rollback seulement du dataset d’artefacts plutôt que de la base de données.

3) « Rollback destroyed snapshots and replication is now stuck »

Symptômes : zfs send incrémental échoue ; le récepteur se plaint de snapshots manquants ; l’outil de réplication renvoie des erreurs après le rollback.

Cause racine : Rollback destructeur (-r/-R) a supprimé des snapshots qui servaient de base aux incrémentaux.

Correctif : Re-seed la réplication avec un envoi complet, ou utilisez des bookmarks si votre stratégie les prend en charge. À l’avenir : ne détruisez jamais les snapshots utilisés comme ancres de réplication ; mettez-les en hold jusqu’à confirmation du récepteur.

4) « Space didn’t come back after deleting data »

Symptômes : Vous supprimez des gigaoctets, mais zfs list montre peu de changement ; le pool reste plein ; les écritures ralentissent.

Cause racine : Les snapshots retiennent les blocs supprimés.

Correctif : Identifiez quels snapshots ont un USED élevé et taillez selon les besoins de rétention/réplication. Envisagez de séparer les datasets pour que des répertoires à forte activité ne bloquent pas l’espace du service entier.

5) « We rolled back the wrong dataset »

Symptômes : Des services non liés régressent ; des logs disparaissent ; le monitoring montre un voyage dans le temps ; plusieurs équipes se présentent.

Cause racine : Le mapping mountpoint→dataset a été supposé et non vérifié. Ou le rollback a été exécuté au niveau du pool.

Correctif : Mappez toujours le mountpoint au dataset et rollbackez uniquement ce dataset. Utilisez des noms de dataset explicites dans les runbooks. Si vous devez annuler sur plusieurs datasets, snapshottez-les ensemble (voir les checklists) et rollbackez-les de manière coordonnée.

6) « Rollback completed, but permissions/ACL behavior is weird »

Symptômes : Erreurs d’accès ou évaluation d’ACL étrange après rollback ; les fichiers « semblent » corrects mais se comportent différemment.

Cause racine : Les propriétés du dataset (type d’ACL, mode xattr) ou la gestion des ACL côté OS ont changé. Les snapshots ne rétablissent pas les propriétés du dataset.

Correctif : Comparez les sorties de zfs get avec une base ; restaurez les propriétés via la gestion de configuration. Traitez les propriétés comme du code.

7) « Rollback on encrypted dataset fails to mount clone »

Symptômes : Le clone existe mais ne monte pas ; statut de clé indisponible ; erreurs d’outillage autour des clés.

Cause racine : Clés non chargées, keylocation incorrecte, ou flux opérationnel qui suppose que les clés sont présentes sur l’hôte de récupération.

Correctif : Assurez-vous que les clés sont chargées et accessibles sur l’hôte où vous clonez/montez. Vérifiez avec zfs get keystatus. Si vous répliquez des datasets chiffrés, ayez un plan de gestion des clés qui fonctionne pendant les incidents.

8) « We used rollback for file recovery and made everything worse »

Symptômes : Un fichier manquant devient un rollback complet de service, perdant des écritures légitimes depuis le moment du snapshot.

Cause racine : Utilisation du rollback de dataset alors qu’il fallait une restauration au niveau fichier.

Correctif : Montez/parcourez le snapshot ou clonez et copiez les chemins spécifiques. Le rollback est le dernier recours pour des réversions larges, pas votre méthode par défaut pour undelete.

Blague #2 : Si votre plan de rollback est « on va juste rollbacker », félicitations — vous avez inventé une stratégie de sauvegarde avec la confiance d’un biscuit chinois.

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

Checklist A: The “I need to restore a few files” plan (no rollback)

  1. Identifiez le dataset pour le chemin (zfs list -o name,mountpoint).
  2. Listez les snapshots autour du moment de l’incident.
  3. Créez un snapshot d’incident de l’état actuel et mettez-le en hold.
  4. Clonez le snapshot cible vers un dataset de récupération.
  5. Copiez les fichiers du clone vers le live (en préservant propriétaire/ACL).
  6. Validez le comportement de l’app. Gardez le clone tant que vous n’êtes pas sûr.

Checklist B: The “Rollback this dataset safely” plan

  1. Stoppez les writers. Arrêt systemd du service, mode maintenance applicatif, ou au moins bloquez les écritures.
  2. Confirmez l’état du pool. Si dégradé, n’ajoutez pas plus de chaos.
  3. Confirmez les limites du dataset. Ne rollbackez pas le pool sauf si vous voulez assumer les problèmes de tous.
  4. Snapshottez l’état actuel. Nommez-le clairement et mettez-le en hold.
  5. Vérifiez les clones. Si des clones dépendants existent, décidez si le rollback est faisable.
  6. Vérifiez les conséquences des « snapshots plus récents ». Déterminez si vous pouvez garder ou devez détruire les snapshots postérieurs.
  7. Envisagez une répétition clone-first. Si vous n’êtes pas sûr, clonez et testez le démarrage de l’app sur le clone.
  8. Rollback. Utilisez la forme la moins destructive qui fonctionne. Évitez -R sauf nécessité.
  9. Redémarrez les services et validez. Validez non seulement « service en marche », mais l’exactitude et la sanity des données.
  10. Nettoyez de manière responsable. Libérez les holds quand c’est sûr, supprimez les clones temporaires, et documentez le snapshot utilisé.

Checklist C: Coordinated rollback across multiple datasets

C’est là que les équipes se brûlent. Un état multi-dataset (app + db + queue) nécessite des snapshots coordonnés et un rollback coordonné, sinon vous obtenez « cohérence interne mais incohérence mutuelle ».

  1. Stoppez toute la stack ou placez-la en mode quiescent.
  2. Créez un snapshot sur chaque dataset avec le même jeton de nom (exemple : @pre_change_TICKET).
  3. Mettre ces snapshots en hold sous un tag « incident » ou « change ».
  4. Lors du rollback, restaurez l’ensemble dans un ordre défini (généralement queue/consommateurs d’abord, puis db, puis app), et validez chaque couche.

FAQ

1) Does ZFS rollback delete data permanently?

Le rollback abandonne les modifications du dataset live effectuées après le snapshot. Si vous supprimez aussi les snapshots plus récents (via -r/-R), alors oui, cet historique est perdu sauf s’il a été répliqué ailleurs.

2) What’s the difference between rollback and cloning a snapshot?

Le rollback recule le dataset existant sur place. Un clone crée un nouveau dataset modifiable basé sur le snapshot. Les clones sont plus sûrs quand vous n’êtes pas sûr, avez besoin d’une récupération fichier, ou voulez tester le démarrage sans toucher la prod.

3) Can I rollback just one directory?

Non. Le rollback s’applique à un dataset. Si vous voulez « juste un répertoire », utilisez un navigateur de snapshot (comme .zfs/snapshot quand disponible) ou clonez et copiez le répertoire.

4) Why is rollback blocked by “newer snapshots exist”?

ZFS empêche la destruction accidentelle de la chronologie des snapshots. Vous pouvez outrepasser, mais ZFS veut que vous reconnaissiez explicitement que vous supprimez le futur.

5) Will rollback restore dataset properties like compression or recordsize?

Non. Les propriétés ne sont pas l’état d’un snapshot au même titre que le contenu des fichiers. Si un changement de propriété a causé le problème, corrigez la propriété directement et gérez-la via la configuration.

6) How does rollback interact with replication?

La réplication dépend de la continuité des snapshots. Si vous supprimez des snapshots qui ont été envoyés (ou qui sont attendus comme bases incrémentales), vous pouvez casser les incrémentaux et nécessiter un re-seed complet. Utilisez des holds pour les ancres de réplication, et planifiez le rollback pour ne pas les supprimer à la légère.

7) Is rollback safe for databases?

Parfois. Cela dépend si la base peut récupérer à partir d’une image consistante au crash et si vous avez coordonné avec les réplicas, le PITR et les migrations de schéma. Si vous ne pouvez pas articuler ces dépendances, préférez cloner-et-valider ou les méthodes de restauration natives de la base.

8) What’s the safest “undo” if I’m not sure what changed?

Snapshotez l’état actuel (et mettez-le en hold), puis clonez un snapshot connu bon et comparez. Si le diff révèle un petit ensemble de fichiers, restaurez-les. Le rollback sert quand vous êtes sûr que l’ensemble du dataset doit être reculé.

9) When should I use holds?

Utilisez les holds pour tout snapshot qui ne doit pas disparaître : snapshots pré-changement, snapshots de preuve d’incident, ancres de réplication et snapshots de conformité. Libérez les holds de manière délibérée quand la fenêtre de risque est passée.

10) Does rollback require unmounting the dataset?

Pas toujours, mais arrêter les writers est la vraie exigence. En pratique, arrêtez le service et assurez-vous qu’il n’y a pas d’écritures actives. Si le dataset est occupé, démontez ou identifiez le processus qui le tient.

Conclusion : prochaines étapes concrètes

Le rollback est un outil tranchant. Il peut vous sauver une nuit, un trimestre, ou votre crédibilité. Mais la manière sûre n’est pas « taper rollback plus vite ». La manière sûre est de réduire l’incertitude et de restreindre le rayon d’impact.

Faites ceci ensuite :

  • Séparez les datasets par propriété et domaine de rollback. Si deux services partagent un dataset, votre risque de rollback est déjà payé.
  • Standardisez les snapshots pré-changement avec holds. Automatisez-les et rendez-les banals, et répliquez-les si possible.
  • Entraînez la récupération « cloner d’abord ». Faites du « cloner, diff, copier en retour » la mémoire musculaire par défaut.
  • Documentez votre politique sur les flags destructeurs. Quand -r est-il autorisé ? Quand est-il interdit ? Qui signe ?
  • Organisez un game day : cassez une config, récupérez avec des snapshots, puis refaites-le en condition « espace bas ». C’est le vrai test.

Si votre réponse aux incidents repose sur des exploits héroïques, vous n’avez pas de réponse aux incidents. Vous avez un rendez-vous récurrent avec le chaos. La restauration ZFS, faite en sécurité, est la façon d’annuler ce rendez-vous.

← Précédent
Debian 13 : un nouveau nom d’interface a cassé le réseau — des noms stables qui survivent aux redémarrages (cas n°7)
Suivant →
WannaCry : le rançongiciel qui a rappelé à tous l’importance des correctifs

Laisser un commentaire