Cela commence généralement de la même manière : la latence grimpe, les tableaux de bord virent au jaune, puis votre service « rapide » devient une pièce de musée. Les sessions SSH se figent en cours de commande. Une base de données cesse de répondre. Le CPU s’ennuie, la RAM est correcte, le réseau semble normal — et pourtant la machine donne l’impression d’être encastrée dans du ciment humide.
Sur Ubuntu 24.04, la version la plus exaspérante de ce problème est un « blocage » du disque sous charge : pas une panne nette, pas un crash évident, mais un arrêt système complet parce que les E/S de stockage ne se terminent pas et que les timeouts sont trop lents (ou inexistants aux couches qui comptent). La solution n’est que rarement « acheter un disque plus rapide ». Il s’agit le plus souvent de « faire en sorte que le système échoue rapidement, isoler les dégâts, et empêcher qu’un périphérique bloqué ne prenne en otage tout l’hôte ».
Ce qu’est vraiment un « blocage de disque » (et pourquoi votre hôte se fige)
Quand les gens disent « le disque a bloqué », ils veulent souvent dire l’une des trois choses suivantes :
- Un périphérique ou un chemin cesse de terminer les E/S. Le noyau attend, réessaie, et attend encore. Les applications bloquent en sommeil non interruptible (
Dstate). Si suffisamment de threads critiques sont bloqués, l’hôte paraît gelé. - Les E/S se terminent, mais si lentement qu’on les prend pour un blocage. Les profondeurs de file d’attente explosent, la latence passe de millisecondes à minutes, et tout ce qui a besoin du stockage devient effectivement indisponible.
- Une couche de la pile de stockage sérialise la gestion d’erreur. Un chemin mort tient un verrou, une file se coince, un contrôleur entre dans une boucle de réinitialisation, et le reste du système se retrouve en file d’attente derrière.
Linux est généralement bon pour ne pas paniquer face aux problèmes de stockage. C’est excellent pour l’intégrité des données. Mais cela peut être terrible pour la disponibilité lorsque le système est configuré pour attendre « indéfiniment » un périphérique qui ne reviendra jamais. Beaucoup d’environnements préfèrent qu’un montage échoue, qu’un contrôle de santé déclenche, ou qu’un nœud soit expulsé plutôt que de laisser un membre de la flotte bloquer.
Il y a une raison pour laquelle cela fait tant mal : les E/S disque sont une dépendance pour presque tout. Journaux, état, fichiers temporaires, gestionnaires de paquets, caches DNS, tampons de métriques, couches de conteneurs — un problème de stockage ne casse pas seulement la base de données. Il brise votre capacité à observer la panne.
Une idée souvent paraphrasée attribuée à Werner Vogels (ingénierie de la fiabilité) : Tout échoue, donc concevez pour l’échec plutôt que de faire semblant que cela n’arrivera pas.
Les timeouts de stockage sont exactement cela : décider comment vous échouez.
Deux vérités inconfortables :
- Aucun réglage de timeout unique ne « résout » les blocages. Il faut des timeouts cohérents à travers les couches pour que la récupération se fasse dans un budget prévisible.
- Des timeouts trop agressifs peuvent provoquer leurs propres pannes — surtout sur des baies très sollicitées, des volumes cloud surchargés ou des tissus multipath instables.
Blague n°1 : Le stockage ne « tombe » jamais, il entre simplement dans une profonde méditation sur l’impermanence des paquets.
Playbook de diagnostic rapide : premières / secondes / troisièmes vérifications
Ceci est la routine « j’ai 5 minutes avant qu’on déclare un incident ». L’objectif n’est pas la cause racine parfaite. L’objectif est d’identifier la couche bloquée et de décider s’il faut basculer, mettre sous isolation (fence) ou redémarrer.
Premier : confirmer que c’est le stockage et identifier le périphérique victime
- Vérifier les logs du noyau pour les timeouts/réinitialisations. Si vous voyez des timeouts SCSI, des réinitialisations de contrôleur NVMe, ou « blocked for more than … seconds », vous êtes au bon endroit.
- Lister les tâches bloquées et les accumulations en état D. Si beaucoup de threads sont en
Dstate, c’est presque toujours une attente I/O sur un périphérique ou le journal/système de fichiers. - Mapper les montages → périphériques. Si
/varou un montage de base de données se trouve sur le périphérique problématique, l’hôte sera plus affecté que si c’est un simple montage de données froides.
Deuxième : déterminer si c’est le périphérique, le chemin ou la charge
- Niveau périphérique ? Logs SMART/NVMe, erreurs médias, réinitialisations de lien, réinitialisations de contrôleur.
- Niveau chemin ? Sessions iSCSI tombées, flaps de liens FC, basculement de groupes de chemins multipath, messages « no path ».
- Niveau charge ? Un processus effectuant des écritures sync intensives, blocages du journal du système de fichiers, congestion de writeback, saturation de la profondeur de file.
Troisième : choisir la mitigation la moins mauvaise
- Si un chemin est mort et que multipath est configuré : ajustez les vérifications de chemin et les timeouts de basculement pour que le failover se produise rapidement.
- Si un périphérique est bloqué : planifiez son retrait/isolation. Sur un hôte mono-disque, c’est souvent un redémarrage. Sur une pile redondante (RAID, multipath, FS en cluster), vous pouvez généralement l’isoler.
- Si c’est une saturation de la charge : réduisez la concurrence, ajustez la profondeur de file/planificateur, ou corrigez la charge (buffering, batching, I/O asynchrone).
Faits intéressants et contexte historique
- Linux utilisait autrefois le planificateur CFQ pour l’équité sur les disques rotatifs ; les noyaux modernes préfèrent
mq-deadlineounoneen raison du multi-queue block I/O. - Les timeouts SCSI remontent à une époque d’appareils lents où attendre 30–60 secondes n’était pas choquant ; sur les services actuels, c’est une éternité.
- Les avertissements « hung task » existent parce que le sommeil non interruptible est une caractéristique, pas un bug. Le noyau ne peut pas toujours tuer en toute sécurité une tâche en attente d’E/S.
- Multipath a été conçu pour des chemins instables, pas pour une pensée instable. Il peut masquer des défaillances transitoires à merveille — jusqu’à ce que les timeouts ne correspondent pas et qu’il bloque plus longtemps que votre SLA.
- NVMe a changé le modèle de défaillance. Il est assez rapide pour que la logique ancienne du « réessayer un peu » devienne catastrophique sous pression de file.
- La congestion writeback n’est pas nouvelle (la VM et la couche bloc s’en débattent depuis des décennies), mais elle mord encore lorsque ratios dirty et journalisation se rencontrent.
- EXT4 et XFS privilégient d’abord l’intégrité. Un journal/log bloqué peut rendre un montage entier apparemment mort même si le reste du périphérique est « correct ».
- Le stockage en cloud a introduit de nouvelles pathologies de latence. Le throttling, les voisins bruyants et la maintenance backend peuvent ressembler à des « blocages aléatoires » dans la VM invitée.
Mécanique : timeouts par couche (bloc, SCSI, NVMe, multipath, systèmes de fichiers)
Pour arrêter les arrêts complets, il faut comprendre qui attend qui. La pile de stockage est une chaîne de promesses :
- L’application promet qu’elle peut bloquer sur les E/S.
- Le système de fichiers promet l’ordre et la récupération (journal/log).
- La couche bloc promet de mettre en file et dispatcher les E/S.
- Le pilote de périphérique promet de parler au matériel et de récupérer des erreurs.
- Le transport (SATA/SAS/NVMe/FC/iSCSI) promet la livraison — ou au moins une erreur.
Quand un disque « bloque », le pire scénario est lorsque les erreurs ne sont pas renvoyées rapidement. Au lieu de cela, le noyau réessaye longuement, le système de fichiers attend des E/S critiques, et les threads applicatifs s’accumulent. Beaucoup de sous-systèmes ont raison d’attendre. Votre travail est de décider combien de temps ce « à raison » doit durer.
Timeouts de la couche bloc (request timeouts)
La couche bloc Linux a un concept de timeout de requête. Pour beaucoup de périphériques, il est exposé comme :
/sys/block/<dev>/device/timeout(commun pour SCSI)/sys/class/block/<dev>/queue/paramètres (profondeur de file, scheduler, etc.)
Si les requêtes ne se terminent pas dans ce timeout, le noyau essaie d’abandonner/réinitialiser. Que cela aide dépend du pilote et du matériel. Si le pilote continue de réinitialiser indéfiniment, vous obtenez le pire des deux mondes : aucun progrès et aucune défaillance nette.
SCSI : timeouts de commande et gestion d’erreur
SCSI a des timeouts de commande explicites (historiquement 30 secondes est courant). Sur un disque SAS local, cela peut être acceptable. Sur un SAN avec multipath et grands caches, cela peut être trop court (faux timeouts). Sur un chemin instable, cela peut être trop long (retarder le basculement).
La gestion d’erreur SCSI peut aussi bloquer. Si le périphérique est dans un mauvais état, vous pouvez voir des tentatives répétées de réinitialisation dans dmesg. L’astuce est d’aligner les timeouts SCSI avec multipath et la récupération du transport pour qu’une seule couche prenne la responsabilité du basculement ou de l’échec rapide — et non que toutes se battent entre elles.
NVMe : timeouts de contrôleur et boucles de réinitialisation
NVMe est généralement « soit ça vole soit c’est en feu ». Lorsqu’il échoue, il le fait souvent par réinitialisation de contrôleur. Vous verrez des messages sur les timeouts et réinitialisations. Le réglage clé est le timeout du core NVMe et le comportement de perte de contrôleur (selon le noyau/driver). Certains paramètres sont des paramètres de module ; d’autres sont par périphérique dans sysfs.
En pratique : si un périphérique NVMe se bloque de façon intermittente, raccourcir les timeouts peut aider à récupérer plus vite — ou provoquer des réinitialisations répétées sous forte charge si le périphérique est simplement lent. Ne modifiez pas cela à l’aveugle ; mesurez la distribution de latence.
Multipath : là où « haute disponibilité » devient « haute anxiété »
Device-mapper multipath peut soit vous sauver soit vous bloquer. Le plus grand mode de défaillance est le mismatch des timeouts :
- Le timeout de commande SCSI est long.
- Le vérificateur de chemin multipath est lent à déclarer un chemin mort.
- Le comportement de mise en file est défini sur « queue forever » quand aucun chemin n’existe.
Ce dernier est le tueur : le système continue de mettre en file les E/S indéfiniment, vos applis bloquent, et l’hôte paraît mort pendant qu’il attend poliment un chemin qui ne revient pas. Dans de nombreux environnements, vous voulez que la mise en file s’arrête après un temps borné pour que les services puissent échouer et que les orchestrateurs puissent reprogrammer.
Systèmes de fichiers : les blocages de journal/log ressemblent à des blocages de périphérique
EXT4 utilise un journal ; XFS utilise un log. Si des écritures critiques de métadonnées ne peuvent pas se terminer, le système de fichiers peut bloquer les appelants. Même si le périphérique bloc sous-jacent est seulement « partiellement » mauvais, le montage peut sembler complètement bloqué parce que les opérations de métadonnées sont sérialisées.
En outre : les patrons d’appel de fsync() peuvent faire paraître votre stockage comme bloqué. Un seul processus effectuant des écritures synchrones en boucle serrée peut dominer la latence pour tout le monde. Si vous avez déjà entendu « pourquoi la machine est gelée ? » et que la réponse a été « quelqu’un a activé l’écriture synchrone partout », bienvenue au club.
Blague n°2 : Le disque n’est pas lent — il est juste en train de mesurer votre patience.
Tâches pratiques : 12+ commandes, lecture des sorties, décisions à prendre
Ce sont des commandes pratiques, sûres pour la production. Utilisez-les pour identifier le goulot d’étranglement et valider si le réglage des timeouts fonctionne. Chaque tâche inclut : commande, sortie d’exemple, ce que cela signifie, et quelle décision prendre.
Task 1: Check for kernel I/O timeout signatures
cr0x@server:~$ sudo dmesg -T | egrep -i 'timed out|timeout|reset|I/O error|blk_update_request|hung task|blocked for more than' | tail -n 40
[Mon Dec 30 10:11:02 2025] sd 2:0:0:0: timing out command, waited 30s
[Mon Dec 30 10:11:02 2025] blk_update_request: I/O error, dev sdb, sector 12345678 op 0x1:(WRITE) flags 0x0 phys_seg 8 prio class 0
[Mon Dec 30 10:11:05 2025] scsi host2: sas: attempt task abort!
[Mon Dec 30 10:11:22 2025] INFO: task postgres:2211 blocked for more than 120 seconds.
Signification : Vous avez une détresse réelle au niveau périphérique/driver, pas seulement « la base de données est lente ». La présence de timing out command et des tentatives d’abandon/réinitialisation implique que le noyau tente de récupérer.
Décision : Identifiez quel périphérique (sdb ici), mappez-le à un montage/charge, et décidez si vous avez une défaillance média (remplacer) ou un problème de chemin/transport (basculement/réglage multipath).
Task 2: Identify D-state pileups quickly
cr0x@server:~$ ps -eo state,pid,comm,wchan:32 --sort=state | head -n 20
S 1 systemd ep_poll
D 2211 postgres io_schedule
D 2450 postgres xfs_log_force_lsn
D 3102 rsyslogd blk_mq_get_tag
R 4021 ps -
Signification : Plusieurs processus en D state, en attente dans des fonctions kernel liées aux E/S. xfs_log_force_lsn est une preuve évidente de pression/ blocage du log XFS.
Décision : Orientez-vous vers les vérifications du système de fichiers et du périphérique sous-jacent. Si les processus bloqués sont des démons critiques (journald, rsyslog, base de données), l’hôte paraîtra « gelé ».
Task 3: See real-time I/O latency and queue depth with iostat
cr0x@server:~$ iostat -x 1 5
Linux 6.8.0-xx-generic (server) 12/30/2025 _x86_64_ (16 CPU)
Device r/s w/s rkB/s wkB/s await svctm %util
sda 5.0 12.0 120.0 900.0 2.1 0.3 3.0
sdb 200.0 80.0 25600.0 6400.0 1800.0 1.2 100.0
dm-2 195.0 75.0 25000.0 6000.0 1850.0 1.1 100.0
Signification : await en secondes avec %util à 100 % signifie que le périphérique est saturé ou bloqué. Le périphérique dm correspond au comportement du disque sous-jacent, ce qui suggère que le goulot est en dessous du système de fichiers.
Décision : Si le périphérique est vraiment saturé, réduisez la concurrence ou corrigez la charge. S’il est « bloqué », recherchez des timeouts/réinitialisations et envisagez un basculement/retrait.
Task 4: Map mounts to devices (find what you’re about to break)
cr0x@server:~$ lsblk -f
NAME FSTYPE FSVER LABEL UUID FSAVAIL FSUSE% MOUNTPOINTS
sda
├─sda1 ext4 1.0 2b4a... 120G 20% /
└─sda2 swap 1 9f31...
sdb
└─mpatha LVM2_member 3JkQ...
├─vg0-data xfs 8d1c... 80G 85% /var/lib/postgresql
└─vg0-log xfs 7a2b... 10G 40% /var/log
Signification : Le disque problématique sdb alimente des volumes LVM contenant les données et logs PostgreSQL. Cela explique la douleur à l’échelle du système.
Décision : Si le problème est dans le SAN/chemin, le réglage multipath importe. Si c’est une défaillance locale du disque, planifiez le remplacement. Dans tous les cas, priorisez la sécurité des données et la récupération du service.
Task 5: Confirm whether you’re on multipath and inspect its behavior
cr0x@server:~$ sudo multipath -ll
mpatha (3600508b400105e210000900000490000) dm-2 LIO-ORG ,TCMU device
size=200G features='1 queue_if_no_path' hwhandler='0' wp=rw
|-+- policy='service-time 0' prio=50 status=active
| `- 2:0:0:0 sdb 8:16 active ready running
`-+- policy='service-time 0' prio=10 status=enabled
`- 3:0:0:0 sdc 8:32 active ready running
Signification : Vous mettez en file des E/S si aucun chemin n’existe (queue_if_no_path). Si les deux chemins clignotent ou disparaissent, les E/S peuvent se bloquer indéfiniment.
Décision : Déterminez si « mettre en file pour toujours » correspond à vos objectifs de disponibilité. Beaucoup de clusters préfèrent une mise en file bornée, puis l’échec.
Task 6: Check SCSI per-device timeout
cr0x@server:~$ cat /sys/block/sdb/device/timeout
30
Signification : Les commandes SCSI expirent après 30 secondes (défaut courant). C’est par commande, et les réessais/réinitialisations peuvent étendre considérablement le temps total de blocage.
Décision : Si vous avez besoin d’un basculement plus rapide (multipath), vous pouvez réduire cela — prudemment. Si vous avez un SAN lent qui se bloque occasionnellement, vous pourriez devoir l’augmenter, mais assurez-vous alors que les autres couches ne mettent pas indéfiniment en file.
Task 7: Inspect queue settings and scheduler (performance vs latency)
cr0x@server:~$ cat /sys/block/sdb/queue/scheduler
[mq-deadline] kyber bfq none
Signification : mq-deadline est actif. C’est souvent un bon choix par défaut pour les périphériques bloc qui bénéficient d’une latence bornée. Pour NVMe, none est aussi courant.
Décision : N’alternez pas les planificateurs en plein incident. Mais si vous êtes sur bfq sur un serveur bloc fortement concurrent, envisagez un changement après tests.
Task 8: Check if requests are timing out at the block layer
cr0x@server:~$ sudo journalctl -k -b | egrep -i 'blk_update_request|Buffer I/O error|reset|timed out' | tail -n 30
Dec 30 10:11:02 server kernel: blk_update_request: I/O error, dev sdb, sector 12345678 op 0x1:(WRITE) flags 0x0 phys_seg 8 prio class 0
Dec 30 10:11:05 server kernel: sd 2:0:0:0: timing out command, waited 30s
Dec 30 10:11:06 server kernel: scsi host2: sas: attempt task abort!
Signification : Confirme que le noyau émet des erreurs et inclut le périphérique et le type d’opération (READ/WRITE).
Décision : Si les écritures échouent, les systèmes de fichiers peuvent être remontés en lecture seule ou se bloquer ; planifiez un basculement de service. Si les lectures échouent sur une installation redondante, évaluez si c’est isolé à un chemin.
Task 9: Find which process is pounding the disk
cr0x@server:~$ sudo iotop -oPa
Total DISK READ: 25.00 M/s | Total DISK WRITE: 8.00 M/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
2211 be/4 postgres 18.00 M/s 4.00 M/s 0.00 % 98.00 % postgres: checkpointer
2305 be/4 postgres 6.00 M/s 2.50 M/s 0.00 % 65.00 % postgres: walwriter
Signification : La base de données est la principale consommatrice d’E/S et passe énormément de temps à attendre les E/S (IO% élevé).
Décision : Si le périphérique est malade, tuer le processus n’aidera pas ; il déplacera juste l’attente ailleurs. Si c’est une surcharge, ajustez la checkpointing/WAL de la BDD et la concurrence de stockage.
Task 10: Check NVMe error log and controller resets (if NVMe)
cr0x@server:~$ sudo nvme list
Node SN Model Namespace Usage Format FW Rev
/dev/nvme0n1 S4G8... ACME NVMe 3.2TB 1 1.20 TB / 3.20 TB 512 B + 0 B 1.2.3
cr0x@server:~$ sudo nvme smart-log /dev/nvme0
critical_warning : 0x00
temperature : 44 C
available_spare : 100%
percentage_used : 3%
media_errors : 0
num_err_log_entries : 12
cr0x@server:~$ sudo nvme error-log /dev/nvme0 | head -n 10
Entry[0]
error_count : 12
sqid : 3
cmdid : 0x0042
status_field : 0x4004
parm_err_loc : 0x0000
Signification : Des erreurs existent (num_err_log_entries). Toutes les erreurs NVMe ne sont pas fatales, mais elles corrèlent fortement avec des tempêtes de réinitialisation et des pics de latence.
Décision : Si le nombre d’erreurs augmente pendant le blocage, traitez-le comme un problème de périphérique/firmware/contrôleur et envisagez un remplacement ou une mise à jour de firmware pendant une fenêtre de maintenance.
Task 11: Confirm multipathd timing and path checker events
cr0x@server:~$ sudo journalctl -u multipathd -b | tail -n 40
Dec 30 10:10:51 server multipathd[812]: sdb: tur checker reports path is down
Dec 30 10:10:55 server multipathd[812]: mpatha: remaining active paths: 1
Dec 30 10:11:15 server multipathd[812]: sdb: reinstated
Signification : Les chemins vacillent. Si le basculement/réintégration prend trop de temps, l’hôte se bloque pendant que multipath décide de la réalité.
Décision : Ajustez les intervalles de vérification multipath et la politique de retry no-path pour les aligner sur la tolérance de pause de votre service.
Task 12: Inspect filesystem health signals (XFS example)
cr0x@server:~$ sudo dmesg -T | egrep -i 'xfs|ext4|journal|metadata' | tail -n 30
[Mon Dec 30 10:11:01 2025] XFS (dm-2): log I/O error -5
[Mon Dec 30 10:11:01 2025] XFS (dm-2): metadata I/O error: block 0x12a3f error 5
Signification : Le système de fichiers voit des erreurs d’E/S. Ce n’est plus « peut-être que c’est lent ». C’est une défaillance.
Décision : Arrêtez les écritures si possible (basculement de service), capturez les logs, et planifiez réparation/récupération. N’insistez pas à frapper un dispositif de log défaillant.
Task 13: Check writeback pressure (dirty ratios) that can mimic hangs
cr0x@server:~$ sysctl vm.dirty_background_ratio vm.dirty_ratio vm.dirty_expire_centisecs vm.dirty_writeback_centisecs
vm.dirty_background_ratio = 10
vm.dirty_ratio = 20
vm.dirty_expire_centisecs = 3000
vm.dirty_writeback_centisecs = 500
Signification : Ce sont des valeurs raisonnables par défaut. Sur des charges très rapides d’ingestion vers des disques plus lents, les limites dirty peuvent être atteintes, provoquant le blocage des threads utilisateur pendant le writeback — un autre aspect qui ressemble à un « blocage ».
Décision : Si vous observez des blocages sans erreurs matérielles et avec beaucoup de pages dirty, ajustez ces paramètres prudemment et corrigez le buffering de la charge.
Task 14: Measure latency distribution quickly with fio (safe mode)
cr0x@server:~$ sudo fio --name=latcheck --filename=/var/lib/postgresql/.fio-testfile --size=256M --rw=randread --bs=4k --iodepth=16 --numjobs=1 --direct=1 --time_based --runtime=20 --group_reporting
latcheck: (groupid=0, jobs=1): err= 0: pid=5123: Mon Dec 30 10:20:01 2025
read: IOPS=18.2k, BW=71.2MiB/s (74.7MB/s)(1.39GiB/20001msec)
lat (usec): min=70, max=540000, avg=880, stdev=12000
Signification : Une latence maxi de 540ms (ou pire) pendant des lectures aléatoires suggère une latence de queue extrême. Si le maximum est en secondes/minutes, vous êtes en territoire de blocage.
Décision : Utilisez cela pour valider les améliorations après réglages. Si la queue de latence reste énorme, les timeouts ne font peut‑être que masquer un problème plus profond de périphérique/chemin.
Paramètres de timeout à régler pour éviter les arrêts complets (quoi ajuster, et comment)
Soyons francs : le paramètre le plus sûr pour « ne jamais bloquer » est « ne jamais faire d’E/S ». Comme ce n’est pas réalisable, l’objectif réel est :
- Détecter une défaillance assez rapidement pour basculer (si redondant) ou marquer le nœud comme mauvais (si non).
- Empêcher la mise en file indéfinie qui transforme un disque/chemin défaillant en gel complet de l’hôte.
- Garder des timeouts cohérents pour qu’une couche n’attende pas 5 minutes pendant qu’une autre s’attend à 10 secondes de récupération.
1) Multipath : arrêter la mise en file éternelle (douleur bornée)
Si vous utilisez multipath, votre levier de disponibilité le plus important est de savoir si les E/S sont mises en file quand il n’y a pas de chemin actif.
Pourquoi queue_if_no_path est dangereux : Il est fantastique pour les brefs micro-blips. Il est catastrophique quand un tissu est down, une cible a disparu, ou l’authentification casse. Vos processus se bloquent en attendant des E/S qui sont mises en file dans le vide.
Conseils pour la production :
- Pour les clusters avec basculement au niveau nœud (Kubernetes, Pacemaker, etc.), préférez la mise en file bornée pour que le nœud échoue et que le service soit relocalisé.
- Pour les systèmes mono-hôte non redondants où attendre est préférable à échouer (rare), la mise en file peut être acceptable — mais vous choisissez consciemment des blocages d’hôte.
Concept de configuration multipath (exemples de paramètres) :
no_path_retry: combien de tentatives quand il n’y a pas de chemins ; peut être numérique oufail.dev_loss_tmoet paramètres de transport : combien de temps le noyau conserve un périphérique après perte de connectivité (commun en iSCSI/FC).fast_io_fail_tmo: rapidité d’échec des E/S quand les chemins tombent (dépendant de FC/iSCSI).polling_interval: fréquence des vérifications de chemin par multipath.
Sur Ubuntu 24.04, multipath est généralement configuré via /etc/multipath.conf. Vous voulez aligner :
- Le temps de détection de chemin (checker + polling) avec
- Combien de temps les applis peuvent attendre (timeouts de service, timeouts BDD) et
- Combien de temps le noyau réessaye les commandes SCSI avant de déclarer un périphérique mort.
Règle pratique : si votre orchestrateur tue/remplace un nœud en 60 secondes, ne configurez pas le stockage pour qu’il bloque 10 minutes « au cas où ». Vous n’obtiendrez qu’une panne au ralenti.
2) Timeout périphérique SCSI : ajuster avec prudence (et jamais seul)
Les timeouts SCSI sont par commande. Le système peut réessayer et réinitialiser plusieurs fois. Réduire le timeout peut accélérer le basculement, mais peut aussi provoquer des réinitialisations inutiles lors d’une charge transitoire.
Quand réduire les timeouts SCSI aide :
- Tissus multipath où un chemin est mort et vous souhaitez un basculement rapide.
- Hôtes où « gel pendant des minutes » est pire que « erreur I/O rapide ».
- Environnements où le backend de stockage est fiable et où un timeout indique réellement une panne.
Quand c’est risqué :
- SANs très sollicités qui se bloquent parfois pendant tens de secondes lors de maintenances.
- Charges avec grosses tailles d’I/O sur médias lents où de longues opérations sont attendues.
- Contrôleurs avec comportement de récupération d’erreur connu long (certains HBA RAID).
En pratique, vous réglez les timeouts SCSI conjointement avec le comportement no-path de multipath et les timers de perte de périphérique du transport. Sinon vous obtiendrez le problème classique : le noyau continue de réessayer pendant que multipath continue de mettre en file.
3) Timeouts de transport (iSCSI/FC) : expliciter l’échec
Beaucoup de « blocages de disque » sur volumes SAN sont en réalité des blocages de transport. Pour iSCSI, les timeouts de session/transport définissent la rapidité de détection d’une session perdue et la vitesse à laquelle les E/S échouent vers l’OS. Pour FC, des concepts similaires existent via des timers de fast I/O fail et de perte de périphérique.
Pourquoi c’est important : si l’OS pense que le périphérique existe toujours, il attendra. Si il déclare de façon décisive « le périphérique est parti », multipath peut basculer (ou le système peut échouer) proprement.
Conseil opérationnel : Alignez les timeouts de transport pour qu’ils soient plus courts que votre budget « l’application peut attendre », mais plus longs que les blips transitoires attendus. Si vous ne savez pas à quoi ressemblent les blips transitoires, mesurez-les pendant une maintenance contrôlée. Oui, planifiez-en une.
4) Timeouts NVMe : éviter les tempêtes de réinitialisation
Sur NVMe, des timeouts trop courts peuvent provoquer qu’un contrôleur se réinitialise en boucle sous forte charge si les latences de complétion grimpent. Les tempêtes de réinitialisation sont un type particulier de misère parce que l’action de récupération devient l’incident.
Ce que vous faites au lieu de raccourcir aveuglément les timeouts :
- Mesurez la latence tail sous charge réaliste (Task 14).
- Vérifiez les problèmes de firmware et les entrées de logs d’erreur (Task 10).
- Validez la stabilité du lien PCIe (les logs du noyau montrent souvent des erreurs AER quand ça chauffe).
5) Timeouts système de fichiers et application : ne faites pas comme si le disque était immortel
Même si le noyau échoue rapidement les E/S, votre service peut toujours se bloquer si la couche applicative attend indéfiniment (ou a des timeouts absurdes). Définissez des timeouts raisonnables et un comportement d’annulation dans :
- Drivers de base de données et pools de connexions
- Clients RPC
- Watchdogs systemd (lorsque pertinent)
- Contrôles de santé de cluster et fencing
Philosophie juste : les défaillances de stockage doivent rendre le nœud malade rapidement et de façon évidente, pas lentement et de manière sournoise.
Trois mini-récits d’entreprise depuis le terrain
Incident causé par une mauvaise hypothèse : « Multipath veut dire pas de pannes »
Ils faisaient tourner un ensemble de serveurs API sur Ubuntu. Le stockage était SAN-backed, multipath activé, et tout le monde dormait tranquille parce qu’il y avait « deux chemins ». Pendant un changement en semaine sur la couche de commutation, un tissu a commencé à perdre des trames de façon intermittente.
L’hypothèse erronée était subtile : l’équipe croyait que le basculement multipath serait quasi-instantané. En réalité, leur configuration mettait en file les E/S quand aucun chemin n’existait, et la vérification des chemins était lente. Quand le « bon » chemin a aussi vacillé, le système n’a pas échoué. Il a attendu. Indéfiniment.
De l’extérieur, les API semblaient à moitié vivantes. Certaines requêtes restaient bloquées. D’autres réussissaient. Les load balancers continuaient d’envoyer du trafic parce que TCP fonctionnait encore et que les checks de santé étaient trop superficiels. Sur les hôtes, les processus s’empilaient en état D. Redémarrer les services n’aidait pas ; les scripts de redémarrage nécessitaient aussi des E/S disque.
Le correctif n’a pas été héroïque. Ils ont changé multipath pour arrêter la mise en file éternelle, resserré le timing des vérifications de chemin et — c’est la partie que les gens sautent — ont rendu les contrôles de santé applicatifs effectuant une petite écriture/lecture sur les montages critiques. Après cela, une vraie panne de stockage faisait échouer les nœuds rapidement, être drainés, et cesser de tromper tout le monde.
Optimisation qui s’est retournée contre eux : « Augmentons queue depth et iodepth »
Un sprint de tuning de performance visait une pipeline d’ingestion en batch. L’équipe a augmenté la concurrence partout : plus de threads worker, plus de connexions BDD, et des profondeurs I/O plus élevées dans leurs outils. Les benchs étaient excellents sur un stockage tranquille.
Puis un pic de trafic prod a frappé pendant une maintenance backend du stockage. La latence a grimpé, les files se sont remplies, et ces profondeurs accrues sont devenues un déni de service auto-infligé. Le système a passé plus de temps à gérer des E/S en file qu’à faire du travail utile. La latence tail est devenue verticale.
Pire, leurs timeouts étaient toujours par défaut. Donc au lieu d’échouer vite et rerouter les jobs, l’hôte s’est bloqué dans de longs cycles de réessai. Le monitoring voyait « hôte up », mais le service était pratiquement mort. Les opérateurs ont dû redémarrer à dur les nœuds pour restaurer la capacité de scheduling.
La solution finale a été de limiter la concurrence selon le comportement mesuré du périphérique, pas selon l’optimisme. Ils ont défini des profondeurs de file raisonnables, utilisé la rétropression dans l’application, et réglé les timeouts pour que la vraie défaillance de stockage entraîne des chemins d’erreur prévisibles plutôt que de longs blocages. Le débit a légèrement baissé dans le cas heureux ; la disponibilité s’est améliorée radicalement dans le cas malheureux. Ce compromis vaut généralement la peine.
Pratique ennuyeuse mais correcte qui a sauvé la mise : « Budget de timeout et exercices réguliers de panne »
Une autre organisation gérait une flotte mixte : certains NVMe locaux, certains SAN, certains volumes cloud. Ils avaient une politique selon laquelle chaque classe de stockage devait avoir un budget de timeout documenté : combien de temps l’OS peut attendre, combien de temps multipath peut mettre en file, combien de temps l’orchestrateur doit isoler.
Ce n’était pas glamour. Le document était un tableau. Il était revu chaque trimestre. L’équipe réalisait aussi des drills contrôlés de « couper le chemin » sur un SAN de staging et simulait une dégradation de performance de volume cloud pendant des tests de charge.
Un jour, un contrôleur de stockage sur un site distant a commencé à glitcher. Une poignée de nœuds ont perdu un chemin puis brièvement le second. Au lieu de se bloquer, les nœuds ont échoué les E/S dans le budget convenu. Le cluster les a expulsés, les workloads ont bougé, et l’incident est devenu un petit événement de capacité, pas une panne plateforme généralisée.
Les notes post-mortem furent courtes : « les timeouts ont fonctionné comme prévu. » C’est la meilleure phrase opérationnelle — ennuyeuse, correcte, et vite terminée.
Erreurs fréquentes : symptôme → cause racine → fix
1) Symptom: host “freezes”, but CPU is low
Cause racine : processus bloqués en sommeil non interruptible (D-state) en attente d’E/S ; souvent un journal/log du système de fichiers bloqué.
Correctif : identifiez le périphérique/montage (Tasks 2–4), vérifiez les logs du noyau (Task 1), et arrêtez la mise en file indéfinie dans multipath si applicable.
2) Symptom: multipath device exists, but I/O stalls for minutes when SAN blips
Cause racine : queue_if_no_path ou no_path_retry trop permissif avec vérification de chemin lente.
Correctif : configurez un retry/échec borné et alignez les intervalles de vérification de chemin avec votre budget de timeout de service (Task 5, Task 11).
3) Symptom: repeated “resetting controller” messages (NVMe or HBA)
Cause racine : instabilité du périphérique/firmware ou timeouts trop agressifs sous charge, provoquant des tempêtes de réinitialisation.
Correctif : validez les logs firmware/health (Task 10), vérifiez les compteurs d’erreur, et ne raccourcissez pas les timeouts avant de comprendre la latence tail.
4) Symptom: “blocked for more than 120 seconds” appears, then clears, then returns
Cause racine : flaps de chemin intermittents ou throttling backend provoquant des pics de latence tail au-delà de la tolérance applicative.
Correctif : corrélez avec les logs multipath (Task 11) et les événements transport ; ajustez le basculement et réduisez la concurrence de la charge pour contrôler la montée de files.
5) Symptom: I/O errors in dmesg, filesystem remounts read-only
Cause racine : vraies erreurs média, câble/chemin cassé, ou défaillance de périphérique backend renvoyant des erreurs.
Correctif : traitez comme un risque de données. Basculez les services, capturez les logs, et remplacez/réparez le hardware ou le volume. Le tuning ne réparera pas un disque mort.
6) Symptom: “everything is slow” during backups or batch jobs, no kernel errors
Cause racine : saturation de profondeur de file et congestion writeback ; parfois mauvais choix de scheduler pour le type de périphérique.
Correctif : limitez la concurrence, planifiez les jobs lourds, envisagez un tuning du scheduler après tests (Task 7), et ajustez prudemment les paramètres de writeback (Task 13).
7) Symptom: only one mount hangs, rest of system ok
Cause racine : blocage du log/journal d’un système de fichiers spécifique ou d’un LV LVM ; autres montages sur d’autres périphériques non affectés.
Correctif : isolez et échouez le montage/service, plutôt que de redémarrer l’hôte entier. Envisagez de séparer logs/journaux sur des périphériques différents quand c’est pertinent.
Check-lists / plan étape par étape
Étape par étape : pendant un incident actif « blocage sous charge »
- Capturez des preuves rapides : extraits de logs noyau (Task 1), preuves de tâches bloquées (Task 2), et iostat (Task 3). Sauvegardez-les hors hôte si possible.
- Cartographiez l’impact : identifiez quel montage/périphérique est impliqué (Task 4). Si c’est
/,/var, ou un montage BDD, attendez un rayon d’impact large. - Déterminez la redondance : êtes-vous sur multipath/RAID/cluster ? Si oui, vous pouvez souvent isoler le mauvais chemin/périphérique. Si non, planifiez un redémarrage contrôlé et remplacement.
- Si multipath : confirmez si vous mettez en file pour toujours (Task 5). Si oui, décidez si passer à un comportement borné fait partie de votre plan de correction.
- Vérifiez les erreurs réelles d’E/S : journalctl logs noyau (Task 8) et messages système de fichiers (Task 12).
- Vérifiez les drivers de charge : iotop (Task 9) pour voir si c’est un unique coupable ou une pression générale.
- Mitigez : basculez les services, videz le nœud, ou isolez/redémarrez. N’insistez pas à redémarrer des applis bloquées sur des E/S.
- Après récupération : effectuez une mesure de latence contrôlée (Task 14) pour valider si la latence tail est redevenue raisonnable.
Étape par étape : implémenter le tuning des timeouts en sécurité (plan de changement)
- Définissez votre budget de timeout (ex : « un nœud peut se bloquer au maximum 30 secondes sur le stockage avant d’être déclaré unhealthy »). Sans cela, vous réglez au hasard.
- Inventoriez les types de stockage : SATA/SAS local, NVMe, iSCSI/FC SAN, volumes cloud, dm-crypt, LVM, RAID, multipath.
- Notez les réglages actuels : timeouts SCSI, config multipath, timeouts transport, scheduler, profondeur de file.
- Décidez du comportement en cas d’échec : préférez-vous des erreurs I/O rapides (fail fast) ou de l’attente (tenter de survivre) ? La plupart des systèmes distribués doivent échouer vite.
- Alignez les couches :
- Le transport détecte la perte de chemin dans le budget.
- Multipath bascule ou fait échouer les E/S dans le budget.
- Les timeouts SCSI/NVMe ne dépassent pas le budget d’un ordre de grandeur.
- Testez par injection de fautes : coupez un chemin, désactivez une cible, throttlez un volume, puis observez la durée de blocage et le comportement applicatif.
- Déployez progressivement : un environnement, une classe de stockage à la fois.
- Surveillez la latence tail et les taux d’erreur pendant le déploiement ; revenez en arrière si vous provoquez des tempêtes de réinitialisation ou de faux échecs.
Checklist de sens : à quoi ressemble le « bon »
- Un seul chemin mort déclenche rapidement le basculement multipath et cela se voit dans les logs.
- Pas de mise en file indéfinie sur les montages critiques, sauf si vous l’avez choisi explicitement.
- Les applications expirent et réessaient au niveau applicatif au lieu de rester bloquées indéfiniment.
- Les contrôles de santé de nœud détectent l’indisponibilité de stockage (pas seulement « le processus existe »).
- La latence tail reste bornée sous charge maximale, pas seulement la latence moyenne.
FAQ
1) Est-ce un problème d’Ubuntu 24.04, ou un problème Linux ?
Principalement une réalité Linux et hardware. Ubuntu 24.04 embarque un noyau et un userspace modernes, mais les modes de défaillance sont inhérents à la pile de stockage : les périphériques peuvent cesser de répondre, et l’OS doit décider combien de temps attendre.
2) Pourquoi un mauvais disque rend-il tout l’hôte gelé ?
Parce que des processus critiques bloquent sur des E/S. Si journald, rsyslog, les services de paquets ou votre base de données sont bloqués en état D, tout, de la connexion au monitoring, peut se figer derrière.
3) Dois-je simplement baisser tous les timeouts à 1 seconde ?
Non. Vous provoquerez des faux échecs et des tempêtes de réinitialisation, surtout sur SAN et NVMe sous charge. Fixez les timeouts sur la base de la latence tail mesurée et du budget de basculement de votre service.
4) Quel est le paramètre multipath le plus dangereux ?
queue_if_no_path sans politique de retry bornée. Il peut transformer « pas de chemins disponibles » en « l’hôte paraît mort », ce qui est une expérience utilisateur profondément problématique.
5) Comment savoir si c’est une saturation de charge ou un périphérique qui meurt ?
La saturation montre généralement une utilisation élevée et une latence croissante sans erreurs I/O noyau. Les périphériques qui meurent montrent timeouts, réinitialisations et erreurs I/O dans les logs du noyau (Task 1 et Task 8).
6) Les systèmes de fichiers peuvent-ils provoquer des blocages même si le disque va bien ?
Ils peuvent amplifier les problèmes. Une charge qui force des commits sync fréquents peut bloquer le montage sous pression. Mais un disque réellement « OK » avec des blocages catastrophiques du système de fichiers est moins fréquent que l’on espère.
7) Mon volume cloud pause parfois 20–60 secondes. Dois-je augmenter les timeouts ?
Si ces pauses sont réelles et attendues chez votre fournisseur, vous devrez peut‑être allonger les timeouts pour éviter des faux échecs — mais vous devez alors vous assurer que votre application et votre orchestration tolèrent ces pauses. Sinon, prévoyez un basculement vers d’autres nœuds et ne laissez pas un volume bloqué figer l’hôte.
8) Pourquoi tuer le processus bloqué ne règle-t-il pas le blocage ?
Parce que le processus est bloqué en sommeil kernel non interruptible en attente d’E/S. Le noyau ne peut pas le nettoyer en toute sécurité tant que l’E/S ne se termine pas ou n’échoue pas.
9) Quelle est la manière la plus sûre de tester le tuning des timeouts ?
Injection de fautes en staging : désactivez un chemin volontairement, désactivez une cible, ou throttlez un volume tout en faisant tourner une charge représentative. Mesurez la durée de blocage et le comportement de récupération, puis ajustez.
10) Quand redémarrer est-il la bonne réponse ?
Quand vous avez un périphérique non redondant qui est bloqué et ne récupère pas, ou quand le noyau/driver est coincé dans une boucle de réinitialisation et que vous avez besoin du nœud rapidement. Redémarrer n’est pas une solution ; c’est un pansement.
Conclusion : prochaines étapes que vous pouvez faire aujourd’hui
Si votre hôte Ubuntu 24.04 « bloque » sous charge disque, ne l’acceptez pas comme un mystère. Traitez-le comme un problème de budget de timeout avec un sous-texte matériel. Vos prochaines étapes :
- Pendant le prochain événement, collectez les trois essentiels : lignes de timeout dmesg, preuves de processus en état D, et sortie
iostat -x(Tasks 1–3). - Mappez les montages aux périphériques pour savoir ce qui bloque réellement (Task 4). Deviner fait perdre des heures.
- Si vous utilisez multipath, auditez si vous mettez en file pour toujours et décidez si cela correspond à vos objectifs de disponibilité (Task 5). La plupart des plateformes modernes préfèrent un échec borné.
- Rédigez un budget de timeout pour votre classe de stockage et alignez SCSI/NVMe/transport/multipath sur celui-ci. Si vous ne pouvez pas dire « nous échouons les E/S dans ~N secondes », vous ne maîtrisez pas vos pannes.
- Réalisez un drill de panne contrôlé et observez si votre nœud échoue rapidement ou se bloque lentement. Puis ajustez avec des données, pas avec de la superstition.
Les blocages disque ne sont pas toujours évitables. Les arrêts complets de l’hôte le sont généralement. Faites en sorte que le système choisisse une défaillance claire, rapidement, et votre vie d’astreinte s’améliorera immédiatement — même si la vie du fournisseur de stockage restera… formatrice.