Intro
La planification de capacité pour Nginx consiste à traduire un objectif de performance en changements de configuration et d’infrastructure sûrs et observables. Ce guide montre comment inventorier votre environnement, dimensionner les paramètres clés (workers, connexions, descripteurs de fichiers, timeouts), vérifier avec des tests de charge et se remettre des défaillances courantes — en avançant par petits pas réversibles, avec des exemples concrets.
Pour qui : développeurs, SRE et équipes DevOps qui exploitent Nginx comme proxy inverse, terminateur TLS ou serveur de contenu statique sur Linux, en conteneur ou sur Kubernetes. Les espaces réservés comme <HOST>, <ENV> et <PATH> sont intentionnels; ne collez jamais de secrets, jetons ou identifiants privés.
Inventaire de la version et de l’environnement
Commencez par observer, pas par modifier. Notez ce qui tourne, où, et comment c’est compilé.
- Portée prise en charge : Nginx open source 1.14+ (la plupart des commandes s’appliquent également aux versions LTS et mainline plus récentes).
- Topologies couvertes : terminaison TLS en bordure, proxy inverse vers des serveurs d’applications en amont, service d’actifs statiques, et déploiements en conteneur/Kubernetes lorsque pertinent pour les limites et la reprise.
- Identifier l’exécutable exact et les modules
# Capturer la version de Nginx, les drapeaux du compilateur et les modules liés
TZ=UTC date -Is
nginx -V 2>&1 | tee /tmp/nginx-version-<ENV>.txt
# Valider la configuration (lecture seule)
nginx -t
- Cartographier le déploiement
- OS/hôte et noyau :
uname -a,/etc/os-release - Gestionnaire de processus :
systemctl status nginxoups -eo pid,cmd | grep nginx - Ports à l’écoute :
ss -tanp | grep -E ':(80|443)\s' - Déchargement TLS : vérifiez que les chemins des certificats/cles existent et que la propriété est correcte (ne copiez jamais leur contenu dans vos notes).
- Topologie amont : nombre de serveurs upstream par service, statut du réemploi de connexions (keepalive) et tailles moyennes de réponse.
- Établir les limites de ressources de base (lecture seule)
# Limite de descripteurs de fichiers au niveau du processus
sudo -u <nginx_user> sh -c 'ulimit -n; echo $PPID' # ou via systemd LimitNOFILE
# Plafond global des FDs et résumé des sockets
cat /proc/sys/fs/file-max
ss -s
# Threads par worker et RSS (sanité)
ps -o pid,psr,pcpu,pmem,rss,cmd -C nginx
- Définir l’objectif et le signal d’échec avant tout changement
- Exemple d’objectif : pic de 2 000 RPS avec p95 < 150 ms en TLS, proxy inverse vers 4 upstreams.
- Signaux principaux : taux de 5xx, taux de 499, erreurs d’accept Nginx, débordement de file/backlog, CPU > 85 % soutenu, pression mémoire, saturation dans
stub_status.
Chemin de configuration sûr
Planifiez le plus petit changement justifié. Gardez un retour arrière prêt. Testez d’abord en préproduction.
Principes clés de dimensionnement
- worker_processes : en général égal au nombre de cœurs CPU. Utilisez
autosauf raison contraire. - worker_connections : borne supérieure des connexions concurrentes par worker (inclut client et amont). En proxy inverse, une requête consomme typiquement une connexion client + une connexion amont.
- Concurrency effective en proxy ≈ (worker_processes × worker_connections) / 2 (règle empirique; tampons, keepalive et sockets inactifs l’influencent).
- Les descripteurs de fichiers (FD) doivent couvrir tous les sockets concurrents. Prévoyez 2× les connexions proxifiées concurrentes, plus 10–20 % de marge pour les logs, fichiers et sockets de contrôle.
Exemple de changement à risque minimal
Prérequis
- Nginx 1.14+ sur Linux, géré par systemd.
- Objectif : supporter ~16 k connexions proxifiées concurrentes sur un hôte 4 vCPU avec TLS.
- Périmètre d’impact : une seule instance Nginx sur <HOST>. Reprise : retour arrière de conf et rechargement immédiats.
Correctif proposé (extraits)
# /etc/nginx/nginx.conf (extraits)
user nginx;
worker_processes auto; # 4 sur un hôte 4 vCPU
worker_rlimit_nofile 200000; # autoriser un grand nombre de FDs dans les workers
events {
worker_connections 8192; # 4 workers * 8192 ~= 32768 connexions totales
multi_accept on;
# n'envisager reuseport qu'après tests par noyau/stack
# utiliser listen 443 reuseport; dans les blocs server si adopté
}
http {
# Keepalive : meilleur rendement CPU mais consomme des FDs
keepalive_timeout 15s;
keepalive_requests 1000;
# Réglages de proxy inverse (exemple)
upstream app_backend {
server 10.0.0.11:8080;
server 10.0.0.12:8080;
keepalive 256; # pool de réemploi des connexions amont
}
server {
listen 443 ssl http2; # HTTP/2 améliore le multiplexage, ajoute du coût CPU
server_name <HOSTNAME>;
ssl_certificate /etc/ssl/certs/<cert>.pem;
ssl_certificate_key /etc/ssl/private/<key>.pem;
location /api/ {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection ""; # permet le keepalive amont
proxy_read_timeout 30s; # aligner avec le SLO de l'app
proxy_send_timeout 30s;
proxy_connect_timeout 5s;
}
}
}
Limites OS à aligner
# Plafond global des FDs et limite par service (exemple systemd)
# /etc/systemd/system/nginx.service.d/limits.conf
[Service]
LimitNOFILE=200000
# Recharger systemd et redémarrer avec grâce pendant une fenêtre de maintenance
sudo systemctl daemon-reload
sudo systemctl restart nginx
# Files noyau et backlog
sudo sysctl -w net.core.somaxconn=8192
sudo sysctl -w net.ipv4.ip_local_port_range="20000 65000" # pour un fort fan-out sortant
Vérification
nginx -t
sudo nginx -s reload
ss -tan 'sport = :443' | wc -l
journalctl -u nginx -n 100 --no-pager | grep -i -E 'error|crit|alert'
Retour arrière
- Conservez une copie de la précédente
nginx.conf(ex./etc/nginx/nginx.conf.bak-<ts>). - Pour revenir en arrière : restaurez le fichier,
nginx -t, puissudo nginx -s reload.
Vérification et diagnostics
Observez d’abord, puis mettez sous pression.
Vérifications de santé en lecture seule
# Dump de configuration pour audit
nginx -T > /tmp/nginx-conf-<ENV>.txt
# Statut léger (stub_status)
# À ajouter dans un bloc protégé (réseau interne/admin uniquement)
# location /nginx_status { stub_status; allow 127.0.0.1; deny all; }
curl -s http://127.0.0.1/nginx_status
# Attendu : Active connections, accepts/handled/requests, Reading/Writing/Waiting
Procédure de test de charge (exemple)
Prérequis : environnement de staging qui reflète les limites de prod, un client proche du serveur, et un jeu de données réaliste.
- Outils suggérés :
wrk,vegeta,heyouk6. Exemple avecwrk:
# 2k RPS pendant 5 minutes avec 200 connexions, HTTP/1.1 keepalive
wrk -t8 -c200 -d300s --rate 2000 https://<HOST>/api/test
- Signal de réussite : RPS cible avec latence stable et taux d’erreur < 0,5 %.
- À collecter pendant le test :
top,mpstat -P ALL 5,iostat -xz 5,ss -s,curl /nginx_status.
Ce qu’il faut surveiller
- 502/504 en hausse : saturation ou timeouts côté amont.
- 499 (client closed request) : impatience client, timeout d’idle du load balancer plus court que Nginx/amont, ou handshake TLS lent sous pression CPU.
- Débordements de file d’accept :
netstat -soudmesgpeuvent montrer des pertes; augmentezsomaxconnet validez le backlog dulistensi nécessaire. - Saturation CPU TLS : baseline
openssl speedvs CPU serveur; envisagez la reprise de session et des courbes ECDHE avec support matériel.
Exemple de calcul simple de dimensionnement
- 4 workers × 8192 worker_connections = 32 768 connexions totales.
- En proxy inverse, on utilise typiquement 2 sockets par requête en vol; plafond effectif de concurrence ≈ 16 384.
- Assurez-vous que les FDs > 2 × 16 384 × 1,2 de marge ≈ 39 322; 200 000 offre une réserve suffisante.
- Avec un p95 amont de 100 ms, un seul worker peut souvent soutenir des milliers de RPS; confirmez par tests.
Modes de défaillance et reprise
Signaux de défaillance courants, causes probables et réponses sûres.
- 502 Bad Gateway
- Causes : processus amont en panne, échec DNS,
proxy_connect_timeouttrop bas, ports éphémères épuisés lors d’un proxy vers de nombreux hôtes. - Actions : confirmer la santé amont (
curl http://<upstream>:<port>/health), augmenter modérémentproxy_connect_timeout(ex. 1 s -> 3 s), élargirip_local_port_range, et monter en capacité des upstreams. - Reprise : revenir au timeout précédent si le SLO de latence se dégrade après le changement.
- 504 Gateway Timeout
- Causes :
proxy_read_timeouttrop court pour des endpoints lents, saturation amont ou problèmes réseau. - Actions : profiler les endpoints lents, calibrer
proxy_read_timeoutpar location (ne pas l’augmenter globalement sans besoin), ajouter cache ou mise en file côté amont.
- 499 Client Closed Request
- Causes : impatience client, timeout d’idle du load balancer plus court que Nginx/amont, ou handshake TLS ralenti par la CPU.
- Actions : aligner les timeouts (LB > Nginx > amont), réduire la taille des charges utiles, activer le keepalive, optimiser les paramètres TLS.
- Saturation de la file/backlog d’accept
- Symptômes : hausse des pertes de SYN backlog, latence qui grimpe en pic.
- Actions : augmenter
net.core.somaxconn, validerlisten ... backlog=<n>s’il est défini explicitement, envisagerreuseportaprès benchmark.
- Pression mémoire / sorties de workers
- Causes : RAM insuffisante pour les tampons, grandes réponses en vol, ou logs volumineux.
- Actions : réduire
proxy_bufferingpour les endpoints en streaming, fixerclient_max_body_sizeavec discernement, ajusterproxy_buffersetproxy_busy_buffers_size, vérifier la politique de swap.
Notes pour conteneurs et Kubernetes
- Docker : définir
--ulimit nofile=200000:200000ou via compose, s’assurer que les sysctl de l’hôte correspondent. - Kubernetes : définir
containerSecurityContextallowPrivilegeEscalation: falseetreadOnlyRootFilesystem: truesi applicable; ajuster les FDs viahostConfigou scripts d’initialisation; Nginx Ingress Controller a ses propres réglages — ne modifiez que ceux qui servent votre objectif (ex.max-worker-connections).
Liste de contrôle opérationnelle
Utilisez-la comme runbook reproductible pour un hôte ou un pod.
- Définir le SLO et la cible de pic (RPS, latence de queue, budget d’erreurs).
- Inventorier
nginx -V,nginx -t,nginx -T(vers un fichier horodaté)- OS/noyau, cœurs CPU, mémoire, gestionnaire de processus
- FDs actuels :
ulimit -n,cat /proc/sys/fs/file-max - Observer la ligne de base sous charge
- Activer et sécuriser
stub_status - Relever CPU, mémoire, stats de sockets, taux 4xx/5xx et 499
- Planifier un changement minimal
worker_processes auto,worker_connectionsdimensionné à l’objectif- Définir
worker_rlimit_nofileetLimitNOFILEsystemd - Calibrer keepalive et timeouts de proxy pour votre app
- OS :
somaxconn,ip_local_port_range - Vérifier en sécurité
nginx -t;sudo nginx -s reload- Test de charge avec RPS et charges utiles réalistes
- Comparer les métriques aux signaux attendus
- Décider de l’étape suivante
- Si lié au CPU : scale-out (plus de pods/instances), optimiser TLS, activer du cache
- Si lié aux FDs/connexions : augmenter prudemment les limites ou décharger les connexions inactives (keepalive plus court)
- Si lié aux upstreams : ajouter des réplicas, réduire la concurrence par connexion, mettre en cache ou shard
- Documenter
- Configuration finale, limites et chemin de reprise en contrôle de version
Conclusion
La planification de capacité Nginx fonctionne le mieux lorsqu’elle est observable, incrémentale et réversible. Commencez par un inventaire, fixez une cible claire, changez un seul paramètre à la fois avec un périmètre d’impact connu, puis vérifiez chaque étape via tests de charge et signaux de statut. Alignez les limites Nginx avec celles de l’OS et des conteneurs, dimensionnez pour les sockets client et amont, et gardez un retour arrière prêt. Ce cycle discipliné — observer, ajuster, vérifier, reprendre — construit une exploitation sûre, sans surprises.