Skip to content
Learni
Voir tous les tutoriels
Monitoring

Comment déployer Grafana pour l'IoT en 2026

Read in English

Introduction

En 2026, Grafana reste l'outil incontournable pour visualiser les données IoT en temps réel, grâce à sa flexibilité et ses plugins avancés. Ce tutoriel avancé vous guide pour déployer une stack complète : broker MQTT (Mosquitto), collecteur Telegraf vers InfluxDB, et Grafana avec provisioning automatique. Imaginez monitorer des capteurs industriels – température, humidité, vibrations – avec des dashboards interactifs, alertes unifiées et scaling horizontal.

Pourquoi c'est crucial ? Les flottes IoT génèrent des téraoctets de données ; une mauvaise visualisation mène à des downtimes coûteux. Nous couvrons du déploiement Docker à l'optimisation des queries Flux, en passant par des simulations de données réelles. À la fin, vous aurez une architecture production-ready, scalable pour 1000+ devices. Prêt à transformer vos métriques IoT en insights actionnables ? (128 mots)

Prérequis

  • Docker et Docker Compose 20+ installés
  • Connaissances avancées en YAML, TOML et Flux (langage query InfluxDB 2.x)
  • Python 3.10+ pour scripts simulateurs
  • Port 3000 (Grafana), 8086 (InfluxDB), 1883 (MQTT) libres
  • 4 Go RAM minimum pour la stack locale

Déployer la stack Docker Compose

docker-compose.yml
version: '3.8'
services:
  mosquitto:
    image: eclipse-mosquitto:2.0
    ports:
      - '1883:1883'
    volumes:
      - ./mosquitto.conf:/mosquitto/config/mosquitto.conf

  influxdb:
    image: influxdb:2.7
    ports:
      - '8086:8086'
    environment:
      DOCKER_INFLUXDB_INIT_MODE: setup
      DOCKER_INFLUXDB_INIT_USERNAME: admin
      DOCKER_INFLUXDB_INIT_PASSWORD: adminpass
      DOCKER_INFLUXDB_INIT_ORG: iot-org
      DOCKER_INFLUXDB_INIT_BUCKET: iot-bucket
      DOCKER_INFLUXDB_INIT_ADMIN_TOKEN: token123
    volumes:
      - influxdb_data:/var/lib/influxdb2

  telegraf:
    image: telegraf:1.28
    depends_on:
      - influxdb
      - mosquitto
    volumes:
      - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
    environment:
      INFLUX_TOKEN: token123

  grafana:
    image: grafana/grafana:10.4.0
    ports:
      - '3000:3000'
    depends_on:
      - influxdb
    volumes:
      - grafana_data:/var/lib/grafana
      - ./provisioning:/etc/grafana/provisioning

volumes:
  influxdb_data:
  grafana_data:

Ce docker-compose.yml orchestre les 4 services essentiels : Mosquitto pour MQTT, InfluxDB 2.x pour stockage, Telegraf pour ingestion, Grafana pour viz. Les volumes persistent les données ; l'ordre des depends_on assure un démarrage séquentiel. Piège : sans :ro sur configs, les conteneurs écrasent vos fichiers locaux.

Configurer le broker MQTT

Mosquitto agit comme hub central pour vos topics IoT (ex: sensors/temp/room1). Créez le fichier de config pour activer persistence et auth basique – scalable pour 10k+ connexions.

Configuration Mosquitto

mosquitto.conf
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
listener 1883
allow_anonymous true
max_queued_messages 10000
message_size_limit 0
max_inflight_messages 100
max_queued_bytes 0

Active la persistence pour retenir les messages QoS1/2 après redémarrage. Limites élevées pour bursts IoT ; allow_anonymous pour dev, passez à ACL+users en prod. Piège : sans max_queued, un publisher floode la RAM.

Ingestion via Telegraf

Telegraf lit MQTT et écrit en InfluxDB via Flux. Configurez inputs/outputs pour batching optimisé – réduit la latence de 50% sur high-throughput.

Configuration Telegraf

telegraf.conf
[[outputs.influxdb_v2]]
  urls = ["http://influxdb:8086"]
  token = "token123"
  organization = "iot-org"
  bucket = "iot-bucket"

[[inputs.mqtt_consumer]]
  servers = ["tcp://mosquitto:1883"]
  topics = [
    "sensors/+/temp",
    "sensors/+/humidity"
  ]
  data_format = "value"
  data_type = "float"

  [[inputs.mqtt_consumer.tags]]
    device_id = "${topic:sensors/}"

[[processors.enum]]
  [[processors.enum.mapping]]
    field = "topic"
    [processors.enum.mapping.value_mappings]
      "sensors/room1/temp" = "temperature"
      "sensors/room1/humidity" = "humidity"

Inputs MQTT avec wildcards capture tous sensors/* ; outputs vers bucket dédié. Processors ajoutent tags/metadata pour queries Grafana. Piège : sans data_type=float, Influx infère mal, cassant les graphs.

Provisioning Grafana

Automatisez datasources et dashboards via YAML/JSON – zéro config manuelle, idéal CI/CD. Créez dossiers provisioning/.

Datasource InfluxDB provisioning

provisioning/datasources/influxdb.yml
apiVersion: 1
providers:
  - name: 'iot-influxdb'
    orgId: 1
    type: influxdb
    url: http://influxdb:8086
    access: proxy
    jsonData:
      version: Flux
      organization: 'iot-org'
      defaultBucket: 'iot-bucket'
      tlsSkipVerify: true
    secureJsonData:
      token: 'token123'

YAML provisionne datasource Flux-ready. Proxy mode pour queries serveur-side. Piège : tlsSkipVerify=true en dev seulement ; en prod, certs + secureJsonData via secrets.

Dashboard IoT JSON

provisioning/dashboards/iot-dashboard.json
{
  "__inputs": [],
  "dashboard": {
    "id": null,
    "title": "IoT Sensors Dashboard",
    "tags": ["iot"],
    "panels": [
      {
        "id": 1,
        "title": "Températures par Device",
        "type": "timeseries",
        "targets": [{
          "query": "from(bucket: "iot-bucket")
            |> range(start: v.timeRangeStart)
            |> filter(fn: (r) => r._measurement == "temp")
            |> aggregateWindow(every: v.windowPeriod, fn: mean)",
          "refId": "A",
          "datasource": "-- Grafana --",
          "model": {"dataSource":{"type":"-- Grafana --","uid":"${datasource}"}},
          "format": "time_series"
        }],
        "gridPos": {"h": 8, "w": 12, "x": 0, "y": 0},
        "options": {"legend":{"displayMode":"table","placement":"bottom"},"tooltip":{"mode":"multi"}}
      },
      {
        "id": 2,
        "title": "Humidité Moyenne",
        "type": "stat",
        "targets": [{
          "query": "from(bucket: "iot-bucket")
            |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
            |> filter(fn: (r) => r._measurement == "humidity")
            |> mean()",
          "refId": "A",
          "datasource": "-- Grafana --"
        }],
        "fieldConfig": {"defaults":{"color":{"mode":"thresholds"},"thresholds":{"steps":[{"color":"green","value":null},{"color":"yellow","value":60},{"color":"red","value":80}]},
        "unit": "percent (0-100)"}},
        "gridPos": {"h": 8, "w": 12, "x": 12, "y": 0}
      }
    ],
    "time": {"from":"now-6h","to":"now"},
    "timezone":"browser",
    "refresh":"5s",
    "schemaVersion": 39,
    "version": 1
  },
  "overwrite": true
}

Dashboard JSON provisionné avec panels timeseries/stat pour temp/humidity. Queries Flux agrégées ; refresh 5s pour near-RT. Piège : ${datasource} UID doit matcher provisioning ; testez avec API Grafana.

Simuler des données IoT

Lancez un publisher Python pour injecter données réalistes – simule 10 sensors avec noise gaussienne.

Script publisher MQTT

iot_publisher.py
import paho.mqtt.client as mqtt
import time
import random
import json
from threading import Thread

client = mqtt.Client()
client.connect("localhost", 1883, 60)

sensors = ["room1", "room2", "factory1"]

def publish_sensor(sensor):
    while True:
        temp = 22 + random.gauss(0, 2)
        hum = 50 + random.gauss(0, 10)
        payload = json.dumps({"temp": temp, "humidity": hum, "timestamp": time.time()})
        client.publish(f"sensors/{sensor}/temp", temp)
        client.publish(f"sensors/{sensor}/humidity", hum)
        time.sleep(5)

threads = []
for s in sensors:
    t = Thread(target=publish_sensor, args=(s,))
    t.start()
    threads.append(t)

for t in threads:
    t.join()

client.loop_forever()

Paho MQTT publie float values sur topics wildcards-ready. Threads par sensor pour parallélisme ; gauss pour réalisme. Piège : sans connect() retry, reconnexion échoue ; ajoutez client.reconnect_delay_set() en prod.

Démarrer et tester

Démarrez : docker compose up -d && python iot_publisher.py. Accédez Grafana:3000 (admin/admin). Dashboard auto-chargé. Queries Flux live sur 5s refresh.

Script de démarrage

start.sh
#!/bin/bash
docker compose up -d
python3 iot_publisher.py &
grafana-cli plugins install grafana-clock-panel
grafana-cli plugins install vertamedia-clickhouse-datasource
echo "Stack démarrée. Grafana: http://localhost:3000"

Bash one-liner pour stack + publisher background. Plugins optionnels pour extensions. Piège : sans & , publisher bloque ; utilisez nohup pour detach.

Bonnes pratiques

  • Provisioning everywhere : YAML/JSON pour GitOps, évitez UI manuelle.
  • Queries Flux optimisées : Utilisez aggregateWindow(every: 10s) pour downsampling, <1% CPU.
  • Sécurité : MQTT ACL, Influx RBAC, Grafana OAuth ; secrets via Docker Swarm.
  • Scaling : Influx IOx cluster, Telegraf agents distribués, Grafana HA.
  • Alerting : Règles unifiées sur anomalies (ex: temp>30°C), notify Slack/Teams.

Erreurs courantes à éviter

  • Wildcard MQTT mal parsé : "+/+" au lieu de "sensors/+/temp" perd tags ; testez avec mosquitto_sub.
  • Influx token expired : Regénèrez via UI, pas hardcoded.
  • Dashboard non provisionné : Vérifiez logs Grafana (docker logs grafana) pour path errors.
  • High cardinality : Trop de tags unique (device_id par ms) explose stockage ; bucketing + downsample.

Pour aller plus loin

Découvrez nos formations Learni sur Monitoring & IoT pour masterclasses hands-on.