Skip to main content

Déploiement Grafana/Prometheus

Déploiement Prometheus + Grafana + Exporters - Guide Complet

Date : 28 Novembre 2025
Environnement : AlmaLinux 10, Podman rootless
Infrastructure : VPS OVH avec monitoring complet des services


Table des matières

  1. Architecture finale
  2. Stack de monitoring déployée
  3. Déploiement Prometheus & Grafana
  4. Configuration des exporters
  5. Configuration Nginx reverse proxy
  6. Dashboard Grafana
  7. Problèmes rencontrés et solutions
  8. Commandes de maintenance
  9. Ressources

Architecture finale

┌─────────────────────────────────────────────────────────┐
│                    VPS AlmaLinux 10                     │
│                                                          │
│  ┌──────────────────────────────────────────────────┐   │
│  │           Conteneurs Podman (rootless)           │   │
│  │                                                  │   │
│  │  ┌──────────────┐    ┌──────────────┐           │   │
│  │  │  Prometheus  │◄───│   Grafana    │           │   │
│  │  │  :9091       │    │   :3000      │           │   │
│  │  └──────┬───────┘    └──────────────┘           │   │
│  │         │                                        │   │
│  │         ├──► Node Exporter (:9100)               │   │
│  │         └──► Autres conteneurs                   │   │
│  └──────────────────────────────────────────────────┘   │
│                                                          │
│  ┌──────────────────────────────────────────────────┐   │
│  │        Services système (hôte)                   │   │
│  │                                                  │   │
│  │  • Podman Exporter (:9882)                       │   │
│  │  • Podman API (socket rootless)                  │   │
│  │  • Nginx reverse proxy                           │   │
│  └──────────────────────────────────────────────────┘   │
│                                                          │
│  ┌──────────────────────────────────────────────────┐   │
│  │             Accès externe HTTPS                  │   │
│  │                                                  │   │
│  │  grafana.sanjyasz.pro → Nginx → Grafana         │   │
│  └──────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────┘

Stack de monitoring déployée

Services déployés

Service Type Port Description
Prometheus Conteneur 9091 Collecte et stockage des métriques
Grafana Conteneur 3000 Visualisation et dashboards
Node Exporter Conteneur 9100 Métriques système (CPU, RAM, disque)
Podman Exporter Systemd user 9882 Métriques des conteneurs Podman
Podman API Systemd user Socket API Podman pour l'exporter
Nginx Système 80/443 Reverse proxy HTTPS

Services monitorés

  • Jenkins (conteneur)
  • HashiCorp Vault (conteneur)
  • BookStack (conteneur)
  • Prometheus (auto-monitoring)
  • Grafana (auto-monitoring)
  • Système hôte (via Node Exporter)

Déploiement Prometheus & Grafana

Structure des fichiers

~/monitoring/
├── docker-compose.yml
├── prometheus/
│   ├── config/
│   │   └── prometheus.yaml
│   └── data/                    # Volume Podman
└── grafana/
    ├── data/                    # Volume Podman
    └── provisioning/
        └── datasources/
            └── prometheus.yml

Création de la structure

mkdir -p ~/monitoring/{prometheus/config,grafana/provisioning/datasources}
cd ~/monitoring

Configuration Prometheus

Fichier prometheus/config/prometheus.yaml :

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  # Prometheus auto-monitoring
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Node Exporter (système)
  - job_name: 'node_exporter'
    static_configs:
      - targets: ['host.containers.internal:9100']

  # Podman Exporter (conteneurs)
  - job_name: 'podman_exporter'
    static_configs:
      - targets: ['host.containers.internal:9882']

  # Nginx Exporter (optionnel)
  - job_name: 'nginx'
    static_configs:
      - targets: ['host.containers.internal:9113']

Points clés :

  • Utilisation de host.containers.internal au lieu de localhost pour accéder aux services de l'hôte depuis les conteneurs
  • Port 9091 exposé sur l'hôte (9090 interne au conteneur)

Configuration datasource Grafana

Fichier grafana/provisioning/datasources/prometheus.yml :

apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: false

Note : Utilisation de prometheus:9090 (résolution DNS interne Docker/Podman entre conteneurs du même réseau).

Docker Compose

Fichier docker-compose.yml :

version: '3.8'

services:
  prometheus:
    image: docker.io/prom/prometheus:latest
    container_name: prometheus
    restart: unless-stopped
    volumes:
      - ./prometheus/config:/etc/prometheus:Z
      - prometheus_data:/prometheus:Z
    command:
      - '--config.file=/etc/prometheus/prometheus.yaml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=30d'
    ports:
      - "9091:9090"
    networks:
      - monitoring

  grafana:
    image: docker.io/grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    user: "472"
    volumes:
      - grafana_data:/var/lib/grafana:Z
      - ./grafana/provisioning:/etc/grafana/provisioning:Z
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD= ******
      - GF_SERVER_ROOT_URL=https://grafana.sanjyasz.pro
      - GF_SERVER_DOMAIN=grafana.sanjyasz.pro
    ports:
      - "3000:3000"
    networks:
      - monitoring
    depends_on:
      - prometheus

  node-exporter:
    image: docker.io/prom/node-exporter:latest
    container_name: node-exporter
    restart: unless-stopped
    command:
      - '--path.rootfs=/host'
      - '--path.procfs=/host/proc'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    volumes:
      - /:/host:ro,rslave
    ports:
      - "9100:9100"
    networks:
      - monitoring

volumes:
  prometheus_data:
  grafana_data:

networks:
  monitoring:
    driver: bridge

Points importants :

  • :Z sur les volumes pour SELinux
  • user: "472" pour Grafana (UID grafana)
  • Port Prometheus changé en 9091 (9090 était utilisé par systemd)

Fix SELinux

# Appliquer les contextes SELinux
sudo chcon -R -t container_file_t ~/monitoring/

# Ou permanent
sudo semanage fcontext -a -t container_file_t "$HOME/monitoring(/.*)?"
sudo restorecon -Rv ~/monitoring/

Démarrage

cd ~/monitoring
podman-compose up -d

# Vérifier les logs
podman-compose logs -f

# Vérifier que tout tourne
podman ps

Accès

  • Prometheus : http://localhost:9091
  • Grafana : http://localhost:3000 (admin / ChangeMe123!)

Configuration des exporters

Node Exporter (conteneur)

Déjà inclus dans docker-compose.yml.

Test :

curl http://localhost:9100/metrics | grep node_

Podman Exporter (service systemd user)

Pourquoi en service systemd et pas en conteneur ?

  • Accès au socket Podman rootless difficile depuis un conteneur
  • Plus simple et stable en service système
  • Évite les problèmes de permissions complexes

La vérité vraie: j'ai juste pas réussi à faire marcher l'image prometheus-podman-exporter :D Si quelqu'un a déjà réussi à la faire marcher qu'il me dise comment svp.

Installation

# Installer depuis les dépôts AlmaLinux
sudo dnf install -y prometheus-podman-exporter

Service Podman API (prérequis)

Créer le service pour exposer l'API Podman :

mkdir -p ~/.config/systemd/user/

cat > ~/.config/systemd/user/podman-api.service << 'EOF'
[Unit]
Description=Podman API Service
Documentation=man:podman-system-service(1)
After=network.target

[Service]
Type=exec
KillMode=process
ExecStart=/usr/bin/podman system service --time=0

[Install]
WantedBy=default.target
EOF

# Activer et démarrer
systemctl --user daemon-reload
systemctl --user enable --now podman-api

# Vérifier
systemctl --user status podman-api

# Vérifier que le socket existe
ls -lah /run/user/$(id -u)/podman/podman.sock

Service Podman Exporter

cat > ~/.config/systemd/user/prometheus-podman-exporter.service << EOF
[Unit]
Description=Prometheus Podman Exporter
After=podman-api.service
Requires=podman-api.service

[Service]
Type=simple
Environment="CONTAINER_HOST=unix:///run/user/$(id -u)/podman/podman.sock"
ExecStart=/usr/bin/prometheus-podman-exporter
Restart=always
RestartSec=5

[Install]
WantedBy=default.target
EOF

# Activer et démarrer
systemctl --user daemon-reload
systemctl --user enable --now prometheus-podman-exporter

# Vérifier
systemctl --user status prometheus-podman-exporter

Test

# Métriques disponibles
curl http://localhost:9882/metrics | grep podman_container

# Vérifier dans Prometheus
curl -G http://localhost:9091/api/v1/query \
  --data-urlencode 'query=podman_container_info' | jq

Configuration Nginx reverse proxy

DNS OVH

Ajouter l'enregistrement A :

Type    Nom       Valeur          TTL
A       grafana   <IP_VPS>        3600

Certificat Let's Encrypt

Étendre le certificat existant :

sudo certbot certonly --nginx \
  -d sanjyasz.pro \
  -d www.sanjyasz.pro \
  -d vault.sanjyasz.pro \
  -d grafana.sanjyasz.pro \
  --expand

Configuration Nginx

Fichier /etc/nginx/conf.d/grafana.conf :

server {
    listen 80;
    server_name grafana.sanjyasz.pro;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name grafana.sanjyasz.pro;

    # SSL
    ssl_certificate /etc/letsencrypt/live/sanjyasz.pro/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sanjyasz.pro/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Headers sécurité
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Logs
    access_log /var/log/nginx/grafana-access.log;
    error_log /var/log/nginx/grafana-error.log;

    # Proxy vers Grafana
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

Test et activation

# Tester la configuration
sudo nginx -t

# Recharger Nginx
sudo systemctl reload nginx

# Fix SELinux si nécessaire
sudo setsebool -P httpd_can_network_connect 1

# Vérifier
curl -I https://grafana.sanjyasz.pro

Accès final

https://grafana.sanjyasz.pro

Dashboard Grafana

Connexion

  • URL : https://grafana.sanjyasz.pro
  • Login : admin
  • Password : password_de_zinzin!

Dashboard "Services Status" (custom)

Création manuelle :

  1. Menu → Dashboards → New Dashboard
  2. Add visualization
  3. Select Prometheus datasource

Query :

podman_container_info{name=~"jenkins|vault|bookstack"} * on(id) group_left(name) podman_container_state

Configuration :

  • Visualization type : Stat
  • Legend : {{name}}
  • Color mode : Background
  • Text mode : Value and name

Value mappings :

  • 1 → Text: UP ✓ → Color: Green
  • 0 → Text: DOWN ✗ → Color: Red

Résultat : Briques vertes/rouges indiquant l'état de chaque service.

Dashboards communautaires (tentative)

IDs testés mais non fonctionnels :

  • 1860 : Node Exporter Full (problème de compatibilité)
  • 15798 : Podman Container Metrics (problème de labels)
  • 19972 : Podman Exporter (problème de compatibilité)

Raison : Les dashboards communautaires attendent des labels ou métriques spécifiques qui ne correspondent pas exactement à la configuration.

Solution : Création de dashboards custom adaptés aux métriques disponibles.


Conclusion

Infrastructure monitoring complète déployée avec succès.

Points clés :

  • ✅ Prometheus + Grafana en conteneurs Podman rootless
  • ✅ Node Exporter pour métriques système
  • ✅ Podman Exporter en service systemd user (solution stable pour rootless)
  • ✅ Reverse proxy Nginx avec SSL Let's Encrypt
  • ✅ Dashboard custom pour monitoring des services critiques
  • ✅ Accès sécurisé via https://grafana.sanjyasz.pro

Stack complètement opérationnelle et prête pour la production.

Prochaines étapes possibles :

  • Ajouter Alertmanager pour les notifications
  • Configurer des alertes (services down, seuils CPU/RAM)
  • Ajouter Nginx Exporter pour monitoring web
  • Créer des dashboards additionnels
  • Automatiser les backups Grafana/Prometheus