ZFS : utiliser NVMe comme L2ARC — quand l’ARC ne suffit pas

Cet article vous a aidé ?

À un moment donné, tout administrateur ZFS rencontre le même antagoniste : un working set qui ne rentre pas en RAM. Le symptôme est familier — pics de latence, disques qui s’affolent, utilisateurs affirmant « le stockage est lent » avec la certitude morale de quelqu’un qui n’a jamais regardé iostat.

Utiliser NVMe comme L2ARC semble être la solution évidente : ajouter un périphérique cache rapide et passer à autre chose. Parfois c’est brillant. Parfois c’est une façon coûteuse d’user prématurément votre NVMe pendant que les performances restent obstinément médiocres. Cet article explique dans quel monde vous vous trouvez — avant de l’apprendre en production.

Ce qu’est (et n’est pas) le L2ARC

ZFS dispose d’un cache primaire appelé ARC (Adaptive Replacement Cache). Il vit en RAM et il est extrêmement efficace pour rendre les lectures répétées peu coûteuses. Quand l’ARC est trop petit pour votre working set, ZFS peut étendre le cache sur un périphérique rapide : le L2ARC, « Level 2 ARC ». L2ARC est un cache de lecture. Pas un tampon d’écriture, pas un accélérateur de journalisation, pas une baguette magique.

Ce qui se passe en pratique :

  • ARC suit ce qui est chaud. Si ARC ne peut pas tout garder, ZFS peut pousser certaines de ces données vers L2ARC.
  • Lors d’un miss dans ARC, ZFS peut regarder dans le L2ARC. Si trouvé, il lit depuis le NVMe plutôt que depuis des disques mécaniques ou des SSD plus lents.
  • Le contenu du L2ARC est rempli au fil du temps. Historiquement il n’était pas persistant après reboot ; les implémentations récentes peuvent le persister (plus loin, on en reparle).

Ce que le L2ARC ne fait pas :

  • Il n’accélère pas les écritures synchrones (c’est le domaine du SLOG, et même là : seulement pour des charges spécifiques).
  • Il ne répare pas un pool lent à cause de fragmentation, d’un mauvais layout de vdev ou d’un goulet CPU.
  • Il n’enlève pas la nécessité de dimensionner correctement la RAM. Le L2ARC a toujours besoin de métadonnées en RAM pour être utile.

Vérité opérationnelle : le L2ARC est un outil pour rendre un type précis de latence de lecture moins coûteuse. Si votre problème est « les lectures aléatoires me tuent et les données sont relues », il peut briller. Si votre problème est « tout est aléatoire et jamais relu », il ne servira à rien.

Une citation à mettre sur chaque planning d’astreinte : L’espoir n’est pas une stratégie — attribuée au général Gordon R. Sullivan. Traitez le L2ARC de la même façon : mesurez, puis décidez.

Faits et historique intéressants (court, utile et légèrement subjectif)

  • ARC précède la plupart des habitudes « cloud ». ZFS et ARC proviennent de l’ingénierie de l’ère Solaris où la mémoire était coûteuse et les disques lents, donc la politique de cache était sérieuse.
  • Le L2ARC a été conçu pour la mise en cache en lecture, pas pour la durabilité. Les premières implémentations perdaient le cache au reboot ; cela a façonné les attentes opérationnelles pendant des années.
  • Le L2ARC nécessite de la RAM pour décrire ce qu’il contient. Chaque bloc mis en cache nécessite des métadonnées dans l’ARC. Un L2ARC gigantesque peut discrètement voler de la RAM dont votre ARC a désespérément besoin.
  • Le NVMe a rendu le L2ARC moins embarrassant. Les premiers périphériques L2ARC étaient souvent des SSD SATA ; les améliorations de latence étaient réelles, mais pas toujours spectaculaires. La faible latence du NVMe change les compromis.
  • Prélecture et L2ARC ont une relation compliquée. Les lectures séquentielles peuvent inonder les caches avec des données que vous ne toucherez jamais à nouveau. ZFS a ajouté des options (comme l2arc_noprefetch) parce que les gens n’arrêtaient pas de cacher leurs regrets.
  • Il y a un « coût de chauffe ». Le L2ARC se remplit progressivement, pas instantanément. Les premières heures (ou jours) peuvent sembler pires que « pas de L2ARC », surtout si vous l’avez mal dimensionné.
  • Le débit d’alimentation du cache est volontairement limité. ZFS limite l’agressivité d’écriture vers le L2ARC pour éviter de transformer votre système en usine d’écriture de cache.
  • Le L2ARC n’est pas une fonctionnalité sans conséquence. Il consomme CPU, mémoire et écritures vers votre NVMe. Cet usure est réelle ; planifiez-la comme vous planifiez la rétention des logs.
  • Le L2ARC persistant existe maintenant dans les implémentations ZFS modernes. Il réduit la douleur de chauffe après un reboot, mais ce n’est pas universel et ce n’est pas gratuit.

Quand le L2ARC NVMe aide vraiment

Le L2ARC sert des charges avec lectures répétées qui échouent dans l’ARC mais pourraient être servies plus rapidement que ce que le pool peut fournir.

Bonnes adéquations

  • Hôtes VM avec blocs « chauds » stables parmi de nombreux invités : bibliothèques partagées, fichiers de démarrage, binaires communs, dépôts de patch.
  • Bases de données à lecture intensive où le working set est juste un peu trop grand pour la RAM (ou si vous refusez d’acheter plus de RAM pour des raisons budgétaires).
  • Caches CI/build où les mêmes toolchains sont réutilisés et votre pool est basé sur des HDD.
  • Clusters d’analytics qui scannent de manière répétée les mêmes partitions « récentes », mais pas de façon purement séquentielle.

La condition clé : le L2ARC doit être plus rapide que ce qu’il remplace

Si votre pool est déjà NVMe ou un miroir SSD performant, le L2ARC peut être redondant. Si votre pool est un RAIDZ HDD avec lectures aléatoires, le L2ARC peut sembler miraculeux — à condition que vous relisiez réellement les mêmes blocs.

Blague #1 : Le L2ARC, c’est comme un deuxième frigo — génial si vous conservez des restes, inutile si vous ne mangez que du takeout.

Quand le L2ARC est un piège

La plupart des récits « le L2ARC a déçu » se résument à l’un de ces cas :

1) Votre charge ne relit pas

Ingestion de sauvegardes, scans analytiques froids, copies de fichiers ponctuelles, traitement média séquentiel volumineux — ces charges ont tendance à balayer le cache et disparaître. Le L2ARC devient du trafic d’écriture vers le NVMe avec peu de retour en taux de hits.

2) Votre ARC est affamé, et le L2ARC aggrave la situation

Le L2ARC requiert des métadonnées en RAM. Si votre système est déjà sous pression mémoire, ajouter un grand L2ARC peut réduire la taille effective de l’ARC et augmenter les misses. Félicitations, vous avez mis plus en cache sur NVMe tout en perdant ce qui rend le caching rapide : la RAM.

3) Votre problème n’est pas en lecture

Si la douleur provient d’écritures synchrones, de petites écritures aléatoires ou de contention sur les métadonnées, le L2ARC aura peu d’effet. Souvent le correctif adéquat est un layout différent de vdev, un vdev spécial pour les métadonnées/petits blocs, plus de RAM, ou le réglage de l’application.

4) Vous venez de construire un cache qui thrash

Le thrash signifie que les blocs sont écrits dans le L2ARC puis évincés avant d’être réutilisés. Cela peut arriver parce que le working set est trop grand, que le taux d’alimentation du cache est trop élevé, ou que le motif est une fenêtre roulante plus grande que ARC+L2ARC.

Choisir un NVMe pour L2ARC : latence, endurance et pourquoi « rapide » ne suffit pas

Pour le L2ARC, vous voulez une basse latence sous charge mixte, pas seulement un débit séquentiel héroïque que vous n’atteindrez jamais dans un cache. Les chiffres marketing ne montrent pas la latence en queue lorsque le périphérique est chaud, partiellement plein et effectue du garbage collection en arrière-plan. C’est votre monde réel.

Latence et comportement en file d’attente

Les hits L2ARC sont des lectures aléatoires. Votre NVMe doit gérer des IOPS élevés sans transformer la latence p99 en surprise hebdomadaire. Les modèles ayant des performances cohérentes (souvent des modèles « entreprise ») comptent ici. Les disques grand public peuvent convenir, mais le risque est un comportement plus saccadé lorsque le cache SLC est épuisé ou sous des écritures soutenues liées au remplissage du cache.

L’endurance est une caractéristique, pas une note de bas de page

Le L2ARC est rempli par des écritures. Certaines charges provoquent un churn constant : des blocs sont écrits dans le cache, remplacés, réécrits. Cela peut user les ratings TBW des disques grand public plus vite que prévu par vos achats.

Règle empirique : si vous ne pouvez pas expliquer de manière convaincante votre taux d’écriture de cache, n’achetez pas le NVMe le moins cher. Achetez celui que vous pourrez remplacer sans discussion de carrière.

Protection contre la perte d’alimentation (PLP)

Le L2ARC est un cache ; il n’a pas besoin d’être durable. Mais le comportement en cas de perte d’alimentation compte toujours car un périphérique qui se comporte mal lors de coupures peut bloquer le bus PCIe, boucher les chemins I/O ou provoquer des resets de contrôleur. Le PLP n’est pas obligatoire pour le L2ARC, mais un comportement « entreprise et sérieux » est précieux en production.

Dimensionner le L2ARC : maths simples, contraintes réelles

Les gens dimensionnent le L2ARC comme s’ils dimensionnaient du stockage objet : « plus c’est mieux. » C’est comme ça qu’on se retrouve avec un cache de 4 To devant un système avec 64 Go de RAM et un ARC qui tousse.

La réalité du surcoût en RAM

Le L2ARC a besoin de métadonnées dans l’ARC pour chaque bloc mis en cache. Le surcoût exact varie selon l’implémentation et le recordsize, mais vous devez supposer un coût RAM réel et non négligeable. Si l’ARC est déjà tendu, un grand L2ARC peut nuire. Vous voulez assez de RAM pour garder les métadonnées les plus utiles et les données fréquemment utilisées dans l’ARC, tandis que le L2ARC attrape ce qui déborde.

Commencez petit et prouvez la valeur

Points de départ opérationnellement sensés :

  • Choisissez une taille L2ARC qui est au plus quelques multiples de la RAM pour des systèmes typiques, sauf si vous avez mesuré et pouvez justifier davantage.
  • Privilégiez un NVMe « à taille adaptée » plutôt que le « plus grand disponible ». Un cache qui ne chauffe jamais est un monument à l’optimisme.
  • Mesurez les taux de hit et l’amélioration de latence avant d’augmenter.

Recordsize et compression comptent

ZFS met en cache des blocs. Si vos datasets utilisent un recordsize de 1M pour des écritures séquentielles volumineuses, cela peut changer le comportement de caching comparé à un recordsize de 16K typique de certaines bases de données. La compression affecte aussi combien de données « logiques » tiennent dans le cache et peut améliorer la capacité effective du cache — parfois de façon spectaculaire.

Réglages importants (et ceux qui comptent peu)

La plupart du tuning du L2ARC vise à réduire la mise en cache inutile et à empêcher le remplissage du cache de devenir une charge à part entière.

Privilégier les lectures à la demande plutôt que la prélecture

La prélecture est ZFS qui essaie d’être utile pour l’accès séquentiel. Pour le L2ARC, elle peut être activement contre-productive car elle remplit le cache de données lues une fois, séquentiellement, et jamais relues.

Approche courante : activer le L2ARC mais le configurer pour éviter de mettre en cache la prélecture. Sur Linux/OpenZFS, cela se contrôle souvent via l2arc_noprefetch. Les valeurs par défaut et le comportement varient selon la version ; mesurez sur votre build.

Contrôler le débit d’alimentation

Le L2ARC est alimenté par l’éviction de l’ARC. Il y a des tunables contrôlant combien est écrit par intervalle et la vitesse de montée en charge. Si vous poussez trop fort, vous :

  • Augmentez la charge d’écriture sur le NVMe (impact endurance).
  • Dépensez du CPU pour la tenue des métadonnées du cache.
  • Potentiellement entrez en compétition avec l’I/O réelle du workload.

L2ARC persistant : utile, mais pas à idolâtrer

Le L2ARC persistant réduit la chauffe après reboot en conservant en-têtes et contenu du cache entre redémarrages. C’est un grand avantage pour les systèmes qui rebootent pour mises à jour et ont besoin de performances post-reboot prévisibles. Mais la persistance peut augmenter la complexité et le comportement de scan au démarrage. Traitez-la comme toute autre fonctionnalité : testez, puis déployez.

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

Voici des tâches réelles que vous pouvez exécuter sur un hôte Linux OpenZFS. Les sorties sont représentatives. Vos chiffres différeront ; vos décisions ne devraient pas être basées sur des impressions.

Task 1: Verify pool health before touching cache

cr0x@server:~$ sudo zpool status -v tank
  pool: tank
 state: ONLINE
  scan: scrub repaired 0B in 02:11:43 with 0 errors on Sun Dec 22 03:10:12 2025
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

errors: No known data errors

Ce que cela signifie : Vous n’êtes pas déjà en feu. Si vous voyez des erreurs de checksum ou des vdevs dégradés, corrigez cela d’abord.

Décision : N’ajoutez un L2ARC qu’à un pool stable. Un périphérique cache ne sauvera pas un pool malade.

Task 2: Check whether an L2ARC already exists

cr0x@server:~$ sudo zpool list -v tank
NAME         SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank        65.4T  41.2T  24.2T        -         -    22%    63%  1.00x  ONLINE  -
  raidz2   65.4T  41.2T  24.2T        -         -    22%    63%
    sda        -      -      -        -         -      -      -
    sdb        -      -      -        -         -      -      -
    sdc        -      -      -        -         -      -      -
    sdd        -      -      -        -         -      -      -
    sde        -      -      -        -         -      -      -
    sdf        -      -      -        -         -      -      -

Ce que cela signifie : Aucune section cache affichée, donc pas de L2ARC.

Décision : Procédez à la sélection et à l’attachement d’un NVMe, ou arrêtez-vous si vous pouvez résoudre le problème avec de la RAM ou un meilleur layout.

Task 3: Confirm the NVMe device identity and health (before ZFS touches it)

cr0x@server:~$ lsblk -o NAME,MODEL,SIZE,ROTA,TYPE,MOUNTPOINT | grep -E 'nvme|NAME'
NAME        MODEL                 SIZE ROTA TYPE MOUNTPOINT
nvme0n1     Samsung SSD 980 PRO  931.5G    0 disk

Ce que cela signifie : Vous vous apprêtez à utiliser /dev/nvme0n1, 1 To, non rotatif.

Décision : Confirmez que vous ne pointez pas sur votre disque système. Si ce NVMe contient également root, arrêtez. Le partage est possible mais rarement judicieux.

Task 4: Check NVMe SMART and endurance indicators

cr0x@server:~$ sudo smartctl -a /dev/nvme0n1 | sed -n '1,35p'
smartctl 7.4 2023-08-01 r5530 [x86_64-linux-6.8.0] (local build)
=== START OF INFORMATION SECTION ===
Model Number:                       Samsung SSD 980 PRO 1TB
Serial Number:                      S5GXNF0R123456A
Firmware Version:                   5B2QGXA7
PCI Vendor/Subsystem ID:            0x144d
IEEE OUI Identifier:                0x002538
Total NVM Capacity:                 1,000,204,886,016 [1.00 TB]
Unallocated NVM Capacity:           0
Controller ID:                      6
Number of Namespaces:               1
Namespace 1 Size/Capacity:          1,000,204,886,016 [1.00 TB]

SMART/Health Information (NVMe Log 0x02)
Critical Warning:                   0x00
Temperature:                        44 Celsius
Available Spare:                    100%
Available Spare Threshold:          10%
Percentage Used:                    2%
Data Units Written:                 14,512,331
Data Units Read:                    22,900,112

Ce que cela signifie : Le disque est sain, usure faible (Percentage Used).

Décision : Si l’usure est déjà élevée, ne pas proposer ce périphérique pour le churn du cache. Si vous devez l’utiliser, limitez le débit d’alimentation et surveillez les écritures.

Task 5: Observe current ARC size and pressure

cr0x@server:~$ arcstat 1 3
    time  read  miss  miss%  dmis  dm%  pmis  pm%  mmis  mm%  arcsize  c
12:10:01  8160  1432     17   902   11   420    5   110    1     46G  58G
12:10:02  7992  1470     18   961   12   401    5   108    1     46G  58G
12:10:03  8421  1522     18  1002   12   413    5   107    1     46G  58G

Ce que cela signifie : L’ARC est ~46G, target/limit ~58G. Taux de miss ~18%. Ça peut être acceptable ou catastrophique selon la latence du pool.

Décision : Si l’ARC est loin de sa cible parce que l’OS la prive de mémoire, corrigez la pression mémoire d’abord. Le L2ARC ne remplace pas la RAM.

Task 6: Measure where your reads are coming from right now

cr0x@server:~$ sudo zpool iostat -v tank 1 3
              capacity     operations     bandwidth
pool        alloc   free   read  write   read  write
----------  -----  -----  -----  -----  -----  -----
tank        41.2T  24.2T   8900    420   195M  6.8M
  raidz2    41.2T  24.2T   8900    420   195M  6.8M
    sda         -      -   1500     70  33.0M  1.2M
    sdb         -      -   1490     72  32.8M  1.1M
    sdc         -      -   1520     71  33.5M  1.1M
    sdd         -      -   1475     68  32.4M  1.1M
    sde         -      -   1460     69  32.1M  1.1M
    sdf         -      -   1455     70  31.9M  1.1M

Ce que cela signifie : Les lectures frappent fortement les vdevs HDD. Si la latence est élevée et que le working set est relu, le L2ARC peut aider.

Décision : Si les disques sont saturés et les lectures aléatoires, un cache est plausible. Si les lectures sont petites et axées sur les métadonnées, envisagez plutôt un vdev spécial.

Task 7: Attach NVMe as L2ARC

cr0x@server:~$ sudo zpool add tank cache /dev/nvme0n1
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
        cache
          nvme0n1                   ONLINE       0     0     0

Ce que cela signifie : Le NVMe est maintenant un périphérique cache (L2ARC).

Décision : Ne déclarez pas la victoire. Maintenant vous surveillez la chauffe, le taux de hit et les écritures NVMe.

Task 8: Verify L2ARC is being used (hit rates and size)

cr0x@server:~$ arcstat 1 5 | sed -n '1,6p'
    time  read  miss  miss%  ...  l2hit  l2miss  l2miss%  l2bytes  arcsize  c
12:18:01  9010  1210     13  ...   2200     980       31     190G     47G  58G
12:18:02  9155  1198     13  ...   2350     960       29     191G     47G  58G
12:18:03  9033  1160     12  ...   2480     910       27     192G     47G  58G
12:18:04  9199  1205     13  ...   2605     920       26     194G     47G  58G
12:18:05  9122  1188     13  ...   2710     890       25     195G     47G  58G

Ce que cela signifie : Le L2ARC contient ~195G et sert des hits (l2hit). Le pourcentage de L2 miss diminue à mesure qu’il chauffe.

Décision : Si l2bytes reste minuscule pendant des heures sous charge stable, quelque chose cloche : débit d’alimentation, charge ou simplement absence d’éviction de blocs utiles.

Task 9: Watch NVMe I/O to ensure cache fill isn’t clobbering latency

cr0x@server:~$ iostat -x 1 3 | sed -n '1,25p'
Linux 6.8.0 (server)  12/26/2025  _x86_64_  (32 CPU)

Device            r/s     w/s   rMB/s   wMB/s  await  svctm  %util
nvme0n1         3200.0  180.0   125.0    40.0   0.7    0.2   68.0
sda              250.0   12.0     4.1     0.3  18.4    2.2   55.0
sdb              240.0   11.0     4.0     0.3  19.1    2.2   54.0

Ce que cela signifie : Le NVMe est occupé, mais la latence (await) est faible. Les HDD montrent un await plus élevé, typique.

Décision : Si le await du NVMe monte à plusieurs millisecondes et concurrence l’I/O applicative, réduisez le débit d’écriture du L2ARC ou reconsidérez la conception. Votre cache ne doit pas devenir votre périphérique le plus chaud.

Task 10: Confirm dataset properties that influence cache behavior

cr0x@server:~$ sudo zfs get -o name,property,value,source recordsize,primarycache,secondarycache,compression tank/vmstore
NAME          PROPERTY        VALUE     SOURCE
tank/vmstore  recordsize      128K      local
tank/vmstore  primarycache    all       default
tank/vmstore  secondarycache  all       default
tank/vmstore  compression     lz4       local

Ce que cela signifie : ARC et L2ARC sont autorisés (primarycache=all, secondarycache=all).

Décision : Si un dataset a secondarycache=none, le L2ARC ne le mettra pas en cache. Cela peut être souhaitable pour des sauvegardes en streaming, ou une mauvaise configuration silencieuse.

Task 11: Exclude streaming datasets from L2ARC to prevent pollution

cr0x@server:~$ sudo zfs set secondarycache=none tank/backups
cr0x@server:~$ sudo zfs get -o name,property,value,source secondarycache tank/backups
NAME         PROPERTY        VALUE  SOURCE
tank/backups secondarycache  none   local

Ce que cela signifie : Le dataset de sauvegarde ne remplira pas le L2ARC.

Décision : Faites cela lorsque vous avez de grands lecteurs/écrivains séquentiels qui évinceraient des blocs utiles mis en cache. Gardez le cache pour les workloads qui le méritent.

Task 12: Inspect L2ARC-related module parameters (Linux OpenZFS)

cr0x@server:~$ sudo sysctl -a 2>/dev/null | grep -E 'l2arc_|zfs\.arc_' | head
zfs.l2arc_noprefetch = 1
zfs.l2arc_write_max = 8388608
zfs.l2arc_write_boost = 33554432
zfs.arc_max = 62277025792
zfs.arc_min = 15569256448

Ce que cela signifie : La prélecture n’est pas mise en cache dans le L2ARC, et des limites d’écriture sont définies (octets par intervalle).

Décision : Si l2arc_noprefetch vaut 0 et que vous avez des workloads séquentiels, envisagez de l’activer. Si le remplissage du cache est trop agressif, ajustez prudemment l2arc_write_max et validez.

Task 13: Change an L2ARC tunable safely (temporary) and validate impact

cr0x@server:~$ sudo sysctl -w zfs.l2arc_write_max=4194304
zfs.l2arc_write_max = 4194304

Ce que cela signifie : Débit maximal d’écriture réduit vers le L2ARC (ici à 4 MiB par intervalle ; l’intervalle dépend de l’implémentation).

Décision : Utilisez cela si les écritures NVMe concurrencent des lectures/écritures sensibles à la latence. Re-vérifiez iostat et la latence p99 des applications après le changement.

Task 14: Confirm that you are not confusing SLOG with L2ARC

cr0x@server:~$ sudo zpool status tank | sed -n '1,35p'
  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
        cache
          nvme0n1                   ONLINE       0     0     0

Ce que cela signifie : Seule une vdev cache est présente. L’absence d’une section logs signifie pas de SLOG.

Décision : Si votre douleur vient d’écritures synchrones (NFS avec sync, bases de données avec modèles fsync intensifs), le L2ARC ne résoudra pas ça. Envisagez le SLOG — prudemment — uniquement après mesure.

Task 15: Remove L2ARC (if it’s not helping) without drama

cr0x@server:~$ sudo zpool remove tank nvme0n1
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

Ce que cela signifie : L2ARC détaché. Le pool reste inchangé structurellement (les vdevs cache ne contiennent pas de données uniques).

Décision : Si les performances ne changent pas ou s’améliorent après suppression, votre cache était du bruit ou nuisible. Arrêtez d’essayer de le faire fonctionner et corrigez le vrai goulet.

Task 16: Evaluate memory pressure and reclaim behavior (Linux)

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           128Gi        94Gi       4.1Gi       1.2Gi        30Gi        26Gi
Swap:           16Gi       2.3Gi        13Gi

Ce que cela signifie : La RAM est fortement utilisée, available est 26Gi, swap est utilisé.

Décision : L’activité de swap sur une machine de stockage est souvent un signe que l’ARC est étranglé ou que l’hôte est surchargé (VMs, containers). Avant d’ajouter un L2ARC, envisagez d’ajouter de la RAM ou de réduire les charges en colocation. Le surcoût mémoire du L2ARC n’aidera pas un hôte qui swap.

Procédure de diagnostic rapide : trouver le goulot en minutes

Ceci est l’ordre qui fait gagner du temps en production. L’objectif n’est pas « collecter toutes les métriques ». L’objectif est « identifier la ressource limitante et le correctif le plus simple ».

Première étape : déterminer si vous avez un problème de latence de lecture ou autre

  • Vérifiez l’I/O du pool et des proxys de latence : zpool iostat -v 1, iostat -x 1.
  • Si les disques ne sont pas occupés et que la latence est faible, votre problème peut être CPU, réseau, verrous applicatifs ou comportement d’écriture sync.

Deuxième étape : vérifier l’efficacité de l’ARC et la pression mémoire

  • Utilisez arcstat pour évaluer le taux de misses et la stabilité de la taille ARC.
  • Utilisez free -h et observez le swap. Si l’hôte swappe, corrigez cela. Le L2ARC n’est pas un remède à la famine mémoire.

Troisième étape : confirmer que la charge a de la localité temporelle

  • Recherchez des lectures répétées : comportement de cache de DB, vagues de démarrage de VM, builds CI répétés.
  • Si c’est principalement du streaming, le L2ARC sera un générateur d’usure.

Quatrième étape : tester un petit L2ARC et mesurer

  • Ajoutez un NVMe L2ARC et surveillez l2hit, l2miss et la latence p95/p99 applicative.
  • La chauffe importe ; évaluez sur un cycle de workload, pas sur 10 minutes.

Cinquième étape : si c’est lourd en métadonnées, envisagez une autre conception

  • L’I/O aléatoire des métadonnées sur des pools HDD répond souvent mieux à un vdev spécial qu’au L2ARC.
  • Si la latence des écritures sync est le problème, mesurez et envisagez le SLOG (avec le périphérique adéquat et des attentes réalistes).

Trois micro-récits du milieu professionnel

Micro-récit 1 : l’incident causé par une fausse hypothèse

Ils avaient un cluster de virtualisation chargé sur RAIDZ2 HDD. Les utilisateurs se plaignaient de « lenteurs aléatoires », surtout le lundi matin. L’équipe storage a constaté des IOPS de lecture sur le pool et a décidé de « réparer proprement » avec un gros NVMe L2ARC — plusieurs téraoctets, parce que les achats aiment les chiffres ronds.

Cela s’est bien installé. Les graphes semblaient enthousiasmants : l’utilisation du NVMe a bondi et les IOPS de lecture du pool ont chuté. Tout le monde s’est senti malin pendant environ un jour.

Puis la latence a commencé à grimper. Pas sur le pool HDD — sur l’hôte. La taille de l’ARC a diminué. L’hyperviseur a commencé à swaper sous charge. Les vagues de démarrage de VM se sont aggravées, pas améliorées, et le helpdesk a appris du vocabulaire nouveau.

L’hypothèse erronée était simple : « L2ARC c’est du cache en plus, ça ne peut pas empirer la mémoire. » En réalité, le L2ARC gigantesque a consommé les métadonnées ARC et réduit la cache RAM effective. Le système a échangé des hits RAM rapides contre des hits NVMe plus lents et plus de misses. Ils ont retiré le L2ARC, ajouté de la RAM aux hôtes, et réintroduit un cache plus petit ensuite, ciblé sur des datasets spécifiques. Les performances se sont normalisées et sont restées ennuyeuses.

Micro-récit 2 : l’optimisation qui s’est retournée contre eux

Une équipe de plateforme data exécutait des analytics sur un pool ZFS supporté par des SSD. Ils voulaient accélérer des requêtes de dashboard, et quelqu’un a proposé un L2ARC sur un NVMe grand public de rechange. « C’est juste du cache ; si ça casse, rien ne se casse. » C’était techniquement vrai dans le sens le plus étroit.

Ils ont réglé les paramètres d’écriture du L2ARC de façon agressive pour « le chauffer plus vite ». Il s’est effectivement chauffé plus vite. Il a aussi écrit constamment, parce que la charge scannait de larges fenêtres de données avec peu de réutilisation. Le L2ARC est devenu un tapis roulant d’écriture.

Quelques semaines plus tard, le NVMe a commencé à renvoyer des erreurs média. Pas catastrophique, mais suffisant pour générer des alertes et des micro-saccades I/O. Lors d’un incident, le reset du périphérique a provoqué des blocages temporaires ressemblant à une panne de stockage à l’échelle du cluster. Les gens ont accusé ZFS. ZFS a majoritairement haussé les épaules ; le périphérique faisait une mauvaise journée.

Le postmortem était gênant car l’« optimisation » n’avait pas amélioré le p99 du dashboard de toute façon. Le correctif était plat : retirer le L2ARC, optimiser les requêtes pour réduire le churn, et plus tard ajouter un petit vdev spécial pour métadonnées et petits blocs. Les dashboards se sont améliorés et le NVMe a cessé de mourir pour une fonctionnalité que personne ne savait quantifier.

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

Un établissement financier utilisait ZFS pour le stockage VM et services internes. Ils avaient un L2ARC sur NVMe en miroir (oui, en miroir — ils avaient les emplacements et préféraient dormir tranquille). Leur politique de changements était douloureusement stricte : chaque changement storage nécessitait une baseline pré-change, un plan de rollback et un indicateur de succès explicite.

Les patchs trimestriels exigeaient des reboots, et ils avaient déjà observé des baisses de performance post-reboot pendant la chauffe des caches. Ils ont testé le L2ARC persistant en staging, confirmé le comportement au reboot, et l’ont déployé avec des tunables choisis et une procédure documentée pour « désactiver la persistance ».

Puis est arrivé une semaine difficile : un déploiement applicatif a augmenté l’amplification de lecture et rendu les caches moins efficaces. Parce qu’ils avaient des baselines, ils ont pu prouver que ce n’était pas « le stockage qui vieillissait ». Ils ont ajusté les politiques de cache des datasets pour la charge bruyante et protégé le cache de la pollution. Pas d’héroïsme. Pas d’appels au constructeur. Juste de la compétence.

Ce n’était pas glamour, mais cela a empêché la boucle classique : « le stockage est lent » → « ajoutons du cache » → « toujours lent » → « ajoutons plus de cache ». Leur processus ennuyeux a sauvé des jours de travail.

Blague #2 : La seule chose plus persistante que le L2ARC est un acteur qui demande si on peut « juste ajouter plus de NVMe ».

Erreurs courantes : symptômes → cause → correctif

1) Symptom: L2ARC hit rate stays near zero

Cause : La charge est en streaming ou a peu de localité de relecture ; ou le dataset a secondarycache=none ; ou le cache est trop petit et thrash immédiatement.

Correctif : Vérifiez les propriétés des datasets avec zfs get secondarycache. Excluez les datasets en streaming. Si la localité est faible, retirez le L2ARC et investissez ailleurs.

2) Symptom: ARC size shrinks after adding L2ARC, misses increase

Cause : Le surcoût RAM pour les métadonnées L2ARC réduit la capacité ARC ; hôte sous pression mémoire ; L2ARC surdimensionné.

Correctif : Réduire la taille du L2ARC (partition/périphérique plus petit), ajouter de la RAM, ou retirer le L2ARC. Confirmez avec arcstat et free -h.

3) Symptom: NVMe utilization high, latency spikes, application gets worse

Cause : Débit d’alimentation du L2ARC trop agressif ; NVMe grand public avec comportement soutenu médiocre ; remplissage du cache qui concurrence le workload.

Correctif : Baisser l2arc_write_max/l2arc_write_boost. Utiliser un NVMe à performance cohérente. Envisager d’exclure les datasets bruyants du L2ARC.

4) Symptom: Performance great… until reboot, then awful for hours

Cause : L2ARC non persistant requiert une chauffe ; le workload dépend fortement des hits cache.

Correctif : Évaluer le L2ARC persistant dans votre version de ZFS. Si non disponible ou non souhaitable, planifiez les reboots et préchauffez, ou augmentez la RAM pour réduire la dépendance au L2ARC.

5) Symptom: You expected faster writes, but nothing changed

Cause : Le L2ARC est un cache de lecture. Les écritures dépendent du comportement ZIL/SLOG, du layout du pool et des sémantiques sync.

Correctif : Mesurez les écritures sync. Si nécessaire, évaluez le SLOG avec le bon périphérique et testez. Ne faites pas de cargo-cult « NVMe = plus rapide ».

6) Symptom: L2ARC helps some workloads, but backups slow everything down

Cause : Pollution du cache et pression d’éviction causées par des lectures/écritures séquentielles de sauvegarde.

Correctif : Mettez secondarycache=none (et parfois primarycache=metadata) sur les datasets de sauvegarde. Réservez le cache aux workloads interactifs/chauds.

7) Symptom: Lots of CPU usage in kernel during load after enabling L2ARC

Cause : Overhead de bookkeeping du cache plus activité d’éviction élevée ; possiblement trop de petits blocs, alimentations trop agressives.

Correctif : Réduire le débit d’écriture du L2ARC ; s’assurer que vous ne mettez pas en cache la prélecture ; envisager d’augmenter le recordsize ou repenser le pattern I/O du workload.

8) Symptom: NVMe wears out faster than expected

Cause : Churn constant dû à faible localité ; cache surdimensionné avec fort turnover ; tunables d’écriture agressifs.

Correctif : Mesurez le taux d’écriture, limitez l’alimentation, excluez les datasets en streaming, ou retirez le L2ARC. Achetez des périphériques à endurance supérieure si la charge le justifie.

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

Plan A: Decide whether you should add L2ARC at all

  1. Confirmez que c’est un problème de lecture. Si votre pool est limité en écriture ou en sync, arrêtez et diagnostiquez cela plutôt.
  2. Mesurez le taux de miss ARC et la marge de RAM. Si l’hôte est sous pression mémoire, priorisez la RAM et le placement des workloads.
  3. Validez la localité de relecture. Le L2ARC sert les « lectures qui reviennent ». Si elles ne reviennent pas, ne les mettez pas en cache.
  4. Vérifiez le layout du pool et les douleurs métadonnées. Si les métadonnées sont le goulot, un vdev spécial peut surpasser le L2ARC.

Plan B: Implement NVMe L2ARC safely

  1. Baseline avant les changements. Capturez arcstat, zpool iostat, iostat -x et la latence applicative.
  2. Choisissez un NVMe raisonnable. Favorisez la latence cohérente et l’endurance plutôt que le débit peak.
  3. Commencez avec une taille de cache modeste. Prouvez la valeur avant d’augmenter.
  4. Attachez le périphérique en tant que cache. Vérifiez avec zpool status.
  5. Prévenez la pollution du cache. Mettez secondarycache=none sur les datasets en streaming.
  6. Surveillez la chauffe et la charge du périphérique. Regardez l2hit/l2miss et le await du NVMe.
  7. Réglez prudemment. Réduisez le débit d’écriture L2ARC si cela concurrence l’I/O réelle.
  8. Documentez le rollback. Sachez comment zpool remove le périphérique cache et ce que « succès » signifie.

Plan C: Operational guardrails that keep you out of trouble

  • Alertes sur l’usure NVMe et erreurs média. Le L2ARC peut être dur pour les disques ; traitez-le comme un composant consommable.
  • Suivez les ratios de hit du cache dans le temps. Un cache utile peut devenir inutile après des changements applicatifs.
  • Planification des reboots. Si le L2ARC n’est pas persistant, planifiez les reboots quand la chauffe ne posera pas de problème.
  • Gardez les changements petits. Si vous changez la taille du cache, les tunables et les propriétés des datasets en même temps, vous ne saurez jamais ce qui a fonctionné.

FAQ

1) Is L2ARC the same thing as SLOG?

Non. Le L2ARC est un cache de lecture. Le SLOG est un périphérique de journal séparé utilisé pour accélérer les écritures synchrones en raccourcissant le chemin de commit du ZIL. Outil différent, problème différent.

2) Should I mirror L2ARC devices?

En général non, parce que le L2ARC ne détient pas de données uniques. S’il tombe, vous perdez du cache et les performances retombent sur le pool. Miroitez-le seulement si le coût opérationnel de perdre le cache est élevé et que vous avez les emplacements et le budget.

3) Can L2ARC make performance worse?

Oui. Les mécanismes habituels sont la réduction de taille de l’ARC (surcoût métadonnées), la contention d’écriture du remplissage du cache et la pollution du cache par des workloads en streaming. « Cache » n’est pas automatiquement synonyme de « plus rapide ».

4) How long does L2ARC take to warm up?

Ça dépend de votre working set, du taux d’éviction de l’ARC et des limites d’alimentation du L2ARC. Pour des systèmes chargés, cela peut prendre des heures ; pour des systèmes plus calmes, des jours. Si vous voulez des gains instantanés, achetez d’abord plus de RAM.

5) Should I cache prefetch in L2ARC?

La plupart du temps : non. La prélecture peut inonder le L2ARC de données séquentielles qui ne seront pas relues. Si votre workload est majoritairement séquentiel et rejoué, testez-le — ne supposez pas.

6) How do I prevent backups from wrecking my cache?

Mettez secondarycache=none sur les datasets de sauvegarde. Dans certains environnements, envisagez aussi primarycache=metadata pour les datasets en streaming afin que l’ARC garde les métadonnées mais pas les données en bloc.

7) Is persistent L2ARC worth enabling?

Si vos workloads sont sensibles à la chauffe post-reboot et que votre version de ZFS le supporte de façon fiable, cela peut grandement améliorer la qualité de service. Testez les reboots en staging et surveillez le comportement au boot et l’utilisation mémoire.

8) I have an all-NVMe pool. Do I still need L2ARC?

Rarement. L’ARC en RAM reste plus rapide que le NVMe. Mais si le working set est énorme et relu fréquemment, et que votre pool est suffisamment chargé pour que décharger les lectures aide, le L2ARC peut encore servir. Mesurez d’abord ; sinon vous ajoutez juste de la complexité.

9) What’s better: more RAM or more L2ARC?

Plus de RAM, presque toujours. Les hits ARC sont moins coûteux que les hits L2ARC, et la RAM ne s’use pas parce que vous avez relu le même fichier deux fois. Utilisez le L2ARC quand la RAM est déjà raisonnablement dimensionnée et que vous avez encore des misses.

10) How do I know if L2ARC is paying for itself?

Surveillez la latence applicative p95/p99 et le débit, pas seulement les ratios de cache. Une augmentation de l2hit est agréable, mais la métrique métier est « moins de requêtes lentes ». Si vous ne pouvez pas démontrer une amélioration, retirez-le.

Étapes pratiques suivantes

  1. Baselinez aujourd’hui. Capturez arcstat, zpool iostat -v et iostat -x pendant une période identifiée comme « lente ».
  2. Décidez si la charge relit. Si c’est du streaming, ne bâtissez pas un temple du cache.
  3. Corrigez la pression mémoire d’abord. Si vous swappez ou si l’ARC n’atteint pas une taille stable, le L2ARC est une distraction.
  4. Commencez par un petit NVMe L2ARC et protégez-le. Excluez les datasets en streaming, évitez de cacher la prélecture et gardez des débits d’alimentation raisonnables.
  5. Mesurez les résultats, pas les impressions. Si la latence p99 s’améliore et que l’usure NVMe est acceptable, gardez-le. Sinon, retirez-le et passez au changement de layout ou à plus de RAM.
← Précédent
La course aux armements DirectX : pourquoi les pilotes battent parfois le silicium
Suivant →
Histoires « rm -rf / » : la commande devenue un genre d’horreur IT

Laisser un commentaire