IT-Admin.tech

Optimisation du noyau pour bases de données : THP, vm.swappiness et I/O‑Scheduler — approche pragmatique

Architekturdiagramm eines Datenbankhosts mit Page-Cache, THP, Swap und Block-I/O-Queue vor einer NVMe-SSD
Technisches Diagramm: Transparent Hugepages, Page Cache, Swap und Block-I/O-Queue eines Datenbankhosts — NVMe-SSD als klares Artefakt für Storage-Entscheidungen.

Pour des bases de données de production stables, un ajustement ciblé du noyau pour bases de données est souvent plus efficace qu’une simple montée en charge. Trois réglages du noyau influent particulièrement sur les performances et la latence : Transparent Hugepages (THP), vm.swappiness et le I/O‑Scheduler. Ce guide pratique explique comment ces mécanismes fonctionnent, quelles conséquences ils ont sur l’exploitation, le monitoring et la sécurité, comment mesurer les changements, les déployer en toute sécurité et les annuler — y compris des remarques spécifiques pour les conteneurs (Docker/Podman) et la virtualisation.

Kernel-Tuning für Datenbanken: Vor dem Tunen: Ziele, Metriken und Change-Plan

Avant de modifier des paramètres du noyau, définissez des objectifs mesurables (p. ex. réduction du p95/p99, stabilisation des temps fsync) et les risques acceptables. Définissez des KPI que vous pouvez collecter automatiquement : latences des requêtes depuis la base de données, iostat/iowait côté hôte, vmstat (si/so = swap-in/swap-out), PSI (Pressure Stall Information — un mécanisme du noyau pour mesurer la pression CPU/mémoire/IO), ainsi que les journaux du noyau (dmesg/journal). Sans métrique claire, les conclusions sont difficiles.

Kurze Baseline-Checks

Shell
# Systemübersicht
uname -r; cat /etc/os-release; systemd-detect-virt || true

# Speicher, Swap und PSI
free -h; swapon --show; vmstat 1 5; sudo cat /proc/pressure/memory

# I/O
lsblk -o NAME,TYPE,SIZE,ROTA,MOUNTPOINTS
iostat -xz 1 5 || true

# THP-Status
for f in /sys/kernel/mm/transparent_hugepage/enabled /sys/kernel/mm/transparent_hugepage/defrag; do
  [ -f "$f" ] && echo "$f: $(cat $f)"
done

Documentez les informations de version (noyau, distribution, pilotes de stockage), car le comportement peut varier selon la version du noyau.

Transparent Hugepages (THP): Mechanik, Risiken und Praxis

THP tente de réduire les TLB-misses (TLB = Translation Lookaside Buffer, un cache pour adresses virtuelles→physiques) en regroupant de nombreuses petites pages en pages plus grandes (généralement 2 MiB). Cela profite aux charges de travail intensives en calcul, mais peut provoquer des pauses inattendues pour les bases de données transactionnelles : la défragmentation du noyau et les opérations de copie lors de la fusion de grandes pages entraînent des blocages temporaires CPU ou mémoire, qui augmentent nettement les latences p99.

Wann THP wahrscheinlich Probleme macht

  • Pics p99 soudains sans déclencheur d’E/S identifiable.
  • Activité de défragmentation du noyau ou de kswapd en cas d’utilisation mémoire élevée.
  • Pics de latence reproductibles pour certains profils de requêtes.

Testen, Deaktivieren und Persistenz

Les modifications peuvent être testées à chaud via sysfs ; en production, utilisez des mécanismes persistants et réversibles (unité systemd, ligne de commande GRUB ou ajustement d’initramfs).

Shell
# Laufzeit-Test: THP deaktivieren
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

# Kontrolle
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag

Exemple d’une unité systemd courte et sûre désactivant THP au démarrage. Créez le contenu de l’unité dans un fichier :

Shell
sudo tee /etc/systemd/system/disable-thp.service >/dev/null <<'EOF'
[Unit]
Description=Disable Transparent Huge Pages
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled'
ExecStart=/bin/sh -c 'echo never > /sys/kernel/mm/transparent_hugepage/defrag'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now disable-thp.service

En alternative, vous pouvez définir dans GRUB le paramètre du noyau transparent_hugepage=never (voir la section suivante). Important : testez sur plusieurs profils de charge et mesurez p95/p99 avant et après la modification.

vm.swappiness : compréhension, réglage et risques

vm.swappiness est un paramètre du noyau (0–100) qui décrit à quel point le noyau déplace agressivement la mémoire anonyme vers le swap. Une valeur faible réduit le swapping en fonctionnement normal — souvent pertinent pour des hôtes de base de données, car les latences de swap ralentissent fortement les requêtes. Néanmoins, ce n’est pas automatiquement le meilleur choix que de définir vm.swappiness=0 : sur des systèmes avec peu de RAM ou des charges de travail mixtes, une éviction agressive du swap peut entraîner une récupération de pages plus importante, ce qui augmente la charge CPU et I/O.

Définir et rendre persistant

Shell
# Aktuellen Wert prüfen
sysctl vm.swappiness; cat /proc/sys/vm/swappiness

# Laufzeit setzen
sudo sysctl -w vm.swappiness=10

# Dauerhaft (sysctl.d)
sudo tee /etc/sysctl.d/99-db-tuning.conf >/dev/null <<'EOF'
# DB-Tuning: Swap-Verhalten
vm.swappiness = 10
EOF
sudo sysctl --system

Spécificités pour les conteneurs et les cgroups

Dans des environnements de conteneurs, un swap inapproprié est souvent un problème secondaire : un conteneur peut atteindre la limite de sa cgroup alors que l’hôte affiche du RAM libre. Les paramètres et le comportement diffèrent entre cgroup v1 et v2 ; les réglages pertinents incluent notamment memory.swap.max et memory.high (cgroup v2). Les orchestrateurs (Kubernetes, Docker Engine) appliquent parfois des valeurs par défaut qui influent sur le comportement des conteneurs.

Shell
# Docker: Memory-Limits prüfen und Container-Startbeispiel
docker inspect --format '{{.Name}}: Memory={{.HostConfig.Memory}} MemorySwap={{.HostConfig.MemorySwap}}' postgres

# Starten ohne zusätzliches Swap (Host verhindert swap usage durch MemorySwap)
docker run -d --name postgres 
  --memory=8g --memory-swap=8g 
  -v /srv/dbdata:/var/lib/postgresql/data 
  my-postgres-image

Recommandation : définissez de manière cohérente les limites des conteneurs et de l’hôte, testez le comportement OOM (Kernel OOM ou systemd-oomd) et surveillez dmesg/journal pour des événements OOM ou OOM-Killer.

I/O‑Scheduler : choix selon le type de stockage et pièges d’empilement

L’ordonnanceur I/O influence l’ordonnancement, la priorisation et la mise en file d’attente des E/S bloc. Les noyaux modernes Linux utilisent le Multi-Queue (blk-mq). Règles typiques :

  • NVMe locales : none (l’ordonnanceur côté périphérique est souvent préférable au queueing Linux).
  • Disques virtuels (VirtIO, VMware) : mq-deadline réduit les pics de latence.
  • HDDs ou charges de travail interactives sur poste : bfq peut offrir une meilleure équité et une sensibilité à la latence.

Important : pour des couches telles que LVM, Device-Mapper (dm‑crypt) ou Multipath, vous devez définir l’ordonnanceur au bon niveau — souvent sur le device physique, pas sur le device LVM.

Vérifier, définir et rendre persistant

Shell
# Ordonnanceurs actuels
for d in /sys/block/*/queue/scheduler; do
  echo "${d%/queue/scheduler}: $(cat $d)"
done

# Changement à chaud (exemple pour nvme0n1)
echo none | sudo tee /sys/block/nvme0n1/queue/scheduler

# Persistance avec une règle udev
sudo tee /etc/udev/rules.d/60-io-scheduler.rules >/dev/null <<'EOF'
ACTION=="add|change", KERNEL=="nvme*", ATTR{queue/scheduler}="none"
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/scheduler}="mq-deadline"
EOF
sudo udevadm control --reload-rules; sudo udevadm trigger --type=devices --action=change

Tenez compte des instances cloud (p. ex. AWS EBS gp3, Azure Managed Disks) : le comportement sous-jacent peut être virtualisé ; testez avec une charge de travail réelle. Pour le multipath : réglez l’ordonnanceur sur les périphériques backend, pas seulement sur /dev/mapper/…

Méthodes de mesure : tests et outils fiables

Le tuning du noyau n’est pertinent que si vous mesurez précisément son effet. Exécutez des tests combinant l’hôte et la base de données :

  • Outils de charge DB : pgbench pour PostgreSQL, sysbench pour MySQL, suites de benchmarks natives. Ceux-ci génèrent des schémas d’accès plus réalistes que les outils I/O synthétiques seuls.
  • Outils hôte : iostat (await, %util), blktrace pour une analyse approfondie du block I/O, fio pour des profils I/O contrôlés.
  • Observabilité du noyau : /proc/pressure/* pour PSI, profilage eBPF (bcc, bpftrace) pour rendre visibles les stalls et les files d’attente.
Shell
# Exemple : fio pour fsync-stress (écriture synchrone + fsync)
fio --name=fsync-test --filename=/srv/dbdata/testfile --size=4G 
  --bs=4k --iodepth=1 --numjobs=1 --rw=write --direct=1 --fsync=1 --runtime=300

# Exemple simplifié d'exécution pgbench
docker exec -it postgres pgbench -c 50 -T 120 -r mydb

Important : exécutez les tests sur une fenêtre temporelle représentative (pas seulement brièvement) afin de capturer le comportement p99.

Dépannage : pourquoi le tuning n’a pas d’effet

Si les modifications n’apportent aucune amélioration, vérifiez :

  • Le fichier de la base de données se trouve-t-il réellement sur le périphérique que vous avez ajusté ? (bind‑mounts, LVM, dm‑crypt, multipath).
  • La latence provient-elle du storage array ou du réseau (NAS/SAN/Cloud) ?
  • Le temps processeur est-il consommé dans la base de données elle-même (verrous, checkpoints) plutôt que dans le chemin I/O de l’hôte ?
  • Les cgroups des conteneurs, systemd-oomd ou des politiques d’orchestrateur en sont-ils la cause ?

Le tuning du noyau n’est souvent qu’une partie d’un ensemble de mesures plus large : optimisation du stockage, réglage des valeurs de la base de données (intervalle des checkpoints, background writer) et analyse du chemin I/O doivent être considérés conjointement.

Stratégie de retour arrière et script d’exemple

Préparez toujours des retours arrière automatisables. Sauvegardez les valeurs actuelles avant toute modification et prévoyez une procédure de restauration simple.

Shell
#!/bin/bash
# rollback-tuning.sh - einfache Rücksetz-Routine
set -euo pipefail

echo "Sichern aktueller Werte..."
mkdir -p /root/kernel-tuning-backup
cat /sys/kernel/mm/transparent_hugepage/enabled > /root/kernel-tuning-backup/thp_enabled
cat /sys/kernel/mm/transparent_hugepage/defrag > /root/kernel-tuning-backup/thp_defrag
cat /proc/sys/vm/swappiness > /root/kernel-tuning-backup/swappiness
for d in /sys/block/*/queue/scheduler; do
  dev=${d%/queue/scheduler}
  cat $d > "/root/kernel-tuning-backup/$(basename $dev)_scheduler"
done

# Rollback-Schritte (Beispielwerte aus Backup zurücklesen)
echo "Rollback: THP zurücksetzen"
[ -f /root/kernel-tuning-backup/thp_enabled ] && cat /root/kernel-tuning-backup/thp_enabled | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
[ -f /root/kernel-tuning-backup/thp_defrag ] && cat /root/kernel-tuning-backup/thp_defrag | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

echo "Rollback: swappiness zurücksetzen"
[ -f /root/kernel-tuning-backup/swappiness ] && sudo sysctl -w vm.swappiness=$(cat /root/kernel-tuning-backup/swappiness)

# Hinweis: Scheduler-Rollback kann ein Reboot erfordern, je nach udev/driver

echo "Rollback abgeschlossen - prüfen Sie Logs und KPIs"

Documentez les valeurs d’origine dans votre système de ticketing et effectuez, après le rollback, un contrôle de validation des KPIs.

Focus particulier : Docker et cgroup v2

Dans les scénarios avec conteneurs, la plupart des paramètres du noyau prennent effet au niveau de l’hôte ; toutefois, les droits des conteneurs et la configuration des cgroups peuvent modifier le comportement. Sous cgroup v2, les paramètres pertinents dans /sys/fs/cgroup sont : memory.high (limite souple), memory.swap.max (limite de swap) et memory.max (limite stricte). Kubernetes utilise des classes QoS (Guaranteed/Burstable/BestEffort) — définissez correctement requests et limits pour garantir un comportement prévisible des conteneurs.

Shell
# Beispiel: Werte in cgroup v2 prüfen (Pfad kann je nach Engine variieren)
cat /sys/fs/cgroup//memory.high
cat /sys/fs/cgroup//memory.swap.max

# Kubernetes: PodSpec (Ausschnitt)
# requests/limits sicher definieren, um unerwarteten Swap zu vermeiden

Créez des cas de test pour les scénarios OOM et vérifiez comment vos politiques d’orchestrateur (Eviction thresholds, PodDisruptionBudget) y réagissent.

Règles opérationnelles et recommandations pratiques

  • Ne modifiez qu’une seule variable du noyau par fenêtre de test, afin que les effets soient clairement attribuables.
  • Automatisez les sauvegardes des valeurs précédentes et les scripts de rollback.
  • Pour les stockages cloud ou SAN, vérifiez d’abord si la source de latence se situe en dehors de l’hôte.
  • Utilisez des outils eBPF pour rendre visibles les courts kernel‑stalls que les outils de monitoring ignorent souvent.
  • Conservez les règles de persistance (sysctl.d, udev, systemd) versionnées dans le dépôt de configuration.

Conclusion

Optimisation du noyau pour les bases de données est une tâche efficace mais exigeante : les Transparent Hugepages sont souvent responsables des pointes p99, vm.swappiness doit s’aligner sur la planification de la RAM et la politique cgroup, et l’I/O‑Scheduler doit être choisi en fonction du type de stockage. Travaillez de manière méthodique : baseline, changement ciblé, mesure, test de persistance (reboot) et plan de rollback clair. Ce n’est qu’ainsi que vous obtiendrez des améliorations reproductibles sur Bare‑Metal, VMs et environnements conteneurisés.

Ce runbook est destiné à servir de guide opérationnel : adaptez les valeurs à votre infrastructure, testez avec des charges de travail réelles et consignez toutes les étapes de manière auditable dans votre gestion des changements.

Exploitation, aspects de mise à niveau et d’intégration

En complément d’un réglage ponctuel des paramètres, il est pertinent d’inscrire le tuning du noyau dans un contexte opérationnel : mises à niveau du noyau et des pilotes, niveau NVMe/firmware, topologie NUMA et configurations de base de données interagissent fortement et peuvent masquer ou amplifier des changements. Avant un déploiement large, vérifiez la compatibilité avec les pilotes de stockage (nvme, virtio, multipath) et les releases de firmware ; certaines variations de latence proviennent du pilote ou du firmware et ne peuvent pas être corrigées via sysctl.

Remarques d’architecture

  • NUMA : placez les threads DB, le page cache et les fichiers de données de préférence sur la même domaine NUMA ; une affinité incorrecte augmente le trafic inter-nœuds.
  • Configuration DB : ajustez shared_buffers/innodb_buffer_pool de manière à ce que le cache de pages de l’hôte et le cache DB ne se concurrencent pas ; cela réduit les reclaims inutiles.
  • Cloud/Managed DB : pour les services managés, les réglages du noyau sont souvent indisponibles — choisissez à la place des classes d’instances appropriées, des Provisioned IOPS ou des options de stockage spécialisées.

Intégration opérationnelle et CI

Automatisez les tests dans votre pipeline : exécutez des runs fio/pgbench comme partie des pipelines de release sur une petite flotte canary et intégrez la comparaison des résultats (p50/p95/p99) dans le reporting CI. Versionnez sysctl.d, udev‑Rules et systemd‑Units dans le dépôt de configuration et déployez de manière idempotente via Ansible/Chef.

Monitoring‑Checkliste

  • Alerte pour PSI‑Memory > seuil défini (p. ex. 100ms) et pour des swap‑outs persistants.
  • Surveillance des tendances : latences p99, iowait, await et kernel OOM‑Events.
  • Audit : vérifier les Kernel‑Parameter et les udev‑Rules via des scans de dérive de configuration (Configuration‑Drift‑Scan).

Ces perspectives opérationnelles garantissent que le tuning du noyau reste partie intégrante d’une gestion des changements fiable pour votre paysage logiciel d’entreprise sur mesure et n’entraîne pas d’effets secondaires inattendus.

Pour ce sujet, la désactivation de Transparent Hugepages et les I/O‑Schedulers Mq‑Deadline, Bfq et None sont également importants. L’article remet ces aspects en perspective de manière claire et précise ce qui compte au quotidien.