Vous avez activé le chiffrement parce que la sécurité l’a demandé gentiment (ou parce que les auditeurs l’ont exigé sèchement).
Puis vous avez activé la compression parce que le stockage coûte cher et que le pool est toujours « mystérieusement » plus plein que prévu.
Et maintenant la performance est étrange : pics CPU, variations de latence, et la question « pourquoi ce dataset est-il plus lent que l’autre non chiffré ? »
devient un rituel hebdomadaire.
ZFS est déterministe. Votre charge ne l’est pas. L’écart entre les deux est où se cache la plupart des douleurs en production. Fermons-le :
quel ordre le pipeline utilise, quels réglages comptent, et comment prouver ce qui vous limite vraiment.
L’ordre du pipeline : ce qui se passe d’abord, et pourquoi ça compte
ZFS ne « compresse pas à moitié » et ne « chiffre pas à moitié ». Il fait les deux dans un pipeline très spécifique, et les résultats
de performance suivent cet ordre comme une ombre.
Ce que ZFS fait à vos données (modèle simplifié mais exact)
Pour le chiffrement natif de ZFS (fonction sur le dataset), la séquence importante est :
- L’application écrit des blocs logiques (fichiers, pages de BD, blocs de VM) dans l’espace défini par recordsize/volblocksize du dataset.
-
La compression intervient en premier (si activée). ZFS tente de compresser chaque enregistrement (par ex., 128K) indépendamment.
Si le résultat n’est pas suffisamment plus petit, il peut stocker non compressé (comportement dépendant de l’algorithme, mais l’issue est simple :
il n’empilera pas l’espace pour rien). -
Le chiffrement intervient après la compression. C’est le point crucial. Chiffrer des données qui ressemblent à du bruit rend la
compression impossible ; si vous chiffrez d’abord, la compression devient essentiellement un no-op. - Les checksums sont calculés pour l’intégrité, et ZFS écrit les blocs dans la disposition vdev du pool, avec une sémantique copy-on-write.
Cet ordre (compresser puis chiffrer) explique pourquoi vous pouvez avoir à la fois sécurité et efficacité d’espace—sans magie.
C’est aussi la raison pour laquelle certains problèmes de performance n’apparaissent qu’après activation du chiffrement :
la compression peut toujours économiser de l’I/O, mais vous avez déplacé du travail sur le CPU. Si vous n’avez pas de marge CPU,
la latence devient votre nouveau passe-temps.
Le modèle mental qui évite les erreurs stupides
Pensez-y comme ceci : la compression réduit les octets ; le chiffrement détruit les motifs. Vous voulez donc réduire les octets tant que
les motifs existent encore. Ensuite vous chiffrez.
Si vous utilisez le chiffrement natif de ZFS, vous obtenez le bon ordre par conception. Si vous faites le « chiffrement » au niveau de l’application
ou au-dessus de ZFS (fichiers chiffrés dans un dataset non chiffré), vous chiffrez peut-être avant que ZFS voie les données,
et dans ce cas la compression ZFS est surtout décorative.
Blague n°1 : Activer la compression pour des données déjà chiffrées, c’est comme installer un turbo sur un vélo—techniquement impressionnant, fonctionnellement déroutant.
Ce que « l’ordre » signifie dans le monde réel
Cet article ne débat pas d’un ordre philosophique ; il s’agit de savoir où vont les cycles CPU et l’I/O. L’ordre qui compte est :
- Où le chiffrement a-t-il lieu ? Chiffrement natif ZFS ? Niveau applicatif ? Système de fichiers au-dessus de ZFS ?
- Où la compression a-t-elle lieu ? Propriété du dataset ZFS ? Compression applicative ? Outil de sauvegarde ?
- Quand les données deviennent-elles incompressibles ? Le plus souvent : après chiffrement, après formats déjà compressés (JPEG, MP4),
ou après compression au niveau applicatif (par ex., compression de pages de base de données).
Faits & historique qui influencent les décisions
Un peu de contexte rapporte des dividendes. Voici des faits concrets et des points historiques qui comptent quand vous effectuez des changements sur un pool de production.
- Le chiffrement ZFS est natif et par dataset. Ce n’est pas une couche de périphérique additionnelle greffée après coup ; c’est une fonctionnalité de dataset avec options d’héritage des clés.
- Le chiffrement natif est arrivé bien plus tard que ZFS lui-même. ZFS a été créé au milieu des années 2000 ; le chiffrement natif est apparu des années après, après de longs débats sur la gestion des clés et les flags de fonctionnalité.
- La compression ZFS existe depuis « toujours » en termes ZFS, et elle a été la valeur par défaut dans beaucoup d’environnements car elle améliore souvent la performance en réduisant l’I/O.
- AES-GCM est courant pour le chiffrement ZFS car il fournit un chiffrement authentifié (confidentialité + intégrité). Cette intégrité est distincte mais complémentaire aux checksums ZFS.
- Les checksums ZFS sont bout en bout : stockés et vérifiés à la lecture, permettant la détection de corruptions silencieuses. Le chiffrement ne remplace pas cela ; il s’ajoute à la protection.
- La compression se fait par bloc (record) et localement. ZFS ne compresse pas des « fichiers » ; il compresse des blocs, d’où l’importance de recordsize et de la forme de la charge.
- L’ARC met en cache les données compressées (et les datasets chiffrés ont leurs implications). L’efficacité du cache dépend de la taille post-compression et des motifs d’accès.
- ZFS send/receive prend en charge les modes de réplication chiffrée. Vous pouvez envoyer des flux chiffrés bruts qui ne nécessitent pas de clés sur le récepteur—utile pour des cibles de sauvegarde non fiables.
- Les CPU modernes disposent d’accélération AES (AES-NI sur x86, équivalents sur d’autres plates-formes), transformant « le chiffrement est lent » en « le chiffrement est généralement acceptable, jusqu’à un certain point ».
Une citation, parce qu’elle est douloureusement vraie en exploitation. Gene Kranz a dit : « Failure is not an option. » (C’est une devise culturelle, pas un paramètre du noyau.)
Réalités de performance : chiffrement, compression et le CPU dont vous disposez réellement
Les gens aiment les réponses simples : « La compression est rapide », « Le chiffrement est lent », « NVMe règle tout ». La réalité est plus rugueuse et plus intéressante.
La performance est une négociation à trois entre cycles CPU, bande passante mémoire/comportement du cache, et latence/IOPS du stockage.
La compression peut accélérer les choses, même si elle coûte du CPU
Si votre pool est lié par l’I/O, la compression gagne souvent deux fois :
- Elle écrit moins d’octets, donc vos disques font moins de travail.
- Elle lit moins d’octets, ce qui peut transformer des pics de latence en choses que vous cessez de remarquer.
Mais la compression n’est pas gratuite. Des algorithmes comme lz4 sont optimisés pour la vitesse ; zstd peut échanger du CPU pour de meilleurs ratios.
Vous choisissez selon votre goulet. Si vous êtes déjà lié par le CPU (utilisation élevée, file d’attente run queue, changements de contexte fréquents),
activer une compression plus lourde transforme un problème léger en une file de tickets.
Le surcoût du chiffrement est souvent « acceptable », jusqu’à ce qu’il ne le soit plus
Avec l’accélération matérielle, AES-GCM peut être très rapide. Mais le chiffrement ajoute quand même :
- Du travail CPU par bloc écrit et lu.
- Un peu de gestion métadonnée supplémentaire.
- Une pression potentielle sur le cache et la bande passante mémoire sous haut débit.
Le mode d’échec n’est pas toujours évident. Vous pouvez avoir beaucoup de « CPU moyen » tout en manquant de marge par cœur.
Les threads de stockage peuvent devenir sensibles à la latence ; s’ils tournent sur des cœurs déjà occupés par du travail applicatif, vous obtenez des variations.
L’ordre vous donne un levier : réduisez les octets avant de payer le coût du chiffrement
Parce que ZFS compresse avant de chiffrer, la compression réduit la quantité de données à chiffrer et à écrire.
Cela importe quand :
- Vous avez un dataset qui se compresse bien (logs texte, JSON, images VM avec zéros, beaucoup de pages de bases de données).
- Vous êtes limité en débit par le stockage ou la réplication réseau.
- Vous répliquez des données chiffrées (send/receive), où les octets sur le réseau coûtent du temps.
Si les données sont déjà compressées (médias, nombreuses sauvegardes, blobs chiffrés), la compression ne réduira pas les octets.
Vous payez toujours le coût de tentative de compression, bien que faible pour lz4 et non négligeable pour des niveaux zstd élevés.
Le niveau de compression est une décision de politique, pas une impression
La tentation est de choisir un algorithme qui sonne bien (« zstd-19, parce que le chiffre est grand ») et d’appeler ça de l’optimisation.
Ce n’est pas de l’ingénierie ; c’est du cosplay.
Voici la posture pratique :
- Par défaut, privilégiez
compression=lz4presque partout. C’est le choix « sûr » et il gagne souvent en espace et en rapidité. - Utilisez
compression=zstd(niveau modéré) pour les datasets où vous avez mesuré des bénéfices réels et où vous avez du budget CPU. - Désactivez la compression pour les datasets qui sont démontrablement incompressibles et extrêmement sensibles à la latence (rare, mais réel).
La gestion des clés de chiffrement peut devenir votre problème de performance
Pas directement—le crypto est rapide—mais parce que des erreurs opérationnelles causent des délais et des indisponibilités. Si les clés ne sont pas chargées au démarrage,
vos systèmes ne montent pas, vos applis ne démarrent pas, et vous vous retrouvez à déboguer une « performance de stockage » qui est en réalité « stockage indisponible ».
Blague n°2 : Le système de fichiers le plus rapide est celui qui monte ; le deuxième plus rapide est celui qui ne réveille pas votre astreinte à 3 h du matin.
Conception des datasets : recordsize, volblocksize et adéquation avec la charge
Le chiffrement et la compression ne sont pas des commutateurs indépendants. Ils interagissent avec la taille des blocs et les motifs d’accès. La plupart des incidents « ZFS lent »
sont en réalité des « ZFS fait exactement ce que vous avez demandé, et ce que vous avez demandé était étrange. »
recordsize : le multiplicateur caché
recordsize affecte les datasets de fichiers (pas les zvols) et contrôle la taille maximale de bloc que ZFS utilise pour les données de fichier.
Des records plus grands :
- Améliorent le débit séquentiel (moins d’opérations I/O).
- Augmentent l’efficacité de la compression (plus de données par bloc, plus de motifs).
- Peuvent nuire à la latence des lectures aléatoires pour de petites lectures (amplification de lecture).
Le chiffrement et la compression opèrent tous deux par enregistrement. Si vous choisissez un recordsize qui ne convient pas à votre charge, vous amplifiez
le travail CPU et l’I/O au mauvais endroit.
volblocksize : pour les zvols, vous n’avez qu’une seule chance (en général)
Pour les zvols, volblocksize est la taille de bloc exposée au consommateur (VM, iSCSI, etc.). Elle est fixée à la création et
difficile à changer sans recréer le volume.
Si vous exécutez des bases de données ou des images VM sur des zvols, choisissez le bon volblocksize. Si l’invité écrit des blocs de 8K et que votre volblocksize est 128K,
vous allez réaliser une masterclass d’amplification d’écriture.
vdevs spéciaux et métadonnées : la porte dérobée de la performance
Le chiffrement et la compression concernent les blocs de données, mais le comportement des métadonnées peut dominer la latence. Si votre charge est riche en métadonnées
(millions de petits fichiers, conteneurs, artefacts de build), votre dataset « données » peut sembler correct tandis que les métadonnées s’affolent.
Les vdevs spéciaux peuvent aider, mais ils doivent être conçus avec soin et protégés comme des citoyens de première classe.
Tâches pratiques : commandes, sorties et décisions à prendre
La théorie est bon marché. Voici des tâches pratiques que vous pouvez exécuter sur un système ZFS pour comprendre si le chiffrement et la compression aident,
nuisent ou se contentent de faire joli. Chaque tâche inclut : commande, ce que la sortie signifie, et la décision à prendre.
Task 1: Confirm encryption and compression properties on a dataset
cr0x@server:~$ zfs get -o name,property,value,source encryption,keystatus,keylocation,keyformat,compression,compressratio pool/app
NAME PROPERTY VALUE SOURCE
pool/app encryption aes-256-gcm local
pool/app keystatus available -
pool/app keylocation prompt local
pool/app keyformat passphrase local
pool/app compression zstd local
pool/app compressratio 1.72x -
Ce que cela signifie : le chiffrement est activé, la clé est chargée (keystatus=available), la compression est zstd, et le ratio réel est 1.72x.
Décision : Si compressratio est proche de 1.00x et que la charge est sensible à la latence, envisagez compression=lz4 ou off.
Si keystatus n’est pas available, corrigez le chargement des clés avant de poursuivre le « dépannage de performance ».
Task 2: Check whether you’re compressing incompressible data
cr0x@server:~$ zfs get -o name,property,value compressratio,compression pool/media
NAME PROPERTY VALUE SOURCE
pool/media compressratio 1.01x -
pool/media compression zstd local
Ce que cela signifie : zstd ne fait quasiment rien. Probablement des fichiers média ou des objets déjà compressés.
Décision : Passez à compression=lz4 ou compression=off si le CPU est saturé et que ce dataset n’en bénéficie pas.
Task 3: Measure whether encryption is present where you think it is
cr0x@server:~$ zfs get -o name,property,value encryption -r pool
NAME PROPERTY VALUE SOURCE
pool encryption off default
pool/app encryption aes-256-gcm local
pool/app/db encryption aes-256-gcm inherited from pool/app
pool/backups encryption off local
Ce que cela signifie : Tout n’est pas chiffré. L’héritage fonctionne pour pool/app/db ; les backups ne sont pas chiffrés.
Décision : Définissez une politique : les backups doivent-ils être chiffrés ? Si oui, activez le chiffrement au niveau dataset (ou utilisez des sends bruts).
Task 4: Check CPU features that make encryption cheap (or not)
cr0x@server:~$ grep -m1 -oE 'aes|sha_ni|pclmulqdq' /proc/cpuinfo | sort -u
aes
pclmulqdq
Ce que cela signifie : Les jeux d’instructions AES et carry-less multiply existent ; AES-GCM peut être accéléré matériellement.
Décision : Si ces fonctionnalités manquent sur du matériel ancien, attendez-vous à un coût CPU de chiffrement nettement plus élevé et planifiez la capacité en conséquence.
Task 5: Inspect per-dataset I/O load and latency clues
cr0x@server:~$ zpool iostat -v pool 1 3
capacity operations bandwidth
pool alloc free read write read write
-------------------------- ----- ----- ----- ----- ----- -----
pool 2.10T 5.14T 120 980 18.3M 210M
mirror-0 1.05T 2.57T 60 490 9.2M 105M
nvme0n1 - - 30 250 4.6M 52.0M
nvme1n1 - - 30 240 4.6M 53.0M
mirror-1 1.05T 2.57T 60 490 9.1M 105M
nvme2n1 - - 30 245 4.5M 52.5M
nvme3n1 - - 30 245 4.6M 52.5M
-------------------------- ----- ----- ----- ----- ----- -----
Ce que cela signifie : Écritures lourdes. Cela indique que le pool fait du travail réel ; pas qui blâmer, mais où regarder ensuite.
Décision : Si la bande passante est élevée mais la latence mauvaise, investiguez les écritures sync, le SLOG et la saturation CPU plutôt que de dire « le chiffrement est lent » sans preuve.
Task 6: Check ARC health and whether caching is helping compressed/encrypted workloads
cr0x@server:~$ arcstat 1 3
time read miss miss% dmis dm% pmis pm% mmis mm% size c
12:10:01 920 180 19 45 25 120 67 15 8 24.1G 31.8G
12:10:02 910 175 19 44 25 116 66 15 9 24.1G 31.8G
12:10:03 950 190 20 50 26 125 66 15 8 24.1G 31.8G
Ce que cela signifie : ~80% de hit rate ; l’ARC est utile. Si miss% est très élevé, vous allez sur disque et la latence suivra.
Décision : Si les misses dominent et que le jeu de travail est plus grand que l’ARC, ajustez la mémoire, envisagez L2ARC/vdev spécial (avec prudence),
ou redessinez le layout des datasets. Ne blâmez pas le chiffrement pour des échecs de cache.
Task 7: Verify recordsize and decide whether it matches access patterns
cr0x@server:~$ zfs get -o name,property,value recordsize pool/app
NAME PROPERTY VALUE SOURCE
pool/app recordsize 128K local
Ce que cela signifie : 128K est un défaut courant. Excellent pour le séquentiel, pas toujours pour les petites lectures aléatoires.
Décision : Pour des charges à petits fichiers ou en lecture aléatoire intensive, envisagez un recordsize plus petit (par ex., 16K ou 32K) sur un dataset dédié.
Task 8: For zvols, validate volblocksize (and regret nothing later)
cr0x@server:~$ zfs get -o name,property,value volblocksize pool/vm-01
NAME PROPERTY VALUE SOURCE
pool/vm-01 volblocksize 16K local
Ce que cela signifie : 16K est souvent raisonnable pour des charges VM ; alignez sur l’I/O invitée si possible.
Décision : Si le volblocksize est énorme et que la charge fait de petites écritures aléatoires, planifiez une migration/recréation. Il n’y a pas de sysctl héroïque qui corrige un mauvais dimensionnement.
Task 9: Check sync behavior and whether you’re paying for durability you don’t need
cr0x@server:~$ zfs get -o name,property,value sync pool/app/db
NAME PROPERTY VALUE SOURCE
pool/app/db sync standard default
Ce que cela signifie : ZFS honore les requêtes sync de l’application. Les bases de données peuvent forcer des écritures sync ; la latence se manifestera.
Décision : Gardez sync=standard pour la correction sauf si vous comprenez vraiment le risque. Si vous avez besoin d’un faible délai sync, envisagez un SLOG sur NVMe protégé contre la perte d’alimentation.
Task 10: Confirm encryption key status across boot (operational reliability)
cr0x@server:~$ zfs get -o name,property,value keystatus -r pool/app
NAME PROPERTY VALUE
pool/app keystatus available
pool/app/db keystatus available
Ce que cela signifie : Les clés sont chargées maintenant. Cela ne garantit pas qu’elles se chargeront automatiquement au prochain démarrage.
Décision : Choisissez une stratégie de chargement de clés (prompt vs fichier vs agent externe) qui correspond à votre automatisation de démarrage et à votre modèle de menace.
Task 11: Benchmark compression effect without lying to yourself
cr0x@server:~$ zfs create -o encryption=aes-256-gcm -o keyformat=passphrase -o keylocation=prompt -o compression=lz4 pool/bench-lz4
Enter passphrase:
Re-enter passphrase:
cr0x@server:~$ dd if=/dev/zero of=/pool/bench-lz4/zeros bs=1M count=2048 status=progress
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 2.31 s, 930 MB/s
cr0x@server:~$ zfs get -o name,property,value compressratio used,logicalused pool/bench-lz4
NAME PROPERTY VALUE SOURCE
pool/bench-lz4 compressratio 200.00x -
pool/bench-lz4 used 12.5M -
pool/bench-lz4 logicalused 2.00G -
Ce que cela signifie : Les zéros se compressent extrêmement bien ; vous voyez le « meilleur cas ». Notez aussi : le chiffrement n’a pas empêché la compression parce que la compression s’est produite en premier.
Décision : Utilisez aussi des données réalistes (pages de BD, logs, images VM). Se baser uniquement sur des zéros est la manière de créer un beau mensonge.
Task 12: Validate send/receive mode for encrypted replication
cr0x@server:~$ zfs send -nvpw pool/app@daily | head
send from @daily estimated size is 58.2G
send from @daily to pool/app@daily incremental size 2.14G
Ce que cela signifie : -w indique un send raw (le flux chiffré est préservé). Le récepteur n’a pas besoin de déchiffrer pour le stocker.
Décision : Utilisez les sends bruts pour des cibles de sauvegarde non fiables. Si le récepteur doit accéder aux données, utilisez des sends normaux et gérez les clés en conséquence.
Task 13: Check per-dataset space savings and whether you’re “winning”
cr0x@server:~$ zfs list -o name,used,logicalused,compressratio,encryption -r pool/app | head -n 6
NAME USED LOGICALUSED RATIO ENCRYPTION
pool/app 620G 1.02T 1.69x aes-256-gcm
pool/app/db 410G 710G 1.73x aes-256-gcm
pool/app/log 42G 120G 2.85x aes-256-gcm
pool/app/tmp 168G 170G 1.01x aes-256-gcm
Ce que cela signifie : Les logs compressent bien ; tmp ne compresse pas. Le chiffrement est cohérent.
Décision : Envisagez compression=off (ou lz4) pour tmp si le CPU est contraint, et conservez une compression plus forte là où elle rapporte.
Task 14: Inspect pool health and scrub status (because performance issues love sick pools)
cr0x@server:~$ zpool status -v pool
pool: pool
state: ONLINE
scan: scrub repaired 0B in 03:12:44 with 0 errors on Sun Dec 15 03:30:12 2025
config:
NAME STATE READ WRITE CKSUM
pool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
nvme0n1 ONLINE 0 0 0
nvme1n1 ONLINE 0 0 0
mirror-1 ONLINE 0 0 0
nvme2n1 ONLINE 0 0 0
nvme3n1 ONLINE 0 0 0
errors: No known data errors
Ce que cela signifie : Pool sain, scrub récent propre. Bonne base.
Décision : Si vous voyez des erreurs ou un resilvering, arrêtez de « tuner le chiffrement/la compression » et traitez d’abord la santé matérielle/du pool.
Task 15: Identify whether the workload is random IOPS or sequential bandwidth
cr0x@server:~$ iostat -x 1 3
avg-cpu: %user %nice %system %iowait %steal %idle
35.2 0.0 9.8 1.2 0.0 53.8
Device r/s w/s rkB/s wkB/s await svctm %util
nvme0n1 30.0 250.0 4700.0 52000.0 1.5 0.4 11.2
nvme1n1 30.0 240.0 4600.0 53000.0 1.6 0.4 11.0
Ce que cela signifie : Faible iowait et faible utilisation des dispositifs suggèrent que le stockage n’est pas saturé. Le CPU effectue du vrai travail.
Décision : Si vous êtes lent mais que les disques ne sont pas occupés, suspectez le CPU (niveau de compression, surcoût chiffrement, checksumming) ou le comportement applicatif (écritures sync).
Mode d’intervention rapide : trouver le goulot en quelques minutes
Quand la performance chute après activation du chiffrement ou changement de compression, n’entamez pas la danse « toucher trois réglages et espérer ».
Faites ceci dans l’ordre. Arrêtez-vous quand vous trouvez la contrainte.
Première étape : le pool est-il sain et n’est-il pas occupé par une opération de récupération ?
- Exécutez
zpool status. Cherchez resilvering, scrubs, erreurs de checksum. - Si un resilver ou scrub est en cours, acceptez la dégradation de performance ou replanifiez. Les réglages ne corrigeront pas la physique.
Deuxième étape : êtes-vous I/O-bound ou CPU-bound ?
- Exécutez
zpool iostat -v 1etiostat -x 1. - Si les dispositifs sont à forte
%utilet queawaitaugmente : I/O-bound. - Si les dispositifs sont tranquilles mais le CPU est chaud : CPU-bound (souvent compression/chiffrement/checksum, ou surcharge applicative).
Troisième étape : la latence des écritures sync est-elle le coupable ?
- Vérifiez la propriété
syncdu dataset. - Vérifiez si la charge est une base de données ou une VM qui fait des patterns fsync-intensifs.
- Si les écritures sync dominent et que vous n’avez pas de SLOG rapide et protégé, la performance sera « correcte » jusqu’à ce qu’elle ne le soit plus.
Quatrième étape : vos données se compressent-elles ? Ou brûlez-vous du CPU pour rien ?
- Vérifiez
compressratioetlogicalusedvsused. - Si le ratio est ~1.00x sur des datasets chauds et que le CPU est tendu, choisissez lz4 ou désactivez la compression là-bas.
Cinquième étape : le dimensionnement des blocs est-il inadapté à la charge ?
- Vérifiez
recordsizepour les datasets de fichiers. - Vérifiez
volblocksizepour les zvols. - Le décalage cause de l’amplification, qui ressemble à un « surcoût de chiffrement » parce que tout ralentit ensemble.
Trois mini-histoires d’entreprise issues du terrain
1) Incident causé par une mauvaise hypothèse : « Le chiffrement a cassé la compression »
Une entreprise SaaS de taille moyenne a déployé le chiffrement natif ZFS pour répondre à un questionnaire client. L’ingénieur en charge a activé
le chiffrement sur de nouveaux datasets et a laissé la compression telle quelle (zstd). Une semaine plus tard, la finance a remarqué que la croissance du stockage ralentissait.
Tout le monde s’est détendu. Puis les plaintes de latence ont commencé : appels API en timeout, jobs en retard, et un récit « ZFS est lent maintenant »
a envahi le canal d’incident hebdomadaire.
L’hypothèse erronée était subtile : l’équipe croyait que le chiffrement empêcherait la compression et augmenterait donc l’I/O. Dans leur tête,
le stockage deviendrait plus occupé, ils se sont donc focalisés sur le pool : disposition des vdevs, profondeur de file, « peut-être qu’il nous faut plus de NVMe ».
Pendant ce temps, les graphiques du pool semblaient ennuyeux—faible utilisation, pas de saturation évidente.
La correction est venue de quelqu’un qui a posé une question peu à la mode : « Le CPU fait-il quelque chose de différent ? » Ils ont vérifié
compressratio et ont vu que la compression était toujours efficace. Ils ont aussi remarqué que les nœuds applicatifs étaient devenus CPU-tight parce qu’un déploiement séparé
avait augmenté la charge TLS sur les mêmes hôtes qui faisaient tourner les services de stockage. Le changement de chiffrement a été la paille,
pas le camion.
Ils ont déplacé les services de stockage vers des hôtes avec plus de marge par cœur et ont ajusté la compression de zstd à lz4 sur le dataset d’écritures aléatoires le plus chargé.
La latence s’est stabilisée. Le post-incident a été franc : le chiffrement n’a pas tué la compression ; la mauvaise planification de capacité l’a fait.
2) Optimisation qui s’est retournée contre eux : « zstd-19 partout »
Une équipe IT d’entreprise a migré d’un array legacy vers ZFS et a adoré les économies de compression. Quelqu’un a lu que zstd a de bons ratios et a décidé de standardiser
un niveau élevé sur tous les datasets, y compris le stockage VM et un cache de build très chargé.
Les résultats immédiats semblaient bons sur le tableau de bord : le ratio de compression s’améliorait, et les graphiques de croissance du stockage rendaient tout le monde intelligent.
Puis la hotline a commencé à recevoir des tickets « VM lente » difficiles à reproduire. La ferme de build a commencé à manquer des SLA par petites marges—juste assez pour irriter les équipes sans déclencher un incident majeur.
Le retour de bâton était classique : ils ont amélioré l’efficacité d’espace au prix d’une latence CPU par I/O. Les niveaux de compression élevés augmentent le temps CPU
par bloc. Sur les charges séquentielles, on peut masquer cela par le débit. Sur l’I/O aléatoire, on ne peut pas. Chaque I/O portait maintenant une petite taxe CPU,
et la somme des petites taxes crée des jitter systémiques.
Ils ont remis les datasets VM à lz4, gardé zstd (modéré) pour les archives de logs, et retenu la leçon : la compression est une caractéristique de charge, pas une religion globale.
3) La pratique ennuyeuse mais correcte qui a sauvé la mise : chargement des clés et discipline de réplication
Une entreprise multi-sites utilisait des datasets chiffrés et les répliquait chaque nuit. Leur pratique « ennuyeuse » reposait sur deux principes :
(1) les clés étaient gérées avec une hiérarchie cohérente, et (2) la réplication était testée trimestriellement via un exercice de restauration. Pas d’héroïsme, juste de la répétition.
Un nœud de stockage est tombé en panne de façon irréversible—niveau matériel, pas d’histoire romantique. Ils ont promu la réplique, importé le pool et relancé les services.
La restauration n’a pas été rapide, mais elle a été prévisible. Surtout, cela n’a pas tourné en fiasco de gestion de clés.
Le détail salvateur : ils utilisaient des sends bruts pour les copies hors site et s’assuraient que le site de récupération disposait des clés nécessaires (et du processus
pour les charger) documenté et répété. Le récepteur n’avait pas besoin de déchiffrer le flux brut pour le stocker, ce qui a réduit les « pièces mobiles »
au milieu d’un événement stressant.
Le postmortem n’avait pas de feux d’artifice. C’était presque décevant. Voilà à quoi ressemble le succès en production : une récupération sans histoire et
pas d’improvisation cryptographique nocturne.
Erreurs courantes : symptômes → cause racine → correction
Ce sont des motifs récurrents. Si vous voyez le symptôme, ne le debatez pas sur Slack. Allez directement à la cause racine et corrigez.
1) Symptom: compression ratio stuck near 1.00x, CPU elevated
Cause racine : Les données sont déjà compressées ou chiffrées avant que ZFS ne les voie (fichiers média, sauvegardes chiffrées, chiffrement applicatif).
Correction : Utilisez compression=lz4 ou compression=off sur ce dataset. Gardez la compression là où elle est rentable.
2) Symptom: performance dropped after enabling encryption, but disks are not busy
Cause racine : Limitation CPU : chiffrement + compression + surcharge de checksum concurrencent maintenant les charges applicatives.
Correction : Réduisez le niveau de compression (zstd → lz4), ajoutez de la marge CPU, isolez les services de stockage, ou scale out. Prouvez avec iostat et statistiques ARC.
3) Symptom: latency spikes on database writes, especially during peak
Cause racine : Écritures sync (fsync) forçant le comportement ZIL ; pas de SLOG rapide protégé contre la perte d’alimentation, ou SLOG mal dimensionné/mal configuré.
Correction : Conservez sync=standard ; ajoutez un vrai SLOG ; validez avec des tests de charge. Ne mettez pas sync=disabled comme « correction de performance » sauf si vous aimez expliquer des pertes de données.
4) Symptom: VM storage feels “randomly slow,” small I/O is terrible
Cause racine : Mauvais volblocksize causant amplification d’écriture ; parfois combiné à des niveaux de compression élevés.
Correction : Recréez le zvol avec le bon volblocksize (souvent 8K/16K selon la charge) et migrez les données ; utilisez lz4 pour les zvols VM sauf mesure contraire.
5) Symptom: system boots, but datasets won’t mount; services fail “mysteriously”
Cause racine : Datasets chiffrés avec clés non chargées au démarrage ; keylocation=prompt sur des systèmes sans console ; automatisation manquante.
Correction : Mettez en place un mécanisme de chargement de clés conforme à votre modèle de menace (fichier avec permissions restreintes, agent externe, prompt manuel avec runbooks) et testez la récupération après reboot.
6) Symptom: replication is slow, CPU on sender or receiver spikes
Cause racine : Les sends non-raw nécessitent déchiffrement/rechiffrement ou recompression ; la compression élevée sur des datasets vivants peut aussi augmenter le coût CPU pendant le send.
Correction : Utilisez les sends bruts pour des sauvegardes chiffrées quand le récepteur n’a pas besoin de texte clair. Envisagez d’ajuster le niveau de compression sur les datasets à fort taux de changement.
Listes de vérification / plan étape par étape
Checklist A: Setting up an encrypted + compressed dataset (production-safe defaults)
- Créez un dataset dédié par classe de charge (db, logs, media, vm, backups).
- Activez le chiffrement à la création du dataset (concevez l’héritage des clés intentionnellement).
- Démarrez avec
compression=lz4sauf si vous avez une raison mesurée pour zstd. - Réglez
recordsizepour correspondre à la charge (grand pour le séquentiel ; plus petit pour les lectures aléatoires). - Pour les zvols, choisissez
volblocksizeavec soin (et documentez-le). - Décidez la politique
syncet si vous avez besoin d’un SLOG. - Test de redémarrage : le système peut-il importer le pool et charger les clés de manière prévisible ?
Checklist B: Changing compression on an existing dataset without drama
- Mesurez la base : latence, CPU,
compressratio, et iostat du pool sous charge représentative. - Changez la propriété de compression (elle s’applique aux nouvelles écritures ; les anciens blocs restent tels quels).
- Observez sous charge réelle ; ne vous fiez pas aux microbenchmarks seuls.
- Si vous devez recomprimer les données existantes, planifiez une réécriture (send/receive dans un nouveau dataset ou copie/rsync).
- Réévaluez après une semaine de charge typique ; les tests courts manquent l’entropie réelle du monde.
Checklist C: Encryption operational hygiene (the part that prevents “it won’t mount”)
- Standardisez keyformat et keylocation entre environnements quand c’est possible.
- Documentez les étapes de chargement des clés et qui y a accès.
- Testez la récupération : importer le pool, charger les clés, monter les datasets, démarrer les services.
- Validez que le mode de réplication (raw vs non-raw) correspond aux objectifs de sécurité.
- Auditez l’héritage : assurez-vous que des datasets enfants sensibles n’ont pas été laissés déchiffrés par erreur.
FAQ
1) Does ZFS encrypt before it compresses?
Pour le chiffrement natif ZFS, ZFS compresse d’abord, puis chiffre. C’est pourquoi la compression fonctionne encore sur des datasets chiffrés.
2) Why is compression ineffective on some encrypted datasets?
Généralement parce que les données étaient déjà chiffrées ou compressées avant que ZFS ne les voie (chiffrement applicatif, formats média,
sauvegardes compressées). ZFS ne peut pas compresser du hasard.
3) Should I use zstd or lz4 with encrypted datasets?
Par défaut, privilégiez lz4 pour les datasets chauds et sensibles à la latence. Utilisez zstd quand vous avez mesuré des gains d’espace significatifs et que vous avez du budget CPU.
Le chiffrement ne change pas cette règle ; il ajoute simplement un consommateur CPU supplémentaire.
4) If I change compression, does ZFS recompress existing data?
Non. La propriété affecte les blocs nouvellement écrits. Pour recomprimer les données existantes, il faut les réécrire (copier, send/receive vers un nouveau dataset).
5) Does encryption hurt ARC caching?
Le chiffrement modifie ce que ZFS doit faire aux lectures/écritures, mais l’efficacité de l’ARC dépend principalement des motifs d’accès et de la taille du jeu de travail.
Si vous manquez souvent l’ARC, vous le ressentirez indépendamment du chiffrement.
6) Is raw send the right choice for encrypted backups?
Si la cible de sauvegarde n’a pas besoin d’accéder au texte clair, le raw send est excellent : il préserve le chiffrement et évite l’exposition des clés sur le récepteur.
Si vous avez besoin de restaurations montables et lisibles sur le récepteur, planifiez la gestion des clés en conséquence.
7) Can I enable encryption on an existing unencrypted dataset?
Pas in-place comme certains l’espèrent. En pratique, créez un nouveau dataset chiffré et migrez les données (send/receive ou copie), puis basculez.
8) What’s the biggest performance knob besides compression algorithm?
Le dimensionnement des blocs : recordsize pour les datasets de fichiers et volblocksize pour les zvols. Un mauvais dimensionnement crée une amplification que aucun algorithme ne pourra compenser.
9) Should I set sync=disabled to make encrypted datasets fast?
Non, pas comme mesure générale. Cela échange durabilité contre vitesse et transforme certains incidents en perte de données. Si la latence sync est le problème,
résolvez-le avec un vrai SLOG ou en adaptant l’application.
10) How do I know if encryption overhead is my bottleneck?
Si les disques ne sont pas saturés, l’ARC n’est pas le problème, et le CPU est à fond pendant les opérations I/O intensives, le chiffrement (plus compression/checksums)
peut contribuer. Confirmez avec des métriques CPU système et comparez le comportement entre lz4 et des compressions plus lourdes.
Conclusion : prochaines étapes pratiques
L’« ordre qui fait la performance » est simple : réduisez les octets tant qu’ils sont encore compressibles, puis chiffrez. Le chiffrement natif ZFS
le fait déjà. Votre travail n’est pas de le combattre ; votre travail est de vous assurer que le reste du système—marge CPU, dimensionnement des blocs,
politique sync, et opérations de clés—ne sabote pas le gain.
Prochaines étapes que vous pouvez exécuter cette semaine
- Inventoriez les datasets : chiffrement on/off, algorithme de compression, compressratio, recordsize/volblocksize.
- Identifiez les datasets chauds avec compressratio ~1.00x et décidez si la compression doit être lz4 ou off.
- Exécutez le mode d’intervention rapide pendant la charge de pointe une fois, enregistrez les résultats et conservez-les comme baseline.
- Choisissez une classe de charge (VM ou bases de données) et validez le dimensionnement des blocs ; planifiez des migrations pour les pires cas.
- Testez une séquence reboot + chargement des clés + démarrage des services dans une fenêtre contrôlée. Si ce n’est pas ennuyeux, ce n’est pas terminé.