Ubuntu 24.04 : Arrêtez de redémarrer pour « réparer » les problèmes — comment isoler correctement les causes racines (cas n°60)

Cet article vous a aidé ?

L’habitude du redémarrage est une taxe que vous payez pour toujours. Elle vous apporte quelques minutes de calme, efface vos empreintes sur l’incident et garantit discrètement que vous reverrez le même incident — généralement à 2h13 du matin, pendant un déploiement, quand quelqu’un « a juste besoin que ça revienne ».

Ubuntu 24.04 est une base solide. Quand ça déraille, ce n’est pas parce que l’OS s’est réveillé en mode chaos. C’est parce que quelque chose de mesurable s’est produit : une file s’est accumulée, la pression mémoire a franchi un seuil, un worker noyau s’est bloqué, une carte réseau a vacillé, un système de fichiers a marqué une pause, un service s’est enlisé dans un mauvais état. Votre travail n’est pas de redémarrer les preuves. Votre travail est d’isoler la cause racine et de décider du correctif le plus petit et sûr.

Redémarrer n’est pas une réparation : l’état d’esprit en production

Un redémarrage est un instrument grossier. Il efface la mémoire, réinitialise les pilotes, tue les processus bloqués et rend les métriques « bonnes » parce que vous remettez les compteurs à zéro. C’est l’équivalent technique de baisser la musique pour mieux entendre le bruit du moteur : vous vous sentirez mieux, mais le moteur est toujours en train de mourir.

En production, vous optimisez pour la récupération reproductible et l’isolation de la cause racine. Cela signifie :

  • Confinement d’abord : arrêter l’impact utilisateur, limiter le blast radius, réduire la charge.
  • Collecte de preuves : logs, état, compteurs, files—avant de tout réinitialiser.
  • Changement le plus petit et réversible : redémarrer un service, recharger une config, drainer un nœud, désactiver un feature flag.
  • Cause racine : la prouver avec des données, pas des impressions.

Si votre processus est « redémarrer et espérer », vous habituez votre organisation à accepter des interruptions inexpliquées comme normales. Ce n’est pas de la résilience. C’est du syndrome de Stockholm avec tableaux d’uptime.

Une citation à garder : Gene Kranz (directeur de vol Apollo) a promu une culture « dure et compétente ». Idée paraphrasée : Soyez durs et compétents — utilisez un processus discipliné sous pression. C’est le boulot des ops un mardi banal.

Blague n°1 : Redémarrer pour réparer la production, c’est comme mettre son téléphone au micro-ondes parce qu’il est lent. Vous aurez peut-être de la chaleur, mais vous ne réglez pas le bon problème.

Faits et contexte : pourquoi cela se répète

Voici quelques faits concrets et non mythiques qui expliquent pourquoi « un redémarrage l’a réparé » est si courant — et si trompeur :

  1. Linux demandait moins souvent de redémarrer que Windows, mais les réinitialisations de pilotes et les bugs noyau existent toujours. Beaucoup de « réparations par reboot » sont en réalité des histoires de réinitialisation d’état de pilote.
  2. systemd a rendu la gestion des services beaucoup plus cohérente que des scripts init bricolés. Cela signifie aussi que vous pouvez souvent corriger avec un systemctl restart ciblé au lieu d’un redémarrage complet.
  3. Le passage d’Ubuntu aux noms d’interface réseau prévisibles a réduit le chaos « eth0 disparu », mais un netplan mal configuré peut encore provoquer des problèmes de lien/route subtils qui persistent jusqu’au reload.
  4. Les cgroups sont passés de « sympa à avoir » à « plan de contrôle des ressources » (surtout avec les conteneurs). Beaucoup de « ralentissements aléatoires » sont en réalité du throttling cgroup, de la pression mémoire ou des IO weights qui font exactement ce que vous leur avez demandé.
  5. NVMe a apporté une latence incroyable — et de nouveaux modes de défaillance : bizarreries de firmware, gestion d’alimentation PCIe, et erreurs média intermittentes qui apparaissent comme des blocages IO, pas des pannes nettes.
  6. L’OOM killer n’est pas une erreur ; c’est une politique. Il tue quelque chose pour garder le noyau vivant. Rebooter après un OOM, c’est souvent refuser d’apprendre quel processus a mangé la machine.
  7. journald et ses logs structurés ont changé la réponse aux incidents : vous pouvez filtrer par boot, unité, priorité, PID et fenêtre temporelle. Ce sont des preuves que vous n’aviez pas avec des fichiers texte dispersés.
  8. Les noyaux modernes peuvent « se bloquer » sans planter : soft lockups, RCU stalls, IO bloqué et attentes de transaction de système de fichiers. Le serveur semble vivant, mais le progrès est gelé.
  9. Les environnements cloud ont rendu le « reboot » dangereusement bon marché : l’habitude est passée des postes de travail aux flottes, et soudain personne ne pense à préserver les données médico-légales.

Ubuntu 24.04 (Noble) est particulièrement « observable » si vous utilisez ce qui est déjà présent : systemd, journald, logs noyau, compteurs de performance et les métriques que vous auriez dû avoir de toute façon. Le playbook ci‑dessous suppose que vous êtes prêt à regarder.

Playbook de diagnostic rapide (premier/deuxième/troisième)

Ceci est la séquence de triage qui trouve rapidement les goulets sans se perdre dans les détails. Utilisez-la lorsque la page sonne et que vous avez des minutes pour rendre le système moins en feu.

Premier : établir le mode de défaillance (CPU, mémoire, disque ou réseau ?)

  • La machine est-elle réactive ? Pouvez-vous SSHer ? Pouvez-vous lancer des commandes en 1–2 secondes ?
  • La moyenne de charge ment-elle ? La charge peut être élevée à cause d’une pression CPU exécutable ou parce que des tâches sont coincées en sommeil IO non interrompable.
  • Y a‑t‑il un swap actif ou des OOM ? La pression mémoire provoque des allocations lentes, des tempêtes de swap, des IO et des timeouts en cascade.
  • La latence disque grimpe‑t‑elle ? Un await élevé / des files longues gèlent tout ce qui touche au stockage.
  • Le réseau est‑il le goulot ? Retransmissions, pertes, échecs DNS, incompatibilités MTU — classique « c’est down mais c’est up ».

Deuxième : identifier le « qui » (quel processus/unité et quelle dépendance)

  • Principaux coupables : hog CPU, fuite mémoire, threads bloqués, ou trop de processus.
  • Cartographie des dépendances : votre appli attend‑elle la BD, le DNS, NFS, un object store ou le disque local ?
  • État des services : état des unités systemd, boucles de redémarrage, déclenchements watchdog.

Troisième : prendre la plus petite action corrective sûre, puis confirmer avec les métriques

  • Réduire la charge : drainer le nœud du LB, mettre en pause les jobs batch, limiter le débit, désactiver un feature flag coûteux.
  • Redémarrage ciblé : redémarrer le service, pas la machine, sauf si vous faites une réinitialisation contrôlée du noyau/du pilote pour un problème connu.
  • Confirmer : latence en baisse, taux d’erreur en baisse, files vidées, utilisation des ressources normalisée ?
  • Capturer des preuves : même si vous devez redémarrer, sauvegardez d’abord des extraits du journal, les logs noyau et l’état.

Cette séquence évite le piège « j’ai vu une charge élevée, donc CPU », qui amène les gens à redimensionner des instances alors que le vrai coupable est une file disque bloquée derrière un timeout NVMe.

Tâches pratiques (commandes, sorties, décisions)

Ci‑dessous des tâches pratiques à exécuter sur Ubuntu 24.04 pendant un incident. Chacune inclut : la commande, un extrait de sortie réaliste, ce que ça signifie, et la décision à prendre.

Task 1: Identify if you’re looking at CPU pressure or IO wait

cr0x@server:~$ uptime
 14:22:10 up 18 days,  3:11,  2 users,  load average: 18.72, 17.95, 16.40
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 6  0      0 412180  90244 3218120   0    0    12   110  980 2100 45 10 40  5  0
 3  2      0 398200  90244 3221200   0    0   240  9010 1200 2600 18  6 22 54  0
 2  4      0 390112  90244 3221456   0    0   180 12050 1180 2500 10  4 18 68  0

Sens : la charge est élevée, mais b (bloqué) augmente et wa (IO wait) est énorme. Ce n’est pas « juste CPU ». Ce sont des threads bloqués en attente de stockage.

Décision : arrêter de monter en CPU. Se concentrer sur la latence disque et vérifier filesystem/RAID/NVMe.

Task 2: Check per-disk latency and queue depth

cr0x@server:~$ iostat -x 1 3
Linux 6.8.0-41-generic (server)  12/30/2025  _x86_64_  (8 CPU)

Device            r/s   w/s   rkB/s   wkB/s  aqu-sz  await  r_await  w_await  %util
nvme0n1         12.0 220.0   384.0  9012.0   18.40  78.20    6.10   82.10   99.2
nvme1n1          0.0   0.0     0.0     0.0    0.00   0.00    0.00    0.00    0.0

Sens : %util ~99% et await ~78ms sur nvme0n1 est mauvais pour un système qui attend une latence de quelques millisecondes. aqu-sz est profond : les requêtes sont en file d’attente.

Décision : trouver qui écrit, vérifier le système de fichiers, chercher saturation ou erreurs, et envisager de brider le coupable.

Task 3: Identify top IO writers by process

cr0x@server:~$ sudo iotop -oPa
Total DISK READ:         1.10 M/s | Total DISK WRITE:       102.45 M/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN  IO>    COMMAND
 8921 be/4   postgres  0.00 B/s   68.20 M/s  0.00 %  7.10 % postgres: checkpointer
25140 be/4   root      0.00 B/s   22.30 M/s  0.00 %  3.20 % /usr/bin/rsync -aH --delete /var/lib/app/ /mnt/backup/

Sens : PostgreSQL checkpointer et un job de backup écrivent beaucoup. La sauvegarde peut voler l’IO au pire moment.

Décision : mettre en pause/renice/ionice la sauvegarde, vérifier le tuning des checkpoints DB, et confirmer que vous ne snapshottez pas en période de pic.

Task 4: Confirm memory pressure and swap behavior

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:            31Gi        28Gi       510Mi       2.1Gi       2.5Gi       1.1Gi
Swap:          4.0Gi       3.6Gi       410Mi

Sens : Le swap est fortement utilisé ; « available » est faible. Cela transforme souvent une latence acceptable en bourbier.

Décision : trouver le consommateur mémoire, arrêter la fuite, la limiter via systemd/cgroups, ou augmenter la mémoire — mais seulement après avoir prouvé que ce n’est pas un job hors de contrôle.

Task 5: Catch OOM killer events and the victim

cr0x@server:~$ journalctl -k -b | grep -i -E "oom|out of memory|killed process" | tail -n 5
Dec 30 13:58:41 server kernel: Out of memory: Killed process 18221 (java) total-vm:9643212kB, anon-rss:6123400kB, file-rss:10240kB, shmem-rss:0kB, UID:1001 pgtables:18432kB oom_score_adj:0

Sens : Le noyau a tué un processus Java par épuisement mémoire. Rebooter « répare » parce que vous avez supprimé le coupable et vidé les caches, pas parce que le système a guéri.

Décision : corriger le dimensionnement/les limites mémoire, trouver la fuite, ajouter des garde‑fous (MemoryMax systemd, limites de conteneur), et vérifier que les paramètres heap de l’appli correspondent à la réalité.

Task 6: Find which unit is flapping or in a restart loop

cr0x@server:~$ systemctl --failed
  UNIT                 LOAD   ACTIVE SUB    DESCRIPTION
● app-api.service       loaded failed failed App API service
cr0x@server:~$ systemctl status app-api.service --no-pager -l
× app-api.service - App API service
     Loaded: loaded (/etc/systemd/system/app-api.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Mon 2025-12-30 14:10:18 UTC; 2min 1s ago
    Process: 24410 ExecStart=/usr/local/bin/app-api (code=exited, status=1/FAILURE)
     Memory: 1.2G
     CPU: 11.203s

Dec 30 14:10:18 server app-api[24410]: FATAL: cannot connect to Redis: dial tcp 10.20.0.15:6379: i/o timeout
Dec 30 14:10:18 server systemd[1]: app-api.service: Main process exited, code=exited, status=1/FAILURE
Dec 30 14:10:18 server systemd[1]: app-api.service: Failed with result 'exit-code'.

Sens : L’appli n’est pas « cassée » ; elle échoue parce que Redis est injoignable ou lent. Redémarrer l’hôte applicatif ne réparera pas un chemin réseau ou une surcharge Redis.

Décision : basculer vers la dépendance : tester la reachabilité Redis, vérifier sa latence, et valider routage/pare‑feu.

Task 7: Check kernel warnings that hint at stalls or driver resets

cr0x@server:~$ journalctl -k -b -p warning..alert --no-pager | tail -n 20
Dec 30 14:01:12 server kernel: INFO: task kworker/u16:3:1123 blocked for more than 120 seconds.
Dec 30 14:01:12 server kernel: nvme nvme0: I/O 224 QID 3 timeout, aborting
Dec 30 14:01:42 server kernel: nvme nvme0: Abort status: 0x371
Dec 30 14:02:10 server kernel: EXT4-fs warning (device nvme0n1p2): ext4_end_bio:340: I/O error 10 writing to inode 524313 (offset 0 size 4096)

Sens : Timeouts NVMe et erreurs ext4 IO ne sont pas une « lenteur aléatoire ». C’est un problème de stockage, potentiellement matériel ou firmware.

Décision : protéger les données, planifier une maintenance, vérifier SMART/NVMe health, envisager de retirer le périphérique et arrêter de prétendre qu’un reboot « répare ».

Task 8: Inspect NVMe health and error log

cr0x@server:~$ sudo nvme smart-log /dev/nvme0
Smart Log for NVME device:nvme0 namespace-id:ffffffff
critical_warning                    : 0x00
temperature                         : 49 C
available_spare                     : 100%
available_spare_threshold           : 10%
percentage_used                     : 7%
data_units_read                     : 193,421,112
data_units_written                  : 882,100,420
media_errors                        : 12
num_err_log_entries                 : 98
cr0x@server:~$ sudo nvme error-log /dev/nvme0 | head -n 8
Error Log Entries for device:nvme0 entries:64
 Entry[ 0]
  error_count     : 98
  sqid            : 3
  cmdid           : 0x00d1
  status_field    : 0x4004
  lba             : 182736128

Sens : media_errors et un journal d’erreurs croissant corrèlent avec les timeouts noyau. C’est une tendance vers une défaillance réelle.

Décision : programmer un remplacement, réduire l’amplification d’écriture, vérifier les backups et déplacer les services critiques hors de ce périphérique.

Task 9: Validate filesystem space/inodes (the boring outage generator)

cr0x@server:~$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p2  220G  218G  1.2G 100% /
tmpfs            16G  1.2G   15G   8% /run
cr0x@server:~$ df -i
Filesystem       Inodes  IUsed    IFree IUse% Mounted on
/dev/nvme0n1p2  14417920 14399811   18109  100% /

Sens : Disque plein ou exhaustion d’inodes provoque des échecs « aléatoires » : le service ne peut plus écrire des PID, les logs échouent, les bases refusent des commits, apt casse, les sockets échouent.

Décision : supprimer/rotater les logs, nettoyer les anciennes releases, corriger la création de fichiers incontrôlée, ajouter des quotas et définir des alertes avant d’atteindre 100% à nouveau.

Task 10: Spot file descriptor exhaustion (the stealth limiter)

cr0x@server:~$ cat /proc/sys/fs/file-nr
10240	0	1048576
cr0x@server:~$ sudo lsof | wc -l
245112

Sens : Le plafond global de file handle est correct ici, mais le nombre énorme de fichiers ouverts suggère soit une forte concurrence soit une fuite (sockets/fichiers non fermés).

Décision : vérifier les limites par processus (ulimit, systemd LimitNOFILE=), identifier le processus qui fuit et le corriger — ne redémarrez pas pour « fermer des fichiers ».

Task 11: Prove network loss, retransmits, and route weirdness

cr0x@server:~$ ip -s link show dev enp5s0
2: enp5s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    link/ether 3c:ec:ef:12:34:56 brd ff:ff:ff:ff:ff:ff
    RX:  bytes packets errors dropped  missed   mcast
    10498312323  8123312      0   24810       0   12901
    TX:  bytes packets errors dropped carrier collsns
     9983211121  7921101      0     120       0       0
cr0x@server:~$ ss -s
Total: 2135 (kernel 0)
TCP:   1980 (estab 1120, closed 650, orphaned 3, timewait 645)

Transport Total     IP        IPv6
RAW       0         0         0
UDP       62        55        7
TCP       1330      1211      119
INET      1392      1266      126
FRAG      0         0         0

Sens : Les pertes RX sont significatives. Ce n’est pas « l’appli est lente », c’est « des paquets sont perdus », ce qui entraîne des retries, des timeouts et des dashboards tristes.

Décision : investiguer les tailles de rings NIC, la saturation CPU softirq, les erreurs de port de switch, les incompatibilités MTU et les rafales de trafic. Le redémarrage peut temporairement vider des files, mais il ne réparera pas un lien défectueux ou une sur‑souscription.

Task 12: Check DNS failures quickly (because everything depends on it)

cr0x@server:~$ resolvectl status
Global
         Protocols: -LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
  resolv.conf mode: stub
Current DNS Server: 10.10.0.53
       DNS Servers: 10.10.0.53 10.10.0.54

Link 2 (enp5s0)
Current Scopes: DNS
     DNS Servers: 10.10.0.53 10.10.0.54
cr0x@server:~$ dig +time=1 +tries=1 api.internal A @10.10.0.53

; <<>> DiG 9.18.24-1ubuntu0.1-Ubuntu <<>> +time=1 +tries=1 api.internal A @10.10.0.53
;; connection timed out; no servers could be reached

Sens : Le DNS timeoute. De nombreux services échouent « mystérieusement » quand la résolution de noms bloque.

Décision : basculer vers des résolveurs alternatifs, réparer le DNS amont, et éviter les redémarrages d’appli qui ne font qu’amplifier la charge sur un étage DNS mourant.

Task 13: Inspect cgroup throttling (containers and systemd both do this)

cr0x@server:~$ systemctl show app-api.service -p CPUQuota -p MemoryMax -p IOWeight
CPUQuota=50%
MemoryMax=2147483648
IOWeight=100

Sens : Vous avez explicitement limité le CPU à 50% et la mémoire à 2GiB. Si le service est lent sous charge, il se conforme peut‑être à vos contraintes, pas à un mauvais comportement.

Décision : confirmer si le throttling correspond aux SLO ; ajuster les quotas délibérément, ne « corrigez » pas en redémarrant dans les mêmes limites.

Task 14: Capture evidence before you change anything

cr0x@server:~$ sudo journalctl -b --since "2025-12-30 13:30" --until "2025-12-30 14:30" -o short-iso > /tmp/journal-incident.txt
cr0x@server:~$ sudo dmesg -T > /tmp/dmesg-incident.txt
cr0x@server:~$ ps -eo pid,ppid,cmd,%cpu,%mem,stat --sort=-%cpu | head -n 15 > /tmp/ps-topcpu.txt
cr0x@server:~$ ps -eo pid,ppid,cmd,%cpu,%mem,stat --sort=-%mem | head -n 15 > /tmp/ps-topmem.txt

Sens : Vous avez maintenant préservé l’histoire. Si vous devez redémarrer des services — ou même redémarrer la machine — vous ne jetez pas les indices.

Décision : procédez aux mitigations en sachant que vous pouvez toujours faire un RCA post‑incident basé sur les artefacts capturés.

Blague n°2 : Si redémarrer est votre unique étape de dépannage, félicitations — vous avez inventé un bouton d’alimentation très coûteux.

Trois mini-histoires d’entreprise (réalistes, douloureuses, utiles)

Mini-histoire 1 : L’incident causé par une mauvaise hypothèse

Ils avaient une couche d’API interne sur Ubuntu. Quand la latence a grimpé, le réflexe on-call a été de redémarrer le service API. Quand cela n’a pas suffi, ils ont rebooté la VM. Ça fonctionnait assez souvent pour que personne ne s’interroge.

Un vendredi, le reboot n’a rien changé. Les erreurs sont revenues immédiatement : timeouts vers un cluster de cache. Le responsable d’incident a supposé « le cache est en panne ». L’équipe cache a été paginée, puis le réseau, puis la sécurité. Sport d’équipe corporatif classique : trois équipes qui se disputent dans un chat pendant que les clients attendent.

Le vrai problème était plus stupide et plus instructif. Un nouveau changement netplan avait ajouté une route statique qui masquait accidentellement le sous‑réseau du cache via la mauvaise passerelle. La plupart du trafic fonctionnait parce que la route par défaut était correcte. Seul le trafic cache prenait le chemin scénique via un firewall qui le limitait.

Les reboots « corrigeaient » auparavant parce que la route ne s’appliquait pas de façon cohérente après des poussées de configuration partielles — timing et état. Cette fois la route s’est appliquée proprement, donc ça a cassé de façon déterministe. Le reboot n’a pas supprimé la mauvaise route ; il l’a rechargée.

Après coup, ils ont changé deux choses : (1) traiter « dépendance injoignable » comme un problème de réseau/chemin jusqu’à preuve du contraire, et (2) stocker les diffs de routes et valider la config dans CI. L’habitude du reboot masquait une mauvaise configuration, elle ne résolvait pas les incidents.

Mini-histoire 2 : L’optimisation qui s’est retournée contre eux

Un service lourd en stockage a été « optimisé » en déplaçant les logs sur NVMe local plus rapide et en augmentant la verbosité des logs pour mieux déboguer. L’équipe a aussi resserré la rotation des logs parce qu’ils avaient déjà souffert d’un disque plein. Motifs sensés. Mauvaise interaction.

À l’échelle, les logs verbeux ont généré des écritures fréquentes. Le schedule de logrotate était agressif, et le hook post-rotation envoyait des signaux pour recharger plusieurs services. Sous trafic bursty, logrotate se déclenchait, compressait les logs et faisait monter CPU et IO au moment où l’appli en avait le plus besoin.

Les utilisateurs voyaient des chutes de latence périodiques chaque heure. L’on-call rebootait les nœuds parce que « ça efface la lenteur ». Le reboot aidait parce qu’il interrompait la compression et réinitialisait les files. Personne n’avait relié le motif horaire parce que les gens sont mauvais pour les séries temporelles dans leur tête.

Quand ils ont enfin tracé await disque et iowait CPU, c’était évident : chaque chute correspondait à logrotate. La correction était ennuyeuse : réduire le volume de logs, passer à un envoi asynchrone, échelonner la rotation et supprimer les hooks de reload inutiles. Ils ont aussi ajouté des alertes sur la latence disque, pas seulement sur « disque utilisé ».

Conclusion : une « optimisation » sans mesure des effets de second ordre, c’est du pariage habillé avec un meilleur vocabulaire.

Mini-histoire 3 : La pratique ennuyeuse mais correcte qui a sauvé la mise

Une fintech utilisait des nœuds Ubuntu 24.04 pour le traitement des transactions. Ils avaient une règle stricte d’incident : avant tout reboot, capturer le journal et les logs noyau pour la fenêtre concernée, plus un snapshot de l’état des processus et du réseau. Aucune exception sauf si l’hôte corrompt activement des données.

Une nuit, un sous‑ensemble de nœuds a commencé à caler. Pas planter. Simplement caler : charge élevée, latences en hausse, timeouts intermittents. La solution la plus rapide aurait été de recycler les nœuds. À la place, l’on-call a suivi la règle et a capturé des preuves.

Les logs noyau montraient des timeouts NVMe, mais seulement après des motifs spécifiques : une rafale de sync writes issue d’une version particulière du service. Les snapshots de processus montraient que cette version avait activé un feature flag qui augmentait la fréquence des fsync.

Ils ont rollbacké le feature flag, la latence s’est stabilisée et les nœuds ont récupéré sans reboots. Plus tard, avec les logs préservés, ils ont travaillé avec le vendeur pour mettre à jour le firmware NVMe et ajuster la stratégie de durabilité de l’appli. Les preuves ont transformé un mystère nocturne en plan d’action.

Cette règle « ennuyeuse » n’a pas seulement aidé à diagnostiquer. Elle a empêché une défaillance plus grave : un reboot aurait caché un problème de fiabilité stockage jusqu’à perte de données. En production, l’ennuyeux est souvent synonyme de « sûr ».

Erreurs courantes : symptôme → cause racine → correction

1) « Une charge élevée signifie que le CPU est saturé »

Symptôme : La moyenne de charge dépasse 20, l’appli est lente, mais les graphiques CPU ne montrent pas une saturation évidente.

Cause racine : Tâches bloquées sur IO (état D). La charge inclut le sommeil non interrompable ; c’est souvent la latence stockage.

Correction : Utiliser vmstat (b, wa), iostat -x (await, util), puis identifier les processus IO‑hog (iotop).

2) « Le reboot l’a réparé, donc c’était un bug noyau »

Symptôme : Le reboot efface les problèmes pendant des heures/jours ; l’incident revient.

Cause racine : Fuite mémoire, fuite de descripteurs, accumulation graduelle de files, logs/disque plein, ou dépendance bloquée.

Correction : Capturer des preuves ; suivre la croissance (RSS, fichiers ouverts, espace disque, longueurs de file). Redémarrer l’unité fautive et corriger la fuite ou mettre des limites.

3) « L’application est down » alors que c’est le DNS

Symptôme : Timeouts aléatoires vers des services internes ; redémarrer les applis ne change rien.

Cause racine : Timeouts du résolveur, upstream cassé, ou split‑horizon mal configuré.

Correction : Vérifier resolvectl et tester des requêtes avec de faibles timeouts (dig +time=1 +tries=1). Basculer de résolveur ou réparer l’étage DNS.

4) « Le disque n’est pas plein, donc le stockage n’est pas en cause »

Symptôme : Espace libre suffisant, mais IO lent ; services bloquent.

Cause racine : Pics de latence dus à des erreurs de périphérique, firmware, write amplification, ou un écrivain bruyant. L’exhaustion d’inodes peut aussi survenir alors qu’il reste des octets libres (ou inversement).

Correction : Vérifier la latence (iostat), les erreurs (journalctl -k), la santé (nvme smart-log) et les inodes (df -i).

5) « Ça doit être le réseau » quand c’est en fait softirq CPU ou conntrack

Symptôme : Pertes de paquets, timeouts intermittents, forts nombres de connexions.

Cause racine : CPU occupé à gérer des softirq pour les paquets, ou pression sur la table conntrack provoquant des drops/timeouts, souvent après des rafales.

Correction : Corréler les pertes RX avec l’utilisation CPU et les stats de connexion ; atténuer en façonnant le trafic, en tuning, ou en répartissant la charge.

6) « Les boucles de redémarrage sont inoffensives »

Symptôme : Un service flappe ; parfois il « revient », parfois non.

Cause racine : Timeout de dépendance, mauvaise config, ou limite de ressource atteinte. Les boucles de restart amplifient la charge et peuvent déclencher un effet de foule (thundering herd).

Correction : Inspecter systemctl status, définir un backoff de restart sensé, et corriger la santé de la dépendance ou la config. Préférer des circuit breakers aux redémarrages aveugles.

7) « On a augmenté la fiabilité en rendant tout synchrone »

Symptôme : Pics de latence pendant les rafales ; métriques de stockage en pointe.

Cause racine : fsync excessif ou écritures synchrones, surtout si plusieurs services partagent un périphérique.

Correction : Mesurer le pattern d’IO ; batcher les écritures, ajuster les paramètres de durabilité consciemment, isoler les workloads, ou déplacer logs/écritures temporaires hors des chemins critiques.

8) « C’est une fuite mémoire » alors que c’est cache de pages + charge

Symptôme : Mémoire libre faible, panique générale.

Cause racine : Linux utilise la mémoire pour le cache ; un faible « free » est normal. Le signal utile est « available » et l’activité swap, pas « free ».

Correction : Utiliser free -h, vmstat (si/so) et suivre les tendances RSS de l’appli. Corriger seulement si « available » s’effondre ou si le swap churn commence.

Checklists / plan étape par étape

Checklist A: La routine de 10 minutes « ne pas redémarrer encore »

  1. Confirmer l’impact : ce qui échoue (API, BD, disque, DNS), et pour qui (une AZ/nœud vs global).
  2. Capturer des preuves : fenêtre journal, dmesg, processus top, snapshot réseau. (Utiliser Task 14.)
  3. Classer le goulot : CPU vs mémoire vs disque vs réseau en utilisant vmstat, iostat, free, ip -s link.
  4. Trouver le coupable : processus top CPU/mémoire, écrivains IO, unité qui flappe.
  5. Vérifier les erreurs de dépendance : logs appli pour « cannot connect » et timeouts ; valider rapidement le DNS.
  6. Atténuer en sécurité : drainer du LB, arrêter les jobs batch, réduire la concurrence, mettre en pause les backups.
  7. Redémarrage ciblé si nécessaire : redémarrer un service ou recharger la config ; confirmer la récupération via métriques.
  8. Puis seulement envisager le reboot : scénario de reset pilote/firmware connu, boucle kernel panic, ou deadlock irréparable — après capture des preuves.

Checklist B: Si vous devez redémarrer, faites‑le comme un adulte

  1. Déclarez la raison : « Redémarrage pour réinitialiser le contrôleur NVMe après des timeouts », pas « parce que c’est lent ».
  2. Préservez d’abord les preuves : snapshots journal/dmesg ; noter versions du noyau et du firmware.
  3. Drainer le trafic : sortir le nœud de la rotation.
  4. Redémarrer et valider : confirmer que le symptôme a disparu et surveiller sa réapparition sous charge.
  5. Ouvrir une tâche de suivi : RCA obligatoire ; sinon vous avez juste programmé le prochain incident.

Checklist C: Workflow post-incident pour la cause racine (la partie que tout le monde saute)

  1. Timeline : quand les symptômes ont commencé, ce qui a changé, ce qui a empiré, ce qui a réparé.
  2. Corréler les signaux : latence disque vs taux d’erreur, pression mémoire vs timeouts, pertes de paquets vs retries.
  3. Prouver une cause racine : sélectionner le plus petit ensemble de faits qui explique la majorité des symptômes.
  4. Définir la prévention : changement de config, limite, alerte, plan de capacité, mise à jour du runbook, ou politique de rollback.
  5. Ajouter un test/garde‑fou : validation CI pour netplan routes, alertes pour usage inode, autoscaling basé SLO, etc.

FAQ

1) Quand redémarrer est‑il réellement le bon choix ?

Lorsqu’il existe des preuves d’un deadlock noyau/pilote, de réinitialisations NVMe répétées, ou d’un bug connu avec contournement documenté — et que vous avez d’abord capturé les logs. Aussi quand l’hôte corrompt des données ou ne peut plus progresser et que le confinement nécessite son retrait.

2) Pourquoi un reboot « répare » les fuites mémoire ?

Parce qu’il tue le processus qui fuit et efface l’état mémoire. La fuite est toujours là. Vous venez juste de remettre le compteur à zéro jusqu’à ce qu’elle remplisse la RAM à nouveau.

3) Comment distinguer rapidement saturation CPU et IO wait ?

vmstat 1 : un us/sy élevé avec wa bas suggère CPU. Une b montante et un wa élevé suggèrent IO wait. Confirmer avec iostat -x pour la latence des périphériques.

4) Pourquoi la moyenne de charge est‑elle élevée alors que le CPU est inactif ?

Parce que la charge inclut les tâches coincées en sommeil non interrompable (souvent IO). Elles comptent dans la charge mais ne consomment pas de cycles CPU.

5) journald semble « différent ». Comment l’utiliser sans se perdre ?

Filtrer par boot (-b), fenêtre temporelle (--since/--until), unité (-u) et priorité (-p). Traitez‑le comme un moteur de requêtes, pas un concours de scrolling.

6) Quel est le signal de défaillance disque le plus sous‑estimé ?

Les pics de latence et les timeouts IO intermittents dans les logs noyau. Les disques peuvent être « up » et « pas pleins » tout en échouant à faire ce qui compte : compléter les IO rapidement et correctement.

7) Que faire si une dépendance est lente mais pas down ?

Mesurer et isoler : ajouter des timeouts, des circuit breakers et du backpressure. Réduire la charge sur la dépendance (contrôle du cache stampede, limites de requêtes), et séparer les locataires bruyants. « Pas down » peut être « inutilisable ».

8) Comment empêcher les gens de redémarrer par réflexe ?

Faire de la capture de preuves et de la remédiation ciblée la norme. Ajouter une règle simple : « Pas de reboot sans hypothèse écrite et logs préservés. » Puis récompenser les mitigations rapides et correctes — pas les exploits héroïques de minuit.

9) Quelle est la manière la plus rapide de détecter « disque plein » avant que ce soit une panne ?

Alerter à la fois sur l’usage de df -h et sur l’usage d’inodes df -i, plus la latence d’écriture. Le disque plein est souvent précédé d’une augmentation du volume de logs ou d’une création de fichiers incontrôlée — les deux sont mesurables.

10) Pourquoi redémarrer un service aide parfois plus qu’un reboot ?

Parce que cela réinitialise l’état cassé (connexions mortes, threads bloqués, descripteurs fuités) sans effacer tout le système. C’est plus rapide, moins risqué et ça préserve les autres services sains.

Prochaines étapes pour réduire les incidents (sans héros)

Arrêtez d’utiliser les reboots comme soutien émotionnel. Sur Ubuntu 24.04 vous avez déjà les outils pour isoler la cause racine : systemd, journald, les logs noyau et les compteurs de performance qui vous disent où se trouve vraiment le goulot.

Faites ceci ensuite :

  • Adoptez la routine des 10 minutes : capturez des preuves, classez le goulot, trouvez le coupable, puis atténuez.
  • Faites de « pas de reboot sans hypothèse » une norme : écrivez la raison dans le canal/ticket d’incident.
  • Alertez sur les bonnes choses : latence IO, usage d’inodes, activité swap, pertes RX — pas seulement CPU et « pourcentage disque utilisé ».
  • Limitez le blast radius : quotas/limites pour les services, limites de débit pour les clients, isolation pour les workloads bruyants.
  • Pratiquez la récupération ciblée : redémarrez des unités, drenez des nœuds, désactivez des fonctionnalités — prouvez que vous pouvez récupérer sans réinitialiser le monde.

Vous n’avez pas besoin d’être un chuchoteur de noyau. Vous devez être discipliné, méfiant des récits confortables et allergique à « ça a marché après un reboot » comme réponse définitive.

← Précédent
MySQL vs Percona Server : la mise à niveau drop-in qui peut sauver votre production
Suivant →
Pourquoi les GPU chauffent : une explication simple et durable

Laisser un commentaire