Vor drei Monaten habe ich auf einem Raspberry Pi 4 ein Prometheus und ein Grafana aufgesetzt. 12 Hosts, auf jedem ein node_exporter, Scrape-Intervall 15 Sekunden, Retention 15 Tage. Die Frage, die mich seither begleitet: Was kostet das eigentlich? Nicht in Euro, sondern in RAM, Platte und Nerven. Kurze Antwort: weniger als jeder Cloud-Monitoring-Vertrag, aber mehr, als die meisten Blog-Artikel dir erzählen.
In diesem Artikel rechne ich es einmal komplett durch. Mit echten Serienzahlen von meinen 12 Hosts, nicht mit Hersteller-Slides. Am Ende weißt du, wie groß dein Prometheus wirklich sein muss, wann die ehrliche Antwort auf „mehr Metriken!“ schlicht „Overengineering“ lautet, und warum 20 Metriken pro Host ein guter Startpunkt sind.
Die Ausgangslage: 12 Hosts und ein Raspberry Pi
Das Setup ist unspektakulär: drei kleine VMs, vier Raspberry Pis im Haus, fünf ältere Server im Keller. Zwölf Maschinen insgesamt, die meisten mit Ubuntu, zwei mit Debian, und ein NVR-System, das ich lieber im Auge behalte. Auf jedem Host läuft der node_exporter auf Port 9100, die Firewall lässt nur den Monitoring-Host durch.
Der Prometheus selbst wohnt auf dem Pi 4 mit 4 Kernen und 8 GB RAM, als Datengrab dient eine kleine USB-SSD. Die SD-Karte ist mir zu heikel für eine TSDB, nach dem dritten korrupten Dateisystem habe ich das gelernt.
Jetzt kommt der Teil, den niemand in den Blog-Posts erwähnt: Der node_exporter liefert standardmäßig Hunderte Metriken pro Host. Wenn du alles nimmst, bist du sofort bei über 2.000 Serien, nur um zu sehen, ob deine Maschinen atmen. Meine Regel nach ein paar Wochen Experimentieren: 20 Metriken pro Host. CPU, RAM, Disk pro Mount, Netzwerk, Load, Uptime. Der Rest ist Rauschen.
Was eine Metrik wirklich kostet
Fangen wir mit der Grundeinheit an, der Serie. Eine Serie ist ein Metrikname plus ein Satz Labels, also zum Beispiel node_cpu_seconds_total mit den Labels instance, cpu und mode. Bei einem 15-Sekunden-Scrape-Intervall produziert jede Serie vier Samples pro Minute, 240 pro Stunde, 5.760 pro Tag.
Zwölf Hosts mal 20 Metriken ergibt 240 Serien. Hochgerechnet sind das 240 mal 5.760, also rund 1,4 Millionen Samples pro Tag. Das klingt viel, bis du die nächste Zahl siehst: Prometheus komprimiert Samples in Chunks und braucht im Schnitt nur etwa 2 Bytes pro Sample. 1,4 Millionen Samples mal 2 Bytes sind 2,8 MB pro Tag. Bei 15 Tagen Retention landest du bei rund 42 MB für die eigentlichen Daten.
Dazu kommen Head-Chunks, das WAL und der Index. In der Praxis zeigt mein Prometheus nach drei Monaten Laufzeit rund 90 MB auf der Platte, also knapp das Doppelte der reinen Daten. Wer dir erzählt, Monitoring frisst Terabytes: erst ab ein paar Millionen Serien.
# Die Rechnung für 12 Hosts:
240 Serien × 5.760 Samples/Tag = 1.382.400 Samples
1.382.400 × 2 Bytes = 2,8 MB/Tag
× 15 Tage Retention = ~42 MB TSDB
+ WAL, Head, Index = ~60-100 MB gesamt
Und der RAM? Hier kommt die Überraschung: Die Metriken selbst sind fast gratis. Der Prometheus-Prozess hat einen Grundbedarf von rund 150 MB, egal ob du 10 oder 1.000 Serien scrapst. Go-Runtime, Index-Cache, Query-Engine, das alles ist fix. Bei meinen 240 Serien liegt der Prozess bei etwa 200 MB RSS. Erst ab einigen tausend Serien skaliert der Speicher spürbar mit.
prometheus.yml: So scrapst du schlank
Die ganze Kunst steckt im Scrape-Config. Mein prometheus.yml ist bewusst kurz gehalten, und die Hosts stehen als statische Targets, weil sich die Liste selten ändert. Service Discovery über DNS oder Consul kannst du später immer noch nachrüsten, wenn es wehtut.
global:
scrape_interval: 15s
evaluation_interval: 30s
scrape_configs:
- job_name: "node"
static_configs:
- targets:
- "vm01:9100"
- "vm02:9100"
- "vm03:9100"
- "pi01:9100"
# ... bis Host 12
relabel_configs:
- source_labels: [__address__]
regex: "([^:]+):.*"
target_label: instance
Der relabel_configs-Block ist kein Schnickschnack: Ohne ihn würde Prometheus die komplette Adresse inklusive Port als instance-Label speichern. Mit dem Regex bekommst du saubere Hostnamen, und deine Queries bleiben lesbar. Kleine Details wie dieses entscheiden, ob dein Dashboard nach zwei Monaten noch Spaß macht.
Recording Rules: Rechenarbeit aus den Queries raus
Die zweite Stellschraube sind Recording Rules. Statt bei jedem Dashboard-Load dieselbe teure Query zu rechnen, lässt du Prometheus sie einmal pro Minute ausrechnen und das Ergebnis als eigene Serie speichern. Das senkt die Query-Last spürbar, gerade wenn Grafana alle paar Sekunden refresht.
# rules.yml
groups:
- name: node.rules
rules:
- record: node:cpu_usage_ratio
expr: |
1 - avg(rate(node_cpu_seconds_total{mode="idle"}[5m]))
by (instance)
- record: node:memory_usage_ratio
expr: |
1 - node_memory_MemAvailable_bytes
/ node_memory_MemTotal_bytes
Ein Hinweis, den ich mir erst nach einem Monat eingestehen wollte: Jede Recording Rule erzeugt eine neue Serie und kostet damit auch Speicher. Zwei, drei gut gewählte Regeln sind Gold. Zwanzig Regeln für jede erdenkliche Metrik sind wieder Overengineering, nur mit anderem Namen.
Grafana: Datasource, Dashboard und der JSON-Test
Grafana selbst ist beim Speicher fast unsichtbar. Die Dashboards liegen als JSON-Dateien auf der Platte, die Metadaten in einer kleinen SQLite-Datenbank. Was zählt, ist die Konfiguration der Datasource, damit Grafana weiß, wo es fragen soll.
# grafana/provisioning/datasources/prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://localhost:9090
access: proxy
isDefault: true
Wenn ich prüfen will, ob alles sauber läuft, frage ich nicht zuerst Grafana ab, sondern die Prometheus-API direkt. Ein curl auf die Query-Schnittstelle sagt dir in einer Zeile, ob deine Hosts da sind:
curl "http://localhost:9090/api/v1/query?query=up"
Zurück kommt JSON mit dem Status deines ganzen Setups, und genau hier hilft der JSON Formatter von bitcalc: Die Antwort aus der API ist ein einziger langer Zeilenwust, und mit Formatierung siehst du sofort, welcher Host down ist. Monitoring und JSON gehören eben zusammen.
Das ehrliche Gespräch: Mehr Metriken ist oft Overengineering
Der häufigste Satz in Monitoring-Chats lautet: „Wir brauchen mehr Metriken!“ Meistens stimmt das nicht. Meistens fehlt keine Metrik, sondern eine Frage, die man mit den vorhandenen Daten nicht beantworten kann. Und dann ist die Lösung eine Query, nicht eine neue Metrik.
Mein Startpunkt nach den Experimenten: 20 Metriken pro Host. CPU-Auslastung, freier RAM, Disk-Belegung pro Mount, Netzwerk rein und raus, Load Average, Uptime. Das reicht, um 95 Prozent der Alerts zu bauen, die du wirklich brauchst. Alles Weitere fügst du hinzu, wenn eine echte Frage es verlangt, nicht weil der Exporter es anbietet.
Was du getrost weglassen kannst: die process_-Metriken des node_exporter, die Per-CPU-Aufschlüsselung, wenn du sie nie anschaust, und Filesystem-Serien für jedes tmpfs. Bei mir hat das Ausmisten die Serienzahl halbiert, ohne dass ein Dashboard dunkel wurde.
Und dann ist da noch die Cardinality-Falle. Mehr Labels bedeuten mehr Serien, und zwar multiplikativ. instance, job, device und mountpoint reichen als Labels völlig aus. Wer build_version oder user_email als Label in Metriken schreibt, baut sich gerade ein Speicherproblem, das erst in sechs Monaten sichtbar wird.
Wo der 4-Kerner an seine Grenzen kommt
Bei 12 Hosts ist der Pi schlicht gelangweilt. Die CPU-Last von Prometheus liegt im Promillebereich, und Grafana refresht nur, wenn du es brauchst. Bei 50 Hosts, also 1.000 Serien, wird es interessant: rund 350 MB Disk pro Monat und ein Prozess bei etwa 500 MB RAM. Das passt immer noch locker auf die Kiste.
Bei 200 Hosts und 4.000 Serien sieht die Welt anders aus: 1,4 GB Disk pro Monat, der Prozess hängt bei 2,5 GB RAM, und die ersten Queries werden zäh. Spätestens dann stellt sich die Frage nach längerer Retention, nach VictoriaMetrics oder Thanos, oder nach der ehrlichen Einsicht, dass man nicht alle Metriken 15 Tage lang behalten muss.
Wichtig ist aber: Das eigentliche Problem ist fast nie die Platte. Es ist die Cardinality und die Query-Last. Ein Dashboard mit 20 Panels, die alle 5 Sekunden refreshen, drückt einen kleinen Server stärker als 4.000 brav schlafende Serien. Überwache deine Queries, nicht nur deine Hosts.
Fazit
Monitoring kostet weniger, als die Hersteller dich glauben lassen wollen, wenn du schlank scrapst. Ein Prometheus auf vier Kernen mit 15-Sekunden-Intervall und 15 Tagen Retention ist für ein Dutzend Hosts eine Sache von ein paar hundert MB RAM und einer Handvoll GB im Jahr. Das schafft jeder Mini-Server nebenbei.
Fang mit 20 Metriken pro Host an, beobachte deine Cardinality, und füge Metriken nur hinzu, wenn eine Frage es wirklich verlangt. Und wenn du das JSON aus der Prometheus-API lesen musst: Der JSON Formatter macht aus dem Zeilenwust eine lesbare Antwort. Monitoring soll dir Arbeit abnehmen, nicht welche machen.