ZFS pour les sauvegardes : snapshots et send/receive sans larmes

Cet article vous a aidé ?

Votre sauvegarde n’est pas réelle tant que vous ne l’avez pas restaurée. Et votre réplication ZFS n’est pas réelle tant qu’elle ne survit pas aux problèmes ennuyeux : liens instables, pools pleins, snapshots hors ordre, et cette personne qui a « juste renommé le dataset vite fait ».

ZFS rend l’ingénierie des sauvegardes injustement facile — jusqu’à ce que ce ne soit plus le cas. L’objectif de ce guide est de rester dans la voie « facile » : habitudes claires de snapshot, modèles de send/receive raisonnables, et un playbook de dépannage pour quand la réalité débarque.

Le modèle mental : les snapshots incarnent le temps, send/receive est le transport

Les sauvegardes ZFS sont deux mécanismes rivetés :

  • Les snapshots capturent l’état d’un dataset à un instant donné. Ils sont bon marché (au départ), rapides et cohérents.
  • Send/receive sérialise les deltas de snapshot et les déplace ailleurs, pour que vous puissiez perdre un serveur et garder votre emploi.

Tout le reste — rétention, nommage, réplication incrémentale, tokens de reprise, chiffrement, limites de bande passante — existe pour faire en sorte que ces deux mécanismes se comportent sous pression.

Les snapshots ne sont pas des copies. Ce sont des références.

Un snapshot ZFS est une vue en lecture seule des blocs. Quand vous faites un snapshot d’un dataset, ZFS ne duplique pas les données. Il « pin » les blocs qui font partie de cette vue point-in-time. Au fur et à mesure que le système de fichiers vivant change, de nouveaux blocs sont alloués, et les anciens blocs sont conservés tant qu’un snapshot les référence.

Cela signifie :

  • La création de snapshots est rapide.
  • Conserver beaucoup de snapshots peut coûter cher si votre charge churn beaucoup de données (images VM, bases de données, artifacts CI).
  • La suppression de snapshots peut être lente s’ils référencent beaucoup de blocs uniques.

Send/receive est déterministe — vos politiques ne le sont pas

zfs send produit un flux représentant le contenu du snapshot (full) ou les différences (incremental). zfs receive applique ce flux sur un dataset cible.

La réplication fonctionne quand les deux côtés s’accordent sur la lignée des snapshots. Elle échoue quand vous cassez la lignée en supprimant le mauvais snapshot, en renommant des datasets à la légère, ou en mélangeant des ensembles de snapshots « manuels » et « automatisés » sans règles.

Une vérité sèche : la plupart des incidents de sauvegarde ZFS sont des bugs de politique, pas des bugs ZFS.

Blague n°1 (courte, pertinente) : Les snapshots ZFS sont comme le voyage dans le temps — faciles à créer, difficiles à expliquer quand vous en avez gardé 9 000.

Le nommage des snapshots n’est pas esthétique ; c’est votre plan de contrôle

Décidez tôt d’un schéma de nommage qui encode :

  • qui l’a créé (système vs humain),
  • le but (horaire/journalier/hebdomadaire, pré-upgrade, pré-déploiement),
  • le temps (UTC, toujours).

Si vous n’encoderez pas cela, la rétention et la réplication deviennent un jeu de devinettes. Les jeux de devinettes sont amusants jusqu’à ce que les auditeurs arrivent.

Prise de position : séparez « snapshots de sauvegarde » et « snapshots opérationnels »

Les snapshots opérationnels (pré-upgrade, avant une migration risquée) sont formidables. Mais les mélanger dans votre chaîne de réplication sans règles finira par casser le send incrémental. Utilisez des préfixes distincts.

Exemples de préfixes de snapshot :

  • bk-hh / bk-dd / bk-ww pour les niveaux de sauvegarde planifiés
  • ops- pour les snapshots de workflow humain/automatisation

La règle fondamentale : ne laissez jamais votre cible de sauvegarde « chaude »

Si votre pool de sauvegarde est à 85–95% plein, vous vivez sur du temps emprunté. Les performances et le comportement de ZFS se dégradent à mesure que l’espace libre diminue, et la suppression devient du travail. Vous aurez des sends lents, des receives lents, des suppressions de snapshot lentes, et éventuellement des gaps de réplication qui forcent des envois complets.

Gardez les pools de sauvegarde sous ~70–80% d’utilisation en état stable. Oui, la direction financière demandera pourquoi vous avez « gaspillé » des disques. Expliquez que vous achetez de la prévisibilité, pas des octets bruts.

Une citation (idée paraphrasée)

« L’espoir n’est pas une stratégie. » — idée paraphrasée souvent attribuée aux responsables opérations et ingénieurs fiabilité

Les systèmes de snapshot et de réplication sont là où l’espoir va mourir. Tant mieux. Construisez des systèmes qui n’en ont pas besoin.

Faits intéressants & petite histoire à utiliser au travail

  1. ZFS est né chez Sun Microsystems comme un design « filesystem plus volume manager », pas comme un outil RAID ajouté par-dessus. C’est pour ça que snapshots et réplication semblent natifs.
  2. Copy-on-write n’a pas été inventé par ZFS, mais ZFS a popularisé un modèle bout-en-bout où le filesystem, les checksums et le pooling coopèrent au lieu de se faire concurrence.
  3. ZFS checksum chaque bloc et vérifie à la lecture ; c’est pourquoi ZFS est si adapté aux sauvegardes. La corruption silencieuse est l’ennemi qui ne vous prévient pas.
  4. « RAID-Z » existe parce que les contrôleurs RAID traditionnels mentent (parfois involontairement) sur l’ordre d’écriture et le caching. ZFS voulait un modèle natif en logiciel.
  5. Les flux zfs send sont portables entre de nombreuses plateformes implémentant OpenZFS, d’où la réplication entre Linux et systèmes dérivés d’illumos.
  6. Le receive reprenable (« resume tokens ») a été ajouté parce que les réplications volumineuses meurent sur les réseaux réels. C’est une des évolutions les plus pratiques en ops ZFS.
  7. Les snapshots ne figent pas le temps pour les applications à moins que vous ne coordonniez les écritures. ZFS vous donne des snapshots crash-consistents par défaut ; application-consistent nécessite des étapes supplémentaires.
  8. La dédup existe, mais elle est rarement votre amie pour les cibles de sauvegarde à moins de savoir exactement ce que vous faites. C’est une optimisation gourmande en RAM avec des angles vifs.
  9. La compression est généralement un avantage pour les sauvegardes : moins d’octets sur le réseau, moins d’octets sur disque, souvent plus rapide globalement grâce à moins d’E/S. C’est une des rares fonctionnalités « avoir le gâteau et le manger ».

Concevoir un système de sauvegarde ZFS qui résiste aux humains

Choisissez une topologie de réplication volontairement

Vous vous retrouverez dans l’une de ces configurations :

  • Un-à-un : l’hôte de production réplique vers un hôte de sauvegarde. Simple, courant, efficace.
  • Plusieurs-vers-un : plusieurs hôtes de production répliquent vers une box de sauvegarde centrale. Idéal pour les opérations ; surveillez le nommage des datasets, les quotas et la capacité du pool.
  • Fan-out : répliquer vers une cible locale puis vers une cible hors site. C’est comme ça que vous obtenez des restaurations rapides plus une reprise après sinistre.

Recommandation : faites du many-to-one seulement si vous avez des standards de nommage stricts et des quotas. Sinon, une équipe remplira le pool et tout le monde apprendra ce que signifie « les sauvegardes sont hors-service ».

Décidez ce que vous répliquez : des datasets, pas des pools

Répliquez des datasets (et leurs enfants) avec des propriétés cohérentes. Si vous répliquez un pool entier, vous héritez de chaque erreur de propriété et de chaque expérimentation. Les datasets sont votre contrôle du rayon d’impact.

Utilisez des snapshots récursifs, mais ne soyez pas négligent

La plupart des services réels vivent dans un arbre : pool/app, pool/app/db, pool/app/logs. Si vous voulez un point-in-time cohérent à travers cet arbre, vous snapshottez récursivement avec un nom de snapshot commun. ZFS fournit zfs snapshot -r et les outils de réplication s’appuient sur cela.

Faites de la rétention une politique, pas un effet secondaire

La rétention est là où les systèmes de sauvegarde meurent. Vous allez créer des snapshots indéfiniment, la réplication fonctionnera magnifiquement, puis vous manquerez d’espace et commencerez à supprimer des choses dans le mauvais ordre alors que la production est en feu.

Choisissez une rétention en niveaux qui correspond à votre réalité business :

  • Horaire pour 24–72 heures (récupération rapide « oups »)
  • Journalier pour 14–35 jours (la plupart des incidents détectés tardivement)
  • Hebdomadaire pour 8–12 semaines (problèmes à lent développement)
  • Mensuel pour 6–18 mois (besoins conformité)

Puis implémentez-le avec de l’automatisation qui tagge les snapshots et supprime par tag/préfixe. Ne supprimez pas des snapshots par « plus anciens d’abord » sans comprendre les holds, clones, et dépendances de réplication.

Gardez les datasets de sauvegarde en lecture seule (côté cible)

Sur la cible, mettez les datasets répliqués en lecture seule pour éviter les « correctifs rapides » qui scinderont définitivement votre lignée de snapshots.

Définissez :

  • readonly=on
  • éventuellement canmount=off pour des datasets purement de sauvegarde

Chiffrement : décidez chiffrement au repos, en transit, ou les deux

SSH fournit le chiffrement du transport. Le chiffrement natif ZFS fournit le chiffrement au repos. Votre modèle de menace décide.

  • Si vous envoyez vers un lieu tiers ou un média amovible : le chiffrement natif compte.
  • Si c’est à l’intérieur de votre propre DC sécurisé : SSH peut suffire, mais les auditeurs peuvent ne pas être d’accord.

Avertissement pratique : les datasets chiffrés compliquent la réplication si vous ne planifiez pas le chargement des clés et l’héritage des propriétés. Testez les restaurations. Toujours.

Privilégiez la réplication incrémentale, mais prévoyez des envois complets

Les incrémentales sont efficaces et rapides. Elles dépendent aussi d’un historique de snapshots partagé. Si cet historique est cassé, vous devez soit :

  • recréer un snapshot de base commun (parfois possible), ou
  • faire un envoi complet (parfois douloureux).

Prévoyez des envois complets occasionnels en vous assurant de pouvoir tolérer l’impact bande passante et stockage, ou en conservant des snapshots de base plus longs pour avoir plus d’options.

Tâches pratiques (commandes + sorties + décisions)

Voici les tâches que j’exécute réellement pour construire ou déboguer la réplication de sauvegarde ZFS. Chacune inclut une commande, une sortie typique, et la décision que vous en tirez.

Tâche 1 : Identifier les pools et l’état basique

cr0x@server:~$ zpool status
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 02:11:18 with 0 errors on Sun Dec 22 03:10:42 2025
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz1-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0

errors: No known data errors

Ce que cela signifie : Le pool est en ligne, pas d’erreurs IO, scrub récent propre.

Décision : Si vous voyez DEGRADED, des erreurs de checksum, ou des scrubs échoués, réparez la santé du stockage avant d’ajuster la réplication. La réplication ne peut pas dépasser des disques défaillants.

Tâche 2 : Vérifier la capacité du pool (le tueur silencieux)

cr0x@server:~$ zfs list -o name,used,avail,refer,mountpoint -t filesystem tank
NAME   USED  AVAIL  REFER  MOUNTPOINT
tank  6.12T  1.45T   192K  /tank

Ce que cela signifie : Seulement 1.45T disponible. Selon la taille du pool, cela peut être inconfortablement serré.

Décision : Si le pool est au-dessus de ~80% utilisé, commencez à planifier des changements de rétention ou une expansion de capacité. Attendez-vous à ce que les suppressions de snapshot et les receives ralentissent.

Tâche 3 : Inspecter les datasets et le nombre de snapshots (repérer la rétention folle)

cr0x@server:~$ zfs list -t all -r tank/prod -o name,used,refer,creation | head
NAME                         USED  REFER  CREATION
tank/prod                    820G   96K   Sun Dec  1 10:02 2025
tank/prod@bk-dd-2025-12-01   2.1G   96K   Sun Dec  1 23:00 2025
tank/prod@bk-dd-2025-12-02   2.4G   96K   Mon Dec  2 23:00 2025
tank/prod@bk-dd-2025-12-03   1.9G   96K   Tue Dec  3 23:00 2025

Ce que cela signifie : Vous voyez les snapshots et leur impact d’espace (USED). USED est l’espace unique au snapshot par rapport au dataset vivant.

Décision : Si USED du snapshot est grand et en croissance, votre charge churn beaucoup de données. Serrez la rétention ou séparez les datasets à fort churn (comme les images VM) dans des arbres séparés.

Tâche 4 : Créer des snapshots récursifs cohérents avec un seul nom

cr0x@server:~$ zfs snapshot -r tank/prod@bk-hh-2025-12-25T0200Z

Ce que cela signifie : Chaque dataset enfant sous tank/prod reçoit un snapshot avec exactement le même nom, permettant une réplication cohérente.

Décision : Si vous ne pouvez pas snapshotter récursivement parce que votre arbre est désordonné, c’est un problème structurel. Corrigez la disposition des datasets ; ne « snapshottez que ce qui compte » en espérant que ça ira.

Tâche 5 : Vérifier l’existence des snapshots sur tout l’arbre

cr0x@server:~$ zfs list -t snapshot -r tank/prod -o name | grep bk-hh-2025-12-25T0200Z | head
tank/prod@bk-hh-2025-12-25T0200Z
tank/prod/db@bk-hh-2025-12-25T0200Z
tank/prod/web@bk-hh-2025-12-25T0200Z
tank/prod/logs@bk-hh-2025-12-25T0200Z

Ce que cela signifie : Le snapshot est présent là où vous l’attendiez.

Décision : Si un enfant manque le snapshot, la réplication avec -R ne se comportera pas comme prévu. Corrigez l’automatisation de création des snapshots.

Tâche 6 : Faire une première réplication complète (avec propriétés) pour initialiser la sauvegarde

cr0x@server:~$ zfs send -R tank/prod@bk-dd-2025-12-25 | ssh backup1 'zfs receive -u backup/prod'

Ce que cela signifie : -R inclut les datasets descendants et les propriétés ; -u évite le montage au receive.

Décision : Utilisez -u pour les cibles de sauvegarde, puis montez explicitement seulement lors de la restauration. Si le receive échoue, vérifiez d’abord l’existence des datasets, l’espace du pool et les permissions.

Tâche 7 : Réplication incrémentale entre deux snapshots

cr0x@server:~$ zfs send -R -i tank/prod@bk-dd-2025-12-24 tank/prod@bk-dd-2025-12-25 | ssh backup1 'zfs receive -u backup/prod'

Ce que cela signifie : N’envoyer que les changements entre le snapshot du 24 et celui du 25.

Décision : Si cela échoue avec « incremental source does not exist », votre lignée de snapshots a divergé. Ne maquillez pas le problème — identifiez ce qui a été supprimé/renommé et pourquoi.

Tâche 8 : Utiliser des « replication streams » avec rollback forcé (avec prudence)

cr0x@server:~$ zfs send -R -i tank/prod@bk-dd-2025-12-24 tank/prod@bk-dd-2025-12-25 | ssh backup1 'zfs receive -u -F backup/prod'

Ce que cela signifie : -F force le receiver à revenir au snapshot le plus récent qui correspond au flux entrant, en abandonnant les changements locaux plus récents.

Décision : Utilisez -F uniquement sur des cibles de sauvegarde si vous imposez readonly=on et comprenez que vous jetez toute modification locale (ce que vous ne devriez pas avoir).

Tâche 9 : Vérifier et définir la lecture seule sur les datasets répliqués

cr0x@server:~$ ssh backup1 'zfs get -H -o name,property,value readonly backup/prod'
backup/prod	readonly	off

Ce que cela signifie : Le dataset cible est modifiable. C’est une invitation aux problèmes.

Décision : Activez-le :

cr0x@server:~$ ssh backup1 'zfs set readonly=on backup/prod'

Tâche 10 : Diagnostiquer « pourquoi mon send est lent » (CPU vs disque vs réseau)

cr0x@server:~$ zfs send -nPv tank/prod@bk-dd-2025-12-25
full send of tank/prod@bk-dd-2025-12-25 estimated size is 812G
size	812G

Ce que cela signifie : Exécution à blanc (-n) avec progression/verbose donne une estimation. Si vous poussez 800G sur un lien 1Gb, ça va être une longue après-midi.

Décision : Si la taille estimée est grande de façon inattendue, vérifiez si vous avez accidentellement perdu le snapshot base incrémental ou si vous envoyez un dataset avec un churn massif.

Tâche 11 : Surveiller la progression du receive et détecter les blocages

cr0x@server:~$ ssh backup1 'zpool iostat -v tank 5 2'
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        6.12T  1.45T     12    205   8.1M  112M
  raidz1-0                  6.12T  1.45T     12    205   8.1M  112M
    sda                         -      -      4     68   2.7M  38.0M
    sdb                         -      -      3     69   2.4M  37.1M
    sdc                         -      -      5     68   3.0M  36.9M
--------------------------  -----  -----  -----  -----  -----  -----

Ce que cela signifie : Le receive écrit ~112MB/s sur le pool. C’est sain pour beaucoup d’ensembles de disques HDD.

Décision : Si les écritures tombent presque à zéro mais que le send est toujours en cours, vérifiez le réseau, la backpressure SSH, et si le pool est proche du plein ou fortement fragmenté.

Tâche 12 : Gérer un receive interrompu en utilisant les resume tokens

cr0x@server:~$ ssh backup1 'zfs get -H -o name,property,value receive_resume_token backup/prod'
backup/prod	receive_resume_token	1-fd1b6a8c9d-118-789c...

Ce que cela signifie : Le receive a été interrompu et a laissé un resume token.

Décision : Reprenez au lieu de recommencer :

cr0x@server:~$ zfs send -t 1-fd1b6a8c9d-118-789c... | ssh backup1 'zfs receive -u backup/prod'

Tâche 13 : Confirmer la lignée des snapshots source et cible (éviter les incrémentales cassées)

cr0x@server:~$ zfs list -t snapshot -o name -s creation -r tank/prod | tail -5
tank/prod@bk-dd-2025-12-21
tank/prod@bk-dd-2025-12-22
tank/prod@bk-dd-2025-12-23
tank/prod@bk-dd-2025-12-24
tank/prod@bk-dd-2025-12-25
cr0x@server:~$ ssh backup1 'zfs list -t snapshot -o name -s creation -r backup/prod | tail -5'
backup/prod@bk-dd-2025-12-21
backup/prod@bk-dd-2025-12-22
backup/prod@bk-dd-2025-12-23
backup/prod@bk-dd-2025-12-24
backup/prod@bk-dd-2025-12-25

Ce que cela signifie : La cible a les mêmes snapshots. Les incrémentales devraient fonctionner.

Décision : Si la cible manque un snapshot intermédiaire, arrêtez et corrigez la chaîne. Ne continuez pas à « incrémenter » en espérant ; vous vous condamnez.

Tâche 14 : Vérifier les propriétés du dataset qui affectent les sauvegardes (compression, recordsize, atime)

cr0x@server:~$ zfs get -o name,property,value -s local,default compression,recordsize,atime tank/prod
NAME       PROPERTY    VALUE
tank/prod  compression zstd
tank/prod  recordsize  128K
tank/prod  atime       off

Ce que cela signifie : Valeurs raisonnables pour beaucoup de charges serveur : compression activée, atime désactivé.

Décision : Si la compression est désactivée, envisagez de l’activer avant de monter la réplication. Si recordsize est fortement inadapté à la charge (ex. 1M pour des DB), vous pouvez amplifier le churn et les deltas de sauvegarde.

Tâche 15 : Valider que vous pouvez restaurer (monter un snapshot reçu en lecture seule)

cr0x@server:~$ ssh backup1 'zfs clone backup/prod@bk-dd-2025-12-25 backup/restore-test && zfs set readonly=on backup/restore-test && zfs mount backup/restore-test && ls -la /backup/restore-test | head'
total 12
drwxr-xr-x  3 root root  3 Dec 25 02:10 .
drwxr-xr-x  5 root root  5 Dec 25 02:10 ..
drwx------ 12 root root 12 Dec 25 02:00 data

Ce que cela signifie : Vous pouvez accéder au contenu restauré. Le clonage est rapide car c’est CoW.

Décision : Si les tests de restauration échouent, vos sauvegardes sont décoratives. Corrigez les procédures de restauration et les contrôles d’accès maintenant, pas en incident.

Tâche 16 : Trouver les gros consommateurs d’espace de snapshot (ce qui garde l’espace épinglé)

cr0x@server:~$ zfs list -t snapshot -o name,used -s used -r tank/prod | tail -5
tank/prod@bk-dd-2025-11-29  48.2G
tank/prod@bk-dd-2025-11-30  51.7G
tank/prod@bk-dd-2025-12-01  55.3G
tank/prod@bk-dd-2025-12-02  62.9G
tank/prod@bk-dd-2025-12-03  73.4G

Ce que cela signifie : Certains jours épinglent beaucoup plus de données uniques. Cela correspond souvent à des événements de charge (reindex, mise à jour d’un template VM, rotation de logs ratée).

Décision : Si un dataset spécifique est toujours en cause, isolez-le et appliquez-lui une rétention différente. Une taille unique ne convient à personne.

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

1) Incident causé par une mauvaise hypothèse : « Les snapshots sont essentiellement gratuits, non ? »

Dans une entreprise de taille moyenne, une équipe utilisait ZFS sur un hôte de stockage hébergeant des disques VM. Ils étaient fiers de leur snapshotting : snapshots horaires pendant deux semaines, journaliers pendant trois mois. Personne n’a demandé combien churnait la donnée ; ils ont juste supposé que CoW = magie.

La charge était surtout des VM Windows avec cycles de patch fréquents, plus un système CI qui reconstruisait souvent des images. Le churn était violent. Les snapshots ne copiaient pas les données, mais ils ETPINNAIENT les anciens blocs à un rythme qui faisait que le pool avait l’air de se bouffer lui-même.

Le premier symptôme fut subtil : la réplication a commencé à prendre plus de temps. Ensuite la suppression des snapshots a commencé à prendre des heures. Puis un receive a échoué parce que le pool cible n’avait pas assez d’espace contigu pour les allocations metadata. Le pool de production a atteint un niveau d’utilisation où la latence est devenue une caractéristique.

Ils ont essayé de réparer en supprimant des snapshots agressivement — les plus anciens d’abord — pendant les heures ouvrées. Ça a empiré les I/O parce que la suppression de snapshot est du travail réel. Soudain, les VM étaient lentes, le helpdesk était mécontent, et l’équipe stockage était en conférence avec cinq managers demandant si « on peut juste rebooter le SAN ».

La solution n’était pas brillante. Ils ont réduit la fréquence des snapshots pour les disques VM, séparé les datasets à fort churn (artifacts CI) dans leur propre arbre avec une rétention plus courte, et imposé des cibles d’espace libre sur les pools. Ils ont aussi programmé les suppressions de snapshots en dehors des heures de pointe et suivi le USED des snapshots. L’hypothèse a changé : les snapshots sont bon marché à créer, pas à conserver.

2) Optimisation qui a mal tourné : « Activons dedup sur la cible de sauvegarde »

Une autre organisation disposait d’un grand serveur de sauvegarde et de nombreux datasets similaires. Quelqu’un s’est enthousiasmé pour la déduplication. En théorie, activer dedup sur la cible de sauvegarde pouvait réduire dramatiquement la consommation parce que « tellement de fichiers sont identiques entre serveurs ».

Ils ont activé dedup=on sur les datasets de sauvegarde juste avant d’intégrer une nouvelle flotte. La réplication « fonctionnait » encore, et les graphiques initiaux de stockage étaient formidables. Tout le monde souriait. Finance souriait aussi, ce qui est souvent dangereux.

En quelques semaines, le système de sauvegarde est devenu imprévisible. Les receives étaient en pics. La latence explosait pendant les fortes ingestes. Parfois, la suppression de snapshot rampait. La table dedup voulait de la RAM, puis plus de RAM, puis a commencé à utiliser le disque d’une manière qui empirait tout. Ils avaient construit un système où le chemin lent était devenu le chemin normal.

Le retour de bâton fut opérationnel : les restaurations étaient plus lentes et moins fiables, ce qui annule le but des sauvegardes. Ils ont fini par migrer les nouveaux datasets entrants vers des arbres sans dedup, planifier une évacuation soignée des datasets dédupliqués, et définir des SLOs de performance stricts pour les restaurations. Leçon : la dedup n’est pas un repas gratuit ; c’est une hypothèque.

3) Pratique ennuyeuse mais correcte qui a sauvé la mise : « Drills de restauration mensuels »

Une entreprise réglementée faisait quelque chose presque offensivement peu sexy : une fois par mois, ils réalisaient un drill de restauration. Pas un exercice sur table. Une vraie restauration vers un environnement de test. Ils validaient le contenu du système de fichiers, les permissions, et quelques vérifications au niveau applicatif.

C’était bureaucratique. Ça prenait du temps. Les ingénieurs levaient les yeux au ciel. Mais l’équipe l’avait automatisé suffisamment pour que ce ne soit pas un projet héros. Ils clonaient un snapshot reçu, le montaient en lecture seule, exécutaient des vérifications, puis détruisaient le clone.

Un mois, le drill a échoué. Les données se sont restaurées, mais la vérification applicative a signalé une incohérence. Il s’est avéré que les snapshots de la base de données étaient crash-consistents mais pas application-consistents. Ils ne coordonnaient pas avec le mode sauvegarde de la BD. Personne n’avait remarqué car « les snapshots ZFS sont cohérents ». Cohérents, oui. Application-consistents, non.

Parce que c’était un drill, c’était un ticket, pas un incident. Ils ont mis à jour leur processus de snapshot : utiliser les mécanismes natifs DB (ou fsfreeze/backup mode coordonné) avant de prendre les snapshots. Quand ils ont eu plus tard une vraie corruption en production, la restauration a fonctionné proprement. La pratique ennuyeuse a payé en un jour, ce qui est un excellent ROI si vous aimez dormir.

Blague n°2 (courte, pertinente) : Les drills de sauvegarde sont comme le fil dentaire — agaçants jusqu’à ce que vous les sautiez et payiez en sang.

Playbook de diagnostic rapide : trouver le goulot d’étranglement vite

Quand la réplication est lente ou échoue, vous voulez du signal vite. Pas trois heures d’archéologie dans les logs.

Premier : est-ce un problème de santé/capacité du pool ?

  • Pool source : zpool status propre ? Des erreurs de checksum ? Historique de scrub sain ?
  • Pool cible : assez d’espace libre ? Pas proche du plein ? Un resilver en cours ?

Si un pool est dégradé ou plein, cessez de blâmer le réseau. Le stockage collecte toujours sa dette.

Deuxième : le flux d’envoi a-t-il la taille que vous pensez ?

  • Exécutez zfs send -nPv ... pour estimer la taille du flux.
  • Si la taille incrémentale est énorme, vous avez probablement perdu le snapshot base incrémental ou votre charge churn fortement.

Troisième : le goulot est-il le réseau, le CPU ou le disque ?

  • Réseau : le lien est-il saturé ? Y a-t-il des retransmissions ? (Utilisez vos outils réseau habituels ; sur beaucoup de systèmes vous pouvez inspecter les erreurs d’interface et le débit.)
  • Disque : zpool iostat -v 5 montre le débit et les opérations en temps réel.
  • CPU : la compression/le chiffrement peuvent être limités par le CPU. Si le send compresse beaucoup ou si les ciphers SSH sont coûteux, vous le verrez.

Quatrième : êtes-vous bloqué sur une suppression de snapshot ou des holds ?

  • La suppression de snapshot peut bloquer la récupération d’espace et faire échouer des receives.
  • Les holds peuvent empêcher la suppression de snapshots et casser silencieusement la rétention.

Cinquième : un receive interrompu a-t-il laissé un resume token ?

  • Vérifiez receive_resume_token sur le dataset cible.
  • Reprenez avec zfs send -t au lieu de tout renvoyer.

Le diagnostic rapide consiste à éliminer des catégories. Ne peaufinez pas la compression quand le pool est à 97% plein. N’ajoutez pas de disques quand le snapshot base a été supprimé.

Erreurs courantes : symptômes → cause racine → correction

1) Envoi incrémental échoue : « incremental source … does not exist »

Symptômes : Votre script fonctionnait hier. Aujourd’hui il plante pendant zfs send -i.

Cause racine : Le snapshot « from » a été supprimé sur la source ou la cible, ou la lignée du dataset a divergé (modifications locales sur la cible, ou réception dans un chemin de dataset différent).

Correction : Comparez les listes de snapshots des deux côtés ; rétablissez un snapshot de base commun. Si vous ne pouvez pas, faites un envoi complet (planifiez l’impact), puis resserrez les règles de rétention pour préserver les snapshots base jusqu’à réplication confirmée.

2) Les receives ralentissent soudainement jusqu’à une lenteur extrême

Symptômes : Le débit de réplication chute ; zfs receive écrit à peine ; la latence IO augmente.

Cause racine : Pool cible trop plein, forte fragmentation, resilver/scrub en cours, ou pression sur la table dedup. Parfois ce sont de petites tailles de record provoquant du churn metadata.

Correction : Vérifiez l’utilisation du pool et les scans en cours. Arrêtez l’hémorragie : libérez de l’espace, ajoutez de la capacité, ou réduisez le débit d’ingestion. Si vous avez activé dedup, reconsidérez et planifiez une migration.

3) « cannot receive: destination has snapshots » / « destination is busy »

Symptômes : Le receive se plaint de snapshots existants ou de snapshots non assortis sur la cible.

Cause racine : Quelqu’un a créé ou supprimé des snapshots sur la cible, ou vous recevez dans le mauvais chemin de dataset.

Correction : Imposer readonly=on et restreindre qui peut administrer le pool de sauvegarde. Utilisez zfs receive -F seulement si vous êtes sûr de pouvoir revenir en arrière en toute sécurité.

4) Vous supprimez des snapshots, mais l’espace ne revient pas

Symptômes : Vous détruisez des snapshots, mais zfs list montre peu d’espace libéré.

Cause racine : Les données sont référencées par des clones, des holds, ou d’autres snapshots ; possible aussi que le dataset vivant soit le principal consommateur d’espace.

Correction : Cherchez les clones et les holds. Supprimez les holds si approprié. Identifiez les clones et promouvez-les ou détruisez-les après validation qu’ils ne sont pas nécessaires.

5) Le dataset de sauvegarde contient des propriétés ou des comportements de montage « inattendus »

Symptômes : Les datasets reçus se montent automatiquement, ou des propriétés comme compression ne correspondent pas aux attentes.

Cause racine : Utilisation de zfs send/receive avec flags de réplication et propriétés héritées sans politique côté cible.

Correction : Recevez avec -u et définissez des politiques cibles explicitement : readonly=on, canmount=off, points de montage contrôlés. Décidez de conserver ou d’écraser les propriétés.

6) La réplication chiffrée échoue ou produit des restaurations inutilisables

Symptômes : Le receive se termine, mais le dataset ne monte pas ; les clés sont indisponibles ; les restaurations bloquent.

Cause racine : La gestion des clés n’a pas été conçue. La réplication a déplacé des datasets chiffrés sans assurer le chargement des clés sur l’environnement de restauration.

Correction : Documentez et testez le chargement des clés. Assurez-vous que votre runbook de restauration inclut la récupération et la vérification des clés. Exécutez des drills de restauration qui incluent le chiffrement.

7) « Ça a répliqué, mais la restauration applicative est cassée »

Symptômes : Les fichiers sont là ; l’application signale corruption/incohérence.

Cause racine : Des snapshots crash-consistents ont été utilisés pour des apps qui exigent des snapshots coordonnés (bases de données, certains systèmes de messagerie, etc.).

Correction : Utilisez des hooks applicatifs : mode backup DB, freezer de système de fichiers où approprié, ou répliquez des sauvegardes logiques dans des datasets ZFS.

Checklists / plan étape par étape

Étape par étape : configurer une réplication propre depuis zéro

  1. Créez la disposition des datasets source pour que « la chose que vous restaurez » soit un arbre de datasets, pas des répertoires aléatoires.
  2. Choisissez le nommage des snapshots (UTC, préfixe de niveau) et notez-le. Les humains suivront le chemin que vous tracez.
  3. Activez des propriétés sensées sur la source : compression=zstd pour la plupart des charges ; atime=off.
  4. Prenez un snapshot récursif initial avec un nom de base que vous conserverez un moment.
  5. Initialisez la réplication avec un zfs send -R complet vers la cible de sauvegarde avec zfs receive -u.
  6. Verrouillez la cible de sauvegarde : définissez readonly=on, envisagez canmount=off, restreignez l’accès admin.
  7. Automatisez la réplication incrémentale en utilisant le même schéma de nommage et des snapshots « from »/« to » explicites.
  8. Mettez en œuvre la rétention par niveaux ; supprimez les snapshots par préfixe et âge.
  9. Ajoutez la surveillance : capacité des pools, retard de réplication (dernier snapshot répliqué), état des scrubs, et échecs de receive.
  10. Exécutez des drills de restauration mensuels (au moins) : clonez, montez, validez, détruisez.

Checklist : avant d’activer des fonctionnalités « intelligentes »

  • Dedup : avez-vous le budget RAM et avez-vous testé les pires cas d’ingestion et de restauration ?
  • Chiffrement natif : avez-vous la gestion des clés et les procédures de restauration testées ?
  • Modifications massives de recordsize : comprenez-vous l’impact sur le churn et la taille incrémentale ?
  • Changements de compression : avez-vous benchmarké la marge CPU et vérifié la vitesse de réplication ?
  • Multiples cibles de réplication : avez-vous des conventions de nommage et une application stricte des quotas ?

Checklist : restaurer sous pression

  • Identifiez le dataset et le snapshot temporel. Ne devinez pas ; vérifiez la liste des snapshots.
  • Clonez le snapshot vers un dataset de restauration (rapide, risque minimal).
  • Montez en lecture seule d’abord ; validez le contenu et la propriété.
  • Pour les applications : exécutez les étapes de récupération/validation spécifiques à l’app.
  • Ensuite seulement copiez les données de retour ou promouvez/renommez selon besoin.
  • Documentez quel snapshot a été utilisé et pourquoi. Votre futur vous posera la question.

FAQ

1) Les snapshots ZFS sont-ils des « sauvegardes » ?

Non. Les snapshots sur le même pool protègent contre les suppressions accidentelles et les mauvais déploiements. Ils ne protègent pas contre la perte du pool, l’incendie, le vol, ou les erreurs d’administration. Répliquez-les ailleurs.

2) Dois-je snapshotter horaire partout ?

Seulement si la charge et la rétention en valent la peine. Les datasets à fort churn vous pénaliseront. Commencez par des horaires pour des fenêtres courtes et des journaliers pour des durées plus longues, puis ajustez selon la croissance de USED des snapshots.

3) Quelle est la différence entre snapshot crash-consistent et application-consistent ?

Crash-consistent ressemble à couper l’alimentation : le système de fichiers est cohérent, mais les applications peuvent nécessiter une récupération. Application-consistent signifie que l’application a coopéré (flush, freeze, mode backup), donc les restaurations sont plus propres.

4) Quand devrais-je utiliser zfs receive -F ?

Sur une cible de sauvegarde destinée à être un miroir exact, et uniquement quand vous êtes à l’aise de remettre la cible dans l’état du flux entrant. Si votre cible est modifiable ou utilisée pour d’autres buts, -F est une arme dangereuse.

5) Pourquoi la suppression de snapshots prend-elle parfois une éternité ?

Parce que ZFS doit libérer les blocs référencés et mettre à jour les metadata. Si le snapshot référence beaucoup de blocs uniques (fort churn) ou si le pool est sous pression, la suppression peut être lente. Planifiez les suppressions hors heures de pointe et évitez de faire tourner les pools de sauvegarde à chaud.

6) Puis-je répliquer des datasets chiffrés en toute sécurité ?

Oui, mais « en toute sécurité » inclut la gestion des clés et des drills de restauration. Si les clés ne sont pas disponibles lors d’un incident, vos sauvegardes sont des presse-papier chiffrés.

7) La réplication remplace-t-elle les logiciels de sauvegarde traditionnels ?

Parfois. La réplication est excellente pour des restaurations rapides et le DR de l’état du système de fichiers. Mais vous pourriez encore avoir besoin d’outils séparés pour les archives long terme, les restaurations cross-plateforme, et les sauvegardes applicatives-aware. Ne forcez pas un outil unique pour toute la stratégie.

8) Comment éviter des chaînes incrémentales cassées ?

Utilisez des noms de snapshot cohérents, ne supprimez pas manuellement les snapshots base de réplication tant que vous n’avez pas confirmé leur réplication, gardez les datasets cibles en lecture seule, et surveillez le « dernier snapshot répliqué » par dataset.

9) Dois-je répliquer tout le pool avec -R ?

Répliquez l’arbre de datasets que vous avez réellement besoin de restaurer. La réplication de pool entier a tendance à devenir un dépotoir incontrôlé avec des propriétés et des expérimentations que vous ne vouliez pas conserver.

10) Quelle est la façon la plus sûre de tester les restaurations sans impacter la production ?

Sur l’hôte de sauvegarde, clonez un snapshot reçu dans un dataset temporaire, montez-le en lecture seule, validez, puis détruisez le clone. Les clones sont bon marché et réversibles.

Conclusion : prochaines étapes qui font vraiment la différence

Si vous voulez « sans larmes », arrêtez de courir après l’ingéniosité et commencez à imposer la correction ennuyeuse :

  1. Standardisez le nommage des snapshots (préfixe + timestamp UTC) et séparez snapshots backup vs opérationnels.
  2. Initialisez la réplication proprement avec un zfs send -R complet, puis n’envoyez des incrémentales que quand la lignée des snapshots est vérifiée.
  3. Verrouillez la cible de sauvegarde : readonly=on, recevez avec -u, restreignez l’accès admin.
  4. Surveillez la capacité des pools et gardez-la en dessous de la zone dangereuse ; ne faites pas tourner le stockage de sauvegarde à chaud.
  5. Programmez des drills de restauration et traitez les échecs comme des bugs produit, pas des fautes personnelles.

ZFS vous donne des primitives puissantes. Votre travail est de les orienter dans la bonne direction — loin de votre pied, et vers une restauration qui marche du premier coup.

← Précédent
MySQL vs PostgreSQL : pool de connexions — qui en a besoin le plus tôt sur un VPS
Suivant →
Port 25 bloqué : comment envoyer des e-mails sans astuces douteuses

Laisser un commentaire