E-NO
Surveillance Nginx 9 min de lecture

Surveillance et alertes Nginx avec exemples pratiques

calendar_today Publié : 2026-07-26
update Dernière mise à jour : 2026-07-26
analytics Efficacité SEO : 97%
Illustration du guide technique pour « Surveillance et alertes Nginx avec exemples pratiques ».

Introduction

Nginx est souvent la porte d'entrée de votre application. Lorsqu'il ralentit ou tombe en panne, tout semble indisponible. Ce guide montre quoi surveiller, les métriques et signaux de logs qui comptent, des règles d'alerte concrètes, des tableaux de bord qui répondent vite aux questions d'astreinte, et un workflow d'incident utilisable sous pression. Il se termine par un pilote local étroit et mesurable que vous pouvez exécuter de bout en bout avant tout déploiement.

Vue d'ensemble du workflow

Un workflow clair et reproductible garde les changements de surveillance sûrs et ciblés :

  1. Objectifs et périmètre
  • Définir les questions principales à résoudre en quelques minutes : Nginx est-il up ? Les clients échouent-ils (4xx/5xx) ? Une défaillance amont cause-t-elle des 502/504 ? La latence ou la capacité est-elle le problème ?
  • Choisir un petit ensemble de signaux par question : métriques pour la disponibilité/la capacité, logs pour les codes de statut et la latence.
  1. Instrumentation
  • Activer le statut Nginx pour les métriques de connexions (stub_status).
  • Exporter les métriques vers Prometheus via nginx-prometheus-exporter.
  • Collecter et parser les logs d'accès pour les codes de statut et la latence.
  1. Visualisation
  • Construire un tableau de bord Vue d'ensemble pour l'astreinte : santé, connexions, taux de requêtes, taux d'erreurs, latence, et principaux contrevenants.
  1. Alerting
  • Pager sur les symptômes qui affectent les utilisateurs (taux 5xx, Nginx down).
  • Créer un ticket sur les tendances de capacité (connexions actives en hausse, approchant les limites).
  • Router vers les propriétaires avec contexte et lien vers le runbook.
  1. Réponse aux incidents
  • Utiliser un arbre de décision simple : erreurs côté client vs erreurs serveur vs erreurs amont vs problèmes TLS.
  • Documenter et tester les étapes de rollback et de rechargement sécurisé.

Ce qu'il faut surveiller dans Nginx

Santé et capacité de base

  • Disponibilité : processus up, exporter up.
  • Connexions : actives, en lecture, en écriture, en attente.
  • Débit : requêtes par seconde (approximé via les deltas accepted/handled).
  • Succès du rechargement de configuration et continuité de l'uptime.

Qualité du trafic

  • Taux d'erreurs : 5xx et 4xx depuis les logs d'accès.
  • Erreurs amont : 502, 503, 504.
  • Déconnexions client : 499.
  • Latence : request_time, upstream_response_time depuis les logs.

Hygiène sécurité et TLS

  • Expiration des certificats TLS pour les endpoints publics (sonde via Blackbox exporter).

Contexte plateforme

  • Saturation hôte : CPU, mémoire, descripteurs de fichiers, réseau.

Métriques à collecter (Nginx standard)

Depuis nginx-prometheus-exporter (scrapant stub_status) :

  • nginx_connections_active
  • nginx_connections_reading
  • nginx_connections_writing
  • nginx_connections_waiting
  • nginx_connections_accepted
  • nginx_connections_handled
  • nginx_up

Métriques hôte (node exporter ou équivalent) :

  • node_filesystem_avail_bytes, node_network_receive_bytes_total, node_load1, node_cpu_seconds_total, utilisation des descripteurs de fichiers.

Note Kubernetes Ingress Si vous utilisez le Nginx Ingress Controller, privilégiez ses métriques natives telles que : nginx_ingress_controller_requests, nginx_ingress_controller_nginx_process_connections, et les buckets d'histogramme pour la latence quand disponibles.

Logs à collecter et parser

Utilisez un format de log qui émet le statut, request_time et upstream_response_time. Exemple :

log_format main 'remote=$remote_addr host=$host method=$request_method uri=$request_uri '
  'status=$status bytes=$body_bytes_sent referer=$http_referer '
  'ua=$http_user_agent rt=$request_time urt=$upstream_response_time';
access_log /var/log/nginx/access.log main;

Parsez en labels et champs numériques pour :

  • status (ex. 200, 499, 502, 504)
  • request_time (secondes)
  • upstream_response_time (secondes ; peut être - si pas d'amont)
  • host, préfixe d'uri, méthode (pour les vues top-N)

Exemples d'alertes qui comptent

Exemples Prometheus (exporter Nginx standard) :

# Processus Nginx ou exporter down
- alert: NginxDown
  expr: up{job="nginx"} == 0
  for: 1m
  labels:
    severity: page
  annotations:
    summary: Nginx down sur {{ $labels.instance }}

- alert: NginxExporterDown
  expr: up{job="nginx-exporter"} == 0
  for: 2m
  labels:
    severity: ticket
  annotations:
    summary: Exporter Nginx down sur {{ $labels.instance }}

# Connexions actives au-dessus du seuil de base pour une période soutenue
# Calibrez ce seuil par hôte : observez nginx_connections_active une semaine, alertez à ~80 % du pic observé
- alert: NginxHighActiveConnections
  expr: nginx_connections_active > 500
  for: 5m
  labels:
    severity: ticket
  annotations:
    summary: Connexions actives élevées sur {{ $labels.instance }}

# Accepted moins handled indique des connexions perdues
- alert: NginxConnectionDrops
  expr: rate(nginx_connections_accepted[5m]) - rate(nginx_connections_handled[5m]) > 0
  for: 2m
  labels:
    severity: page
  annotations:
    summary: Perte de connexions sur {{ $labels.instance }} en augmentation

Si vous utilisez le Nginx Ingress Controller, vous pouvez aussi alerter sur les codes HTTP directement depuis les métriques :

- alert: IngressHigh5xxRate
  expr: sum by (ingress) (rate(nginx_ingress_controller_requests{status=~"5.."}[5m])) > 5
  for: 5m
  labels:
    severity: page
  annotations:
    summary: Taux 5xx élevé sur l'ingress {{ $labels.ingress }}

Exemple Loki Ruler (5xx basé sur les logs pour Nginx standard) :

# En supposant que promtail extrait un label 'status' depuis les logs d'accès
- alert: NginxHigh5xxFromLogs
  expr: sum(rate({job="nginx_access", status=~"5.."}[5m])) > 5
  for: 5m
  labels:
    severity: page
  annotations:
    summary: Taux 5xx élevé dans les logs Nginx

Expiration TLS avec Blackbox exporter :

- alert: TLSSoonToExpire
  expr: (probe_ssl_earliest_cert_expiry - time()) < 14 * 24 * 3600
  for: 0m
  labels:
    severity: ticket
  annotations:
    summary: Certificat TLS expire bientôt sur {{ $labels.instance }}

Tableaux de bord qui répondent aux questions d'astreinte

Vue d'ensemble (premier écran)

  • Nginx up, exporter up
  • Connexions actives avec états : lecture, écriture, attente
  • Requêtes par seconde (dérivé des deltas accepted/handled)
  • Taux d'erreurs : 5xx, 4xx depuis les logs
  • Latence p50, p95 depuis les logs (request_time)
  • Top URIs ou hôtes par 5xx et latence (exemple requête Loki : topk(10, sum by (uri) (rate({job="nginx_access", status=~"5.."}[5m]))))

Capacité et santé

  • Tendance connexions actives vs en attente
  • CPU, mémoire, saturation réseau du nœud
  • Perte de connexions dans le temps

Qualité du trafic

  • 499, 502, 504 au fil du temps
  • Latence amont vs latence totale (upstream_response_time vs request_time)

Chaque panneau doit comporter une description avec : unité, requête, et pourquoi c'est important. Gardez les raccourcis de plage temporelle à 5 min, 1 h, 24 h pour le triage.

Workflow de réponse aux incidents

Triage rapide

  1. Nginx est-il up ? Sinon, vérifiez le gestionnaire de service, les changements récents de config, et rechargez proprement.
  2. Le 5xx a-t-il explosé ? Si oui, regardez 502/504 pour décider si l'amont échoue ou si Nginx sature.
  3. La latence est-elle haute avec un faible taux d'erreur ? Étudiez la lenteur amont ou la saturation réseau.
  4. Le 499 est-il haut ? Les clients ferment tôt ; vérifiez les timeouts, le comportement CDN, et les endpoints à queue longue.

Patterns de correction

  • Nginx down : valider la config, puis recharger.
  nginx -t
  systemctl reload nginx
  # ou : nginx -s reload
  • Connexions actives élevées : augmenter worker_connections (ex. de 1024 à 4096), revoir keepalive_timeout (défaut 75 s, envisager 30 s pour fort trafic), et vérifier la capacité amont.
  • 502/504 : contrôler la santé amont, la résolution DNS, proxy_connect_timeout / proxy_read_timeout / proxy_send_timeout, et les keepalive entre Nginx et les upstreams (proxy_http_version 1.1; proxy_set_header Connection "\);).
  • 5xx élevé depuis l'appli : router l'erreur vers les propriétaires d'appli avec les top endpoints depuis les logs.
  • Expiration TLS : renouveler, déployer, et vérifier avec la sonde blackbox.

Suivi post-incident

  • Documenter le déclencheur, le signal le plus fort, et le changement unique qui a résolu.
  • Ajouter ou ajuster une alerte ou un tableau de bord pour éviter la récurrence.

Plan de pilote local

Objectif : prouver qu'on peut voir la santé, les erreurs et la capacité en local. Restez étroit et mesurable.

Ce que vous allez lancer

  • Nginx avec stub_status et un log d'accès émettant statut et latence
  • nginx-prometheus-exporter pour les métriques
  • Prometheus pour scraper l'exporter (et blackbox optionnel)
  • Grafana pour les tableaux de bord
  • Optionnel : Loki + Promtail pour 5xx et latence basés sur les logs

Config Nginx (Locale)

events { worker_connections 1024; }
http {
  log_format main 'remote=$remote_addr host=$host method=$request_method uri=$request_uri '
    'status=$status bytes=$body_bytes_sent rt=$request_time urt=$upstream_response_time';
  access_log /var/log/nginx/access.log main;

  server {
    listen 80;
    location / {
      return 200 'ok';
    }
    location /nginx_status {
      stub_status;
      allow 127.0.0.1;
      deny all;
    }
  }
}

Docker Compose (Labo local)

services:
  nginx:
    image: nginx:1.25
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./logs:/var/log/nginx
    ports:
      - '8080:80'

  exporter:
    image: nginxinc/nginx-prometheus-exporter:0.11.0
    command: ['-nginx.scrape-uri', 'http://nginx/nginx_status']
    ports:
      - '9113:9113'
    depends_on: [nginx]

  prometheus:
    image: prom/prometheus:v2.54.0
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./alerts.yml:/etc/prometheus/alerts.yml:ro
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--web.enable-lifecycle'
    ports:
      - '9090:9090'
    depends_on: [exporter]

  grafana:
    image: grafana/grafana:11.0.0
    ports:
      - '3000:3000'
    depends_on: [prometheus]

  loki:
    image: grafana/loki:2.9.0
    command: ['-config.file=/etc/loki/local-config.yaml']
    volumes:
      - ./loki.yaml:/etc/loki/local-config.yaml:ro
    ports:
      - '3100:3100'

  promtail:
    image: grafana/promtail:2.9.0
    volumes:
      - ./promtail.yaml:/etc/promtail/config.yml:ro
      - ./logs:/var/log/nginx:ro
    command: ['--config.file=/etc/promtail/config.yml']
    depends_on: [loki]

prometheus.yml

scrape_configs:
  - job_name: nginx
    static_configs:
      - targets: ['exporter:9113']

rule_files:
  - /etc/prometheus/alerts.yml

alerts.yml

groups:
  - name: nginx-basic
    rules:
      - alert: NginxDown
        expr: up{job="nginx"} == 0
        for: 1m
        labels: {severity: "page"}
        annotations: {summary: "Nginx down"}

      - alert: NginxHighActiveConnections
        expr: nginx_connections_active > 50
        for: 2m
        labels: {severity: "ticket"}
        annotations: {summary: "Connexions actives élevées"}

      - alert: NginxConnectionDrops
        expr: rate(nginx_connections_accepted[5m]) - rate(nginx_connections_handled[5m]) > 0
        for: 2m
        labels: {severity: "page"}
        annotations: {summary: "Perte de connexions en augmentation"}

promtail.yaml (extraire statut et latence en labels/champs)

server:
  http_listen_port: 9080
positions:
  filename: /tmp/positions.yaml
clients:
  - url: http://loki:3100/loki/api/v1/push
scrape_configs:
  - job_name: nginx_access
    static_configs:
      - targets: ['localhost']
        labels:
          job: nginx_access
          __path__: /var/log/nginx/access.log
    pipeline_stages:
      - regex:
          expression: '.*status=(?P<status>\d{3}).*rt=(?P<rt>[0-9.]+).*urt=(?P<urt>[0-9.\-]+)'
      - labels:
          status:

Test de fumée

  • Ouvrez Grafana à http://localhost:3000 et ajoutez Prometheus à http://prometheus:9090 comme source de données.
  • Créez un panneau rapide avec nginx_connections_active.
  • Générez de la charge : for i in {1..100}; do curl -s http://localhost:8080/; done
  • Confirmez que les alertes se déclenchent dans Prometheus pour les connexions actives élevées si vous augmentez la charge.
  • Si vous utilisez Loki, construisez un panneau avec la requête : {job="nginx_access"} et ajoutez un panneau stat affichant le taux 5xx : sum(rate({job="nginx_access", status=~"5.."}[5m])).

Critères de sortie du pilote

  • Vous voyez Nginx up, les connexions, et une tendance claire des requêtes.
  • Une hausse de 5xx depuis les logs est visible en quelques minutes.
  • Trois alertes se déclenchent dans des conditions contrôlées et s'arrêtent quand la condition disparaît.

Conclusion

Commencez par un pilote local qui prouve que vous pouvez observer la disponibilité, la capacité et les signaux d'erreur. Gardez les seuils proches de votre ligne de base et ne promouvez que ce que vous avez testé. Étendez ensuite à la santé amont, les percentiles de latence, et les vérifications TLS comme prochaines étapes. Documentez comment trier Nginx vs amont, et gardez les commandes de rechargement et de rollback prêtes.

Score de qualité de l’article

Utilité pour le lecteur 97%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO