Délai d’attente des volumes NFS Docker : options de montage qui améliorent réellement la stabilité

Cet article vous a aidé ?

Vous déployez un conteneur parfaitement banal. Il écrit quelques fichiers. Puis, à 02:17, tout se fige comme s’il attendait une autorisation.
df se bloque. Les threads de votre application s’accumulent. Les logs Docker n’indiquent rien d’utile. Le seul indice est une traînée de « nfs: server not responding ».

NFS dans des environnements conteneurisés échoue de manières qui ressemblent à des bugs applicatifs, des bugs du noyau ou des « vibes réseau ».
En général, ce n’est aucune de ces choses. C’est la sémantique de montage qui entre en collision avec des fautes réseau transitoires, des surprises DNS et un driver de volume qui ne vous dit pas ce qu’il a fait.

Pourquoi les volumes NFS Docker arrivent en timeout (et pourquoi ça semble aléatoire)

Les « volumes NFS » de Docker ne sont que des montages NFS Linux créés par l’hôte, puis bind-montés dans les conteneurs.
Ça paraît simple, et ça l’est—jusqu’à ce que vous vous rappeliez que NFS est un système de fichiers réseau avec une sémantique de retry,
des timeouts RPC, du verrouillage et de l’état.

La plupart des « timeouts » ne sont pas un unique timeout

Quand quelqu’un rapporte « NFS a time-out », il veut généralement dire une des choses suivantes :

  • Le client réessaie indéfiniment (hard mount) et le thread de l’application bloque en sommeil non interruptible (état D). Cela ressemble à un blocage.
  • Le client a abandonné (soft mount) et a renvoyé une erreur d’E/S. Cela ressemble à de la corruption, des écritures échouées ou « mon appli error aléatoirement ».
  • Le serveur est parti puis revenu, mais la vue du client sur l’export ne correspond plus (stale file handles). On a l’impression que « ça marchait hier ».
  • Problèmes de plomberie RPC (surtout NFSv3 : portmapper/rpcbind, mountd, lockd) provoquent des échecs partiels où certaines opérations fonctionnent et d’autres timeout.
  • Fluctuations de résolution de nom ou de routage provoquent des blocages intermittents qui se rétablissent seuls. Ce sont les pires car elles nourrissent les superstitions.

Docker amplifie les modes de panne

NFS est sensible au timing des montages. Docker est très bon pour démarrer des conteneurs rapidement, en parallèle, et parfois avant que le réseau soit prêt.
Si le montage NFS est déclenché à la demande, votre « démarrage de conteneur » devient « démarrage de conteneur plus réseau plus DNS plus réactivité du serveur ».
C’est acceptable en labo. En production, c’est une façon élaborée de transformer une petite gigue réseau en panne majeure.

Hard vs soft n’est pas un réglage de performance ; c’est une décision de risque

Pour la plupart des charges avec état, la valeur sûre par défaut est hard : continuer à réessayer, ne pas prétendre que les écritures ont réussi.
Mais les montages hard peuvent suspendre des processus quand le serveur est inaccessible. Votre travail consiste donc à rendre « serveur inaccessible » rare et bref,
et à rendre le montage résilient face au chaos normal des réseaux.

Il y a une idée paraphrasée de Werner Vogels (CTO d’Amazon) qui vaut la peine d’être gardée en tête : « Tout échoue, donc concevez pour l’échec. »
Les montages NFS sont précisément l’endroit où cette philosophie cesse d’être inspirante et devient une checklist.

Faits et contexte intéressants (brefs, concrets, utiles)

  • NFS précède les conteneurs de plusieurs décennies. Il est né dans les années 1980 pour partager des fichiers sur un réseau sans complexité d’état côté client.
  • NFSv3 est en grande partie sans état. Cela simplifiait certains basculements, mais repoussait la complexité vers des daemons auxiliaires (rpcbind, mountd, lockd).
  • NFSv4 a consolidé les canaux latéraux. v4 utilise typiquement un port bien connu (2049) et intègre verrouillage et état, ce qui améliore souvent la compatibilité avec les pare-feux et le NAT.
  • « Hard mount » est le défaut historique pour une raison. Perdre des données silencieusement est pire qu’attendre ; les montages hard privilégient la correction plutôt que la disponibilité.
  • Le client NFS Linux a plusieurs couches de timeouts. Il y a le timeout par RPC (timeo), le nombre de retransmissions (retrans) et des comportements de récupération de plus haut niveau.
  • Les stale file handles sont une taxe classique de NFS. Ils surviennent quand la correspondance inode/handle côté serveur change sous le client—fréquent après un basculement serveur ou des changements d’export.
  • NFS sur TCP n’a pas toujours été le défaut. UDP était populaire au départ ; TCP est maintenant le choix sensé pour la fiabilité et le contrôle de congestion.
  • Le DNS compte plus que vous ne le pensez. Les clients NFS peuvent mettre en cache la résolution nom→IP différemment de votre application ; un changement DNS en vol peut produire des symptômes « la moitié du monde fonctionne ».

Blague #1 : NFS, c’est comme une imprimante partagée au bureau—quand ça marche, personne ne le remarque ; quand ça ne marche pas, tout le monde a soudain des documents « business-critical » urgents.

Mode opératoire de diagnostic rapide (trouver le goulot vite)

L’objectif n’est pas de « collecter chaque métrique ». L’objectif est de décider, rapidement, si vous avez un problème de chemin réseau,
un problème serveur, un problème de sémantique de montage côté client, ou un problème d’orchestration Docker.
Voici l’ordre qui fait gagner du temps.

Première étape : confirmer que c’est NFS et pas l’application

  1. Sur l’hôte Docker, essayez un simple stat ou ls sur le chemin monté. Si ça bloque, ce n’est pas votre appli. C’est le montage.
  2. Vérifiez dmesg pour server not responding / timed out / stale file handle. Les messages noyau sont directs et généralement fiables.

Deuxième étape : décider « réseau vs serveur » avec un test

  1. Depuis le client, vérifiez la connectivité vers le port 2049 et (si vous utilisez NFSv3) rpcbind/portmapper. Si vous ne pouvez pas vous connecter, cessez de blâmer les options de montage.
  2. Depuis un autre hôte sur le même segment réseau, testez la même chose. Si le problème est isolé à un seul client, suspectez un pare-feu local, une exhaustion de conntrack, un MTU, ou une mauvaise route.

Troisième étape : vérifier la version du protocole et les options de montage

  1. Vérifiez si vous êtes en NFSv3 ou NFSv4. Beaucoup de timeouts « aléatoires » sont en réalité des problèmes rpcbind/mountd de NFSv3 dans les réseaux modernes.
  2. Confirmez hard, timeo, retrans, tcp, et si vous avez utilisé intr (comportement obsolète) ou d’autres flags legacy.

Quatrième étape : inspecter les logs et la saturation côté serveur

  1. La moyenne de charge serveur n’est pas suffisante. Regardez les threads NFS, la latence disque, et les pertes réseau.
  2. Si le serveur est un appliance NAS, identifiez s’il est CPU-bound (chiffrement, checksum) ou I/O-bound (disques, rebuild, suppression de snapshot).

Si vous faites ces quatre phases, vous pouvez généralement nommer la classe de panne en moins de dix minutes. La partie longue, c’est la politique.

Patrons de configuration Docker qui ne vous sabordent pas

Patron 1 : driver local Docker avec options NFS (correct, mais vérifiez ce qui a été monté)

Le driver local de Docker peut monter NFS en utilisant type=nfs et o=....
C’est courant dans Compose et Swarm.
Le piège : les gens supposent que Docker « fait quelque chose d’intelligent ». Il ne le fait pas. Il transmet les options à l’helper de montage.
Si l’helper de montage revient à une autre version ou ignore une option, vous pouvez ne pas le remarquer.

Patron 2 : pré-monter sur l’hôte puis bind-monter dans les conteneurs (souvent plus prévisible)

Si vous pré-montez via /etc/fstab ou des unités mount systemd, vous pouvez contrôler l’ordonnancement, les retries, et observer le montage directement.
Docker se contente ensuite de bind-monter un chemin local. Cela réduit la « magie Docker », ce qui est généralement bon pour dormir tranquille.

Patron 3 : séparer les montages par classe de workload

N’utilisez pas un export NFS et un jeu d’options pour tout.
Traitez NFS comme un service avec des SLO : métadonnées basse latence (caches CI), débit en masse (média), correction d’abord (données applicatives).
Différents montages, différentes options, différentes attentes.

Tâches pratiques : commandes, sortie et la décision que vous prenez

Ce sont les actions de l’astreinte qui transforment « NFS est instable » en une action claire. Exécutez-les sur l’hôte Docker sauf indication contraire.
Chaque tâche inclut (1) la commande, (2) ce que signifie la sortie, (3) la décision à prendre.

Task 1: Identify which mounts are NFS and how they’re configured

cr0x@server:~$ findmnt -t nfs,nfs4 -o TARGET,SOURCE,FSTYPE,OPTIONS
TARGET                SOURCE                     FSTYPE OPTIONS
/var/lib/docker-nfs    nas01:/exports/appdata     nfs4   rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.10.8.21

Signification : Confirme la version NFS, le proto, et si vous êtes en hard ou soft. Montre aussi si rsize/wsize sont énormes et potentiellement non appariés.

Décision : Si vous voyez vers=3 de façon inattendue, prévoyez de passer à v4 ou auditez les ports rpcbind/mountd. Si vous voyez soft sur des workloads intensifs en écriture, changez cela.

Task 2: Confirm Docker volume configuration (what Docker thinks it asked for)

cr0x@server:~$ docker volume inspect appdata
[
  {
    "CreatedAt": "2026-01-01T10:12:44Z",
    "Driver": "local",
    "Labels": {},
    "Mountpoint": "/var/lib/docker/volumes/appdata/_data",
    "Name": "appdata",
    "Options": {
      "device": ":/exports/appdata",
      "o": "addr=10.10.8.10,vers=4.1,proto=tcp,hard,timeo=600,retrans=2,noatime",
      "type": "nfs"
    },
    "Scope": "local"
  }
]

Signification : C’est la configuration, pas la vérité. Les options de Docker peuvent être correctes alors que le montage réel diffère.

Décision : Comparez avec findmnt. Si elles diffèrent, dépannez l’helper de montage, les valeurs par défaut et le support noyau.

Task 3: Look for kernel NFS client errors right now

cr0x@server:~$ dmesg -T | egrep -i 'nfs:|rpc:|stale|not responding|timed out' | tail -n 20
[Fri Jan  3 01:58:41 2026] nfs: server nas01 not responding, still trying
[Fri Jan  3 01:59:12 2026] nfs: server nas01 OK

Signification : « Not responding, still trying » indique un hard mount en train de réessayer pendant une perturbation.

Décision : Si ces événements correspondent aux blocages applicatifs, enquêtez sur des pertes réseau ou des blocages serveur ; ne « fixez » pas l’appli.

Task 4: Confirm the process states during a hang (is it stuck in D-state?)

cr0x@server:~$ ps -eo pid,stat,comm,wchan:40 | egrep 'D|nfs' | head
 8421 D    php-fpm          nfs_wait_on_request
 9133 D    rsync            nfs_wait_on_request

Signification : État D avec nfs_wait_on_request indique un I/O noyau bloqué en attente de NFS.

Décision : Considérez cela comme un incident d’infrastructure. Redémarrer des conteneurs n’aidera pas si le montage est bloqué en hard.

Task 5: Check basic TCP connectivity to the NFS server

cr0x@server:~$ nc -vz -w 2 10.10.8.10 2049
Connection to 10.10.8.10 2049 port [tcp/nfs] succeeded!

Signification : Le port 2049 est joignable maintenant.

Décision : Si cela échoue pendant l’incident, vos options de montage ne sont pas le problème principal ; corrigez le routage, les ACL, le pare-feu ou la disponibilité du serveur.

Task 6: If using NFSv3, confirm rpcbind is reachable (common hidden dependency)

cr0x@server:~$ nc -vz -w 2 10.10.8.10 111
Connection to 10.10.8.10 111 port [tcp/sunrpc] succeeded!

Signification : rpcbind/portmapper joignable. Sans cela, les montages NFSv3 peuvent échouer ou se bloquer pendant la négociation.

Décision : Si le port 111 est bloqué et que vous êtes en v3, passez à v4 ou ouvrez les ports nécessaires correctement (et documentez-les).

Task 7: Identify NFS version negotiated and server address used (catch DNS surprises)

cr0x@server:~$ nfsstat -m
/var/lib/docker-nfs from nas01:/exports/appdata
 Flags: rw,hard,noatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=10.10.8.21,local_lock=none

Signification : Confirme les paramètres négociés. Notez le nom du serveur vs l’IP, et tout comportement local_lock.

Décision : Si le montage utilise un nom d’hôte et que votre DNS est instable, basculez sur l’IP ou épinglez des entrées host—puis planifiez une meilleure stratégie DNS.

Task 8: Measure retransmits and RPC-level pain (is it packet loss?)

cr0x@server:~$ nfsstat -rc
Client rpc stats:
calls      retrans    authrefrsh
148233     912        148245

Signification : Les retransmits indiquent des RPC qui ont dû être renvoyés. Une augmentation de retrans corrèle avec perte, congestion ou blocage serveur.

Décision : Si retrans saute pendant des incidents, inspectez les pertes réseau et la charge serveur ; envisagez d’augmenter timeo modérément, pas de le diminuer.

Task 9: Check interface errors and drops (don’t guess)

cr0x@server:~$ ip -s link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc fq_codel state UP mode DEFAULT group default qlen 1000
    RX:  bytes packets errors dropped  missed   mcast
    128G  98M     0     127      0      1234
    TX:  bytes packets errors dropped carrier collsns
    141G  92M     0      84      0      0

Signification : Des drops en RX/TX peuvent suffire à déclencher « not responding » NFS sous charge.

Décision : Si les drops augmentent, enquêtez sur les rings NIC, les mismatches MTU, la congestion du switch ou la saturation CPU de l’hôte.

Task 10: Spot MTU mismatch quickly (jumbo frames are innocent until proven guilty)

cr0x@server:~$ ping -c 3 -M do -s 8972 10.10.8.10
PING 10.10.8.10 (10.10.8.10) 8972(9000) bytes of data.
From 10.10.8.21 icmp_seq=1 Frag needed and DF set (mtu = 1500)
From 10.10.8.21 icmp_seq=2 Frag needed and DF set (mtu = 1500)
From 10.10.8.21 icmp_seq=3 Frag needed and DF set (mtu = 1500)

--- 10.10.8.10 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2043ms

Signification : Le MTU du chemin est 1500, mais votre hôte pense 9000. Cela provoque du blackholing et des stalls « aléatoires ».

Décision : Corrigez le MTU bout en bout ou baissez à 1500. Puis réévaluez la stabilité NFS avant de toucher aux options de montage.

Task 11: Confirm the server export exists and permissions are sane (server-side view)

cr0x@server:~$ showmount -e 10.10.8.10
Export list for 10.10.8.10:
/exports/appdata 10.10.8.0/24
/exports/shared  10.10.0.0/16

Signification : Montre les exports (utile surtout pour NFSv3 ; pour v4 c’est toujours un indice utile).

Décision : Si l’export n’est pas listé ou que le sous-réseau client n’est pas autorisé, arrêtez de tuner le client et corrigez la politique d’export.

Task 12: Capture a short NFS packet trace during the event (prove loss vs server silence)

cr0x@server:~$ sudo tcpdump -i eth0 -nn host 10.10.8.10 and port 2049 -c 30
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:02:11.101223 IP 10.10.8.21.51344 > 10.10.8.10.2049: Flags [P.], seq 219:451, ack 1001, win 501, length 232
10:02:12.102988 IP 10.10.8.21.51344 > 10.10.8.10.2049: Flags [P.], seq 219:451, ack 1001, win 501, length 232
10:02:13.105441 IP 10.10.8.21.51344 > 10.10.8.10.2049: Flags [P.], seq 219:451, ack 1001, win 501, length 232

Signification : Retransmissions répétées sans réponses serveur indiquent serveur non-réactif ou réponses non retournées.

Décision : Si vous voyez des retransmissions client sans réponse serveur, passez à la santé serveur / chemin de retour réseau. Si vous voyez des réponses serveur mais que le client retransmet encore, suspectez un routage asymétrique ou un pare-feu d’état.

Task 13: Check Docker daemon logs for mount attempts and failures

cr0x@server:~$ journalctl -u docker --since "30 min ago" | egrep -i 'mount|nfs|volume|rpc' | tail -n 30
Jan 03 09:32:14 server dockerd[1321]: time="2026-01-03T09:32:14.112345678Z" level=error msg="error while mounting volume 'appdata': failed to mount local volume: mount :/exports/appdata:/var/lib/docker/volumes/appdata/_data, data: addr=10.10.8.10,vers=4.1,proto=tcp,hard,timeo=600,retrans=2,noatime"

Signification : Confirme que Docker n’a pas pu monter, versus l’appli qui échoue plus tard.

Décision : Si les montages échouent au démarrage des conteneurs, priorisez la préparation réseau et la joignabilité du serveur ; ne courez pas après le tuning runtime.

Task 14: Inspect systemd ordering (network-online is not the same as network)

cr0x@server:~$ systemctl status network-online.target
● network-online.target - Network is Online
     Loaded: loaded (/lib/systemd/system/network-online.target; static)
     Active: active since Fri 2026-01-03 09:10:03 UTC; 1h 2min ago

Signification : Si cette target n’est pas active quand les montages se produisent, votre montage NFS peut être en concurrence avec la disponibilité réseau.

Décision : Si vous observez des problèmes d’ordonnancement, déplacez les montages vers des unités systemd avec After=network-online.target et Wants=network-online.target, ou utilisez automount.

Task 15: Validate that the mount is responsive (fast sanity check)

cr0x@server:~$ time bash -c 'stat /var/lib/docker-nfs/. && ls -l /var/lib/docker-nfs >/dev/null'
real    0m0.082s
user    0m0.004s
sys     0m0.012s

Signification : Les opérations basiques de métadonnées sont rapides. Si cela prend parfois des secondes ou se bloque, vous avez de la latence intermittente ou des stalls.

Décision : Si les métadonnées sont lentes, investiguez la latence disque serveur et la saturation des threads NFS ; les options de montage ne sauveront pas un serveur qui se noie.

Trois mini-histoires d’entreprise (comment ça casse en pratique)

1) Incident causé par une mauvaise hypothèse : « Le volume est local, parce que Docker a dit ‘local’ »

Une entreprise de taille moyenne exécutait un cluster Swarm pour des services internes. Une équipe a créé un volume Docker avec le driver local et des options NFS.
Tout le monde a lu « local » et a supposé que les données vivaient sur chaque nœud. Cette hypothèse a façonné tout : exercices de panne, fenêtres de maintenance, et même la propriété des incidents.

Pendant une maintenance réseau, un switch top-of-rack a vacillé. Seuls certains nœuds ont perdu la connectivité avec le NAS pendant quelques secondes.
Les nœuds affectés avaient des volumes NFS montés en hard. Leurs conteneurs ne sont pas tombés ; ils ont juste cessé de progresser. Les health checks ont expiré.
L’orchestrateur a commencé à rescheduler, mais de nouvelles tâches sont tombées sur les mêmes nœuds dégradés car le scheduler ne connaissait pas le goulot NFS.

La réponse en astreinte était classique : redémarrer le service. Cela n’a fait que créer plus de processus bloqués. Quelqu’un a essayé de supprimer et recréer le volume.
Docker a obéi, mais le montage noyau était toujours coincé. L’hôte est devenu un musée de tâches figées.

La correction n’a pas été héroïque. Ils ont documenté que « driver local » peut être du stockage distant, ajouté une vérification pré-déploiement dans les pipelines pour vérifier le type de montage avec findmnt,
et isolé les services critiques NFS des nœuds qui ne pouvaient pas atteindre le VLAN de stockage.
Le plus grand changement a été culturel : le stockage a cessé d’être « le problème de quelqu’un d’autre » dès que les conteneurs sont entrés en jeu.

2) Optimisation qui s’est retournée contre eux : « Nous avons diminué les timeouts pour que les pannes échouent vite »

Une autre organisation avait un problème intermittent : les applications se figeaient quand NFS hiccupait. Quelqu’un a proposé un changement « simple » :
passer en soft, diminuer timeo, et augmenter retrans pour que le client abandonne rapidement et que l’appli s’en occupe.
Ça semblait raisonnable sur le papier.

En pratique, les applications n’étaient pas conçues pour gérer des EIO en plein écrit.
Un worker écrivait dans un fichier temporaire puis le renameait en place. Sous des montages soft et des timeouts bas,
l’écriture échouait parfois mais le workflow ne remontait pas toujours l’erreur. Le rename s’est produit avec du contenu partiel.
Les tâches en aval ont traité des données corrompues.

L’incident n’a pas été une coupure nette ; c’était pire. Le système est resté « up » tout en produisant des résultats faux.
Cela a déclenché une réponse au ralenti : rollback, retraitement, audit des sorties. Finalement les options de montage ont été rétablies.
Puis ils ont corrigé le vrai problème : perte de paquets intermittente due à une liaison LACP mal configurée et un mismatch MTU qui n’apparaissait qu’en charge.

La leçon inscrite dans leur runbook était douloureusement précise : « Fail fast » est excellent quand l’échec est correctement exposé.
Les montages soft ont rendu l’échec plus facile à ignorer, pas plus facile à gérer.

3) Pratique ennuyeuse mais correcte qui a sauvé la mise : pré-mount + automount + dépendances explicites

Une entreprise financière exécutait des jobs batch stateful en conteneurs, écrivant des artéfacts sur NFS.
Ils avaient une règle terne : les montages NFS sont gérés par systemd, pas par la création de volumes Docker à l’exécution.
Chaque montage avait une unité automount, un timeout défini, et une dépendance sur network-online.target.

Un matin, un cycle de reboot routinier a touché un nœud pendant que le NAS était en maintenance. Le NAS était joignable mais lent pendant quelques minutes.
Les conteneurs ont démarré, mais leurs chemins NFS ont été automountés seulement quand nécessaire. La tentative d’automount a attendu puis a réussi quand le NAS a récupéré.
Les jobs ont démarré avec un peu de retard, et personne ne s’est réveillé.

La différence n’était pas un meilleur matériel. C’était que le cycle de vie du montage n’était pas couplé au cycle de vie des conteneurs.
Docker n’a pas décidé du moment du montage, et les échecs étaient visibles au niveau système avec des logs clairs.

C’est le genre de pratique que les dirigeants ne félicitent jamais parce que rien ne s’est passé. C’est aussi la pratique qui vous garde en poste.

Erreurs fréquentes : symptôme → cause racine → correction

1) Symptom: containers « freeze » et ne veulent pas s’arrêter ; docker stop se bloque

Cause racine : montage NFS en hard bloqué ; processus en état D attendant l’I/O noyau.

Correction : restaurer la connectivité / la santé du serveur ; n’attendez pas des signaux qu’ils fonctionnent. Si vous devez récupérer un nœud, démontez après que le serveur soit revenu, ou redémarrez l’hôte en dernier recours. Prévenir par un réseau stable et des timeo/retrans raisonnables.

2) Symptom: « ça marche sur un nœud, timeouts sur un autre »

Cause racine : différences par nœud de routage/pare-feu/MTU, ou exhaustion de conntrack sur un sous-ensemble de nœuds.

Correction : comparez ip route, ip -s link et règles de pare-feu. Validez le MTU avec des pings DF. Assurez une configuration réseau identique sur toute la flotte.

3) Symptom: montages échouent au boot ou juste après le redémarrage de l’hôte

Cause racine : tentatives de montage qui rivalisent avec la disponibilité réseau ; Docker démarre les conteneurs avant que network-online soit vrai.

Correction : gérer les montages via des unités systemd avec un ordonnancement explicite, ou utiliser automount. Éviter les montages à la demande initiés par le démarrage des conteneurs.

4) Symptom: « permission denied » intermittent ou problèmes d’identité étranges

Cause racine : mismatch UID/GID, comportement root-squash, ou problèmes d’idmapping NFSv4. Les conteneurs aggravent cela car les espaces de noms utilisateurs et les utilisateurs d’images varient.

Correction : standardisez UID/GID pour les écrivains, validez les options d’export serveur, et pour NFSv4 confirmez la configuration d’idmapping. Ne masquer pas cela en mettant 0777 ; ce n’est pas de la stabilité, c’est une capitulation.

5) Symptom: fréquents « stale file handle » après un basculement NAS ou une maintenance d’export

Cause racine : la correspondance file-handle côté serveur a changé ; les clients conservent des références qui ne se résolvent plus.

Correction : évitez de déplacer/réécrire des exports sous les clients ; utilisez des chemins stables. Pour la récupération, remontez et redémarrez les workloads affectés. Pour l’architecture, préférez les méthodes HA stables supportées par votre NAS et testez le basculement avec de vrais clients.

6) Symptom: « montages aléatoires » seulement dans des réseaux sécurisés

Cause racine : ports dynamiques NFSv3 bloqués ; rpcbind/mountd/lockd non autorisés par les pare-feux / security groups.

Correction : passez à NFSv4 si possible. Si vous êtes contraint à v3, fixez les ports des daemons côté serveur et ouvrez-les intentionnellement—puis documentez-les pour que la prochaine personne ne « optimise » pas votre pare-feu.

7) Symptom: pics de latence élevés, puis récupération, qui se répètent sous charge

Cause racine : latence disque serveur (rebuild/snapshot), saturation des threads NFS, ou files réseau congestionnées.

Correction : mesurez la latence I/O côté serveur et les threads du service NFS ; corrigez le goulet. Les options client comme rsize/wsize ne sauveront pas un array saturé.

8) Symptom: passer à soft « corrige » les blocs mais introduit des problèmes de données mystérieux

Cause racine : les montages soft transforment les pannes en erreurs d’E/S ; les applications gèrent mal ces échecs partiels.

Correction : revenez à hard pour les écritures avec état, corrigez la connectivité sous-jacente, et mettez à jour les applications pour gérer les erreurs quand c’est approprié.

Checklists / plan étape par étape

Étape par étape : stabiliser un déploiement NFS Docker existant

  1. Inventoriez les montages avec findmnt -t nfs,nfs4. Notez vers, proto, hard/soft, timeo, retrans, et si vous utilisez des noms d’hôtes.
  2. Confirmez la réalité avec nfsstat -m. Si Docker dit une chose et que le noyau en a monté une autre, faites confiance au noyau.
  3. Décidez du protocole : préférez NFSv4.1+. Si vous êtes en v3, listez les dépendances firewall et les cas de panne que vous ne pouvez pas tolérer.
  4. Corrigez le réseau avant le tuning : validez le MTU bout en bout ; éliminez les drops d’interface ; vérifiez la symétrie de routage ; assurez la stabilité du port 2049.
  5. Choisissez la sémantique de montage :
    • Écritures état : hard, timeo modéré, retrans plutôt bas, TCP.
    • Lecture seule / cache : envisagez soft seulement si votre appli gère EIO et que vous acceptez « erreur plutôt que blocage ».
  6. Rendez les montages prédictibles : pré-montez via systemd ou utilisez automount. Évitez les montages à la demande déclenchés par le démarrage des conteneurs quand c’est possible.
  7. Testez la panne : débranchez le réseau serveur (en labo), redémarrez un client, faites flapper une route, et observez. Si votre test consiste à « attendre et espérer », ce n’est pas un test.
  8. Opérationnalisez : ajoutez des dashboards pour retransmits, drops d’interface, saturation des threads NFS serveur et latence disque. Ajoutez un runbook d’astreinte qui commence par le Mode opératoire de diagnostic rapide ci-dessus.

Une checklist courte pour les options de montage (priorité stabilité)

  • Utilisez TCP : proto=tcp
  • Privilégiez NFSv4.1+ : vers=4.1 (ou 4.2 si supporté)
  • Correction d’abord : hard
  • Ne pas sur-tuner : commencez avec timeo=600, retrans=2 et ajustez seulement sur preuve
  • Réduire le churn métadonnées : noatime pour les workloads typiques
  • Prudence avec actimeo et semblables ; la mise en cache n’est pas une performance gratuite
  • Considérez nconnect seulement après avoir mesuré la capacité serveur et firewall

FAQ

1) Dois-je utiliser NFSv3 ou NFSv4 pour les volumes Docker ?

Utilisez NFSv4.1+ sauf raison de compatibilité spécifique. Dans les réseaux riches en conteneurs, moins de daemons auxiliaires et de ports signifie généralement moins d’échecs « aléatoires » de montage.

2) soft est-il jamais acceptable ?

Oui—pour des données en lecture seule ou de type cache où une erreur d’E/S est préférable à un blocage, et où votre application est conçue pour traiter EIO comme normal. Pour des écritures avec état, c’est un piège dangereux.

3) Pourquoi docker stop se bloque quand NFS est down ?

Parce que les processus sont bloqués en I/O noyau sur un filesystem monté en hard. Les signaux ne peuvent pas interrompre un thread coincé en sommeil non interruptible. Corrigez la joignabilité du montage.

4) Que font réellement timeo et retrans ?

Ils gouvernent le comportement de retry RPC. timeo est le timeout de base pour un RPC ; retrans est le nombre de retries avant que le client n’enregistre « not responding » (et pour soft, avant d’échouer l’E/S).

5) Dois-je tuner rsize et wsize à des valeurs énormes ?

Pas par superstition. Les valeurs par défaut modernes sont souvent bonnes. Des valeurs surdimensionnées peuvent interagir mal avec le MTU, les limites serveur ou les pertes réseau. Faites le tuning seulement après avoir mesuré le débit et les retransmits.

6) Utiliser une IP au lieu d’un nom d’hôte aide-t-il ?

Ça peut aider. Si le DNS est instable, lent ou change de façon imprévue, utiliser une IP évite la résolution de nom comme dépendance de panne. Le compromis est de perdre la migration serveur facile à moins de gérer l’IP comme endpoint stable.

7) Qu’est-ce qui cause « stale file handle » et comment l’éviter ?

C’est généralement causé par des changements côté serveur qui invalident des file handles : déplacement de chemin d’export, comportement de basculement, ou changements de filesystem sous l’export. Évitez cela en gardant des exports stables et en utilisant des méthodes HA supportées par votre NAS, testées avec de vrais clients.

8) Dois-je monter via des volumes Docker ou pré-monter sur l’hôte ?

Pré-monter (mounts systemd/automount) est souvent plus prévisible et plus facile à déboguer. Le montage via volume Docker fonctionne, mais il couple le cycle de vie du montage à celui du conteneur, et ce n’est pas l’endroit où vous voulez faire reposer votre stratégie de fiabilité.

9) Et nolock pour réparer les blocs ?

Évitez-le sauf si vous êtes absolument sûr que votre workload ne dépend pas des verrous. Il peut « réparer » des problèmes liés à lockd en NFSv3 en désactivant le verrouillage, mais cela échange des pannes contre des bugs de correction.

10) Si mon serveur NFS va bien, pourquoi seuls certains clients voient des timeouts ?

Parce que « le serveur va bien » veut souvent dire « il répond au ping ». Les problèmes locaux au client comme mismatch MTU, routage asymétrique, limites conntrack et drops NIC peuvent casser sélectivement NFS tout en laissant d’autres trafics majoritairement corrects.

Conclusion : prochaines étapes pour réduire les alertes

Si vous luttez contre des timeouts de volumes NFS Docker, ne commencez pas par bidouiller timeo comme un bouton radio.
Commencez par nommer la panne : chemin réseau, saturation serveur, friction de version de protocole, ou timing d’orchestration.
Puis faites un choix délibéré sur la sémantique : montages hard correction-d’abord pour les écritures d’état, et soft très ciblé pour les données jetables.

Prochaines étapes pratiques à faire cette semaine :

  1. Auditez chaque hôte Docker avec findmnt et nfsstat -m ; enregistrez les options réelles et la version NFS.
  2. Standardisez sur NFSv4.1+ sur TCP sauf raison contraire.
  3. Corrigez MTU et compteurs de drops avant de changer le tuning des montages.
  4. Déplacez les montages critiques vers des montages gérés par systemd (idéalement automount) avec un ordonnancement explicite network-online.
  5. Rédigez un runbook basé sur le Mode opératoire de diagnostic rapide, et exercez-le une fois pendant une période calme.

Le but ultime n’est pas « NFS ne flanche jamais ». Le but est : quand ça flanche, que ça se comporte de manière prévisible, se rétablisse proprement, et ne transforme pas vos conteneurs en art moderne.

← Précédent
ZFS ZVOL vs Dataset : la décision qui façonne vos douleurs futures
Suivant →
VoIP sur VPN : arrêter l’audio robotique avec MTU, gigue et notions de QoS

Laisser un commentaire