Dédup ZFS : la case à cocher qui grignote la RAM et ruine les week-ends

Cet article vous a aidé ?

La déduplication ZFS est l’équivalent stockage du bouton « argent gratuit ». Elle semble inoffensive, fait de beaux démos, et a littéralement ruiné plus d’un week-end d’astreinte. La promesse est séduisante : stocker les blocs identiques une seule fois, les référencer plusieurs fois, récupérer beaucoup d’espace et passer pour un magicien lors de la saison des budgets.

La réalité ressemble plutôt à ceci : vous échangez du disque contre de la mémoire, et si vous ne payez pas suffisamment cette facture mémoire, ZFS prélève des intérêts sous forme de latence, de thrash et de comportements de pool inquiétants. La dédup peut être un outil valable—mais pas le réglage par défaut. Cet article explique comment l’utiliser en production sans se mentir.

Table des matières

Ce que fait réellement la déduplication (et ce qu’elle ne fait pas)

La déduplication ZFS est une déduplication au niveau du bloc. Lorsque vous activez dedup=on pour un dataset, ZFS calcule le hash de chaque bloc au moment de l’écriture. Si un bloc avec ce hash existe déjà dans le pool, ZFS évite d’écrire une seconde copie et crée une référence supplémentaire vers le bloc existant.

Ce n’est pas une déduplication au niveau fichier, ni un « trouver les fichiers ISO identiques », ni un travail en arrière-plan que vous pouvez suspendre quand la base de données devient irritable. La dédup est inline : elle se produit sur le chemin d’écriture. Cela signifie que chaque écriture inclut désormais du travail supplémentaire : calculer la somme de contrôle, la rechercher, et éventuellement mettre à jour les métadonnées de dédup. Vous ne pouvez pas « déduper plus tard » à moins de réécrire les données ultérieurement—nous reviendrons sur cet inconvénient désagréable.

Important aussi : la dédup n’est pas la compression. La compression réduit les blocs en les encodeant plus efficacement. La dédup évite de stocker des blocs dupliqués. Elles peuvent se compléter, mais la compression est généralement le premier levier à actionner car elle est peu coûteuse, prévisible et améliore souvent l’I/O en réduisant les octets sur disque.

Une phrase à coller sur un autocollant : La déduplication ZFS est un problème de métadonnées déguisé en fonctionnalité de capacité.

Blague #1 : La dédup, c’est comme acheter un destructeur de papier pour gagner de la place dans votre armoire—techniquement correct, jusqu’à ce que vous réalisiez qu’il fonctionne sur électricité et que vous n’avez qu’une seule prise.

Pourquoi la dédup consomme de la RAM : le DDT et la taxe inévitable

Le cœur battant de la dédup est le DDT : la table de déduplication (Deduplication Table). Conceptuellement, c’est un mappage de checksum de bloc → pointeur(s) de bloc physique et comptes de références. À chaque écriture sur un dataset avec dedup, ZFS doit déterminer si un bloc identique existe déjà. Cela nécessite une recherche dans le DDT.

Si le DDT est chaud en mémoire, la dédup est juste « un certain overhead ». Si le DDT n’est pas en mémoire, la dédup devient « des lectures aléatoires de métadonnées pendant que vous essayez d’écrire des données », ce qui transforme un système de stockage respectable en une performance artistique interprétative.

ARC, L2ARC, et pourquoi « ajouter un SSD » n’est pas un plan

ZFS utilise l’ARC (Adaptive Replacement Cache) en RAM pour le cache. La dédup veut que le DDT soit dans l’ARC car il y est constamment accédé. Quand l’ARC est suffisamment grand, tout va bien. Quand l’ARC ne l’est pas, ZFS doit récupérer des entrées du DDT depuis le disque. Ce sont de petites lectures dispersées, pires cas pour des disques rotatifs et toujours problématiques sur des SSD en charge.

Certaines environnements essaient de « réparer » cela avec L2ARC (cache secondaire sur SSD). L2ARC peut aider, mais ce n’est pas magique. L2ARC est plus lent que la RAM et a son propre overhead de métadonnées. Si vous manquez déjà de mémoire, ajouter L2ARC peut empirer la situation en consommant plus de RAM pour les entêtes L2ARC tout en n’offrant pas la latence de la RAM.

Special vdevs : mieux, mais pas gratuit

Sur OpenZFS récent, un special vdev peut stocker les métadonnées (et éventuellement les petits blocs) sur des périphériques rapides. Si votre DDT et autres métadonnées résident sur un special vdev NVMe en miroir, les recherches dedup sont beaucoup moins pénibles. C’est la première approche qui ressemble à une vraie architecture plutôt qu’à un mécanisme de contournement. Mais elle a un inconvénient net : si vous perdez le special vdev, vous pouvez perdre le pool. Traitez-le comme votre vdev le plus sacré, parce que c’est le cas.

Pourquoi existe la règle empirique « RAM par To »

Vous entendrez des règles comme « 1–5 Go de RAM par To de données dédupliquées ». La vraie réponse dépend du recordsize, de la charge de travail, du degré de duplication des données et de la taille du DDT. Mais la croyance existe car le mode d’échec est constant : une fois que le DDT ne tient plus en mémoire, la latence augmente et le débit chute en piqué.

Et il y a un second piège : vous n’avez pas besoin que l’ARC tienne le pool, vous avez besoin que l’ARC tienne le working set du DDT. Si votre working set d’entrées DDT est grand (fort turnover, beaucoup de blocs uniques), vous pouvez avoir beaucoup de RAM et quand même un mauvais comportement.

Faits et contexte historique (ce que l’on oublie)

La dédup n’est pas devenue « controversée » parce qu’elle est cassée. Elle est devenue controversée parce qu’il est facile de l’activer et difficile de l’exploiter en toute sécurité. Quelques points de contexte à connaître :

  1. La déduplication ZFS existe depuis longtemps, et les premières implémentations se sont forgées une réputation de consommation mémoire punitive parce que les systèmes d’alors étaient plus petits et que les couches métadonnées sur SSD étaient rares.
  2. La dédup est par dataset, pas par pool, mais le DDT vit au niveau du pool. Un seul dataset avec dedup activé peut imposer un overhead sur le comportement de l’ensemble du pool.
  3. Vous ne pouvez pas « désactiver » la dédup rétroactivement. Mettre dedup=off n’affecte que les nouvelles écritures. Les blocs existants restent dédupliqués jusqu’à réécriture.
  4. La dédup interagit avec les snapshots : les blocs dédupliqués peuvent être référencés à travers snapshots et clones, augmentant les comptes de références et complexifiant la comptabilité d’espace.
  5. La dédup ralentit certains modes de panne : resilver, scrub et certaines opérations de réparation peuvent durer plus longtemps car plus de métadonnées doivent être parcourues et référencées.
  6. La compression offre souvent la majeure partie du bénéfice avec moins de risques, en particulier sur fichiers de log, JSON, images VM et pages de base de données qui ne sont pas identiques mais compressibles.
  7. Les images golden des VM sont l’exemple-type de gains en dédup, mais les piles modernes de VM utilisent souvent le clonage/linked clones ou des couches d’images qui évitent déjà la duplication.
  8. La croissance du DDT peut vous surprendre lorsque le recordsize est petit ou que les workloads génèrent beaucoup de blocs uniques (bases de données, données chiffrées, blobs déjà compressés).
  9. Les datasets chiffrés réduisent les opportunités de dédup : le chiffrement tend à randomiser les blocs, éliminant les motifs de blocs identiques sauf si la dédup se produit avant le chiffrement dans le chemin de données (ce n’est souvent pas le cas).

Quand la dédup fonctionne (rare, réel et spécifique)

La dédup peut être l’outil adéquat quand toutes les conditions suivantes sont réunies :

  • Vos données sont vraiment identiques au niveau bloc à travers de nombreux fichiers ou images. Pas « similaires », pas « compressibles », mais des blocs identiques à la taille de record que vous utilisez.
  • Votre working set est stable, ou du moins prévisible. La dédup déteste le turnover élevé où le working set du DDT change constamment.
  • Vous pouvez payer la facture métadonnées : assez de RAM et/ou une couche métadonnées rapide (special vdev) pour éviter que les recherches DDT ne deviennent des accès disque.
  • Vous avez testé avec des données proches de la production. Les tests synthétiques mentent ; la dédup est particulièrement sensible à la façon dont les données sont réellement disposées.

Les environnements où j’ai vu la dédup réussir sans drame ressemblent souvent à :

1) Cibles de sauvegarde avec lots de fulls répétés (avec réserves)

Si vous avez de nombreuses sauvegardes complètes qui contiennent des blocs identiques (par exemple, une ferme de machines similaires) et que vous écrivez de larges flux séquentiels, la dédup peut apporter d’importantes économies d’espace. Mais si votre logiciel de sauvegarde déduplique déjà au niveau applicatif, la dédup ZFS est redondante et parfois nocive. De plus, les écritures de sauvegarde sont souvent en rafales—le DDT doit donc survivre au pic d’ingestion, pas seulement à la moyenne.

2) VDI / templates VM (seulement si vous n’utilisez pas déjà des clones)

Des centaines de postes ou VM créés à partir du même template peuvent partager beaucoup de blocs identiques. Mais beaucoup de plateformes utilisent déjà le clonage copy-on-write qui évite la duplication sans la dédup ZFS. Si vous êtes déjà sur ZFS, les clones et snapshots ZFS peuvent apporter la majeure partie du gain avec moins de risque.

3) Datasets majoritairement en lecture avec artefacts identiques

Pensez à de grandes flottes distribuant des couches conteneur identiques, des dépôts de paquets ou des artefacts de build—à condition que ces artefacts soient vraiment identiques au niveau bloc et ne soient pas resignés ou re-timestampés de manière à changer les blocs. C’est plus rare qu’on ne le croit.

Quand la dédup échoue (commun, coûteux, prévisible)

La dédup échoue de la manière que les SRE détestent : lentement au départ, puis d’un coup, et généralement à 2h du matin.

1) Bases de données et tout ce qui a un turnover élevé

Les bases de données réécrivent des pages. Même si le contenu logique est similaire, les blocs diffèrent et le schéma d’écriture fait tourner les métadonnées. Si vos misses DDT augmentent et que le DDT ne peut rester chaud dans l’ARC, vous verrez une latence en pointe et un débit en chute. Vous risquez aussi de transformer des maintenances de routine (scrubs, resilvers) en opérations de plusieurs jours.

2) Données déjà compressées ou chiffrées

Vidéo compressée, archives, beaucoup de formats binaires et blobs chiffrés présentent typiquement peu d’intérêt pour la dédup. Vous payez l’overhead et récupérez peu d’espace. C’est le pire rapport qualité/coût en stockage : overhead sans bénéfice.

3) Workloads mixtes sur un pool partagé

Une équipe active la dédup sur un dataset. Le DDT du pool grossit. Une autre équipe avec des charges sensibles à la latence sur un dataset différent commence à déposer des tickets sur des « pauses aléatoires ». Personne ne fait le lien jusqu’à ce que vous corréliez les pics avec les misses ARC pour métadonnées et que vous voyiez le DDT se battre pour la mémoire.

4) « On rajoutera de la RAM plus tard »

Ce n’est pas un interrupteur réversible. Si vous activez la dédup et ingérez des semaines de données, puis découvrez que le DDT est trop gros, désactiver la dédup ne supprime pas les entrées du DDT. Vous êtes maintenant dans la phase de réécriture ou de migration, l’équivalent stockage de découvrir que votre « bande adhésive temporaire » est devenue structurelle.

Blague #2 : La dédup ZFS est la seule fonctionnalité que je connaisse capable de transformer « on a économisé 20 % de disque » en « on a perdu 80 % de performance » avec le même enthousiasme.

Trois mini-récits du monde de l’entreprise

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

Une entreprise de taille moyenne gérait un cluster de virtualisation privé sur ZFS. Un nouveau responsable stockage a hérité d’une demande d’expansion coûteuse et a décidé de « faire le malin » avant d’acheter plus de disques. Il a activé la dédup sur le dataset contenant les disques VM, s’attendant à une duplication massive des templates.

La mauvaise hypothèse : « Les VM sont toutes similaires, donc la dédup sera énorme. » En réalité, l’environnement avait dérivé. Les templates étaient anciens, beaucoup de VMs avaient été patchées pendant des années, et la plateforme utilisait déjà le clonage pour le déploiement initial. Il y avait de la duplication, mais bien loin des chiffres du tableur.

Les premiers symptômes furent subtils : des pics de latence occasionnels lors des pics de connexion du matin. Puis le helpdesk a rapporté des « VMs lentes » et des « gels aléatoires ». Les IOPS semblaient corrects en moyenne, mais la latence p99 d’écriture était mauvaise. Les scrubs ont aussi commencé à durer plus longtemps—plus de parcours de métadonnées, plus de pression sur le cache.

L’équipe d’astreinte a traité ça comme un problème hyperviseur jusqu’à ce que quelqu’un corrèle les pics avec les misses du cache DDT côté stockage. Le DDT était bien plus gros que prévu, l’ARC évincait constamment des données utiles pour faire de la place aux métadonnées de dédup, et le pool effectuait de petites lectures aléatoires juste pour décider comment écrire.

Ils ont désactivé la dédup sur le dataset, s’attendant à un correctif instantané. Les performances se sont légèrement améliorées (moins de nouvelles recherches dedup), mais le DDT est resté massif car les données existantes étaient toujours dédupliquées. La solution finale fut une migration contrôlée : répliquer les datasets vers un nouveau pool sans dédup et basculer. Les « économies de disque » ont fini par coûter des semaines de planification et beaucoup de réunions où personne n’avait le droit de dire « je vous l’avais dit ».

Mini-récit 2 : L’optimisation qui a mal tourné

Une société SaaS utilisait ZFS comme backend pour un dépôt d’artefacts interne. La charge était surtout en écriture lors des pics CI et en lecture lors des déploiements. La croissance de l’espace posait problème, et quelqu’un a remarqué que beaucoup d’artefacts partageaient des couches de base identiques.

Ils ont fait un test rapide sur un petit sous-ensemble, ont vu d’excellents ratios de dédup, et l’ont généralisé. L’optimisation s’est retournée contre eux car l’échantillon de test était biaisé : il contenait principalement des sorties de build identiques d’un projet unique qui réutilisait fortement des couches. L’environnement plus large contenait de nombreux projets aux dépendances légèrement différentes et des rebuilds fréquents qui changeaient les blocs juste assez pour vaincre la dédup.

En un mois, le système d’artefacts a commencé à manquer les SLA lors des heures de pointe. Pas parce que les disques étaient pleins, mais parce que les recherches métadonnées étaient désormais dans le chemin critique de chaque écriture. L’ARC était affamé ; le système passait son temps à récupérer les entrées DDT. L’équipe a tenté d’ajouter du L2ARC pour « mettre en cache la table », ce qui a augmenté la pression RAM et peu amélioré la latence de pointe.

La solution a été ennuyeuse : revenir en arrière sur la dédup, activer la compression et repenser les politiques de rétention. La compression a offert des économies prévisibles avec moins de douleur métadonnées. La refonte de la rétention a réduit la croissance sur le long terme. La dédup n’était pas exactement le méchant—c’était le mauvais outil pour une charge variable sans couche métadonnées dimensionnée.

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

Une société de services financiers exploitait une plateforme de sauvegarde basée sur ZFS. Ils étaient tentés par la dédup parce que les sauvegardes sont « pleines de répétitions ». L’ingénieur stockage—calme, méthodique et allergique aux surprises—a insisté pour une checklist pré-vol avant d’activer quoi que ce soit.

Ils ont pris un échantillon représentatif : une semaine de vraies sauvegardes, pas des tests synthétiques, et l’ont injecté dans un pool de staging. Ils ont mesuré le ratio de compression, le ratio de dédup, la taille du DDT, le comportement de l’ARC et les performances d’ingestion au pic. Ils ont aussi simulé un scrub et une résilience pendant une charge modérée, parce que les pires échecs arrivent quand la maintenance chevauche le trafic.

Les données montraient que la dédup aiderait, mais seulement si les métadonnées résidaient sur des dispositifs rapides. Ils ont donc construit le pool avec un special vdev miroir dimensionné pour la croissance métadonnées et l’ont traité comme une infrastructure critique (surveillance, pièces de rechange, contrôle des changements strict). Ils ont aussi limité la concurrence d’ingestion pour éviter le thrash DDT en rafales.

Quand un incident matériel ultérieur a forcé un resilver pendant une semaine chargée, le système est resté stable. Ce n’était pas glorieux—personne n’a reçu de trophée—mais ils ont évité l’histoire classique : « on a économisé de l’espace et on a perdu le week-end ». La bonne pratique n’était pas brillante ; elle était disciplinée : tester et construire pour le chemin métadonnées, pas seulement pour le chemin données.

Tâches pratiques : commandes, sorties et comment les interpréter

Ci-dessous des tâches concrètes que vous pouvez exécuter sur un système OpenZFS typique (Linux avec zfsutils). Certaines commandes diffèrent sur FreeBSD/Illumos, mais le modèle mental reste. Le but n’est pas de mémoriser les options ; c’est rendre le comportement dedup mesurable.

Task 1: Identify which datasets have dedup enabled

cr0x@server:~$ sudo zfs get -r -o name,property,value,source dedup tank
NAME                   PROPERTY  VALUE  SOURCE
tank                   dedup     off    default
tank/vmstore           dedup     on     local
tank/backups           dedup     off    inherited from tank

Interprétation : La dédup est par dataset. Si vous voyez même un dataset critique avec dedup=on, supposez qu’il y a un overhead DDT au niveau du pool. Identifiez qui l’a activé et pourquoi.

Task 2: Check the actual dedup ratio at pool level

cr0x@server:~$ sudo zpool list tank
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank  54.5T  38.2T  16.3T        -         -    21%    70%  1.08x  ONLINE  -

Interprétation : DEDUP 1.08x signifie que vous économisez ~8% d’espace logique via la dédup. Cela peut ne pas justifier l’overhead. Si c’est en dessous de ~1.2x, soyez sceptique sauf raison très spécifique.

Task 3: Check DDT size and how “hot” it is

cr0x@server:~$ sudo zpool status -D tank
pool: tank
state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        tank        ONLINE       0     0     0
          raidz2-0  ONLINE       0     0     0
            sda     ONLINE       0     0     0
            sdb     ONLINE       0     0     0
            sdc     ONLINE       0     0     0
            sdd     ONLINE       0     0     0
            sde     ONLINE       0     0     0
            sdf     ONLINE       0     0     0

dedup: DDT entries 48239124, size 34.1G on disk, 19.6G in core

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
     1    36.2M   9.44T   8.81T   8.81T    36.2M   9.44T   8.81T   8.81T
     2     8.7M   2.31T   2.16T   2.16T    18.1M   4.62T   4.32T   4.32T
     4     1.2M   353G    331G    331G     5.0M   1.38T   1.30T   1.30T

Interprétation : La ligne clé est « size X on disk, Y in core ». Si « in core » est élevé par rapport à votre RAM, ou s’il ne tient pas dans l’ARC, vous êtes en danger. Notez aussi combien de blocs ne sont référencés qu’une seule fois : si la plupart sont refcnt=1, vous payez l’overhead pour des blocs qui n’ont pas déduplié.

Task 4: Estimate dedup “waste” by looking at reference counts

cr0x@server:~$ sudo zdb -DD tank | head -n 25
DDT-sha256-zap-duplicate: 48239124 entries, size 34972804096 on disk, 21043748864 in core
DDT histogram (aggregated over all DDTs):

bucket              allocated                       referenced
______   ______________________________   ______________________________
refcnt   blocks   LSIZE   PSIZE   DSIZE   blocks   LSIZE   PSIZE   DSIZE
     1    36.2M   9.44T   8.81T   8.81T    36.2M   9.44T   8.81T   8.81T
     2     8.7M   2.31T   2.16T   2.16T    18.1M   4.62T   4.32T   4.32T

Interprétation : Si la majorité des blocs sont refcnt=1, la dédup ne tient pas ses promesses. Si vous avez un bon regroupement dans des refcounts élevés (8, 16, 32), alors la dédup commence à devenir intéressante.

Task 5: Check ARC size and memory pressure signals

cr0x@server:~$ cat /proc/spl/kstat/zfs/arcstats | egrep '^(size|c |c_min|c_max|misses|hits|demand_data_misses|demand_metadata_misses) '
size                            4    34325131264
c                               4    36507222016
c_min                           4    4294967296
c_max                           4    68719476736
hits                            4    1183749821
misses                          4    284993112
demand_data_misses              4    84129911
demand_metadata_misses          4    162104772

Interprétation : Un fort nombre de demand_metadata_misses sous charge est un signe de dédup. La dédup utilise beaucoup de métadonnées ; si les misses métadonnées augmentent, le pool effectuera plus de petites lectures et la latence suivra.

Task 6: Observe real-time latency and IOPS per vdev

cr0x@server:~$ sudo zpool iostat -v tank 2
                              capacity     operations     bandwidth
pool                        alloc   free   read  write   read  write
--------------------------  -----  -----  -----  -----  -----  -----
tank                        38.2T  16.3T    110    980  11.2M  84.5M
  raidz2-0                  38.2T  16.3T    110    980  11.2M  84.5M
    sda                         -      -     18    165  1.9M  14.2M
    sdb                         -      -     19    164  1.8M  14.0M
    sdc                         -      -     17    162  1.7M  14.1M
    sdd                         -      -     18    163  1.9M  14.1M
    sde                         -      -     19    163  1.9M  14.0M
    sdf                         -      -     19    163  2.0M  14.1M

Interprétation : Cela montre la distribution de la charge. Si la dédup force des lectures métadonnées aléatoires, vous pouvez voir les IOPS de lecture augmenter alors que l’application écrit principalement. Associez cela à des outils de latence pour confirmer.

Task 7: On Linux, catch ZFS-induced stalls via pressure metrics

cr0x@server:~$ cat /proc/pressure/memory
some avg10=0.32 avg60=0.18 avg300=0.07 total=12873631
full avg10=0.09 avg60=0.05 avg300=0.02 total=2219481

Interprétation : La pression mémoire se corrèle fortement avec la douleur de la dédup. Si l’ARC se bat avec le noyau et les applications pour la RAM, vous verrez la pression « full » augmenter lors des pics.

Task 8: Check dataset recordsize and why it matters for DDT growth

cr0x@server:~$ sudo zfs get -o name,property,value recordsize tank/vmstore
NAME         PROPERTY    VALUE
tank/vmstore recordsize  128K

Interprétation : Un recordsize plus petit signifie plus de blocs pour les mêmes données, ce qui entraîne davantage d’entrées DDT. L’overhead dédup s’échelonne avec le nombre de blocs, pas seulement avec les octets totaux.

Task 9: Measure compression ratio before reaching for dedup

cr0x@server:~$ sudo zfs get -o name,property,value,source compression,compressratio tank/vmstore
NAME         PROPERTY       VALUE     SOURCE
tank/vmstore compression    lz4       local
tank/vmstore compressratio  1.52x     -

Interprétation : Si vous obtenez déjà 1.5x de compression, le gain incrémental de la dédup peut être faible—surtout pour le coût. Si la compression est désactivée, corrigez cela d’abord sauf raison forte contraire.

Task 10: Find whether a dataset is paying dedup overhead without benefit

cr0x@server:~$ sudo zfs get -o name,property,value written,logicalused,usedrefreserv usedbydataset tank/vmstore
NAME         PROPERTY       VALUE
tank/vmstore written        19.3T
tank/vmstore logicalused    27.8T
tank/vmstore usedrefreserv  0B
tank/vmstore usedbydataset  31.1T

Interprétation : logicalused vs réel utilisé peut aider à raisonner sur l’efficacité d’espace, mais la dédup complique la comptabilité à cause des blocs partagés. Utilisez le ratio dedup au niveau du pool et les histogrammes DDT pour décider si la dédup « fonctionne », pas seulement les valeurs du dataset.

Task 11: Disable dedup for new writes (and set expectations correctly)

cr0x@server:~$ sudo zfs set dedup=off tank/vmstore
cr0x@server:~$ sudo zfs get -o name,property,value dedup tank/vmstore
NAME         PROPERTY  VALUE
tank/vmstore dedup     off

Interprétation : Cela arrête la dédup sur les nouvelles écritures uniquement. Les blocs existants restent. Les performances peuvent s’améliorer si votre charge est écriture-lourde et que le taux de recherche DDT baisse, mais le pool porte toujours le DDT et sa complexité associée.

Task 12: Remove deduped data the only way that truly works: rewrite or migrate

cr0x@server:~$ sudo zfs snapshot tank/vmstore@migration-start
cr0x@server:~$ sudo zfs send -R tank/vmstore@migration-start | sudo zfs receive -u tank2/vmstore
cr0x@server:~$ sudo zfs set dedup=off tank2/vmstore
cr0x@server:~$ sudo zfs mount tank2/vmstore

Interprétation : Envoyer un snapshot réplique des blocs. La préservation de la dédup dépend de la configuration du côté récepteur et de la nature du flux send/receive. L’approche opérationnellement sûre est : migrer vers un pool/dataset propre avec dedup désactivé et valider. Si votre but est « supprimer le DDT », vous devez typiquement déplacer les données vers un pool qui n’a jamais eu dedup activé ou les réécrire en place (ce qui est rarement amusant).

Task 13: Confirm whether you have a special vdev for metadata

cr0x@server:~$ sudo zpool status tank
  pool: tank
 state: ONLINE
config:

        NAME                              STATE     READ WRITE CKSUM
        tank                              ONLINE       0     0     0
          raidz2-0                        ONLINE       0     0     0
            sda                           ONLINE       0     0     0
            sdb                           ONLINE       0     0     0
            sdc                           ONLINE       0     0     0
            sdd                           ONLINE       0     0     0
            sde                           ONLINE       0     0     0
            sdf                           ONLINE       0     0     0
        special
          mirror-1                        ONLINE       0     0     0
            nvme0n1p2                     ONLINE       0     0     0
            nvme1n1p2                     ONLINE       0     0     0

Interprétation : Un special vdev en miroir est un atténuateur majeur pour la latence métadonnées de la dédup. Il n’élimine pas le besoin de RAM, mais peut maintenir le système en état quand l’ARC est sous pression.

Task 14: Watch ZFS transaction group behavior (a proxy for “is storage stalling?”)

cr0x@server:~$ grep -E "txg_sync|txg_quiesce" /proc/spl/kstat/zfs/* 2>/dev/null | head
/proc/spl/kstat/zfs/tank/txgs:txg_sync 4 9123
/proc/spl/kstat/zfs/tank/txgs:txg_quiesce 4 9123

Interprétation : Si les temps de txg sync flambent pendant les pics dedup, le pool a du mal à valider les changements. La dédup ajoute des mises à jour métadonnées qui peuvent aggraver la pression de sync.

Playbook de diagnostic rapide : trouvez le goulot avant qu’il ne vous trouve

Voici l’ordre que j’utilise quand quelqu’un signale « ZFS est lent » et que la dédup peut être en cause. L’objectif est de converger rapidement, pas d’être exhaustif philosophiquement.

Étape 1 : La dédup est-elle activée et est-elle significative ?

  • Vérifier les datasets : zfs get -r dedup POOL
  • Vérifier le ratio du pool : zpool list
  • Vérifier la taille du DDT : zpool status -D POOL

Décision : Si le ratio dedup est faible (< ~1.2x) et que le DDT est grand, vous avez probablement « coût sans bénéfice ». Prévoyez de sortir de la dédup plutôt que d’ajuster autour.

Étape 2 : Le DDT tient-il en mémoire (ou au moins reste-t-il chaud) ?

  • Statistiques ARC : cat /proc/spl/kstat/zfs/arcstats
  • Regarder les misses métadonnées et les misses globaux augmentant avec la charge.
  • Vérifier la pression mémoire OS : /proc/pressure/memory

Décision : Si la pression mémoire est élevée et que les misses métadonnées grimpent, attendez-vous à des recherches DDT sur disque. Voilà votre latence.

Étape 3 : Les I/O métadonnées atterrissent-elles sur des périphériques lents ?

  • Confirmer le special vdev : zpool status
  • Observer les IOPS de lecture pendant une charge d’écriture : zpool iostat -v 2

Décision : Si vous n’avez pas de special vdev et que vous êtes sur HDD, dedup à grande échelle est rarement heureux.

Étape 4 : Êtes-vous réellement CPU-bound sur le hashing ?

  • Vérifier le CPU système : top / mpstat (selon plateforme)
  • Corréler CPU élevé avec le débit d’écriture et la latence stable.

Décision : L’overhead de hash existe, mais la plupart des catastrophes dedup réelles sont liées à la mémoire / I/O métadonnées, pas au CPU. Ne chassez pas le mauvais dragon.

Étape 5 : Écarter rapidement les problèmes non liés à la dédup

  • État du pool : zpool status -x
  • Activité scrub/resilver : zpool status
  • Pool quasi plein / fragmentation : zpool list (CAP), et surveiller FRAG.

Décision : Un pool à haute capacité et fortement fragmenté performera mal indépendamment de la dédup. La dédup peut amplifier la douleur, mais ce n’est pas toujours la cause racine.

Erreurs courantes (symptômes et corrections)

Erreur 1 : Activer la dédup parce que « nous avons beaucoup de données similaires »

Symptôme : Le ratio dedup reste près de 1.00x–1.15x tandis que la latence empire.

Correction : Activez la compression (si ce n’est pas déjà fait), mesurez l’opportunité réelle de dédup sur un échantillon représentatif, et envisagez la dédup au niveau applicatif ou des stratégies de clonage. Si la dédup est déjà activée et dommageable, planifiez une migration/réécriture ; ne comptez pas sur dedup=off pour effacer l’historique.

Erreur 2 : Sous-estimer la croissance du DDT à cause d’un recordsize petit

Symptôme : Les entrées DDT explosent ; les misses métadonnées ARC augmentent ; des IOPS de lecture aléatoire apparaissent pendant de fortes écritures.

Correction : Réévaluez le recordsize du dataset. Pour images VM et stockage général, 128K est courant ; des tailles plus petites peuvent être nécessaires pour certains workloads mais coûtent en métadonnées. Si vous devez utiliser de petits blocs, la dédup devient plus chère.

Erreur 3 : Compter sur L2ARC pour « résoudre » la dédup

Symptôme : Vous ajoutez du SSD cache et voyez toujours des blocages ; l’usage RAM augmente ; le système semble pire sous charge.

Correction : Traitez L2ARC comme un supplément, pas un substitut à la RAM. Si la dédup est nécessaire, priorisez suffisamment de RAM et envisagez un special vdev pour les métadonnées. Validez avec des tests réels de charge.

Erreur 4 : Activer la dédup sur un pool à usage mixte sans isolation

Symptôme : Un workload change et des services non liés subissent des pics de latence. Les gens commencent à accuser le réseau.

Correction : Si la dédup est nécessaire, isolez-la : pool dédié, ou au moins ressources hardware séparées et tier métadonnées dimensionné. Un pool partagé signifie un rayon d’impact partagé.

Erreur 5 : Oublier que la dédup augmente la complexité opérationnelle

Symptôme : Les scrubs/resilvers prennent plus de temps que prévu ; les fenêtres de maintenance glissent ; les exercices de reprise sont lents.

Correction : Mesurez le comportement scrub/resilver en staging avec la dédup activée. Surveillez et budgétez le temps. Si RTO/RPO comptent, pesez ce coût sérieusement.

Erreur 6 : S’attendre à un rollback facile

Symptôme : Vous mettez dedup=off et rien ne s’améliore suffisamment ; le DDT reste volumineux.

Correction : Acceptez la physique : les blocs dédupliqués restent dédupliqués jusqu’à réécriture. La sortie propre est une migration vers un pool/dataset sans dédup, ou une réécriture contrôlée des données (souvent via send/receive, copie style rsync, ou réhydratation applicative).

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

Checklist A: « Devrait-on activer la dédup ? » (pré-vol)

  1. Définir l’objectif : S’agit-il de repousser un achat de disque, réduire l’empreinte de sauvegarde ou d’activer une fonctionnalité produit spécifique ?
  2. Mesurer la compression d’abord : Activez compression=lz4 dans un dataset de test et mesurez compressratio.
  3. Échantillonner des données réelles : Utilisez un sous-ensemble représentatif (pas un répertoire trié sur le volet) et testez la dédup en staging.
  4. Mesurer le ratio dedup et la taille DDT : Collectez zpool status -D et zdb -DD.
  5. Modéliser l’ingestion en pire cas : Exécutez la charge d’écriture au pic, pas la journée moyenne.
  6. Tester un scrub sous charge : Confirmez que vous pouvez toujours respecter les contraintes latence/débit.
  7. Décider du tiering métadonnées : Si la dédup est vraiment nécessaire, prévoyez un special vdev miroir et assez de RAM.
  8. Rédiger le plan de rollback : Incluez comment migrer hors de la dédup si elle déçoit, et combien de temps cela prendra.

Checklist B: Si la dédup est déjà activée et que vous souffrez

  1. Arrêter l’hémorragie : Mettre dedup=off sur les datasets affectés pour empêcher la croissance DDT par de nouvelles écritures (sauf si la dédup est essentielle pour ces données).
  2. Quantifier l’impact DDT : Utiliser zpool status -D et les stats ARC pour confirmer les misses métadonnées et la pression mémoire.
  3. Réduire temporairement la concurrence : Si la charge le permet (ingestion de sauvegarde, jobs batch), limiter les writers parallèles pour diminuer la pression de recherche.
  4. Ajouter de la RAM si possible : C’est le levier le plus rapide pour « stabiliser maintenant », bien que parfois impossible immédiatement.
  5. Envisager un special vdev : Si supporté et faisable en sécurité, déplacer les métadonnées sur des dispositifs rapides en miroir. Cela peut transformer les lectures métadonnées aléatoires de « mort » à « agaçant ».
  6. Planifier la vraie solution : Migrer les datasets vers un nouveau pool sans dédup, ou réécrire les données de façon contrôlée.
  7. Valider par des tests de charge : Ne déclarez pas victoire après la première heure calme.

Checklist C: « Dédup, mais en sécurité » (garde-fous opérationnels)

  1. Surveiller régulièrement la taille DDT et l’empreinte « in core ».
  2. Alerter sur la montée des misses métadonnées et de la pression mémoire soutenue.
  3. Garder la capacité du pool raisonnable ; éviter d’opérer proche du plein.
  4. Planifier les scrubs en connaissance des fenêtres de charge maximale.
  5. Documenter quels datasets utilisent la dédup et pourquoi, avec un responsable.

FAQ

1) La déduplication ZFS est-elle « mauvaise » ?

Non. Elle est spécialisée. Elle est mauvaise comme réglage par défaut parce que l’inconvénient est important et le rollback difficile. Sur le bon workload et avec le bon matériel (RAM et tier métadonnées rapide), elle peut être excellente.

2) Quelle quantité de RAM faut-il pour la dédup ?

Assez pour garder le working set du DDT chaud. Il existe des règles empiriques, mais la seule réponse sûre est : mesurez la taille « in core » de votre DDT et observez le comportement des misses métadonnées sous charge maximale. Si le système thrash, vous n’en avez pas assez.

3) Puis-je désactiver la dédup et récupérer ma RAM ?

Désactiver la dédup stoppe les nouvelles opérations dedup. Cela ne supprime pas le DDT existant pour les blocs déjà dédupliqués. Vous réduisez la croissance future, mais vous n’effacez pas le passé sans réécriture/migration.

4) La dédup aide-t-elle pour le stockage VM ?

Parfois. Si vous avez de nombreuses images VM quasi identiques et que vous n’utilisez pas déjà le clonage/snapshots efficacement, la dédup peut économiser de l’espace. Mais les workloads VM génèrent aussi du churn, et la « similarité » s’estompe souvent avec le temps. Testez avec de vraies disques VM et une fenêtre temporelle réaliste.

5) La compression est-elle une alternative plus sûre ?

Généralement, oui. compression=lz4 est largement utilisé car il améliore souvent le débit effectif (moins d’octets lus/écrits) avec un coût CPU minimal sur les systèmes modernes. C’est aussi plus simple à raisonner et ne nécessite pas d’énormes tables de métadonnées.

6) Le chiffrement ruine-t-il la dédup ?

Souvent. Si les données sont chiffrées avant que ZFS ne les voie, les blocs paraissent aléatoires et ne dédupliqueront pas. Si ZFS chiffre le dataset lui-même, le comportement dépend des détails d’implémentation et de l’ordre dédup/chiffrement. Dans beaucoup de configurations pratiques, le chiffrement réduit significativement les gains de dédup.

7) Un special vdev peut-il « réparer » la dédup ?

Il peut réduire drastiquement la douleur en gardant les métadonnées sur des périphériques rapides, ce qui aide quand les recherches DDT manquent l’ARC. Il n’élimine pas le besoin de RAM ni la complexité opérationnelle. Il devient aussi une infrastructure critique : le perdre peut compromettre le pool.

8) Pourquoi mon pool est lent alors que le ratio dedup est élevé ?

Un ratio élevé signifie que des blocs sont partagés, mais cela ne garantit pas que le DDT tienne en mémoire ou que le chemin métadonnées soit rapide. Vous pouvez avoir d’importantes économies et être pourtant limité par les recherches DDT, la pression txg sync, ou des périphériques métadonnées lents. Mesurez les misses ARC métadonnées et la taille « in core » du DDT par rapport à la RAM.

9) Quelle est la façon la plus sûre de se débarrasser de la dédup une fois activée ?

Migrer vers un nouveau pool (ou au moins un nouveau dataset sur un pool qui n’a jamais utilisé la dédup) avec la dédup désactivée, suivi de validations et basculement. Le nettoyage in-place est généralement un exercice de réécriture, opérationnellement plus difficile à contrôler.

10) Dois-je activer la dédup sur un pool partagé utilisé par de nombreuses équipes ?

Seulement si vous voulez que le rayon d’impact de la dédup inclue tout le monde. Si la dédup est requise, isolez-la : pool dédié, tier métadonnées dédié, responsabilité claire et plan de rollback.

Conclusion

La déduplication ZFS n’est pas un « gadget agréable ». C’est un choix architectural avec une empreinte permanente sur les métadonnées de votre pool et votre vie opérationnelle. Si vous la traitez comme une case à cocher, elle traitera votre RAM comme une ressource consommable et votre budget latence comme une suggestion.

Quand la dédup fonctionne, c’est parce que les données sont vraiment dupliquées et que le système est construit pour servir rapidement les métadonnées—RAM d’abord, puis un vrai tier métadonnées. Quand la dédup échoue, c’est parce que quelqu’un a supposé que similarité = duplication, ou a cru pouvoir revenir en arrière plus tard, ou a essayé de résoudre un problème de RAM avec un bandage SSD. Votre meilleur plan : tester avec des données réelles, dimensionner le chemin métadonnées, et avoir un plan de sortie avant d’en avoir besoin.

← Précédent
VPN basé sur les routes vs basé sur les politiques : lequel est mieux pour les bureaux et pourquoi
Suivant →
Chiffrement ZFS + Compression : l’ordre qui fait la performance

Laisser un commentaire