Aller au contenu
TAAF-OPS --:-- UTC

TP 9 — Wrapper Starlink HTTP + Grafana (monitorer du non-SNMP) · BROUILLON

Acte 1 · Monitoring Avancé Grafana · Prometheus · HTTP · Starlink · gRPC

Auteur : Thibaut Fontaine — Kodetis Institution : Université de la Réunion Date : 2026



📡 Poste SOC · La Réunion — Acte 1, Voir. Tu superviser déjà 4+4 équipements Concordia + DDU en SNMP (TP 6 + TP 7). Maintenant on ajoute le lien Starlink que IPEV a déployé pour la campagne d’été 2024-2025. Problème : Starlink ne parle pas SNMP.

🎯 Objectif métier — Tu apprends le pattern wrapper HTTP + Prometheus exporter qui s’applique à TOUS les équipements modernes propriétaires : Starlink, équipements IoT, API REST d’onduleurs récents, équipements télécoms 5G… Ce que tu apprends ici est transposable directement chez Orange Marine, Bouygues, EDF, etc.

Section intitulée « 🛰️ Le pivot Starlink dans les stations polaires »

Jusqu’en 2023, les stations TAAF (Concordia, DDU, Kerguelen, Crozet) utilisaient Inmarsat BGAN (492 kbps, latence 1.3 s) ou Iridium (lent mais polaire). Depuis 2024, Starlink polaire est déployé :

CritèreInmarsat BGANIridiumStarlink
Latence vers PoP~1300 ms (GEO)~100 ms (LEO polaire)~30 ms (LEO méga-constellation)
Débit nominal492 kbps1.4 Mbps~200 Mbps
Coût/moistrès élevéélevémodéré
SouverainetéUK / ViasatUS / IridiumUS / SpaceX
Protocole monitoringSNMP standardpropriétairegRPC (port 9200)

→ Concordia + DDU ont basculé. Mais le tooling de monitoring n’a pas suivi : Starlink expose ses métriques en gRPC, pas en SNMP. Si ton équipe attend que Zabbix sache parler gRPC, tu attendras longtemps.

┌──────────────────┐ gRPC ┌─────────────────┐ HTTP ┌────────────┐ PromQL ┌─────────┐
│ Starlink Dishy │ ◄──────────│ starlink-monitor│ ◄───────────│ Prometheus │ ◄──────────│ Grafana │
│ (port 9200) │ binaire │ (wrapper Bun) │ /metrics │ scrape 30s │ dashboard │ panels │
└──────────────────┘ └─────────────────┘ └────────────┘ └─────────┘

Le wrapper starlink-monitor :

  1. Parle gRPC au Dishy (ou simule, dans le lab)
  2. Expose les métriques en format Prometheus exporter (/metrics)
  3. Optionnellement : expose aussi une API REST JSON (/dish/concordia/status) pour intégration custom
  1. Pourquoi gRPC : binaire/typé, fait pour le streaming, mais incompatible avec Zabbix/SNMP
  2. Pattern exporter Prometheus : la convention /metrics en text plain
  3. Format Prometheus : metric naming, labels, types (gauge, counter, histogram)
  4. PromQL basique : rate(), avg(), by (label), alerting
  5. Architecture lab : ajouter un service au docker-compose existant
  6. Trade-off SNMP vs HTTP : quand l’un, quand l’autre
graph LR
 subgraph "Lab Réunion (VM monitoring)"
 P[Prometheus
scrape 30s] G[Grafana
dashboards] P --> G end subgraph "Lab Concordia (VM concordia)" SM[starlink-monitor
:9100/metrics] DC[Dishy Concordia
simulé] SM -.gRPC sim.-> DC end subgraph "Lab DDU" SD[Dishy DDU
simulé] end P --HTTP scrape--> SM SM -.gRPC sim.-> SD

TermeDéfinition courte
gRPCGoogle RPC — protocole binaire HTTP/2 + Protobuf, streaming bidirectionnel natif
ProtobufFormat de sérialisation binaire de Google (schéma .proto → code généré)
ExporterService qui collecte des métriques d’un système et les expose au format Prometheus
/metricsEndpoint conventionnel HTTP qui renvoie les métriques au format text
ScrapeAction de Prometheus qui poll un endpoint /metrics à intervalle régulier
GaugeMétrique qui peut monter ET descendre (latence, température, état)
CounterMétrique monotone croissante (octets transmis, requêtes traitées)
PromQLLangage de query Prometheus — rate(metric[5m]), avg by (label)(...)
LabelCouple clé=valeur attaché à une métrique (site="concordia", pop="sydney-3")
DatasourceDans Grafana, lien vers une source de données (Prometheus, Loki, Postgres…)

Section intitulée « 3. Section 0 — Pourquoi Starlink ne parle pas SNMP (15 min) »

SNMP (Simple Network Management Protocol) est un standard IETF de 1988, conçu pour les équipements réseau de l’époque : switches, routeurs, imprimantes. Il s’appuie sur :

  • UDP/161 : transport stateless
  • OIDs : arbre numérique global (1.3.6.1.2.1.1.1.0 = sysDescr)
  • MIBs : schémas textuels qui décrivent les OIDs
  • GET / GETNEXT / SET : opérations simples

C’est parfait pour des équipements à inventaire stable, basse cardinalité. Mais ça vieillit mal :

Limite SNMPConséquence
Pas de streamingTu polles, tu attends N secondes, tu re-polles
Schéma figé via OIDsAjouter une métrique = négocier un nouveau PEN IANA
Pas de types modernes (struct, repeated)Tableaux émulés via index .1, .2, …
Sécurité v3 ajoutée tardivementLa plupart des équipements restent en v2c
Authentification weak (community string)“public” / “private” en clair encore courants

gRPC, sorti par Google en 2015, est conçu pour le microservices moderne :

  • HTTP/2 : multiplexing, header compression, bidirectionnel
  • Protobuf : sérialisation binaire ultra-compacte avec schéma typé
  • Streaming : tu peux push N événements en flux continu
  • Auth : TLS mutuel + JWT par défaut

Starlink (SpaceX) expose son Dishy en gRPC, port 9200, avec un service SpaceX.API.Device.dish dont la méthode principale est get_status qui retourne une struct DishGetStatusResponse :

message DishGetStatusResponse {
DeviceInfo device_info = 1;
DishState state = 2;
float pop_ping_drop_rate = 3;
float pop_ping_latency_ms = 4;
float downlink_throughput_bps = 5;
float uplink_throughput_bps = 6;
ObstructionStats obstruction_stats = 7;
float snr = 8;
uint32 seconds_to_first_nonempty_slot = 9;
uint32 alerts_bitfield = 10;
// ... et ~60 autres champs
}

→ Tu vois immédiatement le problème : ces noms et ces types ne se mappent pas sur un OID SNMP. Tu ne peux pas demander à Zabbix de parler gRPC nativement.

Quand l’équipement parle un protocole moderne et que ton outil de monitoring parle un protocole legacy, tu mets un wrapper au milieu :

[équipement moderne] ──gRPC──> [wrapper] ──format compatible monitoring──> [Zabbix/Prom/...]

Le wrapper a 3 responsabilités :

  1. Connecter à l’équipement via son protocole natif (gRPC, REST, MQTT, OPC-UA, Modbus…)
  2. Traduire les structures en métriques plat-typées
  3. Exposer sous un format que ton outil de monitoring sait lire

Tu peux exposer en :

  • SNMP (rare, coûteux à coder)
  • HTTP REST JSON (simple, ad-hoc)
  • Prometheus /metrics ⭐ (standard de fait, ce qu’on fait dans ce TP)
  • StatsD / OpenMetrics / OTLP (alternatives modernes)

❓ Question d’évaluation 1 (1 pt · Niveau Standard)

Section intitulée « ❓ Question d’évaluation 1 (1 pt · Niveau Standard) »

Cite 2 raisons techniques pour lesquelles SpaceX a choisi gRPC plutôt que SNMP pour le Dishy. Cite 1 conséquence opérationnelle pour les équipes ops qui veulent monitorer Starlink avec une stack existante (Zabbix, etc.).


Section intitulée « 4. Section 1 — Déployer le wrapper starlink-monitor (15 min) »

Le service starlink-monitor (à ajouter dans zabbix-proxy-lab/docker-compose.yml) :

starlink-monitor:
build: ./starlink-monitor
image: zabbix-lab/starlink-monitor:dev
container_name: starlink-monitor
environment:
MONITOR_PORT: "9100"
SITES: "concordia,ddu"
# En lab : on simule. En prod : pointe sur le Dishy réel.
MODE: "simulator"
DISHY_CONCORDIA: "192.168.100.1:9200"
DISHY_DDU: "192.168.200.1:9200"
ports:
- "9100:9100"
healthcheck:
test: ["CMD-SHELL", "wget --spider -q http://localhost:9100/metrics || exit 1"]
interval: 30s
timeout: 5s
retries: 3
restart: unless-stopped
networks: [proxy-net]
Fenêtre de terminal
cd ~/zabbix-lab/zabbix-proxy-lab
docker compose up -d starlink-monitor
docker compose ps starlink-monitor
# Doit afficher : Up X seconds (healthy)
Fenêtre de terminal
curl -s http://localhost:9100/metrics | head -30

Tu dois voir un dump format Prometheus (voir section suivante).


5. Section 2 — Inspecter l’API HTTP du wrapper (15 min)

Section intitulée « 5. Section 2 — Inspecter l’API HTTP du wrapper (15 min) »

Le wrapper expose 3 endpoints :

EndpointFormatUsage
/metricsPrometheus textScrape par Prometheus
/dish/:site/statusJSONInspection humaine / intégration ad-hoc
/healthztextHealthcheck

Exemple de sortie /metrics :

# HELP starlink_pop_ping_drop_rate Fraction of packets dropped to PoP (0.0-1.0)
# TYPE starlink_pop_ping_drop_rate gauge
starlink_pop_ping_drop_rate{site="concordia"} 0.0
starlink_pop_ping_drop_rate{site="ddu"} 0.0
# HELP starlink_pop_ping_latency_ms Round-trip latency to PoP in milliseconds
# TYPE starlink_pop_ping_latency_ms gauge
starlink_pop_ping_latency_ms{site="concordia"} 32
starlink_pop_ping_latency_ms{site="ddu"} 28
# HELP starlink_downlink_bps Downlink throughput in bits per second
# TYPE starlink_downlink_bps gauge
starlink_downlink_bps{site="concordia"} 215000000
starlink_downlink_bps{site="ddu"} 248000000
# HELP starlink_satellites_connected Number of satellites currently linked
# TYPE starlink_satellites_connected gauge
starlink_satellites_connected{site="concordia"} 4
starlink_satellites_connected{site="ddu"} 5
# HELP starlink_obstruction_fraction Fraction of sky obstructed (0.0-1.0)
# TYPE starlink_obstruction_fraction gauge
starlink_obstruction_fraction{site="concordia"} 0.003
starlink_obstruction_fraction{site="ddu"} 0.001
starlink_pop_ping_latency_ms{site="concordia"} 32
└──────────────┬───────────┘└────────┬───────┘ └┬┘
Nom de métrique Labels Valeur

Conventions Prometheus :

  • snake_case pour les noms
  • Suffix d’unité : _ms, _bytes, _seconds, _total (pour les counters)
  • Labels : multi-valeurs (site, pop, alert_type) — créent les séries temporelles
Fenêtre de terminal
curl -s http://localhost:9100/dish/concordia/status | jq .
{
"site": "concordia",
"deviceInfo": {
"id": "ut01000000-XXXX-YYYY",
"hardwareVersion": "rev4_proto2",
"softwareVersion": "2026.05.0.mr59180"
},
"state": "CONNECTED",
"popPingDropRate": 0.0,
"popPingLatencyMs": 32,
"downlinkBps": 215000000,
"uplinkBps": 28000000,
"obstructionFraction": 0.003,
"obstructionTimeSec": 842,
"snr": 11.5,
"satellitesConnected": 4,
"alertsBitfield": 0,
"pop": "sydney-pop-3"
}

❓ Question d’évaluation 2 (1 pt · Niveau Standard)

Section intitulée « ❓ Question d’évaluation 2 (1 pt · Niveau Standard) »

En t’inspirant des conventions Prometheus, propose 2 nouveaux noms de métriques à exposer pour le Dishy, et justifie le choix de type (gauge vs counter) pour chacun.


6. Section 3 — Configurer le scrape Prometheus (20 min)

Section intitulée « 6. Section 3 — Configurer le scrape Prometheus (20 min) »

Ouvre ~/monitoring/prometheus/prometheus.yml sur la VM monitoring et ajoute :

scrape_configs:
# ... jobs existants (node-exporter, blackbox, etc.) ...
- job_name: 'starlink-monitor'
scrape_interval: 30s
scrape_timeout: 10s
metrics_path: /metrics
static_configs:
- targets: ['<IP_CONCORDIA>:9100']
labels:
environment: 'lab'
location: 'concordia'
team: 'taaf-ops'
Fenêtre de terminal
# Soit reload propre via API admin
curl -X POST http://localhost:9090/-/reload
# Soit restart container
docker restart prometheus

Ouvre http://localhost:9090/targets — tu dois voir starlink-monitor en UP (vert).

Si rouge :

  • DOWN connection refused → wrapper pas démarré
  • DOWN timeout → firewall entre VM monitoring et VM concordia
  • Status: UP, Last Scrape: error → format /metrics invalide (rare)

Dans http://localhost:9090/graph :

starlink_pop_ping_latency_ms

Tu dois voir 2 séries (Concordia + DDU). Click “Graph” pour le voir dans le temps.

❓ Question d’évaluation 3 (2 pts · Niveau Avancé)

Section intitulée « ❓ Question d’évaluation 3 (2 pts · Niveau Avancé) »

Écris 2 requêtes PromQL :

  1. La latence moyenne sur 5 minutes sur Concordia (utiliser avg_over_time())
  2. Le débit downlink en Mbps (pas en bps — convertis dans la requête)

7. Section 4 — Premier panel Grafana en PromQL (15 min)

Section intitulée « 7. Section 4 — Premier panel Grafana en PromQL (15 min) »

Grafana → Dashboards → New → Add visualization → Datasource = Prometheus.

  • Title : Latence vers PoP par site
  • Query A : starlink_pop_ping_latency_ms
  • Legend : {{site}}
  • Visualization : Time series
  • Unit : Milliseconds (ms)
  • Thresholds : 40 = orange, 100 = red

→ Tu obtiens 2 courbes : Concordia (~32 ms) et DDU (~28 ms).

Dans un autre terminal :

Fenêtre de terminal
cd ~/zabbix-lab/zabbix-proxy-lab
make starlink-concordia-obstruct

Attends 30 s (scrape interval). La courbe Concordia saute à 145 ms — tu visualises l’obstruction.

Fenêtre de terminal
make starlink-concordia-restore

La latence retombe à 32 ms.


Section intitulée « 8. Section 5 — Dashboard complet Starlink Concordia + DDU (25 min) »

Construis 6 panels :

#PanelQuery PromQL principale
1Drop rate live (stat single value)starlink_pop_ping_drop_rate * 100
2Latence PoP (time series)starlink_pop_ping_latency_ms
3Throughput downlink (time series)starlink_downlink_bps / 1000000 (Mbps)
4Throughput uplink (time series)starlink_uplink_bps / 1000000
5Satellites connectés (stat)starlink_satellites_connected
6Obstruction du ciel (gauge)starlink_obstruction_fraction * 1000 (en ‰)

Settings → Variables → Add variable :

  • Type : Query
  • Name : site
  • Query : label_values(starlink_pop_ping_latency_ms, site)
  • Multi-value : ✅
  • Include All : ✅

Puis dans chaque panel, change la query :

starlink_pop_ping_latency_ms{site=~"$site"}

→ Tu obtiens un sélecteur en haut du dashboard pour filtrer Concordia / DDU / tous.

Inclure dans le rapport : capture du dashboard complet (6 panels) avec le selector $site qui sélectionne All, en condition nominale (état post-make reset).


9. Section 6 — Alerte sur obstruction prolongée (15 min)

Section intitulée « 9. Section 6 — Alerte sur obstruction prolongée (15 min) »

Si l’obstruction dépasse 5 % (50‰) pendant plus de 2 minutes, déclencher une alerte critique.

Panel “Obstruction du ciel” → onglet Alert → New alert rule :

  • Query : starlink_obstruction_fraction * 1000
  • Reduce : last
  • Condition : IS ABOVE 50
  • Evaluate every : 30s for 2m
  • Annotations :
    • Summary : Obstruction Starlink {{ $labels.site }} > 5%
    • Description : Vérifier la dish (neige, glace, obstacle). Valeur actuelle : {{ $value }}‰
  • Notification : channel Discord ou Google Chat (utiliser le webhook créé en TP 4)
Fenêtre de terminal
make starlink-concordia-obstruct
# Attendre 2 minutes ⏱️
# → notif Discord arrive
make starlink-concordia-restore
# → alert resolved arrive

❓ Question d’évaluation 4 (2 pts · Niveau Avancé)

Section intitulée « ❓ Question d’évaluation 4 (2 pts · Niveau Avancé) »

Pourquoi est-il dangereux de mettre Evaluate every 30s for 30s (seuil franchi pour 30s seulement) ? Donne 1 scénario réel où ça génèrerait des faux positifs Starlink, et propose une condition mieux conçue.


10. Section 7 — Comparaison SNMP vs HTTP/Prometheus (10 min)

Section intitulée « 10. Section 7 — Comparaison SNMP vs HTTP/Prometheus (10 min) »
CritèreSNMP (TP 6/7)HTTP/Prometheus (ce TP)
ModèlePull (poll)Pull (scrape)
TransportUDP/161HTTP/9100
SchémaFigé (OIDs + MIBs)Flexible (labels)
GranularitéUne OID = une valeurUne métrique + N labels
DécouverteWalk de l’arbreup{} + service discovery
AuthentCommunity / v3 USMmTLS / Bearer / IP allowlist
Streaming❌ (pull, pas push)
StandardIETF 1988De facto Prometheus 2015
Adoption ICS/industriel⭐⭐⭐⭐⭐⭐⭐
Adoption cloud/microservices⭐⭐⭐⭐⭐
SituationOutil
Switch / routeur / UPS classiqueSNMP (templates existent)
Onduleur APC / SchneiderSNMP
Container / microservice maisonPrometheus
Équipement propriétaire récent (Starlink, IoT, 5G)Prometheus via wrapper
Mix legacy + moderneHybride : SNMP côté Zabbix, Prom côté Grafana, corrélés

❓ Question d’évaluation 5 (2 pts · Niveau Avancé)

Section intitulée « ❓ Question d’évaluation 5 (2 pts · Niveau Avancé) »

Ton équipe te demande de monitorer un onduleur APC SmartUPS (existe en MIB SNMP standard) et un EV charger Schneider EVlink Pro AC (API REST JSON propriétaire). Quel outil pour chaque ? Justifie en 3 lignes par équipement.


Tu présentes ton dashboard et ton wrapper à un client industriel TAAF qui ne connaît pas Prometheus. En 5-7 lignes, vends-lui :

  1. Pourquoi tu n’as pas mis le Starlink dans Zabbix
  2. Comment ton wrapper se positionne entre l’équipement propriétaire et la stack de monitoring
  3. Quel est l’avantage opérationnel par rapport à attendre que Zabbix supporte gRPC

#LivrableForme
1Wrapper starlink-monitor démarré et healthydocker compose ps capture
2Endpoint /metrics exposécurl /metrics head 30
3Job Prometheus configuréprometheus.yml extrait + capture targets UP
4Dashboard Grafana 6 panelsexport JSON + capture dashboard
5Alerte obstruction configuréescreenshot règle + 1 notif Discord reçue
6Réponses aux 5 questions d’évaluationdans le rapport
7Synthèse client TAAF5-7 lignes dans le rapport

Évaluation : /20

  • Q1 Standard · 1 pt
  • Q2 Standard · 1 pt
  • Q3 Avancé · 2 pts
  • Q4 Avancé · 2 pts
  • Q5 Avancé · 2 pts
  • Wrapper opérationnel · 2 pts
  • Prometheus scrape OK · 2 pts
  • Dashboard 6 panels · 4 pts
  • Alerte fonctionnelle · 2 pts
  • Synthèse client · 2 pts

  • Annexe A : Code source du wrapper starlink-monitor/server.ts commenté
  • Annexe B : Dashboard Grafana JSON pré-livré (à copier-coller pour étudiants en panne)
  • Annexe C : Script Python d’inspection gRPC réel (pour étudiants curieux d’aller plus loin sur un vrai Dishy)
  • Annexe D : Comparaison Prometheus exporter vs OpenTelemetry Collector (architecture moderne 2026)