Introduction
En 2026, Grafana reste l'outil roi pour visualiser des données IoT en temps réel, intégrant nativement MQTT, InfluxDB et Prometheus pour des dashboards interactifs. Ce tutoriel expert vous guide dans l'implémentation d'un stack production-ready : déploiement Dockerisé, provisioning automatisé des datasources et dashboards, alerting sur anomalies de capteurs (température, humidité, vibrations), et scaling horizontal. Pourquoi c'est crucial ? Les flottes IoT génèrent des téraoctets de timeseries ; Grafana excelle à les agréger avec des queries Loki pour logs et des panels géospatiaux pour tracking. Vous apprendrez à éviter les pièges de latence en high-frequency data, à sécuriser via OAuth et à provisionner via GitOps. Résultat : un monitoring pro qui alerte en <5s sur des seuils critiques, bookmarkable par tout DevOps IoT senior. (142 mots)
Prérequis
- Docker 27+ et Docker Compose 2.29+
- Connaissances avancées en YAML provisioning et InfluxDB 3.x
- Accès à un broker MQTT (Mosquitto 2.1+) et capteurs simulés
- Node.js 22+ pour tests API Grafana
- Système Linux prod (Ubuntu 24.04 recommandé)
Déploiement stack Docker Compose
version: '3.8'
services:
grafana:
image: grafana/grafana-enterprise:11.1.0
container_name: grafana-iot
ports:
- '3000:3000'
volumes:
- grafana-data:/var/lib/grafana
- ./provisioning:/etc/grafana/provisioning
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin123!
- GF_AUTH_ANONYMOUS_ENABLED=false
- GF_SERVER_ROOT_URL=http://localhost:3000
restart: unless-stopped
depends_on:
- influxdb
- mosquitto
influxdb:
image: influxdb:3.0
container_name: influxdb-iot
ports:
- '8086:8086'
volumes:
- influxdb-data:/var/lib/influxdb3
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=iot-admin
- DOCKER_INFLUXDB_INIT_PASSWORD=securepass123
- DOCKER_INFLUXDB_INIT_ORG=iot-org
- DOCKER_INFLUXDB_INIT_BUCKET=iot-sensors
- DOCKER_INFLUXDB_INIT_TOKEN=iot-token-abc123
restart: unless-stopped
mosquitto:
image: eclipse-mosquitto:2.0
container_name: mosquitto-iot
ports:
- '1883:1883'
- '9001:9001'
volumes:
- ./mosquitto.conf:/mosquitto/config/mosquitto.conf
restart: unless-stopped
volumes:
grafana-data:
influxdb-data:Ce docker-compose.yml déploie Grafana Enterprise 11.1, InfluxDB 3 pour timeseries IoT et Mosquitto MQTT. Les volumes persistent les données ; provisioning monte un dossier pour configs automatisées. Lancez avec docker compose up -d. Piège : oubliez les depends_on, InfluxDB ne sera pas prêt pour datasource.
Configuration Mosquitto pour MQTT
Créez mosquitto.conf pour activer WebSocket (port 9001) et auth basique, essentiel pour Grafana MQTT plugin. Cela permet des subscriptions temps réel sans polling, réduisant latence à <100ms pour données capteurs haute fréquence.
Config Mosquitto MQTT sécurisé
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
listener 1883
listener 9001
protocol websockets
allow_anonymous true
max_queued_messages 10000
message_size_limit 0
max_inflight_messages 1000
Active persistence et WebSockets pour Grafana. max_queued_messages gère bursts IoT (ex: 10k events/s de fleet). En prod, remplacez allow_anonymous false par users/password. Testez avec mosquitto_sub -h localhost -t iot/sensor/#.
Provisioning datasources Grafana
Utilisez YAML provisioning pour GitOps : datasources auto-créées au boot. InfluxDB pour metrics historiques, MQTT pour live streams. Analogie : comme Terraform pour infra, mais pour UI Grafana.
Provisioning InfluxDB datasource
apiVersion: 1
providers:
- name: 'iot-influxdb'
orgId: 1
folder: ''
type: influxdb
uid: influxdb-iot
url: http://influxdb:8086
access: proxy
database: iot-sensors
user: iot-admin
secureJsonData:
password: 'securepass123'
jsonData:
version: Flux
organization: iot-org
defaultBucket: iot-sensors
tlsSkipVerify: true
editable: false
Configure InfluxDB 3.x avec Flux queries pour IoT timeseries. proxy mode cache queries ; editable: false empêche modifs UI. Ajoutez editable: true en dev. Vérifiez logs Grafana pour 'datasource added'.
Provisioning MQTT datasource
apiVersion: 1
providers:
- name: 'iot-mqtt'
orgId: 1
folder: ''
type: mqtt
uid: mqtt-iot
url: ws://mosquitto:9001
access: proxy
jsonData:
sharedTopic: false
keepAlive: 60
secureJsonData:
user: iot-user
password: mqttpass
editable: false
Plugin MQTT natif Grafana pour subscriptions live (topic iot/sensor/+). WebSocket URL pour browser compat. keepAlive 60s gère reconnexions IoT flaky. Installez plugin via grafana-cli plugins install grafana-mqtt-datasource si non-Enterprise.
Dashboard IoT temps réel
Importez un dashboard JSON expert avec variables (device ID), panels gauge/stat pour capteurs, heatmap pour tendances. Queries Flux pour agrégations (mean temp par heure).
Dashboard JSON sensors IoT
{
"__inputs": [],
"id": null,
"title": "IoT Sensors Dashboard",
"tags": [],
"style": "dark",
"timezone": "browser",
"panels": [
{
"id": 1,
"title": "Température Live",
"type": "timeseries",
"targets": [
{
"refId": "A",
"datasource": {
"type": "mqtt",
"uid": "mqtt-iot"
},
"topic": "iot/sensor/$device/temp",
"measurements": ["value"]
}
],
"fieldConfig": {
"defaults": {
"unit": "celsius",
"min": -20,
"max": 80
}
},
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }
},
{
"id": 2,
"title": "Historique Temp/Humidité",
"type": "timeseries",
"targets": [
{
"refId": "A",
"datasource": {
"type": "influxdb",
"uid": "influxdb-iot"
},
"query": "from(bucket: "iot-sensors")
|> range(start: v.timeRangeStart)
|> filter(fn: (r) => r._measurement == "sensor")
|> filter(fn: (r) => r._field == "temp" or r._field == "humidity")
|> aggregateWindow(every: v.windowPeriod, fn: mean)",
"format": "time_series"
}
],
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }
}
],
"time": {
"from": "now-1h",
"to": "now"
},
"timepicker": {},
"variables": [
{
"name": "device",
"label": "Device ID",
"type": "custom",
"options": [
{ "text": "sensor1", "value": "sensor1" },
{ "text": "sensor2", "value": "sensor2" }
],
"current": { "selected": true, "text": "sensor1", "value": "sensor1" }
}
],
"refresh": "10s",
"schemaVersion": 39,
"version": 1,
"revision": 1
}Dashboard complet avec MQTT live panel et Flux query InfluxDB pour history. Variable $device pour multi-capteurs. Refresh 10s pour near-RT ; unit celsius auto-scale. Provisionnez via dossier dashboards/ et relancez Grafana.
Script test publisher MQTT
Simulez données capteurs pour valider : Python script publie temp/humidité random sur topics.
Publisher Python IoT data
import paho.mqtt.client as mqtt
import json
import random
import time
BROKER = "localhost"
PORT = 1883
TOPICS = ["iot/sensor/sensor1/temp", "iot/sensor/sensor1/humidity"]
client = mqtt.Client()
client.connect(BROKER, PORT, 60)
while True:
for topic in TOPICS:
field = topic.split('/')[-1]
if field == 'temp':
value = round(random.uniform(20, 35), 2)
else:
value = round(random.uniform(40, 70), 2)
payload = json.dumps({"device": "sensor1", "value": value, "ts": time.time()})
client.publish(topic, payload)
print(f"Published {topic}: {payload}")
time.sleep(5)
client.loop_forever()Utilise Paho MQTT pour burst data IoT-like. InfluxDB peut sink via Telegraf (ajoutez-le). json.dumps pour structuré ; loop 5s simule 12 samples/min. Exécutez pip install paho-mqtt puis python iot_publisher.py.
Provisioning alerting rules
apiVersion: 1
groups:
- orgId: 1
name: IoT Alerts
folder: IoT
interval: 30s
rules:
- uid: temp-high
title: "Température capteur élevée"
condition: "B"
data:
- refId: A
datasourceUid: influxdb-iot
model: flux
relativeTimeRange:
from: 600
to: 0
queryText: |
from(bucket: "iot-sensors")
|> range(start: -10m)
|> filter(fn: (r) => r._measurement == "sensor")
|> filter(fn: (r) => r._field == "temp")
|> last()
- refId: B
conditions:
- evaluator:
params: [35]
operator:
type: gt
reducer:
type: last
type: query
noDataState: NoData
execErrState: Error
for: 1m
annotations:
summary: "Temp > 35°C sur {{ $labels.device }}"
labels:
severity: critical
Rule alerte si dernière temp >35°C pendant 1m. Flux last() pour current value ; annotations Jinja pour notifs Slack/Teams. for: 1m anti-flap. Associez à contact point via UI post-provisioning.
Bonnes pratiques
- Provisioning GitOps : Stockez YAML/JSON en Git, sync avec grafana-toolbox pour CI/CD.
- Scaling horizontal : Deployez Grafana en cluster avec HA (multi-replicas + shared DB PostgreSQL).
- Sécurité IoT : Activez mTLS sur MQTT, OAuth2 pour datasources, et rate-limit API Grafana.
- Optim queries : Utilisez downsampling InfluxDB (ex: 1s→1m) pour dashboards legacy.
- Backup : Cron
grafana-cli admin reset-admin-password+ S3 pour snapshots dashboards.
Erreurs courantes à éviter
- Datasource timing : InfluxDB non-ready → attendez 30s post-boot ou healthchecks Docker.
- MQTT reconn : Sans
keepAlive, reconnexion échoue sur flaky networks IoT ; set 60s+. - Dashboard refresh : <5s tue perf (CPU 100%) ; cap à 10s + WebSocket MQTT.
- Alert flap : Oubliez
for: 0→ spam notifs ; toujours set durée min.
Pour aller plus loin
Maîtrisez Grafana Loki pour logs IoT, ou Prometheus + Node Exporter pour edge metrics. Explorez formations Learni DevOps & IoT pour certifications avancées. Docs officielles : Grafana IoT docs. GitHub repo exemple : clonez ce tuto pour fork.