Nous avons un serveur LDAP OpenLDAP. Nous constatons qu'il cesse parfois de répondre aux requêtes.
Regardons le journal (par défaut, c'est rangé dans /var/log/syslog
, mais ici, nous rangeons dans un fichier distinct) :
slapd[16769]: warning: cannot open /etc/hosts.allow: Too many open files
slapd[16769]: warning: cannot open /etc/hosts.deny: Too many open files
[…]
slapd[16769]: daemon: accept(8) failed errno=24 (Too many open files)
Trop de fichiers ouverts amènent à ne plus accepter les connexions entrantes (accept() est un appel système permettant… d'accepter une connexion entrante).
Pourtant, OpenLDAP utilise seulement deux fichiers dans /var/lib/ldap
pour stocker et verrouiller les données… Comment peut-il dépasser une quelconque limite ? Regardons le nombre et la nature des fichiers ouverts par slapd (16769 est l'identifiant du processus slapd) :
$ ls -lh /proc/16769/fd | wc -l
988
$ ls -lh /proc/16769/fd
[…]
lrwx------ 1 root root 64 Mar 26 18:36 95 -> socket:[21061503]
lrwx------ 1 root root 64 Mar 26 18:36 97 -> socket:[21061505]
lrwx------ 1 root root 64 Mar 26 18:36 98 -> socket:[21119854]
lrwx------ 1 root root 64 Mar 26 18:36 99 -> socket:[21119861]
[…]
Hum, des sockets… Donc un grand nombre de fichiers ouverts s'explique par un "grand" nombres de connexions persistantes établies par nos utilisateurs.
Creusons avec ss
(ss -tapn | grep -E ":(389|636)" | grep -v 'LISTEN' | awk '{print $5;}' | cut -d ':' -f 1 | sort | uniq -c
, par exemple) : très peu de connexions en attente de fermeture, les connexions sont réparties donc ce n'est pas un serveur qui s'est emballé. Un grand nombre de connexions n'est pas étonnant vu les différents éléments susceptibles de les déclencher (site web, authentification RADIUS, authentification GNU/linux, mapping UID/GID sur les montages NFS/CIFS par les machines GNU/Linux, etc.).
À combien est positionnée la limite du nombre de fichiers ouverts pour le processus slapd ? (16769 est l'identifiant du processus)
$ grep -i "open files" /proc/16769/limits
Max open files 1024 4096 files
Ha, oui, nous en sommes vraiment très proche de la limite soft…
À partir de là, nous avons plusieurs possibilités dont l'augmentation de la limite ou réduire le timeout après inactivité TCP.
Par simplicité (je n'ai pas vraiment envie de tuner mon sous-système TCP pour un service si banal), j'ai choisi la première option.
Changer ce genre de limite a toujours été une plaie. /etc/security/limits.conf
ne fonctionne pas, et, en général, on se contente d'utiliser la commande ulimit
dans le script d'init.
Systemd permet de positionner plus facilement ce genre de limites :
mkdir /etc/systemd/system/slapd.service.d/
Dans /etc/systemd/system/slapd.service.d/override.conf
, saisir :
[Service]
LimitNOFILE=2048
systemctl daemon-reload
systemctl restart slapd
grep -i "open files" /proc/27079/limits
Max open files 2048 2048 files
Notes :
systemctl edit slapd
;for i in $(seq 1 500); do telnet ldap.exemple 389 & done
. Pour arrêter les connexions : killall -9 telnet
.