Skip to content

#38 — prometheus-alert

EN COURS DE DÉPLOIEMENT

Priorité: 🔴 CRITIQUE · Type: TYPE F · Conteneurs: rgz-prometheus + rgz-alertmanager · Code: config/prometheus/

Dépendances: aucune (déployer en premier)


Description

prometheus-alert regroupe deux composants indissociables : Prometheus 2.x (collecte et stockage des métriques par scraping HTTP) et Alertmanager (routage et déduplication des alertes vers les récepteurs appropriés). C'est la fondation de tout le monitoring RGZ — aucune autre catégorie de monitoring ne fonctionne sans lui. Il n'a aucune dépendance externe au sein du projet, ce qui en fait l'outil à déployer en tout premier dans la phase monitoring.

Prometheus utilise le mode pull : il scrape périodiquement (toutes les 15 secondes) chaque service qui expose un endpoint /metrics au format OpenMetrics. Côté FastAPI, la librairie prometheus-fastapi-instrumentator expose automatiquement les métriques HTTP (latence P50/P95/P99, taux d'erreur, requêtes actives). Les autres services (PostgreSQL, Redis, gateway) utilisent des exporters dédiés déployés en side-car ou sur l'hôte.

Alertmanager reçoit les alertes déclenchées par les règles Prometheus, les déduplique (une seule notification pour une alerte continue), les route selon leur sévérité (P0 → SMS Letexto immédiat, P1 → SMS + email, P2 → email uniquement), et gère les silences durant les maintenances planifiées. Les templates d'alerte sont en français, conformément aux standards du projet.

Les données Prometheus sont conservées selon la durée configurée par PROMETHEUS_RETENTION (par défaut 15 jours). Les données longue durée (>15j) sont répliquées dans TimescaleDB via les tâches de monitoring Celery (#39, #43).

Architecture Interne

Exporters (pull toutes les 15s)

    ├── rgz-api:8000/metrics          (prometheus-fastapi-instrumentator)
    ├── postgres_exporter:9187/metrics (connexions, requêtes, cache hit)
    ├── redis_exporter:9121/metrics    (used_memory, hit_rate, connected_clients)
    ├── node_exporter:9100/metrics     (CPU, RAM, disk I/O, réseau hôte)
    ├── freeradius_exporter/metrics    (auth/acct rate, rejets, sessions)
    └── rgz-gateway:9100/metrics       (nftables counters, QoS stats)


rgz-prometheus:9090

    ├── TSDB (stockage métriques — retention configurable)
    ├── Règles d'alerte (config/prometheus/alerts/*.yml)
    │     ├── infrastructure.yml  (CPU, RAM, disk, réseau)
    │     ├── radius.yml          (auth failures, sessions)
    │     ├── api.yml             (latence, error rate)
    │     ├── sla.yml             (uptime, latence probes)
    │     └── ssl.yml             (expiration certificats)

    └── Alertes déclenchées → rgz-alertmanager:9093

                    ┌──────────────┴──────────────┐
                    ▼                             ▼
           Route P0/P1                      Route P2
        SMS Letexto (immédiat)           Email SMTP (J+1)

Configuration

Variables d'environnement

VariableExempleDescription
PROMETHEUS_RETENTION15dDurée de rétention des métriques TSDB
ALERTMANAGER_SMTP_HOSTsmtp.host:587Serveur SMTP pour notifications email
ALERTMANAGER_SMTP_FROMalertes@rgz.bjAdresse expéditeur
ALERTMANAGER_RECEIVER_EMAILnoc@rgz.bjEmail destinataire NOC
ALERTMANAGER_LETEXTO_KEY...Clé Letexto pour SMS alertes
ALERTMANAGER_SMS_RECIPIENT+22997000001Numéro NOC pour SMS urgents
PROMETHEUS_EXTERNAL_URLhttp://rgz-prometheus:9090URL externe Prometheus

Fichier prometheus.yml

yaml
# config/prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s
  external_labels:
    cluster: 'rgz-production'
    region: 'benin'

rule_files:
  - "alerts/*.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['rgz-alertmanager:9093']

scrape_configs:
  - job_name: 'rgz-api'
    static_configs:
      - targets: ['rgz-api:8000']
    metrics_path: '/metrics'

  - job_name: 'postgres'
    static_configs:
      - targets: ['postgres-exporter:9187']

  - job_name: 'redis'
    static_configs:
      - targets: ['redis-exporter:9121']

  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: 'freeradius'
    static_configs:
      - targets: ['freeradius-exporter:9812']

  - job_name: 'gateway'
    static_configs:
      - targets: ['rgz-gateway:9100']

Alertes définies — Infrastructure

yaml
# config/prometheus/alerts/infrastructure.yml
groups:
  - name: infrastructure
    rules:
      - alert: HighCPU
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
        for: 5m
        labels:
          severity: P1
        annotations:
          summary: "CPU élevé sur {{ $labels.instance }}"
          description: "CPU à {{ $value }}% depuis 5min"

      - alert: HighMemory
        expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 85
        for: 2m
        labels:
          severity: P1
        annotations:
          summary: "RAM élevée sur {{ $labels.instance }}"
          description: "RAM à {{ $value }}% utilisée"

      - alert: DiskSpaceWarning
        expr: (1 - (node_filesystem_avail_bytes / node_filesystem_size_bytes)) * 100 > 80
        for: 10m
        labels:
          severity: P2
        annotations:
          summary: "Disque presque plein sur {{ $labels.instance }}"
          description: "{{ $value }}% utilisé sur {{ $labels.mountpoint }}"

Alertes définies — RADIUS & Sessions

yaml
# config/prometheus/alerts/radius.yml
groups:
  - name: radius
    rules:
      - alert: RadiusAuthFailureRate
        expr: rate(freeradius_authentication_responses_total{code="Access-Reject"}[5m]) /
              rate(freeradius_authentication_responses_total[5m]) > 0.05
        for: 2m
        labels:
          severity: P0
        annotations:
          summary: "Taux d'échec RADIUS > 5%"
          description: "{{ $value | humanizePercentage }} d'échecs d'authentification"

      - alert: SessionCountDrop
        expr: delta(rgz_active_sessions_total[5m]) / rgz_active_sessions_total < -0.3
        for: 5m
        labels:
          severity: P0
        annotations:
          summary: "Chute brutale des sessions actives (> 30%)"

Endpoints API

MéthodeRouteDescription
GEThttp://rgz-prometheus:9090/api/v1/query?query=...Requête PromQL instantanée
GEThttp://rgz-prometheus:9090/api/v1/query_range?...Requête PromQL sur plage temps
GEThttp://rgz-prometheus:9090/api/v1/alertsAlertes actives
GEThttp://rgz-prometheus:9090/-/healthyHealthcheck
GEThttp://rgz-alertmanager:9093/api/v2/alertsAlertes en cours (Alertmanager)
POSThttp://rgz-alertmanager:9093/api/v2/silencesCréer un silence maintenance

Commandes Utiles

bash
# Vérifier que Prometheus est UP
docker exec rgz-prometheus wget -qO- http://127.0.0.1:9090/-/healthy
# Réponse: Prometheus Server is Healthy.

# Vérifier Alertmanager
docker exec rgz-alertmanager wget -qO- http://127.0.0.1:9093/-/healthy

# Lister les targets scrappées et leur statut
curl -s http://127.0.0.1:9090/api/v1/targets | jq '.data.activeTargets[] | {job:.job, health:.health, lastScrape:.lastScrape}'

# Requête PromQL — CPU actuel
curl -s 'http://127.0.0.1:9090/api/v1/query?query=100-(avg(rate(node_cpu_seconds_total{mode="idle"}[5m]))*100)' | jq '.data.result'

# Lister les alertes actives
curl -s http://127.0.0.1:9090/api/v1/alerts | jq '.data.alerts[] | {name:.labels.alertname, severity:.labels.severity, state:.state}'

# Recharger la configuration Prometheus (sans restart)
curl -s -X POST http://127.0.0.1:9090/-/reload

# Logs Prometheus
docker logs rgz-prometheus -f --tail=50

# Logs Alertmanager
docker logs rgz-alertmanager -f --tail=50

# Restart stack monitoring
docker compose -f /home/claude-dev/RGZ/docker-compose.monitoring.yml restart rgz-prometheus rgz-alertmanager

Sécurité

RègleImplémentation
SEC-07Prometheus sans auth par défaut — accès restreint au réseau rgz-net uniquement (pas de port exposé publiquement)
SEC-08Connexion postgres_exporter via rôle PostgreSQL ro (lecture seule)
LL#27Logs Docker : max-size: 10m, max-file: 3 — Prometheus peut générer beaucoup de logs
LL#33restart: unless-stopped dans docker-compose.monitoring.yml
LL#43Healthchecks : wget -qO- http://127.0.0.1:9090/-/healthy (127.0.0.1 explicite)
yaml
# Fragment docker-compose.monitoring.yml
rgz-prometheus:
  image: prom/prometheus:v2.x.x
  restart: unless-stopped
  command:
    - '--config.file=/etc/prometheus/prometheus.yml'
    - '--storage.tsdb.retention.time=${PROMETHEUS_RETENTION:-15d}'
    - '--web.enable-lifecycle'
  volumes:
    - ./config/prometheus:/etc/prometheus:ro
    - prometheus_data:/prometheus
  healthcheck:
    test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:9090/-/healthy || exit 1"]
    interval: 30s
    timeout: 10s
    retries: 3
  logging:
    driver: "json-file"
    options:
      max-size: "10m"
      max-file: "3"
  networks:
    - rgz-net

Implémentation TODO

  • [x] Services rgz-prometheus et rgz-alertmanager dans docker-compose.monitoring.yml
  • [ ] config/prometheus/prometheus.yml — configuration scrape complète (6 targets)
  • [ ] config/prometheus/alerts/infrastructure.yml — CPU, RAM, disk
  • [ ] config/prometheus/alerts/radius.yml — auth failures, sessions
  • [ ] config/prometheus/alerts/api.yml — latence P95, error rate
  • [ ] config/prometheus/alerts/sla.yml — uptime targets
  • [ ] config/prometheus/alerts/ssl.yml — expiration certificats
  • [ ] config/prometheus/alertmanager.yml — routes P0/P1/P2 + templates
  • [ ] Déployer postgres_exporter en side-car dans docker-compose
  • [ ] Déployer redis_exporter en side-car
  • [ ] Déployer node_exporter sur l'hôte
  • [ ] Configurer prometheus-fastapi-instrumentator dans app/main.py
  • [ ] Tester les alertes avec amtool (alertmanager CLI)
  • [ ] Documenter les silences de maintenance planifiés

Dernière mise à jour: 2026-02-21

PROJET MOSAÏQUE — 81 outils, 22 conteneurs, 500+ revendeurs WiFi Zone