Je n'écris pas ceci comme un avis négatif sur FDCServers. Je ne cherche pas non plus à dire aux autres s'ils doivent ou non acheter un VPS chez eux. J'ai eu un serveur, une charge de travail et une suite précise de problèmes. Ce n'est pas suffisant pour juger toute une société d'hébergement.
C'est simplement un épisode de mon quotidien de développeur. Le VPS fonctionnait normalement depuis un certain temps et avait déjà transféré plus de 3 To de trafic. Puis une charge habituelle a commencé à provoquer des délais très importants. Certaines pages mettaient énormément de temps à répondre ou finissaient en timeout. J'ai d'abord soupçonné les causes classiques : l'application, Nginx, la mémoire, le réseau, les limites de connexions ou une charge trop élevée. Les métriques Linux indiquaient autre chose.
Le VPS n'était pas lent au départ
Entre les incidents, la machine pouvait sembler parfaitement saine. Pendant une période normale, aucun processus n'était en D-state, le CPU iowait était proche de 0 %, la latence disque autour de 2–4 ms et l'I/O PSI presque nul :
D-state processes: 0
CPU iowait: ~0%
disk latency: ~2–4 ms
I/O PSI some: 0.04
I/O PSI full: 0.04Si je m'étais connecté uniquement à ce moment-là pour regarder top, free -h, df -h et systemctl status nginx, j'aurais probablement conclu que le VPS allait bien. Puis la charge normale est revenue et l'état de la machine a changé brutalement.
Des lectures à 18,7 secondes ont changé l'enquête
L'un des échantillons iostat les plus parlants était le suivant :
r_await = 18744 ms
f_await = 53561 ms
aqu-sz = 128.54
util = 100.10%
read = 88 KB/sCes chiffres doivent être lus ensemble. Les lectures terminées affichaient une latence moyenne d'environ 18,7 secondes. La latence de flush était d'environ 53,6 secondes. La file I/O moyenne dépassait 128, alors que le débit de lecture utile n'était que de 88 KB/s. Ce n'était pas simplement un disque occupé à déplacer beaucoup de données. Le chemin de stockage passait un temps énorme à attendre la fin des opérations.
iowait et PSI ont montré une pression I/O à l'échelle du système
Dans les pires périodes, vmstat indiquait 4 à 9 processus bloqués, un CPU iowait autour de 97–100 % et 0 % de CPU idle. iowait ne signifie pas que l'application consomme tout le CPU. Cela signifie que le travail utile attend la fin d'opérations I/O en cours.
Linux Pressure Stall Information rendait la situation encore plus claire :
I/O PSI some avg10 = 99.14
I/O PSI full avg10 = 95.55Lors de reproductions ultérieures, full s'est approché de 98 %. L'utilisation du disque indique qu'un périphérique est occupé ; PSI indique à quel point la charge de travail est réellement bloquée par cette ressource. Une pression I/O durable de 95–98 % n'est pas une petite dégradation de performances.
D-state et les stacks kernel pointaient sous l'application
J'ai ensuite vérifié quels processus étaient bloqués. Au même moment, je pouvais voir jbd2, systemd-journald, des workers Nginx, des processus de cache Nginx et d'autres activités du système de fichiers en D-state. Si seule mon application était bloquée, j'aurais enquêté sur l'application. Quand Nginx, le journal système et le journal EXT4 se bloquent ensemble, le stockage devient la dépendance commune la plus évidente.
Les chemins de journaling EXT4 incluaient :
wait_on_buffer
jbd2_log_wait_commit
jbd2_journal_commit_transactionLes workers Nginx attendaient dans des lectures de fichiers ordinaires :
folio_wait_bit_common
filemap_read
generic_file_read_iter
ext4_file_read_iter
vfs_read
pread64À un moment, le kernel a signalé qu'une tâche Nginx était bloquée depuis plus de 122 secondes. Nginx pouvait toujours apparaître comme active, sans que ses workers soient capables de terminer un travail utile. running et sain sont deux choses différentes.
Une réponse backend en 3 ms a séparé l'application du chemin filesystem
La comparaison la plus nette était entre Nginx et le backend local. Les requêtes via Nginx renvoyaient HTTP=000 à cause de timeouts de connexion ou TLS. Une requête directe vers le backend se terminait en environ 3 ms :
connect = 0.000423 s
TTFB = 0.003063 s
total = 0.003139 sLe statut HTTP exact n'était pas important pour ce test. Le backend acceptait la connexion, traitait la requête et produisait une réponse presque immédiatement. Dans le même temps, les workers Nginx étaient visibles en attente de lectures EXT4. Cela séparait clairement l'exécution normale de l'application du chemin dépendant du système de fichiers situé devant elle.
Le problème était reproductible et pouvait aussi disparaître
Avant une reproduction, la machine semblait normale :
HTTP: 200
D-state: 0
CPU iowait: 3%
r_await: ~1.18 ms
I/O PSI full: ~2.95%Environ trente secondes plus tard :
D-state: 4
CPU iowait: 91%
CPU idle: 0%
I/O PSI some: 86.11%
I/O PSI full: 78.02%
r_await: 236.50 ms
HTTP: 000Plus tard, le CPU iowait a atteint 96–100 %, l'I/O PSI full s'est approché de 98 %, la file HTTPS a atteint 512 et les vérifications HTTP continuaient d'échouer. C'était bien plus utile que de dire simplement que le VPS semblait lent.
Une fois la charge retirée, la transition inverse pouvait être rapide :
D-state: 0
CPU iowait: 6%
r_await: ~0.98 ms
queue depth: ~0.07
HTTP: 200C'est pourquoi les problèmes de stockage intermittents sont difficiles à analyser après coup. Le fournisseur peut inspecter le serveur après sa récupération et constater honnêtement une latence normale. Cela n'explique pas ce qui s'est passé dix minutes plus tôt. Les timestamps UTC précis sont donc devenus essentiels.
Deux métriques trompeuses : await=0 et l'espace libre
Pendant certains mauvais intervalles, je voyais r_await = 0 alors que iowait était élevé, que des processus restaient en D-state, que des requêtes étaient toujours en vol et que presque aucune lecture ne se terminait. Les statistiques de latence reposent sur les opérations I/O terminées. Si une opération reste bloquée et ne se termine pas pendant la fenêtre d'échantillonnage, elle ne peut pas contribuer à la latence des opérations terminées. Un zéro ne signifie donc pas toujours un disque instantané.
J'ai aussi envisagé le remplissage du disque. Plus tard, le système de fichiers est devenu plus rempli que je ne l'autoriserais normalement, mais le même type de panne s'était déjà produit lorsque le système de fichiers racine n'était utilisé qu'à environ 24 %. À ce moment-là, environ 1,2 GiB de RAM étaient disponibles, l'utilisation des inodes était proche de 5 % et l'interface réseau n'affichait ni erreur ni paquet abandonné. Le remplissage du disque ne pouvait donc pas expliquer tout l'incident.
Ce que je pouvais prouver et ce que je ne pouvais pas
Depuis le VPS, je pouvais observer l'application, Linux VFS, EXT4 et le périphérique de blocs virtuel. Ensuite commence l'infrastructure du fournisseur : virtualisation, stockage distribué, réseau de stockage, périphériques physiques, scheduling et d'autres couches invisibles depuis le guest.
Je ne peux donc pas affirmer honnêtement qu'un SSD physique précis était défectueux, ni désigner un nœud de stockage, un chemin réseau ou un composant de virtualisation particulier comme cause racine.
Ce que je peux dire est plus limité, mais solidement étayé : le chemin de stockage virtuel présenté à mon guest Linux entrait de façon répétée dans des états où des opérations I/O ordinaires du système de fichiers prenaient plusieurs secondes ou ne se terminaient pas dans un délai raisonnable. Les preuves venaient de iostat, PSI, D-state, des stacks d'attente kernel, des attentes EXT4/jbd2, des attentes filesystem de Nginx, de la profondeur de file et des timings de requêtes. Cela suffisait à mon diagnostic technique, mais pas à identifier une cause physique.
Pourquoi les plus de 3 To de trafic précédents ne contredisent pas les stalls ultérieurs
Au départ, cela m'a dérouté. Si le stockage avait des problèmes, comment le VPS avait-il déjà pu transférer plusieurs téraoctets correctement ?
Parce que le trafic réseau n'est pas la même chose que les I/O physiques du disque. Un fichier peut être lu une fois depuis le stockage, rester dans le page cache Linux puis être servi de nombreuses fois depuis la mémoire. Trois téraoctets transférés sur le réseau ne signifient donc pas trois téraoctets de lectures physiques uniques.
Les conditions d'infrastructure évoluent aussi : état du cache, charge du stockage, files d'attente, placement de l'hôte et autres workloads peuvent changer. Un VPS qui fonctionnait normalement hier ne garantit pas un comportement de stockage identique aujourd'hui.
J'ai fini par arrêter d'attendre une cause racine plus profonde
J'ai collecté des timestamps précis, vmstat, iostat, PSI, des captures de processus bloqués, des kernel stacks, des attentes filesystem, des profondeurs de file et des timings HTTP. J'ai envoyé les diagnostics à FDCServers et attendu une explication plus profonde au niveau de l'infrastructure.
J'ai attendu longtemps. Puis j'ai cessé d'attendre. De mon côté, j'en savais déjà assez pour prendre une décision opérationnelle : le problème était reproductible, grave, visible sous la couche applicative, et sa cause physique se trouvait hors de ce que mon VPS pouvait montrer.
J'ai demandé un remboursement, et FDCServers m'a remboursé
J'ai envoyé à FDCServers un résumé des problèmes et des diagnostics collectés, demandé l'annulation du service et un remboursement. Ils m'ont remboursé.
L'histoire ne se termine donc pas par une longue bataille financière. J'ai attendu une explication technique définitive, décidé que je ne voulais plus attendre, envoyé les éléments dont je disposais et demandé mon argent. FDCServers me l'a rendu.
Ce que j'ai changé ensuite
Le résultat utile de cette expérience n'a pas été de décider si un hébergeur était bon ou mauvais. Elle a changé ma façon de diagnostiquer les serveurs Linux lents.
J'utilise toujours top, free -h et df -h, mais je consulte désormais beaucoup plus tôt :
date -u
uptime
cat /proc/pressure/io
cat /proc/pressure/memory
cat /proc/pressure/cpu
vmstat 1 10
iostat -x 1 10
ps -eo state,pid,ppid,etime,wchan:50,comm,args | awk 'NR==1 || $1 ~ /^D/'
ss -lntp
journalctl -k --since '30 min ago' --no-pagerJe teste aussi séparément les différents chemins de requête lorsque c'est possible : requête publique, Nginx local, backend direct, système de fichiers et métriques du block device. La question n'est plus seulement de savoir pourquoi le serveur est lent. Elle devient : à quelle couche le travail utile cesse-t-il de se terminer ?
Lorsque c'est possible, je capture les preuves avant de redémarrer. Un reboot peut rétablir le service, mais il peut aussi effacer précisément le D-state, PSI, les files et les latences qui rendent un incident intermittent diagnostiquable.
Dernière réflexion
Je n'ai pas acheté un VPS FDCServers pour avoir matière à écrire un article sur l'hébergement. Je voulais un serveur avec beaucoup de bande passante. Pendant un temps, c'est exactement ce que j'ai obtenu : il a géré une vraie charge et transféré plus de trois téraoctets.
Puis une charge normale a commencé à produire de façon reproductible un iowait jusqu'à 100 %, un I/O PSI proche de 100 %, des lectures jusqu'à 18,7 secondes, des flushs au-delà de 53 secondes, de grandes files, Nginx bloqué dans des lectures du système de fichiers et EXT4/jbd2 en attente d'I/O.
Je n'ai jamais su quel composant physique ou côté hôte en était la cause, et je n'ai pas besoin de prétendre le contraire. J'ai identifié la couche où la panne se manifestait, réuni assez de preuves pour la distinguer d'un problème applicatif, cessé d'attendre une explication plus profonde et demandé mon argent. FDCServers m'a remboursé.
Ce n'est pas un verdict sur tous les VPS FDCServers. C'est simplement un rappel bien documenté : un service peut apparaître active, un processus running, alors que la machine passe presque tout son temps utile à attendre le stockage.