Skip to main content

Stack Prometheus + Grafana : monitoring d'un serveur Ubuntu

Monitoring Observabilité VirtualBox Octobre 2025
3
Jobs Prometheus
15s
Scrape interval
1860
Dashboard ID
Exporter custom

🎯 Problématique
#

Dans mon travail quotidien, j’utilise Datadog et Grafana pour superviser des infrastructures critiques. L’objectif de ce projet était de reproduire cette pratique de A à Z sur un environnement de lab personnel, en déployant une stack d’observabilité open-source complète.

Contrainte : partir d’une VM vierge, sans agent pré-installé, et obtenir un dashboard opérationnel avec métriques système en temps réel, ainsi qu’un exporter de métriques Nginx personnalisé en Python.

Architecture globale :
Machine hôte (Windows) — Docker Desktop
   ├── Prometheus :9090 — scraping & stockage TSDB
   └── Grafana :3000 — visualisation

VM Ubuntu 24.04 — VirtualBox, réseau Bridge (192.168.0.41)
   ├── Node Exporter :9100 — métriques système
   ├── Nginx — serveur web cible
   └── Exporter Python custom :9101 — métriques logs Nginx

🖥️ Étape 1 — Installation et configuration de la VM
#

La cible de supervision est une VM Ubuntu 24.04.3 LTS créée sous VirtualBox.

Specs de la VM :
OS  Ubuntu 24.04.3 LTS
RAM  2 Go
Disque  20 Go
Réseau  Accès par pont (Bridge)
User  mug (groupe sudo)
IP  192.168.0.41

Après installation, configuration de base de la VM :

# Clavier en AZERTY
sudo dpkg-reconfigure keyboard-configuration
sudo setupcon
sudo systemctl restart keyboard-setup.service

# Mise à jour du système
sudo apt update && sudo apt upgrade -y

# Création de l'utilisateur et ajout au groupe sudo
sudo adduser mug
sudo usermod -aG sudo mug

# Installation des services nécessaires
sudo apt install openssh-server nginx python3-pip -y
sudo systemctl status nginx

📦 Étape 2 — Déploiement de la stack de supervision (hôte Windows)
#

La stack Prometheus + Grafana tourne sur la machine hôte Windows via Docker Desktop. L’ensemble est défini dans un docker-compose.yml dans le répertoire ~/scripts_supervision/.

mkdir ~/scripts_supervision
cd ~/scripts_supervision

docker-compose.yml
#

version: '3.8'

services:

  # Conteneur 1 : PROMETHEUS
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.path=/prometheus
    restart: unless-stopped

  # Conteneur 2 : GRAFANA
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    depends_on:
      - prometheus
    volumes:
      - grafana-storage:/var/lib/grafana
    restart: unless-stopped

volumes:
  grafana-storage:

Démarrage et vérification :

docker-compose up -d

# Vérification — les deux conteneurs doivent afficher "Up"
docker ps
📸
docker ps — conteneurs prometheus et grafana avec statut Up

⚙️ Étape 3 — Configuration Prometheus (3 jobs de scraping)
#

Le fichier prometheus.yml définit trois cibles de collecte, dont une avec un label instance personnalisé et un exporter Python custom sur le port 9101.

# prometheus/prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:

  # 1. Prometheus s'auto-supervise
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # 2. Node Exporter — métriques système de la VM Ubuntu
  - job_name: 'ubuntu-nginx-server'
    static_configs:
      - targets: ['192.168.0.41:9100']
        labels:
          instance: 'mon-serveur-ubuntu'

  # 3. Exporter Python personnalisé — métriques logs Nginx
  - job_name: 'nginx-custom-exporter'
    static_configs:
      - targets: ['192.168.0.41:9101']
        labels:
          instance: 'python-log-counter'

À ce stade : après docker-compose up -d, l'interface Prometheus sur http://localhost:9090Status → Targets affiche prometheus en UP et ubuntu-nginx-server en DOWN — normal, le Node Exporter n'est pas encore installé sur la VM.

📸
Interface Prometheus — Status → Targets : prometheus UP, ubuntu-nginx-server DOWN (attendu)

🔩 Étape 4 — Installation du Node Exporter sur la VM Ubuntu
#

Le Node Exporter expose les métriques système de la VM sur le port 9100. Il est installé manuellement comme binaire système dédié, avec son propre utilisateur.

# 1. Création de l'utilisateur système dédié (sans shell de connexion)
sudo groupadd --system node_exporter
sudo useradd -s /bin/false -r -g node_exporter node_exporter

# 2. Téléchargement de la dernière version stable
wget https://github.com/prometheus/node_exporter/releases/download/v1.10.2/node_exporter-1.10.2.linux-amd64.tar.gz

# 3. Extraction et installation du binaire
tar xvfz node_exporter-1.10.2.linux-amd64.tar.gz
sudo cp node_exporter-1.10.2.linux-amd64/node_exporter /usr/local/bin

# 4. Nettoyage des archives
rm -rf node_exporter-1.10.2.linux-amd64.tar.gz node_exporter-1.10.2.linux-amd64

# 5. Lancement (ou via service systemd)
/usr/local/bin/node_exporter &

Résultat attendu : retour dans Prometheus Status → Targets, la cible ubuntu-nginx-server passe en UP. Les métriques sont désormais collectées toutes les 15 secondes.

📸
Prometheus Targets — les 3 jobs en statut UP (prometheus, ubuntu-nginx-server, nginx-custom-exporter)

🐍 Étape 5 — Exporter Python personnalisé (port 9101)
#

En complément du Node Exporter standard, un exporter Python custom tourne sur le port 9101 pour exposer des métriques applicatives extraites des logs Nginx (nombre de requêtes, codes HTTP, etc.).

Il utilise la librairie prometheus_client et suit le format d’exposition standard de Prometheus.

# nginx_log_exporter.py — exemple de structure
from prometheus_client import start_http_server, Counter
import time, re

REQUEST_COUNT = Counter(
    'nginx_requests_total',
    'Nombre total de requêtes Nginx',
    ['method', 'status']
)

def parse_nginx_logs():
    log_pattern = re.compile(
        r'"(?P<method>\w+) .+ HTTP/\d\.\d" (?P<status>\d{3})'
    )
    with open('/var/log/nginx/access.log', 'r') as f:
        for line in f:
            m = log_pattern.search(line)
            if m:
                REQUEST_COUNT.labels(
                    method=m.group('method'),
                    status=m.group('status')
                ).inc()

if __name__ == '__main__':
    start_http_server(9101)
    while True:
        parse_nginx_logs()
        time.sleep(15)
# Installation de la librairie et lancement
pip3 install prometheus_client
python3 nginx_log_exporter.py &
📸
Navigateur sur http://192.168.0.41:9101/metrics — métriques Nginx custom au format Prometheus

📊 Étape 6 — Dashboard Grafana (Node Exporter Full — ID 1860)
#

Grafana est accessible sur http://localhost:3000 (admin / admin à la première connexion). Plutôt que de repartir de zéro, j’importe le dashboard communautaire Node Exporter Full (ID 1860), référence de l’écosystème.

Procédure d'import :
1. Ajout de la datasource Prometheus : Connections → Data sources → Add → Prometheus → URL http://prometheus:9090
2. Import du dashboard : Dashboards → Import → entrer l'ID 1860Load
3. Configuration : Name → Node Exporter - Full · Datasource → Prometheus-ProjImport

Le dashboard expose automatiquement les panels suivants, alimentés par les métriques du Node Exporter :

🔥
CPU Usage
Gauge + Time series
🧠
RAM Available
Stat + Threshold
💾
Disk I/O
Time series r/w
🌐
Network Traffic
Bytes in / out
📸
Dashboard Grafana — Node Exporter Full (ID 1860) — vue complète CPU / RAM / Disk / Network
📸
Zoom sur les métriques Nginx custom (job nginx-custom-exporter) — compteur requêtes par code HTTP

✅ Résultats & Bilan
#

3 jobs UP
Toutes les cibles actives
15s
Granularité métriques
Custom
Exporter Python actif

Ce projet reproduit en lab les pratiques d’observabilité de mon quotidien professionnel (Datadog chez Leroy Merlin, supervision OVH). Il m’a permis de comprendre le fonctionnement interne d’une stack Prometheus — le modèle pull, le format d’exposition des métriques, la configuration des scrape_configs — et de créer un exporter sur mesure plutôt que de simplement consommer un outil packagé.

Prochaines évolutions prévues :

  • Création d’un service systemd pour Node Exporter et l’exporter Python (démarrage automatique)
  • Ajout d’Alertmanager pour le routage des notifications (email / Telegram)
  • Migration de la stack vers le VPS de production pour superviser l’infrastructure réelle