DEVOPS
Avance

Optimiser les I/O disque sous Linux : Guide Avance pour la Production

Tuning avance des performances disque sur Linux : filesystem, scheduler, cache, RAID, troubleshooting et benchmarks complets.

Florian Courouge
22 min de lecture
3,823 mots
982 vues
Linux
IO
Disque
Performance
Sysadmin
SSD
XFS
NVMe

Optimiser les I/O disque sous Linux : Guide Avance pour la Production

Quand on travaille avec des bases de donnees, des systemes distribues comme Apache Kafka, ou des workloads containerises intensifs, les performances disque deviennent rapidement un point de contention. Ce guide complet vous permettra de tirer le meilleur de vos I/O.

Architecture du Stack I/O Linux

<svg viewBox="0 0 800 500" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="appGrad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" style="stop-color:#8b5cf6"/>
      <stop offset="100%" style="stop-color:#7c3aed"/>
    </linearGradient>
    <linearGradient id="kernelGrad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" style="stop-color:#f97316"/>
      <stop offset="100%" style="stop-color:#ea580c"/>
    </linearGradient>
    <linearGradient id="hwGrad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" style="stop-color:#22c55e"/>
      <stop offset="100%" style="stop-color:#16a34a"/>
    </linearGradient>
  </defs>

  <rect width="800" height="500" fill="#0f172a"/>

  <!-- Application Layer -->
  <rect x="150" y="30" width="500" height="60" rx="8" fill="url(#appGrad)"/>
  <text x="400" y="65" text-anchor="middle" fill="white" font-size="16" font-weight="bold">Application (PostgreSQL, Kafka, etc.)</text>

  <!-- VFS Layer -->
  <rect x="150" y="110" width="500" height="50" rx="8" fill="#3b82f6"/>
  <text x="400" y="140" text-anchor="middle" fill="white" font-size="14" font-weight="bold">VFS (Virtual File System)</text>

  <!-- Page Cache -->
  <rect x="150" y="180" width="240" height="50" rx="8" fill="#06b6d4"/>
  <text x="270" y="210" text-anchor="middle" fill="white" font-size="13" font-weight="bold">Page Cache</text>
  <rect x="410" y="180" width="240" height="50" rx="8" fill="#06b6d4"/>
  <text x="530" y="210" text-anchor="middle" fill="white" font-size="13" font-weight="bold">Buffer Cache</text>

  <!-- Filesystem -->
  <rect x="150" y="250" width="150" height="50" rx="8" fill="url(#kernelGrad)"/>
  <text x="225" y="280" text-anchor="middle" fill="white" font-size="12" font-weight="bold">ext4</text>
  <rect x="320" y="250" width="150" height="50" rx="8" fill="url(#kernelGrad)"/>
  <text x="395" y="280" text-anchor="middle" fill="white" font-size="12" font-weight="bold">XFS</text>
  <rect x="490" y="250" width="160" height="50" rx="8" fill="url(#kernelGrad)"/>
  <text x="570" y="280" text-anchor="middle" fill="white" font-size="12" font-weight="bold">ZFS/Btrfs</text>

  <!-- Block Layer -->
  <rect x="150" y="320" width="500" height="50" rx="8" fill="#ec4899"/>
  <text x="400" y="350" text-anchor="middle" fill="white" font-size="14" font-weight="bold">Block Layer (I/O Scheduler: none, mq-deadline, bfq)</text>

  <!-- Device Drivers -->
  <rect x="150" y="390" width="240" height="45" rx="8" fill="#a855f7"/>
  <text x="270" y="418" text-anchor="middle" fill="white" font-size="12" font-weight="bold">NVMe Driver</text>
  <rect x="410" y="390" width="240" height="45" rx="8" fill="#a855f7"/>
  <text x="530" y="418" text-anchor="middle" fill="white" font-size="12" font-weight="bold">SCSI/SATA Driver</text>

  <!-- Hardware -->
  <rect x="150" y="455" width="500" height="35" rx="8" fill="url(#hwGrad)"/>
  <text x="400" y="478" text-anchor="middle" fill="white" font-size="14" font-weight="bold">Hardware: NVMe SSD / SATA SSD / HDD</text>

  <!-- Arrows -->
  <path d="M400 90 L400 110" stroke="#94a3b8" stroke-width="2" marker-end="url(#ioArrow)"/>
  <path d="M400 160 L400 180" stroke="#94a3b8" stroke-width="2" marker-end="url(#ioArrow)"/>
  <path d="M400 230 L400 250" stroke="#94a3b8" stroke-width="2" marker-end="url(#ioArrow)"/>
  <path d="M400 300 L400 320" stroke="#94a3b8" stroke-width="2" marker-end="url(#ioArrow)"/>
  <path d="M400 370 L400 390" stroke="#94a3b8" stroke-width="2" marker-end="url(#ioArrow)"/>
  <path d="M400 435 L400 455" stroke="#94a3b8" stroke-width="2" marker-end="url(#ioArrow)"/>

  <defs>
    <marker id="ioArrow" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
      <polygon points="0 0, 10 3.5, 0 7" fill="#94a3b8"/>
    </marker>
  </defs>
</svg>

Pourquoi optimiser les I/O ?

Sans tuning, un disque rapide (NVMe, SSD) peut etre severement bride par :

  • Un mauvais choix de systeme de fichiers
  • Des options de montage par defaut inefficaces
  • Un scheduler I/O inadapte
  • Une mauvaise configuration du cache memoire
  • Un alignement de partition sous-optimal

Impact reel mesure

Composant Avant tuning Apres tuning Gain
IOPS 4K random 45,000 180,000 +300%
Latence moyenne 0.8ms 0.2ms -75%
Debit sequentiel 1.2 GB/s 3.2 GB/s +167%
CPU wait I/O 15% 3% -80%

Choix du systeme de fichiers

Comparaison des filesystems

Filesystem Lectures aleatoires Ecritures seq. Metadata Snapshots Cas d'usage
ext4 Excellent Bon Bon Non General, petits fichiers
XFS Tres bon Excellent Excellent Non BDD, logs, gros fichiers
ZFS Bon Bon Excellent Oui Stockage, backup, integrite
Btrfs Bon Moyen Bon Oui Dev, snapshots frequents

ext4 : classique mais solide

# Creation optimisee ext4
mkfs.ext4 -F \
  -E stride=128,stripe_width=256 \  # Alignement RAID
  -O dir_index,extent,flex_bg \     # Features modernes
  -b 4096 \                         # Block size 4K
  -i 16384 \                        # Plus d'inodes
  /dev/nvme0n1p1

XFS : pour les workloads intensifs

# Creation optimisee XFS
mkfs.xfs -f \
  -d agcount=32 \        # Plus d'allocation groups (parallelisme)
  -l size=512m \         # Log interne plus grand
  -n size=8192 \         # Directory block size
  -i maxpct=25 \         # Plus d'espace pour les inodes
  /dev/nvme0n1p1

ZFS : avec de la RAM

# Creation pool ZFS
zpool create -o ashift=12 tank /dev/nvme0n1

# Dataset optimise
zfs create tank/data
zfs set atime=off tank/data
zfs set compression=lz4 tank/data
zfs set recordsize=128k tank/data  # Pour bases de donnees
zfs set xattr=sa tank/data
zfs set dnodesize=auto tank/data
zfs set sync=standard tank/data    # ou disabled pour max perf (risque)

# Tuning ARC (cache)
echo 8589934592 > /sys/module/zfs/parameters/zfs_arc_max  # 8GB max

Options de montage recommandees

Pour ext4 (Production)

# /etc/fstab
UUID=xxxx /data ext4 defaults,noatime,nodiratime,discard,barrier=0,data=writeback,errors=remount-ro 0 2
Option Description Impact
noatime Pas de MAJ timestamp acces -20% I/O
nodiratime Idem pour directories -5% I/O
discard TRIM automatique pour SSD Longevite SSD
barrier=0 Desactive barriere ecriture +15% perf (avec UPS)
data=writeback Ecriture asynchrone +10% perf

Pour XFS (Production)

# /etc/fstab
UUID=xxxx /data xfs defaults,noatime,nodiratime,discard,nobarrier,logbufs=8,logbsize=256k,allocsize=64m 0 2
Option Description Impact
logbufs=8 8 buffers de log (defaut: 4) +10% ecriture
logbsize=256k Taille buffer log 256K +5% ecriture
allocsize=64m Pre-allocation 64MB +20% gros fichiers
nobarrier Desactive barrieres +15% perf

Pour tmpfs (RAM disk)

# /etc/fstab - Pour caches temporaires
tmpfs /tmp tmpfs defaults,noatime,mode=1777,size=4G 0 0
tmpfs /var/cache/nginx tmpfs defaults,noatime,size=1G,uid=nginx,gid=nginx 0 0

Configuration du scheduler I/O

<svg viewBox="0 0 800 250" xmlns="http://www.w3.org/2000/svg">
  <rect width="800" height="250" fill="#0f172a"/>

  <!-- None/NOOP -->
  <g transform="translate(130, 120)">
    <rect x="-100" y="-60" width="200" height="120" rx="10" fill="#1e293b" stroke="#22c55e" stroke-width="3"/>
    <text y="-30" text-anchor="middle" fill="#22c55e" font-size="16" font-weight="bold">none (NOOP)</text>
    <text y="0" text-anchor="middle" fill="#94a3b8" font-size="11">FIFO simple</text>
    <text y="20" text-anchor="middle" fill="#64748b" font-size="10">Latence minimale</text>
    <text y="50" text-anchor="middle" fill="#22c55e" font-size="12" font-weight="bold">NVMe / SSD</text>
  </g>

  <!-- mq-deadline -->
  <g transform="translate(400, 120)">
    <rect x="-100" y="-60" width="200" height="120" rx="10" fill="#1e293b" stroke="#3b82f6" stroke-width="3"/>
    <text y="-30" text-anchor="middle" fill="#3b82f6" font-size="16" font-weight="bold">mq-deadline</text>
    <text y="0" text-anchor="middle" fill="#94a3b8" font-size="11">Deadlines garanties</text>
    <text y="20" text-anchor="middle" fill="#64748b" font-size="10">Equite lecture/ecriture</text>
    <text y="50" text-anchor="middle" fill="#3b82f6" font-size="12" font-weight="bold">HDD / SATA SSD</text>
  </g>

  <!-- BFQ -->
  <g transform="translate(670, 120)">
    <rect x="-100" y="-60" width="200" height="120" rx="10" fill="#1e293b" stroke="#f97316" stroke-width="3"/>
    <text y="-30" text-anchor="middle" fill="#f97316" font-size="16" font-weight="bold">bfq</text>
    <text y="0" text-anchor="middle" fill="#94a3b8" font-size="11">Budget Fair Queuing</text>
    <text y="20" text-anchor="middle" fill="#64748b" font-size="10">Latence interactive</text>
    <text y="50" text-anchor="middle" fill="#f97316" font-size="12" font-weight="bold">Desktop / Multi-user</text>
  </g>

  <text x="400" y="230" text-anchor="middle" fill="#64748b" font-size="13">Choisir le scheduler selon le type de disque et le workload</text>
</svg>

Verifier le scheduler actuel

# Pour tous les disques
for disk in /sys/block/*/queue/scheduler; do
  echo "$disk: $(cat $disk)"
done

# Exemple de sortie:
# /sys/block/nvme0n1/queue/scheduler: [none] mq-deadline kyber bfq
# /sys/block/sda/queue/scheduler: none [mq-deadline] kyber bfq

Configuration dynamique

# Pour SSD/NVMe - utiliser none (NOOP)
echo none > /sys/block/nvme0n1/queue/scheduler

# Pour HDD - utiliser mq-deadline
echo mq-deadline > /sys/block/sda/queue/scheduler

# Pour desktop/interactif - utiliser bfq
echo bfq > /sys/block/sda/queue/scheduler

Configuration permanente via udev

# /etc/udev/rules.d/60-io-schedulers.rules

# NVMe - toujours none
ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/scheduler}="none"

# SSD SATA (non rotatif) - none
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="none"

# HDD (rotatif) - mq-deadline
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="mq-deadline"

# Recharger les regles
udevadm control --reload-rules && udevadm trigger

Tuning du cache et de la memoire virtuelle

Parametres critiques

# /etc/sysctl.d/99-io-performance.conf

# === SWAPPINESS ===
# Reduire l'utilisation du swap (valeur 1-10 pour serveurs)
vm.swappiness = 1

# === DIRTY PAGES ===
# Quand commencer a ecrire les dirty pages en arriere-plan
vm.dirty_background_ratio = 5     # 5% de la RAM

# Quand bloquer les processus pour forcer l'ecriture
vm.dirty_ratio = 15               # 15% de la RAM

# Duree avant d'ecrire les dirty pages (centisecondes)
vm.dirty_expire_centisecs = 3000  # 30 secondes
vm.dirty_writeback_centisecs = 500 # Reveil toutes les 5 secondes

# === POUR SERVEURS AVEC BEAUCOUP DE RAM ===
# Alternative avec valeurs fixes (mieux pour grosse RAM)
# vm.dirty_background_bytes = 268435456  # 256MB
# vm.dirty_bytes = 536870912             # 512MB

# === CACHE VFS ===
# Pression sur le cache dentries/inodes (100 = normal, 50 = moins agressif)
vm.vfs_cache_pressure = 50

# === OVERCOMMIT ===
# 0 = heuristic, 1 = always, 2 = never
vm.overcommit_memory = 0
vm.overcommit_ratio = 50

# === PAGE CACHE ===
# Minimum de pages libres (en pages de 4K)
vm.min_free_kbytes = 262144  # 256MB

# === ZONE RECLAIM ===
# Desactiver pour NUMA (evite latences)
vm.zone_reclaim_mode = 0

Application et verification

# Appliquer
sysctl -p /etc/sysctl.d/99-io-performance.conf

# Verifier
sysctl -a | grep -E "dirty|swap|cache_pressure"

# Voir l'etat actuel du cache
free -h
cat /proc/meminfo | grep -E "Dirty|Writeback|Cached|Buffers"

Queue depth et parametres avances

Pour NVMe haute performance

# /etc/udev/rules.d/61-nvme-tuning.rules

ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/scheduler}="none"
ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/nr_requests}="1024"
ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/read_ahead_kb}="256"
ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/rq_affinity}="2"
Parametre Description Valeur recommandee
nr_requests Taille de la queue 256-1024 pour NVMe
read_ahead_kb Pre-lecture 256-512 pour sequentiel
rq_affinity Affinite CPU 2 pour localite NUMA
nomerges Desactive fusion I/O 0 (garder les merges)

Pour SSD SATA

# Parametres plus conservateurs
echo 64 > /sys/block/sda/queue/nr_requests
echo 128 > /sys/block/sda/queue/read_ahead_kb
echo 0 > /sys/block/sda/queue/add_random

Pour HDD

# Optimise pour acces sequentiel
echo 128 > /sys/block/sdb/queue/nr_requests
echo 4096 > /sys/block/sdb/queue/read_ahead_kb  # 4MB read-ahead
echo 1 > /sys/block/sdb/queue/iosched/fifo_batch

RAID et LVM

RAID logiciel (mdadm)

# Creation RAID 10 optimise
mdadm --create /dev/md0 --level=10 --raid-devices=4 \
  --chunk=256K \
  /dev/nvme0n1 /dev/nvme1n1 /dev/nvme2n1 /dev/nvme3n1

# Tuning du RAID
echo 32768 > /sys/block/md0/md/stripe_cache_size
echo 4096 > /sys/block/md0/queue/read_ahead_kb

# /etc/mdadm.conf
ARRAY /dev/md0 metadata=1.2 UUID=xxxx

LVM optimise

# Creer PV avec alignement
pvcreate --dataalignment 1m /dev/nvme0n1

# Creer VG
vgcreate -s 32M vg_data /dev/nvme0n1

# Creer LV avec stripping (si plusieurs PV)
lvcreate -L 100G -n lv_data -i 4 -I 256K vg_data

# Tuning read-ahead LVM
lvchange --readahead 256 vg_data/lv_data

Configurations specifiques aux workloads

Apache Kafka

# XFS optimise pour Kafka (logs sequentiels)
mkfs.xfs -f -d agcount=32 -l size=512m -n size=8192 /dev/nvme0n1p1

# Montage
mount -o noatime,nodiratime,nobarrier,logbufs=8,logbsize=256k,allocsize=64m \
  /dev/nvme0n1p1 /var/lib/kafka

# sysctl pour Kafka
vm.dirty_background_ratio = 5
vm.dirty_ratio = 80  # Plus eleve pour Kafka
vm.dirty_expire_centisecs = 30000  # 5 minutes

# Kafka broker.properties
log.segment.bytes=1073741824
log.flush.interval.messages=10000
log.flush.interval.ms=1000
log.preallocate=true

PostgreSQL

# XFS optimise pour PostgreSQL
mkfs.xfs -f -d agcount=16 -l size=256m -n size=8192 /dev/nvme0n1p1

# Montage pour PostgreSQL
mount -o noatime,nodiratime,nobarrier,logbufs=8,logbsize=256k \
  /dev/nvme0n1p1 /var/lib/postgresql

# postgresql.conf complementaire
shared_buffers = 8GB              # 25% de la RAM
effective_cache_size = 24GB       # 75% de la RAM
maintenance_work_mem = 2GB
checkpoint_completion_target = 0.9
wal_buffers = 64MB
wal_compression = on
synchronous_commit = off          # Si acceptable

Elasticsearch

# Montage pour Elasticsearch
mount -o noatime,nodiratime,nobarrier \
  /dev/nvme0n1p1 /var/lib/elasticsearch

# sysctl pour Elasticsearch
vm.max_map_count = 262144
vm.swappiness = 1

# elasticsearch.yml
bootstrap.memory_lock: true
indices.memory.index_buffer_size: 30%

Conteneurs/Kubernetes

# XFS avec ftype=1 pour overlay2
mkfs.xfs -f -n ftype=1 /dev/nvme0n1p1

# Montage pour containerd
mount -o noatime,nodiratime,nobarrier,prjquota \
  /dev/nvme0n1p1 /var/lib/containerd

# containerd config.toml
[plugins."io.containerd.snapshotter.v1.overlayfs"]
  root_path = "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs"

Benchmarking avec fio

Test complet de performance

#!/bin/bash
# benchmark-disk.sh

DEVICE="/dev/nvme0n1"
MOUNT="/data"
SIZE="10G"
RUNTIME="60"

echo "=== Benchmark I/O sur $MOUNT ==="

# 1. Lecture sequentielle
echo -e "\n--- Lecture sequentielle (1MB blocks) ---"
fio --name=seq-read \
    --ioengine=libaio \
    --rw=read \
    --bs=1M \
    --numjobs=4 \
    --iodepth=32 \
    --runtime=$RUNTIME \
    --time_based \
    --filename=$MOUNT/testfile \
    --size=$SIZE \
    --group_reporting

# 2. Ecriture sequentielle
echo -e "\n--- Ecriture sequentielle (1MB blocks) ---"
fio --name=seq-write \
    --ioengine=libaio \
    --rw=write \
    --bs=1M \
    --numjobs=4 \
    --iodepth=32 \
    --runtime=$RUNTIME \
    --time_based \
    --filename=$MOUNT/testfile \
    --size=$SIZE \
    --group_reporting

# 3. Lecture aleatoire 4K
echo -e "\n--- Lecture aleatoire 4K ---"
fio --name=rand-read-4k \
    --ioengine=libaio \
    --rw=randread \
    --bs=4k \
    --numjobs=8 \
    --iodepth=64 \
    --runtime=$RUNTIME \
    --time_based \
    --filename=$MOUNT/testfile \
    --size=$SIZE \
    --group_reporting

# 4. Ecriture aleatoire 4K
echo -e "\n--- Ecriture aleatoire 4K ---"
fio --name=rand-write-4k \
    --ioengine=libaio \
    --rw=randwrite \
    --bs=4k \
    --numjobs=8 \
    --iodepth=64 \
    --runtime=$RUNTIME \
    --time_based \
    --filename=$MOUNT/testfile \
    --size=$SIZE \
    --group_reporting

# 5. Workload mixte (70/30)
echo -e "\n--- Workload mixte 70% lecture / 30% ecriture ---"
fio --name=mixed-rw \
    --ioengine=libaio \
    --rw=randrw \
    --rwmixread=70 \
    --bs=8k \
    --numjobs=8 \
    --iodepth=32 \
    --runtime=$RUNTIME \
    --time_based \
    --filename=$MOUNT/testfile \
    --size=$SIZE \
    --group_reporting

# 6. Test latence
echo -e "\n--- Test latence (iodepth=1) ---"
fio --name=latency \
    --ioengine=libaio \
    --rw=randread \
    --bs=4k \
    --numjobs=1 \
    --iodepth=1 \
    --runtime=30 \
    --time_based \
    --filename=$MOUNT/testfile \
    --size=1G \
    --group_reporting \
    --lat_percentiles=1

# Cleanup
rm -f $MOUNT/testfile

echo -e "\n=== Benchmark termine ==="

Resultats attendus

Test NVMe Gen4 NVMe Gen3 SATA SSD HDD
Seq Read 6-7 GB/s 3-3.5 GB/s 500-550 MB/s 150-200 MB/s
Seq Write 5-6 GB/s 2.5-3 GB/s 450-500 MB/s 130-180 MB/s
4K Rand Read 800K-1M IOPS 400-500K IOPS 80-100K IOPS 100-200 IOPS
4K Rand Write 200-400K IOPS 100-200K IOPS 40-60K IOPS 100-200 IOPS
Latence 4K < 0.1ms 0.1-0.2ms 0.3-0.5ms 5-15ms

Monitoring en temps reel

iostat

# Statistiques detaillees toutes les 2 secondes
iostat -xdh 2

# Metriques cles:
# %util  : Utilisation disque (>80% = saturation)
# await  : Latence moyenne totale (ms)
# r_await/w_await : Latence lecture/ecriture
# avgqu-sz : Profondeur moyenne de la queue
# r/s, w/s : IOPS lecture/ecriture
# rMB/s, wMB/s : Debit MB/s

iotop

# Processus consommant le plus d'I/O
iotop -o -P -d 1

# -o : Seulement les processus avec I/O
# -P : Afficher les processus (pas threads)
# -d 1 : Refresh toutes les secondes

blktrace/blkparse

# Trace detaillee des I/O
blktrace -d /dev/nvme0n1 -o trace

# Analyse
blkparse trace.blktrace.0 | head -100

# Visualisation
btt -i trace.blktrace.0

Prometheus/Grafana

# node_exporter collecte automatiquement les metriques disque
# Metriques utiles:
# - node_disk_io_time_seconds_total
# - node_disk_read_bytes_total
# - node_disk_written_bytes_total
# - node_disk_io_now
# - node_disk_read_time_seconds_total
# - node_disk_write_time_seconds_total

Troubleshooting

Probleme 1: I/O Wait eleve

# Diagnostic
vmstat 1 5
# Colonne 'wa' = I/O wait %

iostat -x 1 5
# %util proche de 100% = disque sature

# Solutions:
# 1. Verifier le scheduler
cat /sys/block/nvme0n1/queue/scheduler

# 2. Verifier les dirty pages
cat /proc/meminfo | grep Dirty
# Si tres eleve: reduire vm.dirty_ratio

# 3. Identifier le processus fautif
iotop -o -P

Probleme 2: Latence elevee

# Diagnostic
iostat -x 1
# await > 10ms sur SSD = probleme

# Causes possibles:
# 1. Queue trop profonde
cat /sys/block/nvme0n1/queue/nr_requests
# Reduire si necessaire

# 2. Scheduler inadapte
# Utiliser 'none' pour NVMe

# 3. TRIM non configure
fstrim -v /data
# Ajouter discard au montage ou cron fstrim

Probleme 3: Debit insuffisant

# Diagnostic
hdparm -Tt /dev/nvme0n1

# Verifier l'alignement des partitions
parted /dev/nvme0n1 align-check opt 1

# Verifier le mode de transfert (SATA)
hdparm -I /dev/sda | grep -i speed

# Solutions:
# 1. Augmenter read_ahead_kb
echo 512 > /sys/block/nvme0n1/queue/read_ahead_kb

# 2. Verifier les options de montage
mount | grep /data

Probleme 4: SSD qui ralentit avec le temps

# Verifier l'etat SMART
smartctl -a /dev/nvme0n1

# Verifier l'usure
nvme smart-log /dev/nvme0n1

# Solutions:
# 1. Activer le TRIM
fstrim -av

# 2. TRIM periodique
# /etc/cron.weekly/fstrim
#!/bin/bash
fstrim -av

# 3. Verifier l'over-provisioning
# Garder 10-20% d'espace libre

Checklist de production

## Pre-mise en production

### Filesystem
- [ ] Filesystem adapte au workload (XFS pour BDD, ext4 general)
- [ ] Options de montage optimisees (noatime, nobarrier)
- [ ] Partitions alignees (multiple de 4K)
- [ ] TRIM configure (discard ou cron fstrim)

### Scheduler
- [ ] Scheduler I/O adapte (none pour NVMe, mq-deadline pour HDD)
- [ ] Queue depth configure
- [ ] Rules udev persistantes

### Kernel
- [ ] vm.swappiness reduit
- [ ] vm.dirty_* ajustes
- [ ] vm.vfs_cache_pressure ajuste

### Monitoring
- [ ] iostat/iotop disponibles
- [ ] Metriques Prometheus configurees
- [ ] Alertes sur %util et latence

### Benchmarks
- [ ] Tests fio realises
- [ ] Resultats conformes aux specs disque
- [ ] Comparaison avant/apres tuning documentee

Conclusion

L'optimisation des I/O disque sous Linux necessite une approche holistique combinant choix du filesystem, tuning du kernel, et configuration adaptee au workload.

Points cles a retenir:

  1. Scheduler : none pour NVMe/SSD, mq-deadline pour HDD
  2. Montage : Toujours noatime, nobarrier si UPS disponible
  3. Cache : Ajuster vm.dirty_* selon la charge d'ecriture
  4. Monitoring : iostat -x est votre meilleur ami
  5. Tests : Toujours benchmarker avant et apres tuning

Les gains peuvent etre spectaculaires : +300% en IOPS, -75% en latence.


Ressources


Besoin d'aide pour optimiser les performances de vos serveurs Linux ? Decouvrez mes services de consulting et audits de performance.

F

Florian Courouge

Expert DevOps & Kafka | Consultant freelance specialise dans les architectures distribuees et le streaming de donnees.

Articles similaires