OpenZFS : tiering avec L2ARC et SLOG pour les workloads mixtes

07 juin 2026 — par admin_libra

OpenZFS est bien plus qu’un simple système de fichiers : c’est une pile de stockage complète qui intègre nativement des mécanismes de cache multiniveaux. Pour les environnements aux besoins variés — serveurs de fichiers, bases de données, machines virtuelles — comprendre et configurer correctement le L2ARC (Level 2 Adaptive Replacement Cache) et le SLOG (Separate Log device) peut faire la différence entre un stockage qui subit les accès et un stockage qui les absorbe.

Cet article s’adresse aux administrateurs qui ont déjà un pool ZFS en production et qui souhaitent aller au-delà de la configuration par défaut. On y couvre l’architecture de cache ZFS, les critères de décision pour ajouter un L2ARC ou un SLOG, les commandes de configuration sur Debian et Ubuntu, les paramètres de tuning du module, et la supervision des métriques pour valider l’efficacité des ajustements.

Les manipulations ont été validées avec OpenZFS 2.2.x sur Debian 12 et Ubuntu 22.04/24.04. Pour une introduction à ZFS, consultez d’abord ZFS sur Linux — Installation et gestion avancée.

Architecture de cache ZFS : ARC, L2ARC et ZIL/SLOG

L’ARC : le cache primaire en RAM

L’ARC (Adaptive Replacement Cache) est le cache principal de ZFS, résidant entièrement en RAM. Contrairement à un LRU classique, l’ARC maintient quatre listes internes qui distinguent les données fréquemment accédées des données récemment accédées, le rendant résistant aux effets de balayage (cache scan). Par défaut, ZFS peut utiliser jusqu’à 50 % de la RAM avec une croissance et réduction dynamiques selon la pression mémoire du système.

Règle fondamentale : chaque gigaoctet de RAM supplémentaire apporte plus de bénéfice qu’un gigaoctet de SSD en L2ARC. Maximiser la RAM reste toujours la première étape avant d’ajouter des disques de cache.

Le L2ARC : extension du cache sur SSD/NVMe

Le L2ARC est un cache en lecture situé sur un ou plusieurs disques rapides (SSD ou NVMe). Lorsqu’une entrée est sur le point d’être évincée de l’ARC, ZFS peut l’écrire dans le L2ARC. Les lectures ultérieures de cette donnée sont servies depuis le SSD plutôt que depuis les disques rotatifs du pool.

Point critique : le L2ARC ne stocke que des données en lecture. Les écritures passent toujours par les disques principaux du pool (ou le SLOG). De plus, chaque bloc en L2ARC nécessite un pointeur en RAM d’environ 80 octets — sur un serveur contraint en mémoire, un L2ARC surdimensionné peut paradoxalement réduire l’efficacité globale de l’ARC en consommant l’espace mémoire disponible pour les pointeurs.

Le ZIL et le SLOG : accélérer les écritures synchrones

Le ZIL (ZFS Intent Log) est le journal d’intention de ZFS. Lorsqu’une application effectue une écriture synchrone (fsync, O_SYNC, NFS en mode sync), ZFS doit confirmer l’écriture sur disque avant de répondre à l’application. Par défaut, le ZIL est intégré au pool principal, ce qui signifie que chaque écriture synchrone attend les disques du pool.

Le SLOG (Separate Log device) déplace ce journal sur un dispositif dédié à très faible latence. L’écriture synchrone est confirmée dès l’écriture sur le SLOG — le flush vers le pool principal se fait en arrière-plan. La latence perçue par l’application chute sans compromettre la durabilité des données.

Important : le SLOG agit sur la latence des écritures synchrones, pas sur le débit global. Si votre workload n’utilise pas fsync ou O_SYNC (écritures asynchrones pures), un SLOG n’apportera aucun bénéfice mesurable.

Quand ajouter un L2ARC ou un SLOG ?

Le L2ARC est pertinent si

  • Le dataset actif est nettement plus grand que la RAM disponible et les lectures sont répétées sur des données « tièdes » (ni très fréquentes, ni très rares)
  • Le workload est majoritairement en lecture aléatoire : images de VM fréquemment accédées, fichiers de travail d’un serveur de fichiers
  • Le hit ratio ARC mesuré via arcstat est bas malgré une RAM raisonnable (< 80 %)
  • Vous disposez d’un NVMe ou SSD performant non utilisé
  • La règle générale : L2ARC = 1× à 4× la RAM ; ne pas dépasser 10× sans justification mesurée

Le L2ARC est inutile (voire contre-productif) si

  • Le dataset actif tient entièrement en RAM (hit ratio ARC > 95 %)
  • Le workload est en lecture séquentielle pure : streaming, backup, exports
  • Le serveur dispose de peu de RAM (moins de 32 Go) — le overhead mémoire des pointeurs L2ARC l’emporte sur le bénéfice

Le SLOG est pertinent si

  • Le pool est sur des disques rotatifs et reçoit des écritures synchrones en volume
  • Des applications utilisent fsync intensif : PostgreSQL, MySQL/InnoDB, NFS avec option sync, iSCSI
  • La latence d’écriture est le goulot d’étranglement identifié (mesuré, pas supposé)

Installer et vérifier OpenZFS sur Debian/Ubuntu

# Debian 12
apt install linux-headers-$(uname -r) zfsutils-linux zfs-dkms

# Ubuntu 22.04 / 24.04 (paquet natif dans main)
apt install zfsutils-linux

# Vérifier la version installée
zpool version
# Résultat attendu : zpool: 2.2.x-x ou supérieur

# Lister les pools existants
zpool list

Ajouter un L2ARC à un pool existant

Identifier les disques disponibles

# Lister les disques avec leur type (ROTA=0 = SSD/NVMe)
lsblk -d -o NAME,SIZE,ROTA,TYPE,MODEL

# Obtenir les identifiants stables recommandés pour la production
ls -l /dev/disk/by-id/ | grep -E "nvme|ssd"

Ajouter le cache au pool

# Ajouter un NVMe comme L2ARC au pool "datapool"
# Toujours utiliser /dev/disk/by-id/ plutôt que /dev/sdX ou /dev/nvmeXnY
zpool add datapool cache /dev/disk/by-id/nvme-Samsung_SSD_980_PRO_1TB_XXXX

# Vérifier la configuration du pool — une section "cache" doit apparaître
zpool status datapool

# Afficher la taille du L2ARC dans le pool
zpool list -v datapool

Retirer un L2ARC

# Le retrait est propre : les données du cache sont perdues,
# mais le pool reste intact et fonctionnel
zpool remove datapool /dev/disk/by-id/nvme-Samsung_SSD_980_PRO_1TB_XXXX

Ajouter un SLOG (dispositif ZIL séparé)

Règle absolue : miroir obligatoire

Un SLOG non mirroré en production est une bombe à retardement. En cas de perte du SLOG pendant une fenêtre de commit (entre l’acquittement à l’application et le flush vers le pool), les écritures synchrones en transit sont perdues. Toujours mirorer le SLOG avec deux devices distincts.

# Ajouter deux NVMe en miroir comme SLOG au pool "datapool"
zpool add datapool log mirror 
  /dev/disk/by-id/nvme-device-A 
  /dev/disk/by-id/nvme-device-B

# Vérifier — la section "logs" doit afficher le miroir
zpool status datapool

Partitionner un seul NVMe pour SLOG + L2ARC

Le SLOG ne nécessite que quelques secondes d’écritures synchrones en tampon (les commits ZFS ont lieu toutes les 5 secondes par défaut). 4 à 16 Go suffisent dans la quasi-totalité des cas. Il est courant de partitionner un NVMe et d’affecter une petite partition au SLOG, le reste au L2ARC :

# Installer l'outil de partitionnement GPT
apt install gdisk

# Partitionner : 16 Go pour le SLOG, le reste pour le L2ARC
sgdisk -n 1:0:+16G -t 1:8300 -c 1:"ZFS-SLOG" 
       -n 2:0:0    -t 2:8300 -c 2:"ZFS-L2ARC" 
       /dev/nvme1n1

# Vérifier les partitions créées
lsblk /dev/nvme1n1

# Ajouter les deux rôles au pool
zpool add datapool log   /dev/nvme1n1p1
zpool add datapool cache /dev/nvme1n1p2

# Confirmer la configuration finale
zpool status -v datapool

Tuning des paramètres du module OpenZFS

Les paramètres du module zfs sont exposés dans /sys/module/zfs/parameters/. Les modifications à chaud sont immédiates mais non persistées au redémarrage. Pour les persister, on utilise /etc/modprobe.d/zfs.conf.

Paramètres L2ARC clés

# Lire la valeur courante d'un paramètre
cat /sys/module/zfs/parameters/l2arc_write_max

# Limiter le débit d'écriture vers le L2ARC (en bytes/s)
# 100 Mo/s = 104857600 — protège l'endurance du SSD
echo 104857600 > /sys/module/zfs/parameters/l2arc_write_max

# Boost d'écriture au démarrage (remplissage initial accéléré)
echo 209715200 > /sys/module/zfs/parameters/l2arc_write_boost

# Empêcher les prefetch de polluer le L2ARC (recommandé)
echo 1 > /sys/module/zfs/parameters/l2arc_noprefetch

# Activer la reconstruction du L2ARC au redémarrage (OpenZFS 2.0+)
echo 1 > /sys/module/zfs/parameters/l2arc_rebuild_enabled

Persister les paramètres

cat > /etc/modprobe.d/zfs.conf << 'EOF'
# L2ARC : débit d'écriture limité pour préserver l'endurance du SSD
options zfs l2arc_write_max=104857600
options zfs l2arc_write_boost=209715200
options zfs l2arc_noprefetch=1
options zfs l2arc_rebuild_enabled=1
EOF

# Mettre à jour initramfs pour prendre en compte la config au boot
update-initramfs -u

Limiter l’ARC pour les serveurs de base de données

# Sur un serveur PostgreSQL/MySQL avec son propre buffer pool,
# limiter l'ARC à 16 Go pour laisser de la mémoire à l'application
# 16 Go = 17179869184 bytes
echo 17179869184 > /sys/module/zfs/parameters/zfs_arc_max

# Persistance
echo "options zfs zfs_arc_max=17179869184" >> /etc/modprobe.d/zfs.conf
update-initramfs -u

# Vérifier la taille ARC courante (en Go)
awk '/^size/ {printf "ARC size: %.2f GBn", $3/1024/1024/1024}' 
  /proc/spl/kstat/zfs/arcstats

Superviser les performances du cache

arcstat : métriques ARC et L2ARC en temps réel

# arcstat est fourni avec zfsutils-linux sur Debian/Ubuntu
# Afficher les métriques toutes les secondes
arcstat 1

# Colonnes essentielles à surveiller :
#   read   = lectures totales (ARC + L2ARC + pool)
#   hits   = hits ARC (lecture servie depuis la RAM)
#   miss   = miss ARC (donnée absente de la RAM)
#   l2hits = hits L2ARC (servi depuis le SSD de cache)
#   l2miss = miss L2ARC (lecture depuis le pool principal)
#   arcsz  = taille ARC courante
#   l2sz   = taille L2ARC courante

Calculer le hit ratio manuellement

# Snapshot des compteurs ARC
grep -E "^hits |^misses |^l2_hits|^l2_misses" /proc/spl/kstat/zfs/arcstats

# Calcul du hit ratio ARC
awk '
/^hits /   { hits=$3 }
/^misses / { misses=$3 }
END { printf "ARC hit ratio: %.1f%%n", hits*100/(hits+misses) }
' /proc/spl/kstat/zfs/arcstats

# Calcul du hit ratio L2ARC
awk '
/^l2_hits /  { hits=$3 }
/^l2_misses/ { misses=$3 }
END {
  if (hits+misses > 0)
    printf "L2ARC hit ratio: %.1f%%n", hits*100/(hits+misses)
  else
    print "L2ARC: pas encore de données"
}
' /proc/spl/kstat/zfs/arcstats

zpool iostat : I/O par composant du pool

# Afficher les I/O par vdev (disques, cache, log) toutes les 2 secondes
zpool iostat -v datapool 2

# Afficher les latences moyennes par vdev (OpenZFS 2.1+)
zpool iostat -l datapool 2

# Latences attendues indicatives :
#   SLOG (NVMe entreprise) : < 100 µs en écriture
#   L2ARC (NVMe consommateur) : 100-500 µs en lecture
#   HDD 7200 rpm : 5-15 ms

Bonnes pratiques et anti-patterns

Ce qu’il faut faire

  • Mesurer avant d’optimiser : surveiller arcstat et zpool iostat pendant 24 à 48h en charge réelle avant tout ajustement
  • Miroir systématique du SLOG : un SLOG non mirroir en production est inacceptable
  • Utiliser les IDs stables (/dev/disk/by-id/) pour référencer les devices, jamais /dev/sdX qui peut changer au reboot
  • Activer l2arc_rebuild_enabled (OpenZFS 2.0+) pour que le cache survive aux redémarrages planifiés
  • Aligner le recordsize sur le type d’application : 16K pour MySQL InnoDB, 32K pour PostgreSQL, 1M pour les fichiers séquentiels

Anti-patterns à éviter

  • Ajouter un L2ARC sur un serveur avec peu de RAM (moins de 32 Go) : le overhead des pointeurs mémoire peut dégrader l’ARC existant
  • Utiliser un SSD grand public sans capacitors pour le SLOG : en cas de coupure électrique, les données dans le cache volatile du SSD sont perdues avec le SLOG
  • Dimensionner un SLOG à plusieurs centaines de Go : le ZIL n’en a jamais besoin, c’est du gaspillage d’espace rapide
  • Modifier les tunables sans mesure baseline : impossible de valider l’impact sans point de référence
  • Mettre le pool et le SLOG/L2ARC sur le même disque physique : aucun gain, et dégradation des performances I/O du pool

À lire également

Références

Index complet

Tous les articles (41)

Date Article Tags
07/06/2026 Docker : comment récupérer de l'espace disque cache conteneurs debian 07/06/2026 Graylog 7 — Centralisation et analyse de logs : l'alternative à ELK sur Debian/Ubuntu centralisation debian elk 07/06/2026 OpenZFS : tiering avec L2ARC et SLOG pour les workloads mixtes cache l2arc nvme 07/06/2026 Scripting Bash avancé — pièges, bonnes pratiques et optimisation automatisation bash bonnes-pratiques 07/06/2026 AppArmor sur Debian/Ubuntu : profils, modes et confinement applicatif apparmor audit confinement 07/06/2026 Durcissement SSH — au-delà des clés publiques 2fa authentification cryptographie 27/05/2026 LXD 6.x : orchestration de conteneurs Linux avec profils et clustering administration clustering conteneurs 27/05/2026 Keepalived — VIP flottante et load balancing sans matériel dédié debian failover haute-disponibilité 27/05/2026 Btrfs sur Linux — snapshots, sous-volumes et compression en pratique administration btrfs compression 21/05/2026 CVE-2026-42945 (NGINX Rift) : analyse et remédiation sur Debian/Ubuntu cve debian heap-overflow 21/05/2026 Tuning kernel Linux — paramètres sysctl essentiels pour la production debian kernel mémoire 21/05/2026 DRBD : réplication de blocs entre deux serveurs en temps réel cluster debian drbd 15/05/2026 CVE-2026-23918 — vulnérabilité Apache 2.4.66 : analyse et correctifs sur Debian/Ubuntu (hors Debian 11) apache cve debian 15/05/2026 CVE-2026-31431 (Copy Fail) — Analyse et remédiation sur Debian/Ubuntu algif_aead copy-fail cve 12/05/2026 Pacemaker et Corosync — cluster haute disponibilité Linux cluster corosync debian 12/05/2026 WireGuard : monter un VPN mesh entre plusieurs serveurs Linux chiffrement linux mesh 12/05/2026 Netdata — monitoring temps réel sans configuration complexe alertes dashboard linux 12/05/2026 nftables en pratique — remplacer iptables sur Debian/Ubuntu debian firewall iptables 12/05/2026 Podman : alternative rootless à Docker — installation et migration conteneurs docker kubernetes 02/05/2026 Prometheus et Grafana sur Debian — installation, configuration et dashboards pratiques alertmanager dashboard debian 02/05/2026 Ansible : automatiser la gestion de serveurs Linux avec des playbooks administration ansible automation 28/04/2026 ZFS sur Linux : snapshots, clones et RAID-Z en pratique administration compression filesystem 28/04/2026 eBPF sur Linux : observabilité et traçage kernel avec bpftrace et BCC bcc bpftrace diagnostic 23/04/2026 Analyse de la mémoire sur Linux — vmstat, free, smem diagnostic mémoire monitoring 23/04/2026 Sécurité Linux — Firewall iptables et nftables firewall iptables nftables 23/04/2026 ZFS sur Linux — Installation et gestion avancée administration filesystem stockage 23/04/2026 Gestion des services avec systemd sur Debian et Ubuntu administration debian services 23/04/2026 Gestion des ressources cgroups v1/v2 avec LXC cgroups conteneurs lxc 23/04/2026 Centralisation logs avec ELK Stack — Elasticsearch, Kibana, Filebeat elasticsearch elk filebeat 23/04/2026 Supervision avec Zabbix 7.0 LTS sur Debian/Ubuntu debian monitoring supervision 23/04/2026 Plusieurs versions PHP-FPM sur Apache Debian/Ubuntu apache debian php-fpm 23/04/2026 Sécurisation avancée PHP-FPM — Multi-VirtualHosts Apache/Nginx apache nginx php-fpm 23/04/2026 Optimisation PHP-FPM — Guide de tuning d'un pool optimisation performance php-fpm 29/07/2025 Docker sur Debian/Ubuntu : Installation, Configuration et Utilisation conteneurs debian docker 03/07/2025 Serveur VPN WireGuard sous linux réseau sécurité vpn 03/07/2025 Authentification par clé publique sur un serveur SSH authentification cryptographie sécurité 27/06/2025 Surveillance et diagnostic d’un serveur Linux avec vmstat, iotop et htop diagnostic htop monitoring 27/06/2025 Mémoire : Utilisation des Huge Pages et implémentation hugepages mémoire noyau 27/06/2025 Mémoire Swap et paramétrage swappiness mémoire noyau performance 18/06/2025 Installation et Configuration des Conteneurs LXC sur Linux administration conteneurs lxc 18/06/2025 Gestion des journaux avec syslog et journalctl administration journalctl logs