Proxmox « Trop de fichiers ouverts » : quelle limite augmenter, et pour quel service

Cet article vous a aidé ?

« Trop de fichiers ouverts » est l’un de ces messages d’erreur qui peut sembler insultant. Linux fait exactement ce que vous lui avez demandé : appliquer des limites. C’est sur Proxmox que vous le remarquez généralement, à 2h du matin, en faisant quelque chose de « sûr » comme une sauvegarde, une migration ou une restauration qui ne peut pas attendre.

La correction n’est que rarement « mettre tout à un million ». La bonne démarche est : trouver le processus qui a atteint le plafond, augmenter le bon plafond (unit systemd, limite utilisateur, limite noyau, ou réglage applicatif), puis prouver que vous n’avez pas simplement masqué une fuite de descripteurs de fichiers qui reviendra pire la semaine suivante.

Ce que « too many open files » signifie réellement sur Proxmox

Sur Linux, « open files » signifie en réalité descripteurs de fichiers : de petits entiers qu’un processus utilise pour référencer des ressources ouvertes. Oui, des fichiers réguliers. Mais aussi des sockets, des pipes, des eventfds, des watches inotify, des nœuds de périphériques, parfois même des objets noyau « anonymes » exposés via une interface fichier. Quand vous voyez :

  • EMFILE : le processus a atteint sa limite de descripteurs par processus
  • ENFILE : le système a atteint une limite globale de la table de fichiers (moins courant sur les noyaux modernes, mais possible)

Dans les environnements Proxmox, EMFILE est le coupable habituel. Cela signifie qu’un processus spécifique — un démon, une instance QEMU, un worker de sauvegarde, un OSD Ceph — a épuisé ses descripteurs. Augmenter les limites à l’aveugle peut masquer une fuite, mais c’est aussi la bonne action si votre charge a besoin légitimement de dizaines de milliers de descripteurs (pensez Ceph, reverse proxies très sollicités, catalogues de sauvegarde énormes, ou une machine virtuelle unique avec beaucoup d’activité virtio-scsi et réseau).

Les limites de descripteurs existent à plusieurs couches :

  • Maximum global du noyau (par ex. fs.file-max) : combien de handles de fichiers le système peut allouer au total.
  • rlimit par processus (ulimit / RLIMIT_NOFILE) : plafond pour un processus donné.
  • limites des unités systemd (LimitNOFILE=) : ce que systemd fixe pour un service avant exec.
  • limites par utilisateur (PAM / /etc/security/limits.conf) : affecte les sessions de connexion et les services démarrés sous un utilisateur, mais pas nécessairement les services système gérés par systemd sauf si PAM intervient.
  • limites internes à l’application : parfois il existe un réglage dans le service lui‑même (configs Ceph, motifs d’ouverture de fichiers dans PBS, etc.).

Proxmox ajoute une complexité : beaucoup de processus importants sont des démons gérés par systemd (pvedaemon, pveproxy, pvestatd, pve-cluster), plus les instances QEMU démarrées dans des scopes systemd (selon la version et la configuration). Donc la « bonne » correction est souvent un override systemd pour une unité spécifique, pas un changement global d’ulimit qui n’affecte pas les services de toute façon.

Feuille de diagnostic rapide (premières/deuxièmes/troisièmes vérifications)

C’est la partie à exécuter quand le pager hurle et que votre patience est limitée.

Première étape : identifier qui l’a signalé

  1. Vérifiez journald pour la ligne d’erreur exacte et le nom du processus. Ne devinez pas.
  2. Confirmez s’il s’agit de EMFILE (par processus) ou de ENFILE (système global). La correction dépend de cela.

Deuxième étape : vérifier l’utilisation des descripteurs dans le processus suspect

  1. Récupérez le(s) PID(s) du démon suspect ou du processus QEMU.
  2. Comptez les fds ouverts et comparez-les à la limite du processus (depuis /proc/<pid>/limits).

Troisième étape : décider quoi augmenter (et où)

  1. Si la limite du processus est basse et que l’utilisation est légitime, augmentez LimitNOFILE pour cette unité systemd (idéal).
  2. Si la table de fichiers système est épuisée, augmentez fs.file-max et investiguez pourquoi le système accumule des handles (souvent une fuite, des services hors de contrôle, ou Ceph à grande échelle).
  3. Si c’est un pic ponctuel lié à une sauvegarde ou une restauration, envisagez de replanifier/limiter la concurrence et de corriger le schéma de charge plutôt que d’augmenter uniquement les limites.

Une phrase qui a crié la vérité en exploitation : (idée paraphrasée) « L’espoir n’est pas une stratégie. » — souvent attribué dans les cercles de direction technique. Pour cette erreur, l’espoir ressemble à « augmenter tout et redémarrer ». La stratégie ressemble à instrumentation et limites ciblées.

Faits intéressants et contexte historique (pourquoi cela se répète)

  • Fait 1 : Les premiers Unix avaient souvent de très petites limites de fd par processus (parfois quelques dizaines). Les systèmes modernes par défaut à 1024 ou plus, mais ces valeurs restent des hypothèses « polyvalentes », pas des hypothèses pour hôtes de virtualisation.
  • Fait 2 : La séparation soft/hard existe pour que les processus puissent augmenter leur soft jusqu’à un hard cap. systemd peut définir les deux.
  • Fait 3 : « Tout est un fichier » inclut les sockets ; un proxy API très chargé peut brûler des milliers de fds sans toucher au disque.
  • Fait 4 : QEMU utilise plusieurs descripteurs par disque, par NIC, par thread vhost, plus les eventfds. Une seule VM peut consommer des centaines ou milliers de fds sur un hôte occupé.
  • Fait 5 : inotify utilise des descripteurs et des watchers ; certaines piles de monitoring et expéditeurs de logs créent beaucoup de watchers et peuvent atteindre les limites de façon surprenante.
  • Fait 6 : systemd a introduit une gestion des limites plus explicite au niveau des unités (LimitNOFILE), réduisant la dépendance aux astuces ulimit dans les shells qui ne s’appliquaient jamais aux démons.
  • Fait 7 : La comptabilisation globale des handles de fichiers s’est améliorée, mais vous pouvez encore épuiser la table si vous exécutez assez de services ou fuyez des fds dans le temps.
  • Fait 8 : Ceph a historiquement tendance à nécessiter des limites fd plus élevées ; les OSD peuvent légitimement demander beaucoup d’open files et de sockets sous charge.

Blague n°1 : Les descripteurs de fichiers sont comme des salles de réunion — si personne ne part, le bâtiment « n’en a plus », et la direction blâme l’agenda.

Où cela se produit dans Proxmox : quel service est généralement en cause

Sur un nœud Proxmox, l’expression « trop de fichiers ouverts » peut apparaître à plusieurs couches. Votre travail est d’arrêter de traiter Proxmox comme un monolithe et de commencer à le considérer comme ce qu’il est : Debian plus systemd plus un empilement de démons plus des charges de travail (VMs/CTs) qui font des choses chaotiques.

Démons Proxmox (courants dans des clusters chargés)

  • pveproxy : interface web et API. Il peut brûler des fds via de nombreuses connexions HTTPS concurrentes, sessions navigateur long‑cours, configurations de reverse proxy et backends d’authentification.
  • pvedaemon : tâches en arrière‑plan et helpers API. Impliqué fréquemment lors des sauvegardes, restaurations, migrations, scans de stockage.
  • pvestatd : collecte des statistiques ; peut solliciter fortement les requêtes de stockage et les connexions réseau dans de grands clusters.
  • pve-cluster / pmxcfs : démon du système de fichiers de cluster ; les problèmes apparaissent souvent comme un comportement de cluster étrange, pas seulement une ligne EMFILE claire.

Processus QEMU/KVM (courant quand « une VM part en vrille »)

Si une VM exécute une charge à nombreuses connexions (proxies, brokers de messages, websockets, gateways NAT), elle peut forcer le processus QEMU côté hôte à ouvrir beaucoup de fds pour vhost-net, devices tap, et interactions io_uring/eventfd. Si la limite du processus QEMU est basse, vous verrez des échecs réseau, d’IO disque, ou de hotplug de périphérique.

Couches de stockage (ZFS, Ceph, PBS)

  • ZFS n’est généralement pas la source directe d’EMFILE sur l’hôte, mais les helpers userland et les processus de sauvegarde qui interagissent avec beaucoup de fichiers peuvent l’être. Pensez aux pipelines zfs send et à l’indexation des sauvegardes.
  • Ceph : OSDs et monitors sont connus pour nécessiter des limites fd élevées dans des environnements réels. « Trop de fichiers ouverts » ici n’est pas exotique ; c’est une vérification de config à faire tôt.
  • Proxmox Backup Server (si co‑localisé ou intégré) : les jobs de sauvegarde ouvrent beaucoup de chunks, d’indices et de connexions. Une limite fd basse peut transformer une fenêtre de sauvegarde en échec au ralenti.

Conteneurs (LXC)

Les containers LXC peuvent atteindre leurs propres limites nofile à l’intérieur du namespace du container. Mais ne supposez pas que le container est fautif ; le démon hôte qui le gère peut être celui qui se plaint. Épinglez toujours l’erreur à un PID puis à une unité.

Tâches pratiques (commandes, sorties, décisions) — la liste de contrôle opérationnelle

Vous voulez des tâches réelles qui réduisent l’incertitude. En voici plus d’une douzaine. Exécutez‑les dans l’ordre jusqu’à obtenir un goulot nommé et un changement justifié.

Tâche 1 : Trouver la ligne d’erreur exacte et le service émetteur

cr0x@server:~$ journalctl -p err -S -2h | grep -iE "too many open files|EMFILE|ENFILE" | tail -n 20
Dec 26 09:31:12 pve1 pveproxy[1432]: error: accept4: Too many open files
Dec 26 09:31:12 pve1 pveproxy[1432]: failed to accept connection: EMFILE

Ce que cela signifie : C’est un EMFILE provenant de pveproxy PID 1432. Ne touchez pas encore aux globals du noyau ; c’est par processus.

Décision : Inspecter les limites et le nombre de fd du PID 1432. Préparer un override systemd pour pveproxy.service si nécessaire.

Tâche 2 : Confirmer si le système est proche d’une exhaustion globale de handles

cr0x@server:~$ cat /proc/sys/fs/file-nr
23872	0	9223372036854775807

Ce que cela signifie : Le premier nombre est le nombre de handles alloués ; le troisième est le max système. Sur beaucoup de noyaux modernes, le max est effectivement énorme (ou dynamique). Si le premier nombre est proche du max, vous avez un problème global.

Décision : Ici, ce n’est pas proche. Concentrez‑vous sur les limites par processus.

Tâche 3 : Vérifier la limite de fd du processus et son utilisation actuelle

cr0x@server:~$ pid=1432; echo "FDs:"; ls -1 /proc/$pid/fd | wc -l; echo; echo "Limits:"; grep -i "open files" /proc/$pid/limits
FDs:
1024

Limits:
Max open files            1024                 1048576              files

Ce que cela signifie : Le processus est exactement au niveau de sa soft limit (1024). La hard limit est plus haute, donc le service pourrait théoriquement l’augmenter, mais il ne l’a pas fait.

Décision : Augmenter LimitNOFILE pour l’unité afin que systemd le démarre avec une soft limit plus élevée. Ciblez une valeur sensée (par ex. 8192–65536 selon la concurrence).

Tâche 4 : Identifier l’unité systemd associée au PID

cr0x@server:~$ systemctl status pveproxy --no-pager
● pveproxy.service - PVE API Proxy Server
     Loaded: loaded (/lib/systemd/system/pveproxy.service; enabled)
     Active: active (running) since Thu 2025-12-26 08:11:02 UTC; 1h 25min ago
   Main PID: 1432 (pveproxy)
      Tasks: 10 (limit: 154675)
     Memory: 76.4M
        CPU: 1min 52.123s

Ce que cela signifie : C’est une unité normale, pas un processus mystère. Bien : on peut la surcharger proprement.

Décision : Utiliser systemctl edit pveproxy pour définir LimitNOFILE. Ne modifiez pas directement les fichiers dans /lib/systemd/system.

Tâche 5 : Inspecter les limites actuelles au niveau de l’unité (si présentes)

cr0x@server:~$ systemctl show pveproxy -p LimitNOFILE
LimitNOFILE=1024:1048576

Ce que cela signifie : systemd l’a démarré avec soft=1024, hard=1048576.

Décision : Faire un override pour augmenter la soft (et optionnellement la hard). Si vous n’avez besoin que d’une soft supérieure, fixez une seule valeur ; systemd accepte LimitNOFILE=65536 (s’applique aux deux) ou LimitNOFILE=65536:65536.

Tâche 6 : Créer un override systemd pour le service Proxmox spécifique

cr0x@server:~$ sudo systemctl edit pveproxy
# (editor opens)

Placez ceci dans le drop-in :

cr0x@server:~$ cat /etc/systemd/system/pveproxy.service.d/override.conf
[Service]
LimitNOFILE=65536

Ce que cela signifie : Au prochain redémarrage, pveproxy aura une limite fd de 65k. C’est suffisant pour la plupart des clusters sans être excessif.

Décision : Rechargez systemd et redémarrez le service. Si c’est le proxy API et que vous êtes en pleine panne, faites‑le pendant une fenêtre sûre ou via la console du nœud.

Tâche 7 : Appliquer et vérifier que les nouvelles limites ont bien pris effet

cr0x@server:~$ sudo systemctl daemon-reload
cr0x@server:~$ sudo systemctl restart pveproxy
cr0x@server:~$ systemctl show pveproxy -p LimitNOFILE
LimitNOFILE=65536:65536

Ce que cela signifie : L’unité est maintenant configurée correctement.

Décision : Confirmer que le PID en cours d’exécution a la nouvelle limite, pas seulement les métadonnées de l’unité.

Tâche 8 : Confirmer la limite effective du PID en cours

cr0x@server:~$ pid=$(pidof pveproxy); grep -i "open files" /proc/$pid/limits
Max open files            65536                65536                files

Ce que cela signifie : Le processus tourne effectivement avec la nouvelle limite. C’est le but.

Décision : Surveillez une éventuelle récidive. Si l’utilisation des fd continue d’augmenter, vous avez peut‑être une fuite ou une surcharge en amont.

Tâche 9 : Voir quel type de fds est consommé (sockets vs fichiers)

cr0x@server:~$ pid=$(pidof pveproxy); sudo ls -l /proc/$pid/fd | awk '{print $11}' | head
socket:[942113]
socket:[942115]
/dev/null
socket:[942118]
anon_inode:[eventfd]

Ce que cela signifie : Si la liste contient majoritairement des socket:, vous gérez de la concurrence de connexions. Si ce sont des chemins réels, vous scannez beaucoup de fichiers ou êtes bloqué sur le stockage.

Décision : Si ce sont des sockets, regardez les proxies en frontal, les keepalives, les backends d’auth, et le comportement des clients. Si ce sont des chemins fichiers, investiguez ce qui les ouvre et pourquoi.

Tâche 10 : Identifier les plus gros consommateurs de fd sur le nœud (triage rapide)

cr0x@server:~$ for p in /proc/[0-9]*; do
  pid=${p#/proc/}
  comm=$(tr -d '\0' < $p/comm 2>/dev/null) || continue
  fdc=$(ls -1 $p/fd 2>/dev/null | wc -l)
  echo "$fdc $pid $comm"
done | sort -nr | head -n 10
18034 28741 ceph-osd
 9123 1942 qemu-system-x86
 5012 1432 pveproxy
 2120 1567 pvedaemon

Ce que cela signifie : Vous avez les coupables classés par nombre de fd.

Décision : Si un OSD Ceph domine, vous devrez peut‑être ajuster aussi les limites Ceph. Si QEMU est gros, concentrez‑vous sur la VM concernée et sa méthode de démarrage.

Tâche 11 : Pour QEMU : mapper un PID QEMU à un VMID

cr0x@server:~$ pid=1942; tr '\0' ' ' < /proc/$pid/cmdline | sed -n 's/.*-id \([0-9]\+\).*/VMID=\1/p'
VMID=104

Ce que cela signifie : Ce processus QEMU est la VM 104.

Décision : Vérifiez s’il monte régulièrement l’utilisation des fd pendant les sauvegardes, sous forte charge de connexions, ou en raison d’une mauvaise configuration de périphérique.

Tâche 12 : Vérifier la limite du processus QEMU et si elle est trop basse

cr0x@server:~$ pid=1942; grep -i "open files" /proc/$pid/limits
Max open files            4096                 4096                 files

Ce que cela signifie : QEMU est limité à 4096. Cela peut être suffisant, ou complètement insuffisant pour une VM passerelle très chargée.

Décision : Si QEMU échoue avec EMFILE et que l’utilisation approche 4096, augmentez la limite pour le scope/service qui lance les VMs (voir la section « Augmenter les limites correctement »).

Tâche 13 : Trouver l’unité/scope systemd pour un PID QEMU

cr0x@server:~$ pid=1942; systemctl status $pid --no-pager
● 104.scope - qemu-kvm -id 104
     Loaded: loaded
     Active: active (running) since Thu 2025-12-26 08:22:51 UTC; 1h 13min ago
   Main PID: 1942 (qemu-system-x86)

Ce que cela signifie : La VM tourne dans un scope systemd nommé d’après le VMID. Les limites peuvent venir du service parent ou des défauts systemd.

Décision : Ajuster les scopes par VM est possible mais généralement pas le meilleur modèle opérationnel. Préférez corriger l’unité/template parent ou le service qui spawn QEMU (souvent via l’outillage Proxmox), ou utilisez les defaults manager systemd si approprié.

Tâche 14 : Vérifier les limites par défaut de systemd (parfois le coupable caché)

cr0x@server:~$ systemctl show --property DefaultLimitNOFILE
DefaultLimitNOFILE=1024:524288

Ce que cela signifie : Les valeurs par défaut de systemd peuvent influencer les scopes et services qui ne définissent pas explicitement leurs limites.

Décision : Ne l’augmentez pas à la légère. C’est un bouton à fort rayon d’action. N’en servez‑vous que si de nombreux services non liés ont besoin d’une limite plus haute et après validation de l’impact mémoire et de la surveillance.

Tâche 15 : Vérifier les limites par utilisateur (surtout utile pour les outils interactifs et les sessions PAM)

cr0x@server:~$ ulimit -n
1024

Ce que cela signifie : Votre session shell a une limite de 1024 open files. Cela ne s’applique pas automatiquement aux services systemd.

Décision : Si vos outils opérationnels (scripts personnalisés, jobs rsync, workflows CLI de sauvegarde) rencontrent EMFILE en session interactive, ajustez les limites PAM. Sinon, priorisez les overrides systemd.

Tâche 16 : Si vous suspectez une fuite, surveillez le nombre de fd dans le temps

cr0x@server:~$ pid=$(pidof pvedaemon); for i in $(seq 1 10); do date; ls -1 /proc/$pid/fd | wc -l; sleep 30; done
Thu Dec 26 09:40:01 UTC 2025
812
Thu Dec 26 09:40:31 UTC 2025
829
Thu Dec 26 09:41:01 UTC 2025
846

Ce que cela signifie : Si le nombre ne fait que grimper et ne redescend jamais sous charge stable, quelque chose fuit peut‑être des fds (ou vous avez un nombre croissant de connexions long‑cours).

Décision : Augmenter les limites peut gagner du temps, mais vous devez traquer la fuite : logs, mises à jour récentes, plugins, backends d’auth, ou un load balancer qui fait quelque chose de « créatif ».

Tâche 17 : Identifier quels pairs distants maintiennent des sockets ouvertes (pour les proxies)

cr0x@server:~$ pid=$(pidof pveproxy); sudo lsof -nP -p $pid | awk '/TCP/ {print $9}' | head
10.20.5.18:8006->10.20.5.40:51522
10.20.5.18:8006->10.20.7.91:50944

Ce que cela signifie : Vous voyez les IPs et ports clients. Si un client ouvre un nombre ridicule de connexions, vous avez trouvé un problème de comportement.

Décision : Corrigez le client, ajoutez un proxy avec des limites sensées, ou ajustez les keepalives. Augmenter les limites sans traiter les clients abusifs, c’est comme acheter une plus grosse poubelle pour un raton laveur.

Augmenter les limites correctement : noyau vs systemd vs appli

Commencez par le correctif le plus chirurgical

Si un service spécifique atteint EMFILE, définissez LimitNOFILE pour ce service. C’est l’approche la plus propre : mesurable, réversible, à collatéral minimal.

Override systemd : le mouvement par défaut pour les services Proxmox

Les démons Proxmox sont des services systemd. Changez les limites avec des drop-ins dans /etc/systemd/system/<unit>.service.d/override.conf. Ce fichier survit aux mises à jour et indique à votre futur vous ce qui a été fait.

Unités Proxmox courantes à considérer :

  • pveproxy.service (UI/API)
  • pvedaemon.service (tâches, helper API)
  • pvestatd.service (statistiques)
  • pve-cluster.service (système de fichiers du cluster)
  • ceph-osd@<id>.service, ceph-mon@<name>.service (si vous exécutez Ceph sur le nœud)

Quelle hauteur pour LimitNOFILE ?

Choisissez des nombres qui correspondent à la réalité opérationnelle :

  • 8192 : une hausse décente pour des démons légers qui ont parfois des pics.
  • 16384–65536 : courant pour des proxies chargés, des démons de management dans de grands clusters, et des processus liés aux sauvegardes.
  • 131072+ : réservé aux gros consommateurs (OSD Ceph à grande échelle, services réseau très haut débit). Ne le faites pas parce que vous l’avez vu sur un forum.

La limite n’est pas gratuite : chaque fd consomme des ressources noyau. Sur les systèmes modernes c’est généralement acceptable, mais « acceptable » dépend de la pression mémoire, du nombre de processus et du nombre de fds réellement utilisés.

Quand les limites globales du noyau importent

L’épuisement global des handles est plus rare, mais survient sur :

  • nœuds exécutant beaucoup de services (monitoring, log shipping, stockage, reverse proxies)
  • nœuds très chargés en Ceph
  • systèmes sous fuite de fds répartie sur plusieurs processus

Inspectez les réglages actuels :

cr0x@server:~$ sysctl fs.file-max
fs.file-max = 9223372036854775807

Sur beaucoup de noyaux modernes, cette valeur est énorme ou effectivement non bornée. Dans ce cas, ENFILE est moins probable, et EMFILE reste le problème principal. Ne faites quand même pas d’hypothèses ; mesurez.

Limites par utilisateur : utiles, mais pas votre levier principal pour les démons Proxmox

/etc/security/limits.conf et ulimit -n comptent pour les sessions utilisateurs, cron et scripts lancés par des humains. Ils ne contrôlent pas de façon fiable les services gérés par systemd (systemd fixe les rlimits lui‑même). Si vous « avez corrigé » un démon Proxmox en éditant limits.conf, vous avez eu de la chance, ou vous avez changé autre chose en même temps.

Augmenter les limites QEMU : ce qu’il faut et ne faut pas faire

Si QEMU atteint les limites fd, vous avez deux questions parallèles :

  1. La charge de cette VM est‑elle légitimement très consommatrice en fd (beaucoup de connexions/périphériques) ?
  2. Les processus QEMU sont‑ils lancés avec un rlimit sensé pour votre environnement ?

Augmenter les limites QEMU peut se faire en ajustant l’environnement systemd qui les spawn (selon votre version de Proxmox et la façon dont la VM est scoppée). En pratique, je recommande :

  • D’abord, confirmez que le PID QEMU atteint la limite (et non le système invité).
  • Puis, envisagez d’augmenter le défaut du service spawner seulement si plusieurs VMs montrent le même problème.
  • Pour une VM isolée hors norme, préférez des corrections au niveau de la charge : pooling de connexions, réduction des keepalives agressifs, correction de fuites applicatives, ou séparation des rôles sur plusieurs VMs.

Blague n°2 : « On va juste mettre LimitNOFILE à l’infini » est la façon dont on apprend ce que « mémoire finie » signifie en production.

Trois mini-récits d’entreprise issus du terrain

Mini-récit 1 : L’incident causé par une mauvaise supposition

Ils exploitaient un cluster Proxmox de taille moyenne pour des services internes et quelques applications clients. Un matin, l’interface web a commencé à faire des timeouts. Puis les appels API ont échoué. Puis les sauvegardes se sont mises en file d’attente. L’équipe a supposé que le nœud était « down » au sens classique : CPU saturé, disque plein, réseau mort. Rien de tout cela n’était vrai.

L’indice était dans journald : pveproxy ne pouvait pas accepter de nouvelles connexions. « Trop de fichiers ouverts. » Quelqu’un avait récemment mis un tableau de bord interne en mode kiosk sur un écran mural. Il se rechargeait agressivement, ouvrait plusieurs connexions API parallèles et ne les fermait pas correctement. Multipliez par quelques téléviseurs et quelques développeurs qui laissaient des onglets ouverts pendant des jours, et vous obtenez un déni de service au ralenti.

La mauvaise supposition était que « trop de fichiers ouverts » devait signifier « ZFS a ouvert trop de fichiers » ou « le stockage est cassé ». Ils ont passé des heures à vérifier l’intégrité des pools et les données SMART. En attendant, le proxy était à 1024 fds et rejetait justement l’UI dont ils avaient besoin pour déboguer.

La correction fut simple : augmenter LimitNOFILE pour pveproxy à une valeur sensée et corriger le comportement du client fautif. La leçon : liez toujours l’erreur à un PID, puis à une unité, puis à une charge. Deviner coûte cher.

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

Une autre organisation voulait des sauvegardes plus rapides. Ils ont optimisé la planification pour lancer plus de jobs en parallèle et ont raccourci les cycles de rétention. Sur le papier, c’était beau : plus de concurrence, plus de débit, moins de temps dans la fenêtre. Ils ont aussi déployé du monitoring supplémentaire qui suivait beaucoup de logs et beaucoup de répertoires.

Puis les sauvegardes ont commencé à échouer de façon intermittente. Parfois c’était le process de sauvegarde. Parfois un démon de management. Parfois un service apparemment sans relation comme un collecteur de métriques. Le motif était « aléatoire », ce que l’on appelle une limite système quand on ne l’a pas encore admis.

Le retour de bâton fut que chaque worker de sauvegarde parallèle et chaque agent de monitoring multipliaient l’usage des fds. Individuellement, chaque service semblait correct. Collectivement, le nœud passait de longues périodes avec beaucoup de processus proches de leurs soft caps. Des pics occasionnels poussaient l’un d’eux au‑dessus du seuil, et celui qui était malchanceux lançait EMFILE en premier.

Ils l’ont « corrigé » une fois en augmentant un défaut global et ont continué. Un mois plus tard, le même schéma est revenu, sauf que maintenant le nœud avait aussi plus de pression mémoire et plus de processus. La correction correcte et ennuyeuse fut : définir explicitement LimitNOFILE pour les services lourds connus, réduire la parallélisation des sauvegardes pour correspondre au backend de stockage, et mesurer l’utilisation des fd pendant les pics. Les performances se sont améliorées, les échecs ont cessé, et ils n’ont plus eu à augmenter les plafonds sans fin.

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

Une équipe exploitant Ceph sur Proxmox avait une habitude peu sexy : ils tenaient un runbook avec trois vérifications simples pour toute erreur plate‑forme. Une de ces vérifications était « utilisation fd vs limites ». Ils versionnaient aussi leurs drop-ins systemd pour les services critiques (pas les fichiers gérés par Proxmox, mais les overrides dans /etc).

Lors d’une expansion de stockage, un nouveau déploiement d’OSD a commencé à flapper. Les symptômes ressemblaient à du réseau : heartbeats manquants, opérations lentes, redémarrages occasionnels de démons. Mais le runbook les a forcés à vérifier les bases. Les processus OSD atteignaient leur limite de fd sous la nouvelle topologie et charge.

Parce qu’ils avaient déjà une politique connue pour les limites Ceph, la correction n’a pas été une recherche frénétique sur les forums. Ils ont appliqué le pattern d’override existant, redémarré les services affectés dans un ordre contrôlé, et validé d’une seule commande que limites et usage avaient désormais une marge.

La journée a été sauvée par quelque chose d’ennuyeux : des vérifications répétables et une hygiène de configuration. Pas de gesticulations héroïques. Pas de « redémarrons juste ». Le cluster a continué de servir des IO, et la fenêtre de changement s’est terminée à l’heure. En exploitation, l’ennuyeux est une fonctionnalité.

Erreurs courantes : symptôme → cause racine → correction

Erreur 1 : « J’ai augmenté ulimit -n et ça échoue toujours »

Symptôme : Vous exécutez ulimit -n 65535 dans votre shell, redémarrez un service Proxmox, et voyez toujours EMFILE.

Cause racine : Les services systemd n’héritent pas de votre ulimit shell. systemd fixe les rlimits lui‑même.

Correction : Définissez LimitNOFILE dans un drop‑in systemd pour l’unité spécifique, puis redémarrez l’unité et vérifiez dans /proc/<pid>/limits.

Erreur 2 : Augmenter le défaut systemd global parce qu’un service s’est mal comporté

Symptôme : Vous changez DefaultLimitNOFILE système‑wide et tout semble aller… jusqu’à ce que des services sans lien entre eux commencent à consommer plus de ressources.

Cause racine : Vous avez étendu le rayon d’action. Maintenant beaucoup de services peuvent ouvrir plus de fds, ce qui peut amplifier des fuites et augmenter la pression mémoire noyau.

Correction : Gardez les valeurs par défaut conservatrices. Augmentez les limites seulement sur les unités qui en ont besoin. N’utilisez le default que si vous avez confirmé que de nombreux services partagent un besoin légitime.

Erreur 3 : Traiter EMFILE comme un « problème de stockage »

Symptôme : Une sauvegarde échoue avec « too many open files », et l’équipe plonge dans le tuning ZFS.

Cause racine : Le processus qui échoue est souvent un démon ou un worker de sauvegarde ouvrant beaucoup de fichiers/sockets, pas ZFS lui‑même.

Correction : Identifiez le PID émetteur et vérifiez sa limite et son nombre de fd. Ensuite augmentez la limite de l’unité ou réduisez la concurrence.

Erreur 4 : Augmenter les limites sans chercher la fuite

Symptôme : Le nœud tient la semaine qui suit l’augmentation, puis s’effondre à nouveau.

Cause racine : Une fuite réelle (fds jamais libérés) ou un comportement de connexion hors de contrôle ; une limite plus haute n’a fait que retarder le crash.

Correction : Suivez l’évolution des fd pour les processus suspects. Si la croissance est monotone, traitez‑la comme un bug ou un problème de charge. Escaladez vers le fournisseur/la communauté avec des preuves (croissance de fd, échantillons lsof, lignes journald).

Erreur 5 : Confondre les limites invitées et hôtes

Symptôme : Une application containerisée lance EMFILE, donc vous augmentez les limites hôtes et rien ne change.

Cause racine : La limite se trouve dans le container ou dans le runtime de l’appli, pas dans le processus hôte.

Correction : Vérifiez à l’intérieur du container (ulimit -n) et vérifiez aussi le process côté hôte. Corrigez la couche qui échoue réellement.

Erreur 6 : Redémarrer des services au hasard jusqu’à disparition de l’erreur

Symptôme : Après des redémarrages, tout « fonctionne à nouveau », mais personne ne sait pourquoi.

Cause racine : Les redémarrages ferment les fds ouverts, masquant temporairement la charge ou les fuites.

Correction : Utilisez les redémarrages pour stabiliser, pas pour diagnostiquer. Avant de redémarrer, capturez : l’erreur journald, les limites PID, le nombre de fd, et un échantillon lsof.

Listes de contrôle / plan étape par étape (séquence de changements sûrs)

Checklist A : Vous avez vu « too many open files » dans l’UI/API Proxmox

  1. Récupérez les erreurs journald des 1–2 dernières heures ; trouvez le binaire émetteur et le PID.
  2. Vérifiez s’il s’agit d’EMFILE vs ENFILE.
  3. Comptez les fds ouverts pour le PID et comparez avec /proc/<pid>/limits.
  4. Si le nombre de fd est proche de la limite : définissez LimitNOFILE pour l’unité spécifique et redémarrez‑la.
  5. Si le nombre de fd est bien en dessous de la limite : vous pouvez avoir des pics transitoires ; investiguez la concurrence, le comportement client et les logs autour de l’horodatage.
  6. Après le changement, vérifiez les nouvelles limites sur le PID en cours et surveillez la récidive.

Checklist B : Vous suspectez que des processus QEMU atteignent les limites

  1. Trouvez le PID QEMU depuis le message d’erreur ou depuis les gros consommateurs de fd.
  2. Mappez le PID au VMID en utilisant la cmdline (-id).
  3. Vérifiez /proc/<pid>/limits et le nombre de fd. Si c’est proche : c’est réel.
  4. Décidez : corriger le motif de charge (préféré pour une VM isolée) vs augmenter les limites (si plusieurs VMs sont affectées).
  5. Après les changements, validez en exécutant la même charge et en surveillant la marge des fds.

Checklist C : Vous exécutez Ceph sur Proxmox et rencontrez EMFILE

  1. Identifiez quel démon Ceph (OSD/MON/MGR) a loggué EMFILE.
  2. Vérifiez la limite de l’unité systemd de ce démon et la limite du PID en cours.
  3. Appliquez un override d’unité pour ce type de démon (souvent des unités templatisées comme ceph-osd@.service).
  4. Redémarrez dans un ordre contrôlé en surveillant la santé du cluster.
  5. Confirmez l’utilisation des fd sous charge et assurez‑vous de ne pas avoir uniquement repoussé une fuite.

Étapes : la manière « correcte » d’augmenter une limite pour un démon Proxmox

  1. Mesurez la limite et l’usage actuel (/proc/<pid>/limits et le compte /proc/<pid>/fd).
  2. Choisissez une nouvelle valeur avec marge (généralement 8–64× le pic actuel, pas 1000×).
  3. Créez un drop‑in systemd avec systemctl edit <unit>.
  4. systemctl daemon-reload.
  5. Redémarrez l’unité pendant une fenêtre appropriée.
  6. Vérifiez avec systemctl show et /proc/<pid>/limits.
  7. Surveillez : nombre de fd dans le temps, logs d’erreur, comportement client.
  8. Consignez pourquoi vous l’avez fait. Le vous du futur est une personne différente avec moins de contexte et plus de caféine.

FAQ

1) Dois‑je augmenter fs.file-max pour corriger « too many open files » sur Proxmox ?

Généralement non. La plupart des incidents Proxmox sont des EMFILE par processus. Augmentez d’abord LimitNOFILE du service. Touchez aux globals du noyau seulement si vous pouvez démontrer une exhaustion globale.

2) Quelle valeur par défaut LimitNOFILE est bonne pour pveproxy ?

Pour de petites installations, 8192 suffit. Pour des clusters chargés avec beaucoup de clients UI/API ou d’automatisation, 65536 est un plafond pragmatique. Si vous avez besoin de plus, vous avez probablement aussi un comportement client à corriger.

3) Pourquoi ulimit -n affiche 1024 alors que j’ai défini des limites plus élevées dans systemd ?

ulimit -n reflète votre session shell courante. Les services systemd ont leurs propres rlimits. Vérifiez le PID du service dans /proc/<pid>/limits pour voir ce qui compte.

4) L’augmentation des limites nofile peut‑elle provoquer de l’instabilité ?

Indirectement, oui. Des limites plus élevées permettent aux processus d’allouer plus de ressources noyau. Si vous avez des fuites, vous venez de donner plus de marge à la fuite. Utilisez des limites plus hautes avec de la surveillance et le suivi des fd.

5) Mon container indique « too many open files ». Dois‑je modifier l’hôte ?

Peut‑être, mais commencez à l’intérieur du container : vérifiez la limite de l’app et la limite du container. Si le process hôte LXC/QEMU est celui qui atteint EMFILE, ajustez la face hôte du service ou du scope.

6) Comment savoir si c’est une fuite ou une concurrence légitime ?

Les fuites ressemblent à des comptes fd qui montent régulièrement et ne redescendent jamais, même quand la charge baisse. La concurrence légitime suit les motifs de trafic. Échantillonnez les comptes fd dans le temps et inspectez le type de fd (sockets vs fichiers).

7) Quels services Proxmox sont les plus sensibles aux limites fd ?

pveproxy et pvedaemon sont courants. Dans les grands clusters, pvestatd et les composants de cluster peuvent montrer des problèmes. Avec Ceph, les démons Ceph sont des candidats fréquents.

8) J’ai augmenté les limites, mais je vois encore des erreurs. Et maintenant ?

Confirmez que le PID en cours a la nouvelle limite (ne vous fiez pas uniquement aux fichiers de config). Ensuite, vérifiez si l’utilisation des fd atteint encore le nouveau plafond. Si oui, vous avez besoin soit d’une limite plus haute soit d’un correctif pour une montée en flèche. Si non, l’erreur peut provenir d’un autre process que vous pensiez être en cause.

9) Existe‑t‑il un nombre universel pour les nœuds Proxmox ?

Non, et c’est le piège. Les nœuds de virtualisation hébergent des charges très diverses. Fixez des limites par service basées sur des pics mesurés et la concurrence attendue, pas sur la superstition.

Conclusion : prochaines étapes pratiques

Si vous retenez une chose : « trop de fichiers ouverts » n’est pas une impression. C’est un plafond de ressource mesurable. Votre premier travail est l’attribution : quel PID, quelle unité, quelle limite. Votre second travail est de choisir le plus petit changement efficace : un override systemd LimitNOFILE pour le service spécifique qui a réellement tapé EMFILE. Votre troisième travail est de vous assurer que vous n’avez pas simplement donné une plus longue mèche à une fuite.

Prochaines étapes que vous pouvez faire aujourd’hui :

  1. Ajoutez une commande rapide de triage fd à votre runbook (PID → compte fd → limites).
  2. Définissez des overrides explicites LimitNOFILE pour les services Proxmox lourds connus dans votre environnement (pveproxy, pvedaemon, démons Ceph si applicable).
  3. Pendant les opérations de pointe (fenêtres de sauvegarde, migrations), échantillonnez l’utilisation des fd et conservez les chiffres. Des preuves valent mieux que des discussions.
← Précédent
Déploiements du vendredi soir : la tradition qui apprend par la douleur
Suivant →
Docker vs iptables/nftables : mettre fin à la guerre des pare-feu et réparer le réseau

Laisser un commentaire