Aller au contenu
Logo
Table des matières
VeryCloud
DocumentationVPS Linux

Stack de monitoring Prometheus + Grafana

Stack de monitoring Prometheus + Grafana

Mettez en place le monitoring de référence open-source : Prometheus pour collecter les métriques, Node Exporter sur chaque VPS, Grafana pour visualiser. La stack la plus utilisée au monde pour le monitoring sysadmin.

Catégorie
VPS Linux
Niveau
Avancé
Lecture
8 min
Publication
17 mai 2026

Introduction

Prometheus est devenu le standard de facto pour le monitoring : utilisé par SoundCloud (ses créateurs), CNCF, Kubernetes natif, et 90% des startups tech. Le combo gagnant :

  • Prometheus : scrape les métriques toutes les 15s, stockage TSDB efficient
  • Node Exporter : agent système (CPU, RAM, disque, réseau) sur chaque VPS
  • Grafana : visualisation et alerting
  • Alertmanager : routing des alertes (email, Discord, Slack)

Bénéfices vs des outils SaaS payants (Datadog, New Relic) :

  • Gratuit, self-hosted, chez vous
  • Pas de limite de métriques
  • Données souveraines

Prérequis

  • 1 VPS "central" pour Prometheus + Grafana (2 Go RAM)
  • N VPS à monitorer (Node Exporter)
  • Docker sur le VPS central
  • Réseau entre VPS (WireGuard recommandé)

Étape 1 : Architecture

   ┌──────────────────┐  ┌──────────────────┐
   │ VPS Web 1        │  │ VPS DB           │
   │  + Node Exporter │  │  + Node Exporter │
   │  + Nginx Exporter│  │  + MySQL Exporter│
   └────────┬─────────┘  └────────┬─────────┘
            │                     │
            └──────────┬──────────┘
                       │
              ┌────────▼────────┐
              │  VPS Central    │
              │  ┌───────────┐  │
              │  │ Prometheus│  │
              │  └───────────┘  │
              │  ┌───────────┐  │
              │  │  Grafana  │  │
              │  └───────────┘  │
              │  ┌───────────┐  │
              │  │Alertmanager│ │
              │  └───────────┘  │
              └─────────────────┘

Étape 2 : Déployer la stack centrale

sudo mkdir -p /opt/monitoring
cd /opt/monitoring
sudo nano docker-compose.yml
services:
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./alerts.yml:/etc/prometheus/alerts.yml:ro
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=90d'
      - '--web.console.libraries=/usr/share/prometheus/console_libraries'
      - '--web.console.templates=/usr/share/prometheus/consoles'
    networks:
      - monitoring

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=UnMotDePasseFort
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana_data:/var/lib/grafana
    networks:
      - monitoring
    depends_on:
      - prometheus

  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    restart: unless-stopped
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
    networks:
      - monitoring

  node_exporter:
    image: prom/node-exporter:latest
    container_name: node_exporter
    restart: unless-stopped
    pid: host
    network_mode: host
    volumes:
      - /:/host:ro,rslave
    command:
      - '--path.rootfs=/host'

volumes:
  prometheus_data:
  grafana_data:

networks:
  monitoring:

Étape 3 : Config Prometheus

sudo nano /opt/monitoring/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - alertmanager:9093

rule_files:
  - "alerts.yml"

scrape_configs:
  # Prometheus lui-même
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # VPS central (Node Exporter)
  - job_name: 'node_central'
    static_configs:
      - targets: ['host.docker.internal:9100']
        labels:
          host: 'srv-central'

  # VPS Web 1
  - job_name: 'node_web1'
    static_configs:
      - targets: ['10.66.66.2:9100']
        labels:
          host: 'srv-web-01'

  # VPS Web 2
  - job_name: 'node_web2'
    static_configs:
      - targets: ['10.66.66.3:9100']
        labels:
          host: 'srv-web-02'

  # VPS DB
  - job_name: 'node_db'
    static_configs:
      - targets: ['10.66.66.4:9100']
        labels:
          host: 'srv-db-01'
  
  # Nginx Exporter
  - job_name: 'nginx'
    static_configs:
      - targets: ['10.66.66.2:9113']
        labels:
          host: 'srv-web-01'

  # MySQL Exporter
  - job_name: 'mysql'
    static_configs:
      - targets: ['10.66.66.4:9104']
        labels:
          host: 'srv-db-01'

Étape 4 : Règles d'alerte de base

sudo nano /opt/monitoring/alerts.yml
groups:
  - name: system_alerts
    interval: 30s
    rules:
      - alert: HighCPU
        expr: 100 - (avg by(host) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU > 90% sur {{ $labels.host }}"
          description: "CPU à {{ $value }}% depuis 5 minutes."

      - alert: HighMemory
        expr: (node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100 > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "RAM > 90% sur {{ $labels.host }}"

      - alert: DiskFull
        expr: (node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) / node_filesystem_size_bytes{mountpoint="/"} * 100 > 90
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Disque > 90% sur {{ $labels.host }}"

      - alert: NodeDown
        expr: up{job=~"node_.*"} == 0
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Host {{ $labels.host }} est DOWN"

      - alert: HighLoad
        expr: node_load5 > 4
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Load > 4 sur {{ $labels.host }}"

Étape 5 : Config Alertmanager (Discord/email)

sudo nano /opt/monitoring/alertmanager.yml
global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'host']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 12h
  receiver: 'discord'

receivers:
  - name: 'discord'
    webhook_configs:
      - url: 'https://discord.com/api/webhooks/VOTRE_WEBHOOK'
        send_resolved: true

  - name: 'email'
    email_configs:
      - to: 'admin@verycloud.fr'
        from: 'monitoring@verycloud.fr'
        smarthost: 'smtp.example.com:587'
        auth_username: 'monitoring@verycloud.fr'
        auth_password: 'password'
        require_tls: true

Étape 6 : Démarrer la stack

sudo docker compose up -d
sudo docker compose ps

Vérifiez :

Étape 7 : Installer Node Exporter sur chaque VPS source

Sur chaque VPS à monitorer :

# Télécharger
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.1/node_exporter-1.8.1.linux-amd64.tar.gz
tar xvf node_exporter-1.8.1.linux-amd64.tar.gz
sudo mv node_exporter-1.8.1.linux-amd64/node_exporter /usr/local/bin/
sudo chown root:root /usr/local/bin/node_exporter

# User dédié
sudo useradd --no-create-home --shell /bin/false node_exporter
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter

Service systemd :

sudo nano /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter \
    --collector.systemd \
    --collector.processes \
    --web.listen-address=0.0.0.0:9100

Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter

Testez :

curl http://localhost:9100/metrics | head -30

Doit afficher les métriques node_cpu_seconds_total, node_memory_MemTotal_bytes, etc.

Étape 8 : Sécuriser Node Exporter

⚠️ Ne pas exposer le port 9100 publiquement (révèle de la donnée sensible). Solutions :

  1. WireGuard entre VPS (recommandé)
  2. UFW : sudo ufw allow from IP_VPS_CENTRAL to any port 9100
  3. Reverse proxy avec auth basique sur le central

Étape 9 : Ajouter Grafana

Tunnel SSH :

ssh -L 3000:127.0.0.1:3000 user@IP_VPS_CENTRAL

http://localhost:3000 → admin / UnMotDePasseFort

Datasource Prometheus

  1. Configuration → Data sources → Add data source
  2. Prometheus
  3. URL : http://prometheus:9090
  4. Save & test

Dashboard Node Exporter

  1. Dashboards → Import
  2. ID : 1860 (Node Exporter Full, le plus populaire)
  3. Datasource : Prometheus
  4. Import

Vous obtenez instantanément CPU, RAM, disque, réseau, load, processus pour tous vos VPS.

Étape 10 : Exporters additionnels

Selon vos services :

Nginx Exporter

docker run -d \
  --restart unless-stopped \
  --name nginx-exporter \
  -p 9113:9113 \
  nginx/nginx-prometheus-exporter \
  -nginx.scrape-uri=http://localhost/nginx_status

Activez stub_status dans Nginx :

server {
    listen 127.0.0.1:80;
    location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}

Dashboard Grafana : ID 12708.

MySQL Exporter

docker run -d \
  --restart unless-stopped \
  --name mysql-exporter \
  -p 9104:9104 \
  -e DATA_SOURCE_NAME='exporter:password@(localhost:3306)/' \
  prom/mysqld-exporter

Créez un user MySQL dédié :

CREATE USER 'exporter'@'localhost' IDENTIFIED BY 'password' WITH MAX_USER_CONNECTIONS 3;
GRANT PROCESS, REPLICATION CLIENT, SELECT ON *.* TO 'exporter'@'localhost';
FLUSH PRIVILEGES;

Dashboard Grafana : ID 7362.

Redis Exporter

docker run -d \
  --restart unless-stopped \
  --name redis-exporter \
  -p 9121:9121 \
  oliver006/redis_exporter \
  --redis.addr=redis://localhost:6379 \
  --redis.password=YOUR_REDIS_PASSWORD

Dashboard : ID 763.

Blackbox Exporter (HTTP/TCP probes)

Pour monitorer des URLs externes (uptime de votre site) :

docker run -d \
  --name blackbox-exporter \
  -p 9115:9115 \
  prom/blackbox-exporter

Étape 11 : Dashboards recommandés

Importer dans Grafana via Dashboards → Import :

  • 1860 : Node Exporter Full
  • 12708 : Nginx Exporter
  • 7362 : MySQL Overview
  • 763 : Redis Dashboard
  • 13639 : Loki + Promtail (logs)
  • 893 : Docker and Host
  • 9628 : PostgreSQL

Étape 12 : Alerting via Grafana (alternative à Alertmanager)

Grafana 10+ a son propre alerting natif :

  1. Alerting → Alert rules → New alert rule
  2. Query : 100 - (avg by(host) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
  3. Add contact point : Discord, Slack, Telegram, etc.
  4. Notification policy : groupage, throttling

Plus pratique qu'Alertmanager pour des setups simples.

Dépannage

Targets en DOWN dans Prometheus

http://localhost:9090/targets → vérifiez la connectivité :

curl http://IP_VPS:9100/metrics

Causes : firewall, IP fausse dans prometheus.yml, node_exporter pas démarré.

Pas de métriques dans Grafana

Vérifiez la datasource (Configuration → Data sources → test). Puis dans Explore, testez up{job="node_web1"}.

Prometheus bouffe trop d'espace

Limitez la rétention :

command:
  - '--storage.tsdb.retention.time=30d'  # au lieu de 90d

Alertes ne sont pas envoyées

sudo docker compose logs alertmanager

Testez le webhook Discord manuellement :

curl -X POST -H "Content-Type: application/json" \
  -d '{"content": "test"}' \
  https://discord.com/api/webhooks/VOTRE_WEBHOOK

Commandes utiles

# État des targets
curl http://localhost:9090/api/v1/targets

# Requêter Prometheus en CLI
curl "http://localhost:9090/api/v1/query?query=up"

# Reload de la config sans restart
curl -X POST http://localhost:9090/-/reload

# Tester les alertes
curl http://localhost:9090/api/v1/alerts

# Vérifier la config Prometheus
sudo docker run --rm -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus promtool check config /etc/prometheus/prometheus.yml

# Vérifier les règles d'alerte
sudo docker run --rm -v $(pwd)/alerts.yml:/etc/prometheus/alerts.yml \
    prom/prometheus promtool check rules /etc/prometheus/alerts.yml

Conclusion

Avec cette stack vous avez :

  • Monitoring CPU/RAM/disque/réseau/charge sur tous vos VPS
  • Alerting automatique en cas de problème
  • Dashboards visuels pour debug rapide
  • Stockage long terme des métriques (90 jours par défaut)

Pour aller plus loin :

  • Ajoutez Loki pour les logs (déjà couvert dans un autre tuto)
  • Ajoutez Tempo pour le tracing distribué
  • Migrez vers Thanos ou Cortex pour de la haute dispo Prometheus
  • Utilisez Prometheus Operator si vous passez à Kubernetes

Ressources

Rejoignez notre serveur communautaire Discord

Pour toute question, suggestion ou simplement pour discuter avec la communauté, rejoignez-nous sur Discord !

900+Membres