ZFS zfs diff : trouver exactement ce qui a changé entre les snapshots

Cet article vous a aidé ?

Les snapshots ZFS sont la chose la plus proche du voyage dans le temps que le stockage puisse offrir tout en passant un audit. Mais le voyage dans le temps n’est utile que si vous pouvez répondre à la question que votre patron, votre équipe de sécurité ou votre cerveau à 3 heures du matin posera : qu’est‑ce qui a changé ?

zfs diff est l’outil franc et direct pour ce travail. Ce n’est pas élégant, ce n’est pas une interface graphique, et il ne se soucie pas de vos sentiments. Il vous indique quels chemins ont été ajoutés, supprimés, modifiés ou renommés entre deux snapshots (ou entre un snapshot et « maintenant »). Bien utilisé, il transforme un effrayant « quelque chose s’est passé » en une liste sur laquelle vous pouvez agir.

Ce qu’est zfs diff (et ce que ce n’est pas)

zfs diff compare deux points dans le temps au sein d’un même dataset (ou zvol, bien que les chemins de fichiers soient le cas courant). Ces points sont généralement des snapshots comme pool/ds@snapA et pool/ds@snapB, ou un snapshot et le système de fichiers actif. Le résultat est un flux de changements au niveau des chemins : fichiers créés, fichiers supprimés, fichiers modifiés, chemins renommés.

Ce n’est pas un diff conscient du contenu comme diff -u. Il ne vous dira pas « la ligne 83 a changé ». Il vous dit « ce fichier a changé », ce qui correspond généralement exactement à ce dont les opérations et la réponse aux incidents ont besoin. Si vous voulez des diffs de contenu, vous pouvez monter les snapshots et exécuter vos propres outils (et oui, c’est plus lent, plus bruyant et plus facile à rater).

Ce n’est également pas un enregistrement faisant autorité du pourquoi quelque chose a changé, ni du processus qui l’a fait. C’est un outil de comptabilité au niveau du système de fichiers : voici l’ensemble des chemins dont l’état de métadonnées/contenu diffère entre deux groupes de transactions.

Blague #1 : Les snapshots ne mentent pas, mais les administrateurs oui — généralement à eux‑mêmes, cinq minutes avant l’appel d’incident.

Points factuels et contexte historique utiles en réunion

Ce sont des points courts et concrets qui vous aident à expliquer pourquoi les diffs de snapshots ZFS se comportent comme ils le font — et pourquoi c’est une fonctionnalité, pas un inconvénient.

  1. Les snapshots ZFS sont en copy-on-write, pas des « copies de sauvegarde ». Un snapshot est une référence cohérente à des blocs existants ; les nouvelles écritures vont ailleurs. C’est pourquoi les snapshots sont bon marché et instantanés.
  2. « Renommer » n’est pas « copier puis supprimer » au niveau de la sémantique du système de fichiers. ZFS peut détecter les renommages comme opération de première classe, et zfs diff peut les signaler quand il peut corréler l’identité des objets.
  3. ZFS a été conçu avec des checksums de bout en bout comme base. Cela signifie que « fichier modifié » peut être lié à de réels changements de blocs, pas seulement à des timestamps modifiés parce qu’une application a touché des métadonnées.
  4. La réplication basée sur snapshots (send/receive) précède le marketing actuel autour des « backups immuables ». ZFS fait des streams de snapshots incrémentaux depuis des années ; « immutabilité » vient de la politique et des permissions, pas d’un nouveau format de fichier.
  5. FreeBSD et illumos ont longtemps traité ZFS comme une priorité. De nombreux comportements en production (y compris la maturité des outils autour des snapshots) ont été éprouvés là‑bas avant que ZFS sur Linux n’atteigne le même niveau opérationnel.
  6. La sortie de zfs diff est une vue de métadonnées et d’état d’objet, pas de l’intention applicative. Par exemple, un checkpoint de base de données peut modifier beaucoup de fichiers même si les « données » logiques ont peu bougé.
  7. Les datasets ZFS peuvent avoir des points de montage différents et peuvent être démontés. zfs diff n’a pas besoin que le dataset soit monté pour comparer des snapshots ; il compare les arbres de snapshots en interne.
  8. Les clones sont des snapshots ré‑écrits en écriture. Le diff entre un snapshot et le snapshot d’un clone peut donner une histoire claire de « ce qui a divergé » — utile en dev/test, ou lorsque la prod a été exécutée par erreur sur un clone (oui, ça arrive).

Comment zfs diff fonctionne réellement en interne

À un niveau élevé, ZFS suit des ensembles d’objets. Un dataset est un ensemble d’objets ; un snapshot est une version en lecture seule et épinglée de cet ensemble d’objets. zfs diff parcourt deux versions et compare les entrées de répertoire et les métadonnées d’objets, puis émet un ensemble de changements de chemins.

La conséquence opérationnelle importante : le diff se base sur des objets du système de fichiers, pas sur la vision applicative. Si une application réécrit un fichier en place, vous verrez une modification. Si elle écrit un nouveau fichier temporaire et le renomme par dessus l’original, vous pouvez voir une modification plus un comportement de renommage selon la façon dont l’opération a été enregistrée dans le txg et si la corrélation d’identité d’objet est possible.

Autre conséquence : le rapport basé sur les chemins est reconstruit. ZFS a des numéros d’objet et des structures de répertoires ; pour afficher « /var/log/messages », l’outil doit parcourir les répertoires et reconstruire les noms. Sur de très grands arbres de répertoires, surtout en présence de churn, cela peut être coûteux. « Coûteux » ici ne signifie pas nécessairement « disque lent » ; cela peut signifier « beaucoup de parcours de métadonnées », ce qui se traduit par de la pression sur l’ARC ou de nombreuses lectures aléatoires si le cache est manqué.

Une subtilité à garder en tête : le système de fichiers actif (« maintenant ») n’est pas un snapshot. Si vous lancez zfs diff pool/ds@snap contre le dataset live pendant qu’il change activement, vous demandez une cible mouvante. ZFS fera de son mieux, mais votre conclusion opérationnelle devrait être « c’est indicatif », pas « c’est une transcription judiciaire ». Pour une comparaison stable, diff snapshot-vers-snapshot.

Lire la sortie sans se mentir

Le format canonique de sortie est un code de changement d’un seul caractère suivi d’un chemin. Codes courants que vous verrez :

  • + chemin ajouté
  • - chemin supprimé
  • M chemin modifié (contenu ou métadonnées changés)
  • R chemin renommé (souvent affiché comme « from » et « to » selon l’implémentation)

Conseils d’interprétation de quelqu’un qui s’est brûlé :

« Modifié » est plus large que « contenu changé »

Un fichier peut être « modifié » à cause des permissions, de la propriété, des ACL, des xattrs, des timestamps, d’un changement du nombre de liens ou du contenu. Si vous faites de la réponse aux incidents, vous vous souciez souvent des changements de contenu ; si vous faites de la conformité, vous pouvez vous préoccuper des métadonnées encore plus.

Les renommages sont vos amis — jusqu’à ce qu’ils ne le soient pas

Quand un renommage est détecté, c’est un cadeau : cela signifie que vous pouvez suivre un déplacement sans paniquer à propos d’un suppression+création. Mais la détection de renommage peut échouer lorsque la corrélation est ambiguë (fort churn, fichiers temporaires, ou schémas qui cassent la correspondance d’identité d’objet). Ne prenez pas l’absence de R comme une preuve qu’un renommage n’a pas eu lieu ; considérez‑la comme « l’outil n’a pas pu le prouver de façon fiable ».

Les suppressions sont souvent le signal le plus précieux

Si vous déboguez un déploiement cassé, un seul fichier supprimé dans /etc peut expliquer plus que 5 000 fichiers « modifiés » dans /var. En lisant les diffs, filtrez par les répertoires qui correspondent à votre domaine de défaillance.

Blague #2 : zfs diff est comme une revue de code : ça ne résout pas le problème, mais ça vous enlève la possibilité de prétendre que rien ne s’est passé.

Tâches pratiques : 14 commandes réelles avec interprétation

Tous les exemples supposent un dataset comme tank/app avec les snapshots @pre et @post. Adaptez les noms à votre environnement.

Task 1: Compare two snapshots (baseline)

cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@post
M       /etc/app/app.conf
+       /var/lib/app/new-index.db
-       /var/lib/app/old-index.db
R       /var/log/app/old.log   -> /var/log/app/old.log.1

Interprétation : La configuration a changé, l’index a été tourné, un fichier a été remplacé, et un journal a été tourné via renommage. Typique d’une mise à jour de paquet ou d’une opération de maintenance applicative.

Task 2: Compare a snapshot to the current live filesystem

cr0x@server:~$ sudo zfs diff tank/app@pre
M       /etc/app/app.conf
+       /var/tmp/app-build-9281.tmp

Interprétation : « Depuis @pre, qu’est‑ce qui diffère maintenant ? » Utile pour des vérifications rapides « qu’avons‑nous changé depuis le dernier known-good ». Méfiez‑vous du churn élevé : les résultats peuvent changer pendant que vous les lisez.

Task 3: Limit noise by grepping to a subtree

cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@post | grep '^M' | grep '^M[[:space:]]\+/etc/'
M       /etc/app/app.conf
M       /etc/app/limits.conf

Interprétation : Réduire le bruit des journaux modifiés. En cas de panne, vous voulez généralement d’abord une courte liste des changements de configuration et des binaires.

Task 4: Count changes by type (cheap triage)

cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@post | awk '{print $1}' | sort | uniq -c
   82 +
   10 -
  911 M
    4 R

Interprétation : 911 chemins modifiés, c’est beaucoup. Si vous attendiez un changement uniquement de configuration, c’est un signal d’alarme. Si vous attendiez une mise à jour de paquet ou une migration de BD, cela peut être normal.

Task 5: Find the “top directories” affected

cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@post \
  | awk '{print $2}' \
  | awk -F/ 'NF>2 {print "/"$2"/"$3} NF==2 {print "/"$2} NF==1 {print "/"}' \
  | sort | uniq -c | sort -nr | head
  640 /var/lib
  210 /var/log
   95 /usr/local
   12 /etc/app

Interprétation : La majorité du churn est sous /var/lib et /var/log. Cela suggère un mouvement de données applicatives et de journalisation — pas une dérive aléatoire de la configuration.

Task 6: Verify snapshots exist and belong to the same dataset lineage

cr0x@server:~$ zfs list -t snapshot -o name,creation -s creation | grep '^tank/app@'
tank/app@pre     Mon Dec 23 11:58 2025
tank/app@post    Mon Dec 23 12:12 2025

Interprétation : Si les snapshots ont été pris à partir de datasets différents (ou après un rollback/clone qui a divergé), les diffs peuvent être dénués de sens ou échouer.

Task 7: Confirm the dataset mountpoint and whether it’s mounted

cr0x@server:~$ zfs get -H -o property,value mountpoint,mounted tank/app
mountpoint  /app
mounted     yes

Interprétation : Pas requis pour zfs diff, mais nécessaire si vous prévoyez d’inspecter des fichiers directement (par ex. monter les snapshots via .zfs/snapshot).

Task 8: Inspect a changed file across snapshots (content-level confirmation)

cr0x@server:~$ sudo sed -n '1,120p' /app/.zfs/snapshot/pre/etc/app/app.conf
# app.conf - baseline
max_workers=32
log_level=info
cr0x@server:~$ sudo sed -n '1,120p' /app/.zfs/snapshot/post/etc/app/app.conf
# app.conf - after deploy
max_workers=64
log_level=debug

Interprétation : zfs diff vous a dit « modifié » ; ceci vous dit « comment ». En cas d’incident, faites cela pour la poignée de fichiers qui comptent.

Task 9: Detect suspicious mass renames (common in ransomware and “log cleanup” scripts)

cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@post | grep '^R' | head
R       /var/lib/app/data/part-0001 -> /var/lib/app/data/part-0001.locked
R       /var/lib/app/data/part-0002 -> /var/lib/app/data/part-0002.locked
R       /var/lib/app/data/part-0003 -> /var/lib/app/data/part-0003.locked

Interprétation : Une rafale de renommages uniformes avec de nouvelles extensions est suspecte. Cela peut être un processus d’archivage légitime. Cela peut aussi être un schéma « encrypt then rename ». Escaladez rapidement.

Task 10: Validate whether incremental send should include the expected changes

cr0x@server:~$ sudo zfs diff tank/app@replica-base tank/app@replica-next | head -20
M       /etc/app/app.conf
+       /var/lib/app/new-index.db

Interprétation : Si votre cible de réplication « n’a pas reçu le changement de config », comparez les snapshots exacts que vous envoyez. Beaucoup de « mystères » de réplication se résument à « nous avons envoyé la mauvaise base de snapshot ».

Task 11: Correlate snapshot diffs with space usage (is this change expensive?)

cr0x@server:~$ zfs list -o name,used,refer,avail,mountpoint tank/app
NAME      USED  REFER  AVAIL  MOUNTPOINT
tank/app  412G  380G   2.1T   /app
cr0x@server:~$ zfs get -o name,property,value -s local,received,default usedbysnapshots,usedbydataset,usedbychildren tank/app
tank/app  usedbysnapshots  31.4G
tank/app  usedbydataset    380G
tank/app  usedbychildren   0B

Interprétation : Beaucoup de fichiers « modifiés » ne signifie pas toujours beaucoup de nouveaux blocs, mais cela corrèle souvent. Si usedbysnapshots augmente rapidement, le churn retient d’anciens blocs.

Task 12: Spot “metadata churn” that looks like content churn

cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@post | grep '^M' | grep '^M[[:space:]]\+/var/log/' | head
M       /var/log/app/access.log
M       /var/log/app/error.log
M       /var/log/app/metrics.log

Interprétation : Les logs qui changent sont normaux ; ne les laissez pas noyer le signal. Si vous avez besoin de « ce qui a changé dans le code/la config », filtrez les répertoires de churn connus.

Task 13: Confirm snapshot naming and ordering to avoid “backwards diff” confusion

cr0x@server:~$ zfs list -t snapshot -o name,creation -s creation tank/app | tail -5
tank/app@daily-2025-12-21   Sun Dec 21 00:00 2025
tank/app@daily-2025-12-22   Mon Dec 22 00:00 2025
tank/app@daily-2025-12-23   Tue Dec 23 00:00 2025
tank/app@pre                Tue Dec 23 11:58 2025
tank/app@post               Tue Dec 23 12:12 2025

Interprétation : Quand vous differez « plus récent vs plus ancien » vous pouvez vous embrouiller sur les signes plus/moins. Vérifiez toujours les dates de création.

Task 14: Use zfs diff output as an allowlist for surgical restores

cr0x@server:~$ sudo zfs diff tank/app@good tank/app@bad | awk '$1 ~ /^M|^-$/ {print $2}' | head
/etc/app/app.conf
/usr/local/bin/app
/usr/local/lib/libapp.so
cr0x@server:~$ sudo cp -a /app/.zfs/snapshot/good/usr/local/bin/app /app/usr/local/bin/app

Interprétation : Parfois vous ne voulez pas un rollback complet ; vous voulez restaurer un petit ensemble de fichiers connus comme bons. La navigation dans les snapshots plus un diff filtré avec soin vous donne un plan qui ne détruira pas des données valides non concernées.

Trois histoires du monde de l’entreprise (avec douleur incluse)

Mini-story 1: The incident caused by a wrong assumption (snapshots as “backups”)

La configuration était familière : un dataset applicatif critique sur ZFS, des snapshots horaires, et un job de réplication vers une machine secondaire. Tout le monde dormait tranquille parce que « nous avons des snapshots ». L’équipe avait même une page wiki qui disait « snapshots = backups », ce qui est le genre de phrase qui devrait être accompagnée d’un avertissement et d’un extincteur.

Puis un développeur a lancé un script de nettoyage en production. Ce n’était pas malveillant ; il visait juste la mauvaise variable d’environnement. Quelques répertoires sous /var/lib/app ont été supprimés récursivement. En quelques minutes, la surveillance est devenue des cris. L’astreinte a prononcé la phrase que vous ne voulez jamais entendre : « C’est bon, on a des snapshots, je vais juste faire un rollback. »

Le rollback a restauré les données supprimées. Il a aussi rétabli une poignée d’écritures légitimes faites après le snapshot — écritures qui incluaient l’état visible par les clients. L’incohérence résultante n’a pas été catastrophique, mais elle a été moche : tentatives répétées, événements doublons, et quelques heures de réconciliation manuelle avec le support et les opérations. Le postmortem ne portait pas sur le fait que ZFS soit risqué ; il portait sur la fausse hypothèse que l’action « la plus sûre » est la plus rapide.

Ce qui a corrigé la situation la fois suivante fut de la discipline ennuyeuse : avant tout rollback, ils exécutaient zfs diff entre le dernier snapshot connu bon et l’état courant. Le diff a rendu visible le rayon d’impact. Au lieu de restaurer l’ensemble du dataset, ils ont restauré uniquement les sous‑arborescences supprimées depuis le snapshot. Ils ont conservé les écritures légitimes. L’incident suivant n’était pas agréable, mais il a été contenu — et contenir, c’est à quoi ressemble la « résilience » quand le pager sonne fort.

Mini-story 2: The optimization that backfired (aggressive snapshot cadence + diff in cron)

Une autre organisation voulait de « l’audit quasi temps réel » pour une initiative de conformité. Le plan : prendre des snapshots toutes les cinq minutes, exécuter zfs diff entre les deux derniers, archiver la sortie et l’envoyer vers un système central. Sur le papier, c’était élégant. En pratique, c’était un petit déni de service contre leur propre stockage.

Premier problème : le dataset était un cache de build avec des millions de petits fichiers. zfs diff devait parcourir d’énormes arbres de répertoires et reconstruire des chemins. Toutes les cinq minutes. Cela s’est traduit par une pression metadatael sans relâche. Les ratios d’ARC ont chuté. La latence a grimpé. Les développeurs se sont plaints que « ZFS est lent », ce qui est l’équivalent stockage de blâmer la route pour une mauvaise conduite.

Deuxième problème : la sortie était gigantesque et majoritairement du bruit. Les systèmes de build tournent. Ils créent des fichiers temporaires, renomment, suppriment des répertoires, répètent. L’équipe conformité voulait « ce qui a changé », mais ils ont obtenu « tout change tout le temps ». Le rapport signal/bruit était si faible que personne ne regardait les rapports, ce qui est le mode d’échec secret de la conformité : on peut générer une quantité infinie de preuves que personne ne lit.

Le plan de reprise fut pragmatique. Ils ont réduit la fréquence des snapshots pour correspondre aux besoins métier (horaire pour la plupart, plus fréquent seulement pour quelques petits datasets). Ils ont arrêté d’exécuter des diffs sur des caches bruyants et se sont concentrés sur les datasets de configuration et de données officielles. Et quand ils exécutaient des diffs, ils filtraient vers des sous‑arbres significatifs et résumaient les comptes plutôt que d’archiver chaque chemin. L’optimisation n’a pas échoué parce que ZFS ne peut pas le faire ; elle a échoué parce que la charge de travail ne méritait pas ce niveau de surveillance.

Mini-story 3: The boring but correct practice that saved the day (diff before replication cutover)

Celle‑ci est du genre d’histoire qu’on n’entend pas aux conférences parce qu’elle n’est pas glamour. Une équipe planifiait une migration de stockage : nouveaux serveurs, nouveau layout de pool, réplication ZFS send/receive, puis une fenêtre de cutover. L’anxiété habituelle : « La cible sera‑t‑elle identique ? » et « Et si on raté quelque chose ? »

Ils ont fait quelque chose de peu sexy : ils ont écrit un runbook qui exigeait un zfs diff pré‑cutover sur une paire de snapshots gelée — un sur la source, un sur la destination après receive. Pas « faire confiance au job de réplication », pas « comparer les sorties de zfs list », mais une vérification explicite de la liste des changements sur des datasets représentatifs.

Pendant la répétition générale, le diff a montré une poignée de changements inattendus sous un répertoire qui « ne devrait jamais changer ». Il s’est avéré qu’un service sur l’hôte de destination avait démarré automatiquement et avait commencé à écrire des fichiers de cache dans un point de montage qui était censé rester inactif jusqu’au cutover. La réplication elle‑même était correcte ; c’est l’environnement qui ne l’était pas.

Ils ont corrigé l’ordre de démarrage des services, répété la répétition, et les diffs sont devenus silencieux. La nuit du cutover, tout s’est passé de façon anticlimatique dans le meilleur sens. La pratique ennuyeuse — diff des snapshots représentant la « source de vérité » et la « reçue comme vérité » — a détecté une divergence réelle avant qu’elle ne devienne une dispute nocturne sur l’intégrité des données.

Mode opératoire pour diagnostic rapide

Quand vous avez besoin de réponses rapidement, ne commencez pas par fixer des milliers de lignes de diff. Commencez par un petit nombre de vérifications qui restreignent le problème en « changement attendu », « changement inattendu », « problème d’outil » ou « goulot de performance ».

Step 1: Confirm you’re comparing the right snapshots

cr0x@server:~$ zfs list -t snapshot -o name,creation -s creation tank/app | tail -10

Regardez : Les noms des snapshots sont‑ils corrects ? Sont‑ils dans l’ordre que vous pensez ? Quelqu’un a‑t‑il rollbacké et recréé des snapshots avec des noms confus ?

Step 2: Determine whether the change is “data churn” or “control-plane churn”

cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@post | awk '{print $2}' | head

Puis immédiatement : résumez où cela se produit.

cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@post \
  | awk '{print $2}' \
  | awk -F/ 'NF>2 {print "/"$2"/"$3} NF==2 {print "/"$2} NF==1 {print "/"}' \
  | sort | uniq -c | sort -nr | head -15

Recherchez : Principalement /var/log et /var/tmp (généralement du bruit) vs /etc, /usr, et les répertoires de données de l’app (généralement significatifs).

Step 3: If performance is the bottleneck, check whether you’re metadata-bound

cr0x@server:~$ arcstat 1 5
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsz     c
12:00:01   210    88     41    60   28    22   10     6    2   128G  192G

Interprétation : Des taux de miss élevés pendant un run de diff suggèrent que les métadonnées ne sont pas dans l’ARC et que le système effectue du travail réel pour parcourir les répertoires. Si vous n’avez pas arcstat, utilisez la télémétrie IO et mémoire native de l’OS ; le schéma est le même : CPU + lectures aléatoires + misses de cache.

Step 4: Validate dataset properties that change the meaning of “modified”

cr0x@server:~$ zfs get -o name,property,value atime,recordsize,compression,acltype,xattr,overlay,encryption tank/app

Recherchez : atime=on peut créer du churn de métadonnées. Le comportement ACL et xattr peut générer des vagues de résultats « modifiés » sur de nombreux fichiers.

Step 5: If the diff is huge, decide whether you need a summary or a surgical answer

Si vous êtes en conférence d’incident, vous n’avez généralement pas besoin de tous les chemins. Vous avez besoin : « Quelque chose a‑t‑il changé sous /etc ? » « Des binaires sous /usr/local/bin ont‑ils changé ? » « Des fichiers ont‑ils été supprimés sous le répertoire de données ? » C’est un travail de filtrage, pas un inventaire complet.

Erreurs courantes (symptômes et corrections)

Mistake 1: Diffing the wrong dataset because mountpoints look similar

Symptôme : zfs diff rapporte des changements qui ne correspondent pas à ce que vous avez vu sur le disque, ou vous ne trouvez pas les chemins dans le système de fichiers actif.

Cause : Plusieurs datasets montés sous des chemins similaires, ou un changement de point de montage hérité. Vous avez diffé tank/app alors que vous regardiez tank/app/data (ou l’inverse).

Correction : Confirmez les points de montage et les limites de dataset.

cr0x@server:~$ zfs list -o name,mountpoint -r tank/app
NAME           MOUNTPOINT
tank/app       /app
tank/app/data  /app/data

Mistake 2: Treating snapshot-to-live diffs as stable truth during active writes

Symptôme : Vous relancez le même diff et les résultats changent ; vous voyez des fichiers temporaires apparaître/disparaître ; vous ne pouvez pas concilier les comptes.

Cause : Le système de fichiers actif change pendant que vous le comparez à un snapshot fixe.

Correction : Prenez un deuxième snapshot et comparez snapshot‑à‑snapshot.

cr0x@server:~$ sudo zfs snapshot tank/app@now
cr0x@server:~$ sudo zfs diff tank/app@pre tank/app@now | head

Mistake 3: Assuming “M” means “file contents changed”

Symptôme : La sécurité signale « des milliers de fichiers modifiés » après un scan, mais le comportement applicatif est normal.

Cause : Les changements de métadonnées (ACL, xattrs, timestamps) sont aussi des modifications.

Correction : Validez avec un hash de contenu sur un petit échantillon, ou examinez quels répertoires changent. Vérifiez aussi si quelque chose a changé dans les politiques ACL ou le comportement des attributs étendus.

Mistake 4: Forgetting that deletes might be masked by later recreation

Symptôme : Un incident suggère qu’un fichier a été supprimé, mais le système de fichiers actuel contient un fichier à ce chemin.

Cause : Le fichier a été supprimé puis recréé ultérieurement (peut‑être avec un contenu/propriétaire différent). Selon le timing et le comportement applicatif, le diff peut montrer une modification ou un delete+add plutôt qu’une histoire claire.

Correction : Utilisez la navigation dans les snapshots pour inspecter l’historique d’inode par contenu et métadonnées aux deux points dans le temps. Traitez le chemin comme « changé », pas « même nom implique même fichier ».

Mistake 5: Running huge diffs on production at the worst possible time

Symptôme : Pics de latence pendant zfs diff, plaintes des utilisateurs, graphiques rouges.

Cause : Le parcours metadatael peut concurrencer la charge de travail pour l’ARC et l’IO. Sur certains datasets, c’est effectivement une tempête de lectures.

Correction : Exécutez les diffs en heures creuses, differez des sous‑arbres plus petits (filtrez la sortie), ou effectuez les diffs sur un hôte réplique lorsque possible. Si vous devez diff en production, restez court et ciblé.

Mistake 6: Confusing “no output” with “no change” when permissions block visibility

Symptôme : Vous obtenez des erreurs, une sortie tronquée, ou des résultats vides inattendus alors que vous savez que des changements ont eu lieu.

Cause : Privilèges insuffisants pour traverser les snapshots ou l’interne du dataset, surtout sur des systèmes durcis.

Correction : Exécutez en root (ou avec les permissions ZFS déléguées appropriées). Confirmez que le dataset est accessible et que les répertoires snapshot ne sont pas bloqués par des options de montage ou des cadres de sécurité.

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

Checklist: “What changed since the last known-good deploy?”

  1. Identifiez le dernier snapshot connu bon (souvent pris avant le déploiement).
  2. Prenez un snapshot « now » si le système change encore.
  3. Exécutez zfs diff snapshot‑à‑snapshot.
  4. Résumez les changements par type et par répertoire.
  5. Inspectez une courte liste de chemins à forte valeur : config, binaires, fichiers d’unité de service, et secrets.
  6. Décidez entre rollback, restauration sélective, ou correction forward.
cr0x@server:~$ sudo zfs snapshot tank/app@now
cr0x@server:~$ sudo zfs diff tank/app@predeploy tank/app@now | awk '{print $1}' | sort | uniq -c
cr0x@server:~$ sudo zfs diff tank/app@predeploy tank/app@now | grep -E '^[M+-][[:space:]]+/(etc|usr|opt)/' | head -200

Astuce de décision : Si les changements se concentrent dans les données applicatives et les logs, un rollback pourrait détruire de l’état légitime. Si les changements concernent uniquement binaires/config, le rollback est plus sûr.

Checklist: “Selective restore without a full rollback”

  1. Différenciez le snapshot connu bon vs le snapshot problématique et extrayez les fichiers supprimés/modifiés dans les répertoires critiques.
  2. Vérifiez l’existence et la cohérence des copies de snapshot.
  3. Restaurer avec cp -a (ou rsync -aHAX si disponible) depuis .zfs/snapshot.
  4. Redémarrez le service et vérifiez à nouveau.
  5. Documentez exactement ce que vous avez restauré (parce que la prochaine personne posera la question).
cr0x@server:~$ sudo zfs diff tank/app@good tank/app@bad | grep -E '^[M-][[:space:]]+/(etc/app|usr/local/bin)/' | head -50
cr0x@server:~$ sudo cp -a /app/.zfs/snapshot/good/etc/app/app.conf /app/etc/app/app.conf
cr0x@server:~$ sudo cp -a /app/.zfs/snapshot/good/usr/local/bin/app /app/usr/local/bin/app

Checklist: “Replication sanity check before cutover”

  1. Choisissez un nom de snapshot spécifique qui existe à la fois sur la source et la destination après receive.
  2. Comparez les diffs de snapshots des datasets représentatifs : baseline source vs snapshot cutover source ; puis vérifiez que la destination a le même snapshot et reste quiescente.
  3. Assurez‑vous que rien n’écrit dans les points de montage de la destination avant le cutover.
cr0x@server:~$ zfs list -t snapshot -o name | grep '^tank/app@cutover$'
cr0x@server:~$ sudo zfs diff tank/app@baseline tank/app@cutover | head

FAQ

1) Does zfs diff show file contents?

Non. Il rapporte les chemins modifiés et le type de changement (ajout/suppression/modification/renommage). Pour voir le contenu, parcourez les répertoires de snapshot et utilisez des outils texte, ou calculez des hashs sur les deux versions.

2) Can I diff snapshots across different datasets?

Pas dans le sens de « comparer des arbres arbitraires ». zfs diff est prévu pour les snapshots au sein d’une même lignée de dataset. Si vous avez besoin de comparaisons inter‑datasets, montez les deux snapshots et utilisez des outils externes (avec les mises en garde habituelles de performance et de précision).

3) Why do I see thousands of M entries after a security scan?

Parce que « modifié » inclut les changements de métadonnées, et les scans peuvent toucher atime ou xattrs selon la configuration. Vérifiez atime et si le scanner écrit des attributs étendus ou des tags de quarantaine.

4) Why is zfs diff slow on this one dataset?

Les grands arbres de répertoires avec beaucoup de petits fichiers et du churn sont le pire cas. L’outil doit parcourir et reconstruire les chemins, ce qui est intensif en métadonnées. Si l’ARC est froide, il fera de l’IO réel. Résumez d’abord, filtrez vers des sous‑arbres, et envisagez d’exécuter les diffs sur un hôte réplique.

5) Is a rename always shown as R?

Non. La détection de renommage dépend de la capacité de l’outil à corréler l’identité d’objet et les changements de structure de répertoire. S’il ne peut pas prouver un renommage, vous verrez peut‑être une suppression plus un ajout. Traitez cela comme « quelque chose a été déplacé ou remplacé », puis confirmez en inspectant les contenus des snapshots.

6) Can I use zfs diff to detect ransomware?

C’est un bon signal d’alerte précoce : modifications massives, renommages uniformes, rafales de suppressions soudaines. Mais il ne vous dira pas quel processus l’a fait. Associez‑le à une politique de snapshots immuables, des contrôles d’accès et de la télémétrie hôte.

7) What’s safer in an incident: rollback or selective restore?

Le rollback est rapide et propre quand le dataset contient principalement du code/config et que le système peut tolérer la réversion d’état. La restauration sélective est plus sûre quand le dataset inclut des données en production. Utilisez zfs diff pour décider au lieu de deviner.

8) Does encryption change how diffs work?

Pas conceptuellement. Vous comparez toujours des arbres de snapshots au sein du dataset. Opérationnellement, assurez‑vous d’avoir chargé les clés et les permissions pour traverser le dataset et les snapshots ; sinon vous obtiendrez des erreurs ou une visibilité incomplète.

9) How do I avoid noise when I only care about config drift?

Filtrez la sortie du diff vers les répertoires qui comptent (/etc, définitions de service, config applicative). Envisagez aussi de séparer les datasets : placez logs et caches dans leur propre dataset afin que les diffs sur le « dataset config » restent lisibles.

10) Can I automate zfs diff for audit trails?

Oui, mais attention : des diffs fréquents sur des datasets à fort churn peuvent devenir une charge auto‑infligée et générer du bruit inutile. Résumez et scopez la sortie vers des sous‑arbres significatifs.

Conclusion

zfs diff est l’outil vers lequel vous vous tournez quand la chronologie compte et que vous en avez fini avec les suppositions. Il transforme les snapshots de « on peut revenir en arrière » en « on peut expliquer précisément ce qui s’est passé », ce qui est une capacité différente et plus puissante.

Utilisez‑le comme un opérateur : vérifiez que vous comparez les bons snapshots, résumez avant de fouiller, filtrez agressivement, et confirmez les chemins à fort impact en inspectant le contenu des snapshots. Et quand c’est lent ou bruyant, prenez‑le comme une information sur la conception et le churn de votre dataset — pas comme une insulte personnelle du système de fichiers.

← Précédent
Proxmox « VM verrouillée (sauvegarde/snapshot) » : comment retirer un verrou en toute sécurité
Suivant →
E-mail : Déferlante de spam entrants — survivre à l’attaque sans bloquer les vrais utilisateurs

Laisser un commentaire