Introduction
J'héberge chez moi plusieurs machines : des Raspberry Pi, un NAS, quelques services auto-hébergés. Jusqu'ici, la supervision se résumait à un htop quand quelque chose semblait lent. Pas idéal.
J'ai donc ajouté un module /monitoring à Nerv, mon application personnelle de pilotage de la maison. Ce module lit des métriques au format Prometheus, calcule CPU, mémoire, disque, réseau et uptime, et déclenche des alertes sur seuils. Restait à faire remonter les métriques de chaque machine. C'est là qu'intervient OpenTelemetry.
L'architecture
Le principe est le même sur chaque serveur à superviser :
prometheus-node-exporterexpose les métriques système locales sur127.0.0.1:9100/metrics.- OpenTelemetry Collector scrape ce
node_exporter. - Le Collector re-expose les métriques au format Prometheus sur
0.0.0.0:9464/metrics. - Nerv interroge
http://IP_DU_SERVEUR:9464/metrics.
On pourrait se demander pourquoi intercaler un Collector alors que node_exporter expose déjà du Prometheus. Deux raisons : je ne veux exposer qu'un seul port par machine sur le réseau (node_exporter reste en local), et le Collector me donne un point de contrôle : limitation mémoire, relabeling, et la possibilité d'ajouter d'autres receivers plus tard sans toucher à Nerv.
Choisir le bon binaire selon l'architecture
Premier piège avec les Raspberry Pi : l'architecture. Un uname -m sur la machine donne la réponse :
armv7l(Raspberry Pi 2, ou Pi 3/4 avec un OS 32 bits) : il faut le paquet Contriblinux_armv7, le Collector officiel n'est pas publié pour cette plateforme ;aarch64(Pi 3 et supérieur avec un OS 64 bits) : le Collector officiellinux_arm64suffit.
Installation
D'abord node_exporter, via le paquet système :
sudo apt update
sudo apt install prometheus-node-exporter
sudo systemctl enable --now prometheus-node-exporter
curl http://127.0.0.1:9100/metrics | grep node_cpu_seconds_totalPuis le Collector, ici pour un Pi 2 en armv7l :
VERSION=0.132.0
wget "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${VERSION}/otelcol-contrib_${VERSION}_linux_armv7.tar.gz"
tar xzf "otelcol-contrib_${VERSION}_linux_armv7.tar.gz"
sudo install -m 0755 otelcol-contrib /usr/local/bin/otelcol-contribPour une machine en aarch64, même principe avec l'archive otelcol_${VERSION}_linux_arm64.tar.gz et le binaire otelcol.
Configuration du Collector
Le fichier /etc/otelcol-contrib/config.yaml (ou /etc/otelcol/config.yaml) :
receivers:
prometheus:
config:
global:
scrape_interval: 60s
scrape_timeout: 10s
scrape_configs:
- job_name: raspberry_pi_node_exporter
static_configs:
- targets: ['127.0.0.1:9100']
labels:
host: raspberry-pi-2
processors:
memory_limiter:
check_interval: 5s
limit_mib: 64
spike_limit_mib: 16
exporters:
prometheus:
endpoint: 0.0.0.0:9464
send_timestamps: true
metric_expiration: 5m
service:
pipelines:
metrics:
receivers: [prometheus]
processors: [memory_limiter]
exporters: [prometheus]Trois points importants :
targets: ['127.0.0.1:9100']: le Collector litnode_exporteren local uniquement ;endpoint: 0.0.0.0:9464: c'est le seul port exposé au réseau, celui que Nerv consomme ;- le
memory_limiterà 64 Mo : sur un Pi 2 avec 1 Go de RAM, on ne laisse pas le Collector faire ce qu'il veut.
Le module monitoring de Nerv consomme du texte Prometheus, pas un payload OTLP natif. Le Collector sert donc ici de pont entre node_exporter et Nerv.
Le service systemd
Un test manuel d'abord (otelcol-contrib --config=/etc/otelcol-contrib/config.yaml puis curl sur le port 9464), et si tout répond, le service /etc/systemd/system/otelcol-contrib.service :
[Unit]
Description=OpenTelemetry Collector Contrib
After=network-online.target
Wants=network-online.target
[Service]
User=root
ExecStart=/usr/local/bin/otelcol-contrib --config=/etc/otelcol-contrib/config.yaml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now otelcol-contribVariante Docker Compose pour le NAS
Sur le NAS, Docker est déjà là, autant s'en servir. Même architecture, même endpoint final, mais tout tient dans un docker-compose.yml :
services:
node-exporter:
image: prom/node-exporter:v1.8.2
container_name: node-exporter
restart: unless-stopped
network_mode: host
pid: host
command:
- --path.rootfs=/host
volumes:
- /:/host:ro,rslave
otelcol:
image: otel/opentelemetry-collector:0.154.0
container_name: otelcol
restart: unless-stopped
ports:
- "9464:9464"
extra_hosts:
- host.docker.internal:host-gateway
command:
- --config=/etc/otelcol/config.yaml
volumes:
- ./otelcol/config.yaml:/etc/otelcol/config.yaml:ro
depends_on:
- node-exporterLe network_mode: host sur node-exporter est volontaire : il doit lire les métriques de la machine hôte, pas celles de son conteneur. Le Collector, lui, reste en réseau Docker standard et scrape host.docker.internal:9100 grâce au host-gateway. Dans la config du Collector, la cible devient donc host.docker.internal:9100 au lieu de 127.0.0.1:9100.
Piège rencontré sur le NAS : les ACL. Le conteneur Collector redémarrait en boucle avec un permission denied sur le fichier de config monté. La solution :
chmod 755 . otelcol
chmod 644 otelcol/config.yaml
docker compose up -d --force-recreate otelcolSécuriser les serveurs externes
Sur le réseau local, exposer le port 9464 ne pose pas de problème. Mais pour un serveur externe (un VPS par exemple), ce port serait ouvert sur Internet : n'importe qui pourrait lire les métriques système de la machine. Rien de confidentiel en soi, mais c'est de l'information offerte gratuitement à un attaquant : uptime, charge, points de montage, interfaces réseau.
L'exporter Prometheus du Collector ne propose pas d'authentification, la parade la plus simple est donc le firewall : n'autoriser l'accès au port 9464 qu'à l'IP de Nerv. Avec ufw :
sudo ufw allow from IP_DE_NERV to any port 9464 proto tcp
sudo ufw deny 9464/tcpAttention au cas Docker : les ports publiés via ports: dans un docker-compose.yml contournent ufw (Docker écrit ses propres règles iptables). Dans ce cas, la restriction se fait dans la chaîne DOCKER-USER :
sudo iptables -I DOCKER-USER -p tcp --dport 9464 ! -s IP_DE_NERV -j DROPJe ne l'ai pas encore mis en place puisque mes machines actuelles sont toutes derrière ma box, mais c'est un prérequis avant de brancher le moindre serveur exposé sur Internet.
Branchement dans Nerv
Côté Nerv, il suffit de déclarer le serveur dans /monitoring :
Nom: Raspberry Pi 2
Host: raspberry-pi-2.local
Environnement: home
Endpoint OpenTelemetry Collector: http://IP_DU_SERVEUR:9464/metricsAvec les seuils standards : CPU 80 %, mémoire 80 %, disque 85 %. Le module calcule tout automatiquement à partir des métriques node_exporter : CPU depuis node_cpu_seconds_total, mémoire depuis node_memory_MemTotal_bytes et node_memory_MemAvailable_bytes, disque depuis node_filesystem_*, réseau depuis les compteurs node_network_*_bytes_total.
En complément, je peux suivre des métriques spécifiques via les « métriques observées ». Exemple pour la température CPU d'un Pi :
Libellé: Température CPU
Nom de métrique: node_thermal_zone_temp
Unité: °C
Agrégation: Maximum
Warning: 70
Critical: 80À noter : CPU et réseau peuvent être vides au premier relevé. Ces valeurs sont calculées par delta entre deux collectes, il faut donc deux checks espacés d'une minute pour voir apparaître les premières valeurs. L'historique est conservé 30 jours.
Conclusion
Pour quelques Raspberry Pi et un NAS, cette stack est un bon compromis : node_exporter fait ce qu'il sait faire, le Collector OpenTelemetry sert de point d'exposition unique et contrôlé, et Nerv se contente de lire du Prometheus sans dépendre du détail de chaque machine. Le tout tourne sans broncher, y compris sur un Pi 2 de plus de dix ans, à condition de choisir le bon binaire et de brider la mémoire du Collector.