Monitoring avec Prometheus et Grafana
Un serveur sans monitoring, c'est voler à l'aveugle. Prometheus + Grafana est le standard de facto open source pour surveiller votre infrastructure.
Architecture
Applications / Serveurs
↓ métriques (pull)
Prometheus (collecte + stockage)
↓ requêtes PromQL
Grafana (visualisation)
↓ alertes
AlertManager → Slack / Email
Installation avec Docker Compose
# docker-compose.monitoring.yml
version: '3.9'
services:
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
ports:
- "9090:9090"
grafana:
image: grafana/grafana:latest
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana-data:/var/lib/grafana
ports:
- "3000:3000"
depends_on:
- prometheus
node-exporter:
image: prom/node-exporter:latest
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--collector.filesystem.ignored-mount-points=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- "9100:9100"
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
volumes:
- /:/rootfs:ro
- /var/run:/var/run:rw
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
volumes:
prometheus-data:
grafana-data:
Configuration Prometheus
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
rule_files:
- "alerts/*.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
relabel_configs:
- source_labels: [__address__]
target_label: instance
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'laravel'
static_configs:
- targets: ['app:9001']
metrics_path: '/metrics'
Métriques Laravel avec Prometheus
composer require spatie/laravel-prometheus
php artisan vendor:publish --provider="Spatie\LaravelPrometheus\LaravelPrometheusServiceProvider"
// Métriques personnalisées
use Spatie\LaravelPrometheus\Metrics\Counter;
use Spatie\LaravelPrometheus\Metrics\Histogram;
// Dans un middleware ou service
Counter::name('http_requests_total')
->help('Total HTTP requests')
->labels(['method', 'route', 'status'])
->register()
->increment(['GET', 'articles.index', '200']);
Histogram::name('http_request_duration_seconds')
->help('HTTP request duration')
->buckets([0.1, 0.25, 0.5, 1, 2.5, 5, 10])
->register()
->observe(0.234, ['GET', 'articles.index']);
Requêtes PromQL essentielles
# CPU usage (%)
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# RAM disponible
node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100
# Disk usage (%)
(node_filesystem_size_bytes - node_filesystem_avail_bytes)
/ node_filesystem_size_bytes * 100
# Requêtes HTTP par seconde
rate(http_requests_total[5m])
# Latence P95
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
# Containers en cours d'exécution
count(container_last_seen{name!=""} > time() - 60)
Alertes
# alerts/server.yml
groups:
- name: server
rules:
- alert: HighCPU
expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "CPU élevé sur {{ $labels.instance }}"
description: "CPU à {{ $value | humanize }}%"
- alert: DiskAlmostFull
expr: (node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100 > 85
for: 1m
labels:
severity: critical
annotations:
summary: "Disque presque plein sur {{ $labels.instance }}"
Dashboards Grafana recommandés
Importez ces dashboards depuis grafana.com :
- 1860 — Node Exporter Full (métriques système complètes)
- 893 — Docker and system monitoring
- 14057 — Laravel metrics
Accédez à Grafana sur http://votre-serveur:3000 (admin / votre password) et importez via Dashboards → Import → ID.
Aucun commentaire pour le moment.