## 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 nginx ou ps -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 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 auto sauf 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 , puis sudo 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 , hey ou k6 . Exemple avec wrk :

# 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 
 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 -s ou dmesg peuvent montrer des pertes; augmentez somaxconn et validez le backlog du listen si nécessaire.

- Saturation CPU TLS : baseline openssl speed vs 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_timeout trop bas, ports éphémères épuisés lors d’un proxy vers de nombreux hôtes.

- Actions : confirmer la santé amont ( curl http://<upstream>:/health ), augmenter modérément proxy_connect_timeout (ex. 1 s -> 3 s), élargir ip_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_timeout trop court pour des endpoints lents, saturation amont ou problèmes réseau.

- Actions : profiler les endpoints lents, calibrer proxy_read_timeout par 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 , valider listen ... backlog= s’il est défini explicitement, envisager reuseport aprè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_buffering pour les endpoints en streaming, fixer client_max_body_size avec discernement, ajuster proxy_buffers et proxy_busy_buffers_size , vérifier la politique de swap.

 Notes pour conteneurs et Kubernetes

- Docker : définir --ulimit nofile=200000:200000 ou via compose, s’assurer que les sysctl de l’hôte correspondent.

- Kubernetes : définir containerSecurityContext allowPrivilegeEscalation: false et readOnlyRootFilesystem: true si applicable; ajuster les FDs via hostConfig ou 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_connections dimensionné à l’objectif

- Définir worker_rlimit_nofile et LimitNOFILE systemd

- 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.