LW IT Solutions logo LW IT Solutions logo LW IT Solutions
« Blog-Übersicht /Raspberry Pi/Tutorials / Raspberry Pi mit Prometheus und Grafana überwachen
Diesen Artikel in anderen Sprachen lesen:

Raspberry Pi mit Prometheus und Grafana überwachen

Teil 7 von 7 der Reihe Homelab auf dem Raspberry Pi

Raspberry Pi mit Prometheus und Grafana überwachen

Management Summary

Überwachung macht den Zustand eines Raspberry Pi im Zeitverlauf sichtbar, statt erst beim Ausfall eines Dienstes. Prometheus sammelt Messwerte etwa zu Temperatur und Auslastung; Grafana stellt diese übersichtlich als Diagramme dar. Bei kleinen Serverinstallationen hilft das, Überhitzung, Stromprobleme oder steigende Belastung zu erkennen. Warnungen lenken den Blick auf ungewöhnliche Zustände, erklären aber nicht automatisch die Ursache. Auch fehlende oder alte Werte sind wichtig, denn ausbleibende Meldungen beweisen keinen gesunden Betrieb.

Inhalt
  1. Auslastung beobachten, ohne Ausfälle vorherzusagen
  2. 1. Firmwarewerte mit Fehlerbehandlung erfassen
  3. 2. Host-Collector und Timer einrichten
  4. 3. Messwerte mit Prometheus speichern
  5. 4. Alarmregeln und Benachrichtigungen trennen
  6. Sinnvolle Panels und deren Grenzen
  7. Fragen und Antworten
  8. Quellen

Auslastung beobachten, ohne Ausfälle vorherzusagen

Prometheus speichert Messwerte im Zeitverlauf, Grafana stellt diese Werte dar. Auf dem Raspberry Pi stellt node_exporter Linux-Messwerte zum Abruf bereit. Ein kleines Sammelskript ergänzt Temperatur und Warnmeldungen der Firmware, also der eingebauten Gerätesteuerung. Monitoring hilft bei der Untersuchung von Engpässen. Ein Dashboard verhindert keine Überhitzung, repariert kein Netzteil und sagt kein Ausfalldatum eines Speichermediums voraus.

Das Beispiel richtet sich an einen getrennten, neuen Raspberry-Pi-OS-Aufbau mit Python 3, Docker Engine und Compose. Bestehende Konten, Collector-Verzeichnisse und Dienste müssen vor der Einrichtung abgeglichen werden. Die Host-Konfiguration benötigt Verwaltungsrechte. Alle Netzwerkdienste lauschen nachfolgend auf der lokalen Adresse 127.0.0.1, genannt Loopback. Andere Geräte im Netz können nicht direkt zugreifen; der Browserzugriff erfolgt über einen verschlüsselten SSH-Tunnel zum Pi.

Firmware-Collector, Node Exporter, Prometheus und Grafana mit getrennter Prüfung von Messwertalter und Benachrichtigung
Erfassung, Abruf, Darstellung und Benachrichtigung sind getrennte Schritte. Alte oder fehlende Messwerte benötigen eigene Alarmregeln.

1. Firmwarewerte mit Fehlerbehandlung erfassen

Die Datei rpi-hardware-metrics.py liest ausschließlich Temperatur und Drosselungsstatus. Jeder Aufruf besitzt ein Zeitlimit; unerwartete Ausgaben brechen den Lauf ab. Bei Fehlern bleibt die vorherige Datei erhalten. Der Zeitstempel des letzten Erfolgs unterscheidet alte von neuen Messwerten; ein erfolgreicher HTTP-Abruf allein erkennt einen stehen gebliebenen Collector nicht.

Python
#!/usr/bin/env python3
import os
import re
import subprocess
import sys
import tempfile
import time
from pathlib import Path

FLAGS = ("undervoltage", "frequency_capped", "throttled", "soft_temperature_limit")

def read_value(argument):
    return subprocess.run(
        ["/usr/bin/vcgencmd", argument], check=True,
        capture_output=True, text=True, timeout=5
    ).stdout.strip()

def collect(reader=read_value):
    temperature = re.fullmatch(r"temp=(-?[0-9]+(?:[.][0-9]+)?)'C", reader("measure_temp"))
    throttle = re.fullmatch(r"throttled=0x([0-9a-fA-F]{1,8})", reader("get_throttled"))
    if temperature is None or throttle is None:
        raise ValueError("Unexpected vcgencmd output")
    mask = int(throttle.group(1), 16)
    lines = [
        "# HELP rpi_soc_temperature_celsius SoC temperature",
        "# TYPE rpi_soc_temperature_celsius gauge",
        "rpi_soc_temperature_celsius " + temperature.group(1),
        "# HELP rpi_soc_throttled_bitmask Complete firmware bitmask",
        "# TYPE rpi_soc_throttled_bitmask gauge",
        f"rpi_soc_throttled_bitmask {mask}",
        "# HELP rpi_hardware_flag Firmware flag; current or since boot",
        "# TYPE rpi_hardware_flag gauge",
    ]
    for state, offset in (("current", 0), ("since_boot", 16)):
        for bit, name in enumerate(FLAGS):
            value = (mask >> (offset + bit)) & 1
            lines.append(f'rpi_hardware_flag{{state="{state}",flag="{name}"}} {value}')
    lines += [
        "# HELP rpi_collector_last_success_timestamp_seconds Last successful collection",
        "# TYPE rpi_collector_last_success_timestamp_seconds gauge",
        f"rpi_collector_last_success_timestamp_seconds {time.time():.3f}",
    ]
    return "\n".join(lines) + "\n"

def publish(directory, content):
    directory = Path(directory)
    fd, temporary = tempfile.mkstemp(prefix=".rpi-", suffix=".tmp", dir=directory)
    try:
        with os.fdopen(fd, "w", encoding="utf-8") as output:
            output.write(content)
            os.fchmod(output.fileno(), 0o644)
        os.replace(temporary, directory / "rpi_metrics.prom")
    finally:
        if os.path.exists(temporary):
            os.unlink(temporary)

if __name__ == "__main__":
    if len(sys.argv) != 2:
        raise SystemExit("Usage: rpi-hardware-metrics.py TEXTFILE_DIRECTORY")
    publish(sys.argv[1], collect())

Aktuelle und seit dem Start aufgezeichnete Flags erhalten getrennte Labels. Beispielsweise dokumentiert 0x50000 frühere Unterspannung und Drosselung, ohne einen aktuell anhaltenden Zustand zu behaupten. Minütliche Abfragen können kurze aktuelle Zustände verpassen. Historische Flags bewahren einen Teil dieser Hinweise, liefern jedoch keinen Ereigniszeitpunkt. Unbekannte zukünftige Bits bleiben in der vollständigen Bitmaske sichtbar.

Die Kernspannung fehlt bewusst. Eine interne Versorgungsschiene entspricht weder der USB-Eingangsspannung noch einer Diagnose eines defekten Netzteils. Der Pi 5 liefert separate Messwerte des Chips zur Stromversorgung (PMIC), etwa über vcgencmd pmic_read_adc EXT5V_V; eine Erweiterung benötigt modellspezifisches Parsing und Rechteprüfungen.

2. Host-Collector und Timer einrichten

Die Einrichtungsbefehle setzen die drei gezeigten Dateien im Arbeitsverzeichnis und eine vorhandene Gruppe video voraus. rpi-metrics ist ein neues Dienstkonto ohne Anmeldung; ein bestehendes Konto wird geprüft und nicht erneut angelegt. Raspberry Pi OS muss /usr/bin/vcgencmd bereitstellen. Hardwarezugriff hängt vom installierten Betriebssystem ab und muss unter dem Dienstkonto getestet werden.

Shell
sudo apt update
sudo apt install prometheus-node-exporter python3
sudo useradd --system --user-group --groups video --no-create-home --shell /usr/sbin/nologin rpi-metrics
sudo install -d -o rpi-metrics -g rpi-metrics -m 755 /var/lib/node_exporter/textfile_collector
sudo install -d -m 755 /usr/local/libexec
sudo install -m 755 rpi-hardware-metrics.py /usr/local/libexec/rpi-hardware-metrics.py
sudo install -m 644 rpi-collector.service rpi-collector.timer /etc/systemd/system/

Die Datei rpi-collector.service enthält:

Konfiguration
[Unit]
Description=Collect Raspberry Pi firmware metrics

[Service]
Type=oneshot
User=rpi-metrics
SupplementaryGroups=video
ExecStart=/usr/bin/python3 /usr/local/libexec/rpi-hardware-metrics.py /var/lib/node_exporter/textfile_collector
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/node_exporter/textfile_collector

Die Datei rpi-collector.timer enthält:

Konfiguration
[Unit]
Description=Collect Raspberry Pi firmware metrics periodically

[Timer]
OnBootSec=30s
OnUnitActiveSec=60s
AccuracySec=1s

[Install]
WantedBy=timers.target

sudo -u rpi-metrics /usr/bin/vcgencmd measure_temp und der entsprechende Aufruf für get_throttled prüfen den tatsächlichen Zugriff. Der Exporter benötigt Leserechte auf Verzeichnis und erzeugte Datei. Das installierte Skript gehört root; das Dienstkonto schreibt nur in das Collector-Ausgabeverzeichnis.

Beim Debian-Paket zeigt systemctl cat prometheus-node-exporter, wie Startargumente eingelesen werden. Bei Verwendung von /etc/default/prometheus-node-exporter benötigt das vorhandene ARGS zusätzlich --collector.textfile.directory=/var/lib/node_exporter/textfile_collector und --web.listen-address=127.0.0.1:9100. Andere vorhandene Optionen bleiben erforderlich; doppelte Optionen für das Verzeichnis oder die Empfangsadresse müssen aufgelöst werden. Maßgeblich ist die Konfiguration des tatsächlich installierten Pakets.

Nach der Konfiguration aktivieren sudo systemctl restart prometheus-node-exporter, sudo systemctl daemon-reload und sudo systemctl enable --now rpi-collector.timer die Dienste. sudo systemctl start rpi-collector.service startet einen ersten Lauf. Fehler bleiben über journalctl -u rpi-collector.service sichtbar; wiederholte Einrichtung hängt keine doppelten Cron-Einträge an.

3. Messwerte mit Prometheus speichern

Die folgende compose.yaml verwendet unter Linux Host-Netzwerk, damit die Container-Loopback-Adresse den Host-Exporter erreicht. Ausdrücklich gesetzte lokale Empfangsadressen begrenzen den direkten Zugriff auf Prometheus und Grafana auf den Pi. Eine geschützte .env definiert getestete ARM-kompatible Image-Referenzen für PROMETHEUS_IMAGE und GRAFANA_IMAGE sowie ein eigenes GRAFANA_ADMIN_PASSWORD für die Ersteinrichtung. Eine bestehende Grafana-Datenbank behält das bereits eingerichtete Administratorpasswort.

YAML
services:
  prometheus:
    image: ${PROMETHEUS_IMAGE:?set tested prom/prometheus release}
    network_mode: host
    restart: unless-stopped
    command:
      - --config.file=/etc/prometheus/prometheus.yml
      - --storage.tsdb.path=/prometheus
      - --storage.tsdb.retention.time=7d
      - --web.listen-address=127.0.0.1:9090
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - ./alerts.yml:/etc/prometheus/alerts.yml:ro
      - prometheus-data:/prometheus
  grafana:
    image: ${GRAFANA_IMAGE:?set tested grafana/grafana release}
    network_mode: host
    restart: unless-stopped
    environment:
      GF_SERVER_HTTP_ADDR: 127.0.0.1
      GF_SERVER_HTTP_PORT: "3000"
      GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD:?set initial admin password}
      GF_AUTH_ANONYMOUS_ENABLED: "false"
    volumes:
      - grafana-data:/var/lib/grafana
volumes:
  prometheus-data:
  grafana-data:

Die Datei prometheus.yml im selben Ordner enthält:

YAML
global:
  scrape_interval: 15s
  evaluation_interval: 15s
rule_files:
  - /etc/prometheus/alerts.yml
scrape_configs:
  - job_name: raspberry_pi
    static_configs:
      - targets: ["127.0.0.1:9100"]

Sieben Tage Aufbewahrung sind ein Beispiel und keine Begrenzung des Speicherplatzverbrauchs. Benannte Volumes erhalten Daten beim Neuerstellen der Container. Freier Speicher, Schreiblast und Sicherungen benötigen eigene Überwachung. Ein Abruf alle 15 Sekunden erhöht nicht die ungefähr minütliche Messfrequenz des Collectors.

4. Alarmregeln und Benachrichtigungen trennen

Die folgende alerts.yml prüft Messwerte und die Funktionsfähigkeit der Erfassung. Die Schwelle 75 °C ist ein beispielhafter Betriebswert und keine universelle Hardwaregrenze. Die Regel für fehlende Reihen setzt diesen Job mit genau einem Ziel voraus; mehrere Hosts benötigen eine zielbezogene Ausfallerkennung.

YAML
groups:
  - name: raspberry_pi
    rules:
      - alert: PiExporterDown
        expr: up{job="raspberry_pi"} == 0
        for: 2m
      - alert: PiCollectorStale
        expr: time() - rpi_collector_last_success_timestamp_seconds{job="raspberry_pi"} > 180
        for: 1m
      - alert: PiCollectorMissing
        expr: absent(rpi_collector_last_success_timestamp_seconds{job="raspberry_pi"})
        for: 2m
      - alert: PiTextfileError
        expr: node_textfile_scrape_error{job="raspberry_pi"} == 1
        for: 1m
      - alert: PiTemperatureHigh
        expr: rpi_soc_temperature_celsius{job="raspberry_pi"} > 75
        for: 5m
      - alert: PiCurrentFirmwareWarning
        expr: rpi_hardware_flag{job="raspberry_pi",state="current"} == 1

docker compose config --quiet prüft Compose. promtool check config und promtool check rules aus dem gewählten Image validieren die Prometheus-Dateien vor dem Start. docker compose up -d startet den Aufbau. Die Regeln zeigen ausstehende oder aktive Alarme in Prometheus; E-Mail- oder Push-Nachrichten entstehen erst nach Einrichtung und Prüfung einer Alertmanager-Anbindung. Auch eine Grafana-Panelschwelle allein ist keine Benachrichtigungsregel.

Auf dem Arbeitsplatzrechner leitet ssh -N -L 3000:127.0.0.1:3000 -L 9090:127.0.0.1:9090 ACCOUNT@PI_ADDRESS die lokalen Browserports weiter. Die Platzhalter bezeichnen das tatsächliche SSH-Konto und die Pi-Adresse. Grafana öffnet unter http://127.0.0.1:3000; die Prometheus-Datenquelle verwendet http://127.0.0.1:9090, weil beide Container das Host-Netz teilen.

Sinnvolle Panels und deren Grenzen

  • rpi_soc_temperature_celsius: abgetastete SoC-Temperatur.
  • rpi_hardware_flag{state="current"}: aktuelle Firmware-Flags; state="since_boot" zeigt aufgezeichnete Vorfälle.
  • 100 * rate(node_disk_io_time_seconds_total[5m]): prozentuale Geräte-Beschäftigungszeit mit Grenzen der Kernel-Zeitrechnung. Das ist weder Flash-Verschleiß noch Anfragelatenz.
  • 100 * node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes: verfügbarer RAM-Anteil, keine Rate pro Sekunde.

Eine passende Geräteauswahl vermeidet irreführende Vergleiche physischer Laufwerke und virtueller Geräte. Speicherverschleiß benötigt unterstützte SMART-/NVMe- oder Hersteller-Gesundheitswerte; viele SD-Karten geben kaum brauchbare Verschleißdaten aus. Hohe Beschäftigungszeit allein identifiziert keinen verschlissenen Controller.

Fragen und Antworten

Wie lässt sich der Datenweg ohne Speicher-Stresstest prüfen?

Exporter-Erreichbarkeit, up, node_textfile_scrape_error, Alter des letzten Erfolgs und Timer-Protokolle bilden die erste Kontrolle. In einer getrennten Testumgebung sollte ein angehaltener Timer einen Veraltungsalarm auslösen; fehlerhafte synthetische Befehlsantworten müssen die letzte gültige Datei unverändert lassen. Ein intensiver zufälliger Schreibtest ist dafür unnötig.

Identifiziert ein Unterspannungs-Flag die Ursache?

Nein. Das Flag meldet einen erkannten Zustand. Netzteil, Kabel, Anschlüsse und Peripherielast benötigen eine getrennte Untersuchung. Temperatur und Drosselung beschreiben Symptome; weder Diagramm noch Flag garantieren die Vermeidung eines Ausfalls.

Bezeichnet 127.0.0.1 immer den Host?

Nein. Gewöhnliche Bridge-Container besitzen eigene Loopback-Schnittstellen. Das Beispiel verwendet ausdrücklich Host-Netzwerk. Ein anderer Aufbau benötigt eine erreichbare Exporter-Adresse und eine dazu passende Grafana-Datenquelle.

Homelab auf dem Raspberry Pi

  1. Raspberry Pi 4 und 5: Vom SSD-Laufwerk booten über den Bootloader
  2. USV für Raspberry Pi: fünf Lösungen und Auswahlkriterien
  3. Lokales CI/CD für den Raspberry Pi: Automatisierung von Docker-Compose-Deployments
  4. Docker-Compose-Heimserver: Traefik, TLS und Update-Prüfung
  5. Jellyfin auf Raspberry Pi 5: Direct Play und Grenzen der Transkodierung
  6. Raspberry Pi als gehärtetes WireGuard-VPN-Gateway mit Split-Tunneling
  7. Raspberry Pi mit Prometheus und Grafana überwachen
Lukas Wojcik

Lukas Wojcik

Systems architect and technology enthusiast specializing in scalable tracking solutions, GMP Stack (GA4 & GTM), and robust backend architectures. Advocate for clean code and privacy-first design.

Kontakt

Eine Frage oder eine Idee für ein Webprojekt? Schreib mir kurz, worum es geht. Das Formular nutzt reCAPTCHA zum Schutz vor Spam.

Kommentar schreiben

Erfahrungen mit anderen Modellen und Rückfragen zum Aufbau sind hier willkommen.

Die E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind mit einem Stern versehen.