MonitoringDockerGrafanaPraxis-Guide

Professionelles Monitoring Setup 2025

Warum erst reagieren, wenn der Server schon brennt? In diesem Guide baust du ein professionelles Monitoring-System auf, das dir zeigt was wirklich auf deinen Servern passiert - bevor Probleme entstehen. Mit Grafana, InfluxDB und Telegraf erstellst du Dashboards wie die Profis.

22. März 2025
35 Minuten Lesezeit
Produktiv getestet

1. Warum überhaupt Monitoring?

Das klassische Szenario

Es ist Sonntagabend, 23:47 Uhr. Dein Handy klingelt. "Die Website ist down!" - "Seit wann?" - "Keine Ahnung, könnte schon Stunden sein..." Kommt dir das bekannt vor?

Monitoring ist nicht nur „nice to have“ - es ist essentiell für jeden Server, der mehr als ein Hobby-Projekt ist. Aber es geht nicht nur um „läuft der Server noch?“. Echtes Monitoring zeigt dir:

🔍 Trends erkennen

CPU-Last steigt kontinuierlich? Vielleicht läuft da ein Memory Leak, der in zwei Wochen zum Problem wird.

Disk-Space füllt sich langsam? Besser jetzt aufräumen als wenn's zu spät ist.

Response-Zeiten werden schlechter? Zeit für Optimierung, bevor User abspringen.

⚡ Probleme vor dem Crash finden

RAM bei 95%? Alert kommt, bevor der OOM-Killer zuschlägt.

Disk I/O explodiert? Du siehst es, bevor alles langsam wird.

Netzwerk-Timeouts? Diagnose in Echtzeit statt Ratespiele.

Was ich in 5 Jahren gelernt habe

Ich betreibe seit 2019 mehrere Server (Raspberry Pis, VPS, Dedicated Server) und hatte alle klassischen Probleme:

  • 2020: Raspberry Pi überhitzt regelmäßig im Sommer → Hätte ich mit Temp-Monitoring sofort gesehen
  • 2021: WordPress-Site wird langsam über Wochen → MySQL slow queries, aber erst nach User-Beschwerden erkannt
  • 2022: Docker-Container läuft voll, lädt aber weiter Daten → Festplatte nach 3 Tagen voll
  • 2023: API-Response-Zeiten verdoppeln sich schleichend → Erst nach Monitoring-Setup erkannt: Database-Connection-Pool zu klein

Das Muster: Alle Probleme waren schleichend und hätten mit Monitoring Wochen früher erkannt werden können.

Was richtiges Monitoring leistet

Proaktiv statt reaktiv: Du siehst Probleme kommen, bevor sie kritisch werden.

Datenbasierte Entscheidungen: „Brauchen wir mehr RAM?“ - Schau ins Dashboard statt zu raten.

Optimierung mit Zahlen: Welche Änderung bringt wirklich was? Die Metriken zeigen es.

Compliance & SLAs: „Uptime 99.9%“ ist messbar, nicht nur ein Versprechen.

2. Den TIG-Stack verstehen

TIG steht für Telegraf, InfluxDB, Grafana - die drei Komponenten unseres Monitoring-Stacks. Aber warum gerade diese Kombination? Und warum nicht einfach ein „All-in-One“-Tool?

Die Philosophie: Jedes Tool macht eine Sache richtig

InfluxDB

Speichert Zeitreihendaten extrem effizient. 1 Million Datenpunkte? Kein Problem.

Telegraf

Sammelt alles: CPU, RAM, Docker, APIs, Logs. 200+ Input-Plugins.

Grafana

Macht aus Daten verständliche Dashboards. Alerts inklusive.

Warum nicht Prometheus + Node Exporter?

Gute Frage! Prometheus ist definitiv der Standard in der Kubernetes-Welt. Aber für kleinere Setups (1-10 Server) hat der TIG-Stack einige Vorteile:

TIG-Stack Vorteile
  • Einfachere Installation: Ein docker-compose, läuft
  • InfluxDB ist SQL-ähnlich: SELECT * FROM cpu WHERE time > now()-1h
  • Telegraf ist unkompliziert: Config-File, Plugin an, fertig
  • Bessere Datenretention: InfluxDB komprimiert brutal gut
Prometheus Vorteile
  • Industry Standard: Jeder Cloud-Provider unterstützt es
  • Kubernetes Integration: Native Service Discovery
  • PromQL: Mächtige Query Language
  • Ecosystem: Mehr Exporter, mehr Community

Meine Empfehlung: TIG für Homelab/kleinere Setups, Prometheus für Production/Kubernetes.

Wie die Daten fließen

1. Telegraf sammelt alle 10 Sekunden Daten:
CPU: 45% | RAM: 2.1GB/8GB | Disk: 45GB free | Network: 1.2MB/s
2. InfluxDB speichert diese als Zeitreihen:
2025-01-12T15:30:00Z cpu_usage_percent=45.0 host=server1
2025-01-12T15:30:00Z mem_used_bytes=2147483648 host=server1
3. Grafana visualisiert die Daten:
SELECT mean(cpu_usage_percent) FROM "cpu" WHERE time > now()-1h GROUP BY time(5m)

Wichtig: Retention Policy verstehen

InfluxDB speichert nicht grundsätzlich endlos. Könnte es aber! Standard: 1 Jahr. Das bedeutet: Daten werden automatisch nach 365 Tagen gelöscht. Für Homelab meist okay, für Business kritisch zu planen. Aber für Raspberry Pi mit nur einer SD-Karte, auch nicht die beste Idee. ;-)

3. InfluxDB: Die Zeitreihendatenbank

InfluxDB ist das Herzstück unseres Setups. Hier landen alle Metriken, und die Art wie wir es konfigurieren entscheidet über Performance und Speicherverbrauch. Ich zeige dir, was ich in der Praxis gelernt habe.

Vorbereitung: Verzeichnisstruktur

Monitoring-Ordner strukturiert anlegen
# Hauptverzeichnis für Monitoring-Stack
mkdir -p ~/monitoring/{influxdb,telegraf,grafana}
cd ~/monitoring

# InfluxDB Datenverzeichnisse
mkdir -p influxdb/{data,config}

# Konfigurationsverzeichnisse
mkdir -p telegraf/config
mkdir -p grafana/{data,dashboards,provisioning}

# Berechtigungen setzen (wichtig für Container!)
sudo chown -R 1000:1000 ~/monitoring
chmod -R 755 ~/monitoring

# Struktur prüfen
sudo apt install tree
tree ~/monitoring
# monitoring/
# ├── influxdb/
# │   ├── data/
# │   └── config/
# ├── telegraf/
# │   └── config/
# └── grafana/
#     ├── data/
#     ├── dashboards/
#     └── provisioning/

InfluxDB 2.x Container starten

docker-compose.yml für InfluxDB
# ~/monitoring/docker-compose.yml erstellen
cat > docker-compose.yml << 'EOF'
version: '3.8'

services:
  influxdb:
    image: influxdb:2.7-alpine
    container_name: influxdb
    restart: unless-stopped
    ports:
      - "8086:8086"
    volumes:
      - ./influxdb/data:/var/lib/influxdb2
      - ./influxdb/config:/etc/influxdb2
    environment:
      # Initial Setup - WICHTIG: Nur beim ersten Start
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=monitoring2025!
      - DOCKER_INFLUXDB_INIT_ORG=homelab
      - DOCKER_INFLUXDB_INIT_BUCKET=metrics
      - DOCKER_INFLUXDB_INIT_RETENTION=365d
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=super-secret-auth-token-change-me
    networks:
      - monitoring

networks:
  monitoring:
    driver: bridge
EOF

# InfluxDB starten
docker compose up -d influxdb

Wichtige Security-Hinweise

Token ändern: `DOCKER_INFLUXDB_INIT_ADMIN_TOKEN` ist dein Master-Key. Generiere einen sicheren Token!

Passwort sicher: `monitoring2025!` nur als Beispiel - wähle ein starkes Passwort.

Port 8086: Nur bei Bedarf extern zugänglich machen (Firewall!)

Ersten Start prüfen und konfigurieren

InfluxDB Setup verifizieren
# Container-Status prüfen
docker compose ps
# Sollte zeigen: influxdb running

# Logs prüfen - wichtig für Troubleshooting
docker compose logs influxdb

# InfluxDB UI öffnen
Öffne: http://YOUR-SERVER-IP:8086
Login: admin / monitoring2025! (was du natürlich anpassen solltest!)

# CLI-Test (optional)
docker exec -it influxdb influx auth list
# Sollte deinen Token zeigen

Warum diese Konfiguration?

Retention Policy: 365 Tage

Warum 1 Jahr? Für Monitoring brauchst du längere Trends. Beispiele aus der Praxis:

  • Saisonale Patterns: Website-Traffic im Dezember vs. Januar
  • Hardware-Trends: RAM-Verbrauch steigt über Monate
  • Kapazitätsplanung: „Wann ist die Festplatte voll?“ → Trend über 6 Monate
Alpine Image: Ressourcenschonend

InfluxDB 2.7-alpine anstelle eines Standard-Images: Nur 150MB Speicherverbrauch statt 300MB. Besonders wichtig bei Raspberry Pi oder VPS mit begrenztem RAM.

InfluxDB läuft! Nächste Schritte

✅ Container läuft stabil

✅ Web-UI ist erreichbar

✅ Admin-User wurde erstellt

✅ Default-Bucket "metrics" existiert

🔄 Jetzt: Telegraf konfigurieren für Datensammlung

4. Telegraf: Der Datensammler

Telegraf ist der Arbeiter in unserem Stack. Er sammelt alle 10 Sekunden Daten von überall und schickt sie an InfluxDB. Aber welche Plugins brauchst du wirklich? Und welche fressen nur Ressourcen?

Basis-Konfiguration: Die wichtigsten Plugins

telegraf.conf erstellen
# ~/monitoring/telegraf/config/telegraf.conf
cat > ~/monitoring/telegraf/config/telegraf.conf << 'EOF'
[global_tags]
  # Wichtig: Eindeutige Identifikation des Servers
  host = "$HOSTNAME"
  datacenter = "homelab"

[agent]
  interval = "10s"          # Alle 10 Sekunden sammeln
  round_interval = true     # Auf volle 10s runden (wichtig für Grafana!)
  metric_batch_size = 1000  # Batch-Größe für bessere Performance
  metric_buffer_limit = 10000
  collection_jitter = "0s"  # Kein Jitter bei einzelnem Host
  flush_interval = "10s"    # Sofort an InfluxDB senden
  flush_jitter = "0s"

# OUTPUT: Verbindung zu InfluxDB
[[outputs.influxdb_v2]]
  urls = ["http://influxdb:8086"]
  token = "super-secret-auth-token-change-me"  # Dein InfluxDB Token
  organization = "homelab"
  bucket = "metrics"
  timeout = "5s"

# INPUT 1: System-Metriken (CPU, RAM, Disk)
[[inputs.cpu]]
  percpu = true             # Pro CPU-Core einzeln
  totalcpu = true          # + Gesamt-CPU
  collect_cpu_time = false # CPU-Zeit brauchen wir nicht
  report_active = false    # Active/Idle-Ratio nicht nötig

[[inputs.disk]]
  ignore_fs = ["tmpfs", "devtmpfs", "devfs", "iso9660", "overlay", "aufs", "squashfs"]
  # Nur echte Filesysteme, nicht temporäre

[[inputs.diskio]]
  # Disk I/O ist oft der Flaschenhals
  
[[inputs.kernel]]
  # Kernel-Statistiken

[[inputs.mem]]
  # RAM-Verbrauch

[[inputs.processes]]
  # Anzahl Prozesse

[[inputs.swap]]
  # Swap-Verbrauch (wichtig bei wenig RAM)

[[inputs.system]]
  # System Load, Uptime etc.

# INPUT 2: CPU-Temperatur (wichtig für Raspberry Pi & Co.)
[[inputs.file]]
  files = ["/sys/class/thermal/thermal_zone0/temp"]
  name_override = "cpu_temperature"
  data_format = "value"
  data_type = "integer"

[[inputs.exec]]
  # Für ein 32bit System (welches überwacht werden soll)
  commands = ["/opt/vc/bin/vcgencmd measure_temp"]
  # Oder für ein 64bit System (welches überwacht werden soll), dann die Raute(#) entfernen und bei 32bit die Raute hinzufügen
  # commands = ["/usr/bin/vcgencmd measure_temp"]
  name_override = "cpu_temperature"
  data_format = "value"
  data_type = "string"

# INPUT 3: Netzwerk
[[inputs.net]]
  interfaces = ["eth*", "en*", "wlan*"]  # Nur echte Interfaces
  ignore_protocol_stats = false

[[inputs.netstat]]
  # TCP-Verbindungen

# INPUT 4: Docker (wenn vorhanden)
[[inputs.docker]]
  endpoint = "unix:///var/run/docker.sock"
  gather_services = false  # Services nicht nötig
  container_names = []     # Alle Container
  container_name_include = []
  container_name_exclude = []
  timeout = "5s"
  perdevice = true        # Per Container einzeln
  total = false           # Gesamt nicht nötig
EOF

Telegraf zu Docker Compose hinzufügen

docker-compose.yml erweitern
# ~/monitoring/docker-compose.yml erweitern
# WICHTIG: Stelle sicher, dass die Einrückung korrekt ist!

cat >> ~/monitoring/docker-compose.yml << 'EOF'

  telegraf:
    image: telegraf:1.28-alpine
    container_name: telegraf
    restart: unless-stopped
    volumes:
      # Konfiguration
      - ./telegraf/config/telegraf.conf:/etc/telegraf/telegraf.conf:ro
      # Host-System-Zugriff für Metriken
      - /:/hostfs:ro
      - /etc:/hostfs/etc:ro
      - /proc:/hostfs/proc:ro
      - /sys:/hostfs/sys:ro
      - /var:/hostfs/var:ro
      - /run:/hostfs/run:ro
      # Docker-Socket für Container-Metriken
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      # Wichtig: Host-Pfade für System-Metriken
      - HOST_ETC=/hostfs/etc
      - HOST_PROC=/hostfs/proc
      - HOST_SYS=/hostfs/sys
      - HOST_VAR=/hostfs/var
      - HOST_RUN=/hostfs/run
      - HOST_MOUNT_PREFIX=/hostfs
    networks:
      - monitoring
    depends_on:
      - influxdb
    user: telegraf:docker  # Docker-Gruppe für Socket-Zugriff
EOF

# Alternative: Vollständige docker-compose.yml erstellen
# Falls das Append nicht funktioniert, erstelle die Datei komplett neu:
cat > ~/monitoring/docker-compose.yml << 'EOF'
version: '3.8'

services:
  influxdb:
    image: influxdb:2.7-alpine
    container_name: influxdb
    restart: unless-stopped
    ports:
      - "8086:8086"
    volumes:
      - ./influxdb/data:/var/lib/influxdb2
      - ./influxdb/config:/etc/influxdb2
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=monitoring2025!
      - DOCKER_INFLUXDB_INIT_ORG=homelab
      - DOCKER_INFLUXDB_INIT_BUCKET=metrics
      - DOCKER_INFLUXDB_INIT_RETENTION=365d
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=super-secret-auth-token-change-me
    networks:
      - monitoring

  telegraf:
    image: telegraf:1.28-alpine
    container_name: telegraf
    restart: unless-stopped
    volumes:
      - ./telegraf/config/telegraf.conf:/etc/telegraf/telegraf.conf:ro
      - /:/hostfs:ro
      - /etc:/hostfs/etc:ro
      - /proc:/hostfs/proc:ro
      - /sys:/hostfs/sys:ro
      - /var:/hostfs/var:ro
      - /run:/hostfs/run:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - HOST_ETC=/hostfs/etc
      - HOST_PROC=/hostfs/proc
      - HOST_SYS=/hostfs/sys
      - HOST_VAR=/hostfs/var
      - HOST_RUN=/hostfs/run
      - HOST_MOUNT_PREFIX=/hostfs
    networks:
      - monitoring
    depends_on:
      - influxdb
    user: telegraf:docker

networks:
  monitoring:
    driver: bridge
EOF

Docker-Socket Security

Problem: Docker-Socket = Root-Zugriff auf Host. Telegraf braucht ihn für Container-Metriken.

Lösung: Docker-Gruppe ID finden und verwenden

# 1. Docker-Gruppe ID prüfen
cat /etc/group | grep docker
# Beispiel Output: docker:x:999:user

# 2. Falls Docker-Gruppe nicht existiert, erstellen:
sudo groupadd docker

# 3. Aktuellen User zur Docker-Gruppe hinzufügen
sudo usermod -a -G docker $USER

# 4. docker-compose.yml anpassen - user-Zeile ändern:
# user: "telegraf:999"  # 999 = docker group id aus Schritt 1

# 5. Telegraf neustarten
docker compose down
docker compose up -d

Alternative: Docker-Plugin deaktivieren (einfacher)

# 1. docker-compose.yml anpassen - user-Zeile entfernen:
# user: telegraf:docker  # Diese Zeile auskommentieren oder löschen

# 2. telegraf.conf anpassen - Docker-Input auskommentieren:
# [[inputs.docker]]
#   endpoint = "unix:///var/run/docker.sock"
#   ... rest der docker config

# 3. Telegraf neustarten
docker compose down
docker compose up -d

Empfehlung: Für den Start: Alternative verwenden (nur System-Metriken). Später kann Docker-Monitoring hinzugefügt werden.

Warum diese Plugin-Auswahl?

Telegraf hat 200+ Input-Plugins. Aber 90% brauchst du nie. Hier meine Erfahrung aus 5 Jahren:

✅ Essentiell (immer aktivieren)
  • cpu, mem, disk: Die großen Drei
  • diskio: I/O-Bottlenecks finden
  • system: Load Average, Uptime
  • net: Netzwerk-Traffic
  • docker: Container-Ressourcen
  • cpu_temperature: Überhitzung verhindern
❌ Überflüssig (vermeide diese)
  • logparser: Macht InfluxDB langsam
  • ping: Netzwerk-Spam
  • sensors: Nur bei Hardware-Problemen
  • iptables: Meist nutzlos
  • snmp: Nur für Enterprise-Hardware
💡 CPU-Temperatur: Warum zwei Inputs?

[[inputs.file]]: Liest direkt aus /sys/class/thermal/thermal_zone0/temp (Linux-Systeme)

[[inputs.exec]]: Verwendet vcgencmd (Raspberry Pi spezifisch)

Beide: Überschreiben den Namen zu "cpu_temperature" für einheitliche Metriken

Wichtig: Nur eine Methode funktioniert pro System - das ist normal!

Telegraf starten und testen

Container starten und prüfen
# Telegraf starten
cd ~/monitoring
docker compose up -d telegraf

# Logs prüfen - wichtig!
docker compose logs telegraf
# Sollte zeigen: "Starting Telegraf " und keine Errors

# Verbindung zu InfluxDB prüfen
docker compose logs telegraf | grep "Error"
# Sollte NICHTS zeigen

# Container-Status
docker compose ps
# Beide Container sollten "Up" sein

# Quick-Test: Daten in InfluxDB angekommen?
docker exec -it influxdb influx query 'from(bucket:"metrics") |> range(start:-1m) |> limit(n:5)'
# Sollte aktuelle Metriken zeigen

Telegraf läuft! Was passiert jetzt?

✅ Alle 10 Sekunden sammelt Telegraf System-Metriken

✅ Daten landen automatisch in InfluxDB bucket "metrics"

✅ Measurements: cpu, mem, disk, diskio, net, docker...

🔄 Nächster Schritt: Grafana für schöne Dashboards

5. Grafana: Aus Daten werden Dashboards

Grafana macht aus nackten Zahlen verständliche Visualisierungen. Aber: Es kann alles - und dadurch wird es schnell überwältigend. Ich zeige dir, wie du effektive Dashboards baust, nicht nur „bunte Diagramme“.

Grafana Container hinzufügen

Vollständige docker-compose.yml mit Grafana
# ~/monitoring/docker-compose.yml - Vollständige Version
# WICHTIG: Korrekte YAML-Einrückung verwenden!

cat > ~/monitoring/docker-compose.yml << 'EOF'
services:
  influxdb:
    image: influxdb:2.7-alpine
    container_name: influxdb
    restart: unless-stopped
    ports:
      - "8086:8086"
    volumes:
      - ./influxdb/data:/var/lib/influxdb2
      - ./influxdb/config:/etc/influxdb2
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=monitoring2025!
      - DOCKER_INFLUXDB_INIT_ORG=homelab
      - DOCKER_INFLUXDB_INIT_BUCKET=metrics
      - DOCKER_INFLUXDB_INIT_RETENTION=365d
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=super-secret-auth-token-change-me
    networks:
      - monitoring

  telegraf:
    image: telegraf:1.28-alpine
    container_name: telegraf
    restart: unless-stopped
    volumes:
      - ./telegraf/config/telegraf.conf:/etc/telegraf/telegraf.conf:ro
      - /:/hostfs:ro
      - /etc:/hostfs/etc:ro
      - /proc:/hostfs/proc:ro
      - /sys:/hostfs/sys:ro
      - /var:/hostfs/var:ro
      - /run:/hostfs/run:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      - HOST_ETC=/hostfs/etc
      - HOST_PROC=/hostfs/proc
      - HOST_SYS=/hostfs/sys
      - HOST_VAR=/hostfs/var
      - HOST_RUN=/hostfs/run
      - HOST_MOUNT_PREFIX=/hostfs
    networks:
      - monitoring
    depends_on:
      - influxdb
    user: telegraf:docker

  grafana:
    image: grafana/grafana:10.2.2
    container_name: grafana
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - ./grafana/data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    environment:
      # Security: Default-Admin ändern
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=grafana2025!
      # Performance: Memory-Limits
      - GF_SERVER_ROOT_URL=http://localhost:3000
      - GF_ANALYTICS_REPORTING_ENABLED=false
      - GF_ANALYTICS_CHECK_FOR_UPDATES=false
      # Security: Anonymous Access disabled
      - GF_AUTH_ANONYMOUS_ENABLED=false
    networks:
      - monitoring
    depends_on:
      - influxdb
    user: "472:472"  # Grafana User/Group

networks:
  monitoring:
    driver: bridge
EOF

# Grafana-Verzeichnisse erstellen und Permissions setzen
mkdir -p ~/monitoring/grafana/data
mkdir -p ~/monitoring/grafana/provisioning

# Permissions für Grafana setzen (wichtig!)
sudo chown -R 472:472 ~/monitoring/grafana/data
sudo chown -R 472:472 ~/monitoring/grafana/provisioning

# Vollständiger Stack starten
docker compose down
docker compose up -d

# Alle Container prüfen
docker compose ps
# Sollte zeigen: influxdb, telegraf, grafana alle "Up"

Grafana Permissions-Problem

Problem: Grafana läuft als User ID 472, aber lokale Verzeichnisse gehören deinem User

Lösung: Verzeichnisse dem Grafana-User geben

Falls du den Fehler bereits hast:

# Container stoppen
docker compose down

# Verzeichnisse erstellen und Permissions setzen
mkdir -p ~/monitoring/grafana/data
mkdir -p ~/monitoring/grafana/provisioning
sudo chown -R 472:472 ~/monitoring/grafana/data
sudo chown -R 472:472 ~/monitoring/grafana/provisioning

# Container neu starten
docker compose up -d

# Logs prüfen
docker compose logs grafana

Alternative: Falls du keine sudo-Rechte hast, entferne die `user: "472:472"` Zeile aus der docker-compose.yml

InfluxDB als Datenquelle einrichten

Grafana konfigurieren

1. Grafana Web-UI öffnen:

http://YOUR-SERVER-IP:3000

Login: admin / grafana2025!

2. Data Source hinzufügen:

  • ⚙️ Connections → Data Sources
  • Add data source → InfluxDB
  • Query Language: Flux (nicht InfluxQL!)
  • URL: http://influxdb:8086
  • Organization: homelab
  • Token: super-secret-auth-token-change-me
  • Default Bucket: metrics

3. Test & Save

Sollte "Data source is working" zeigen

Flux vs. InfluxQL: Warum Flux?

InfluxQL: SQL-ähnlich, einfach, aber limitiert

Flux: Funktional, mächtiger, aber steile Lernkurve

Realität 2025: InfluxDB 2.x pusht Flux. InfluxQL wird weniger unterstützt.

Mein Tipp: Flux lernen. Ich zeige dir die wichtigsten Queries.

6. Effektive Dashboards erstellen

Das Problem: Die meisten Grafana-Dashboards sehen aus wie Weihnachtsbäume - bunt, aber unübersichtlich. Ich zeige dir Dashboard-Design-Prinzipien, die ich in der Praxis gelernt habe.

Dashboard-Philosophie: Das "5-Sekunden-Prinzip"

Regel: In 5 Sekunden muss klar sein: "Läuft alles normal oder gibt es ein Problem?"

✅ Gutes Dashboard
  • Top-Row: Overall Health (CPU, RAM, Disk)
  • Farben: Grün = OK, Gelb = Warning, Rot = Critical
  • Größen: Wichtiges groß, Details klein
  • Zeitrange: Last 1h als Standard
❌ Schlechtes Dashboard
  • Info-Overload: 50 Panels mit allem
  • Bunte Chaos: Jede Metrik andere Farbe
  • Skalierung: Axis von 0-100, Werte bei 2-5
  • Veraltung: Dashboard seit 2 Jahren nicht angepasst

Essential Dashboard: System Overview

System Overview Dashboard erstellen

1. Neues Dashboard: ➕ Create → Dashboard

Panel 1: CPU Temperature (Stat Panel)

// Flux Query für CPU Temperature
from(bucket: "${bucket}")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "cpu_temperature")
  |> filter(fn: (r) => r["_field"] == "value")
  |> filter(fn: (r) => r["host"] =~ /${host}/ )
  |> map(fn: (r) => ({ r with _value: r._value / 1000 }))
  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)
  |> yield(name: "mean")

// Visualization: Stat
// Thresholds: 0-75 Green, 75-80 Yellow, 80+ Red
// Unit: Celsius

Panel 2: CPU Usage (Gauge Panel)

// Flux Query für CPU Percentage
from(bucket: "${bucket}")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r._measurement == "cpu" and r.host == "${host}" and r._field == "usage_idle" and r.cpu == "cpu-total")
  |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
  |> pivot(rowKey: ["_time"], columnKey: ["_field"], valueColumn: "_value")
  |> map(fn: (r) => ({r: r.usage_idle * -1.0 + 100.0}))

// Visualization: Gauge
// Thresholds: 0-70 Green, 70-80 Yellow, 80+ Red
// Unit: Percent (0-100)

Panel 3: RAM Usage (Gauge Panel)

// Flux Query für RAM Percentage
from(bucket: "${bucket}")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "mem")
  |> filter(fn: (r) => r["_field"] == "used_percent")
  |> filter(fn: (r) => r.host == "${host}")
  |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
  |> yield(name: "last")

// Visualization: Gauge
// Thresholds: 0-70 Green, 70-80 Yellow, 80+ Red
// Unit: Percent (0-100)

Panel 4: Disk Usage (Gauge Panel)

// Flux Query für Disk Usage
from(bucket: "${bucket}")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "disk")
  |> filter(fn: (r) => r.host == "${host}")
  |> filter(fn: (r) => r["_field"] == "used_percent")
  |> filter(fn: (r) => r["path"] == "/")
  |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
  |> yield(name: "last")

// Visualization: Gauge
// Thresholds: 0-70 Green, 70-80 Yellow, 80+ Red
// Unit: Percent (0-100)

Panel 5: System Uptime (Stat Panel)

// Flux Query für System Uptime
from(bucket: "${bucket}")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r.host =~ /${host}/ and r._measurement == "system" and r._field == "uptime")
  |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
  |> yield(name: "last")

// Visualization: Stat
// Unit: Seconds
// Shows system uptime in seconds

Alternative: Dashboard JSON importieren

Vollständiges Dashboard als JSON

Für alle, die nicht manuell erstellen möchten:

📥 Dashboard herunterladen

system-overview-dashboard.json

Enthält 9 Panels: CPU, Memory, Disk, Load, Network, Disk I/O

Import-Schritte:

  1. JSON-Datei herunterladen (Button oben)
  2. Grafana öffnen: http://YOUR-SERVER-IP:3000
  3. ➕ Create → Import → Upload JSON file
  4. Datei auswählen und Import klicken
  5. Wichtig: Data Source auswählen: InfluxDB (deine konfigurierte Data Source)
  6. Import bestätigen

Falls Import nicht funktioniert:

  • Stelle sicher, dass die InfluxDB Data Source konfiguriert ist
  • Prüfe, ob Telegraf Daten sammelt: docker compose logs telegraf
  • Teste die Data Source in Grafana: Configuration → Data Sources → Test
  • Falls Probleme: Verwende die manuelle Erstellung oben

Dashboard-Features:

  • Top Row: CPU Temperature, CPU Usage, RAM Usage, Disk Usage (Gauge & Stat Panels)
  • Bottom Row: System Uptime, Load Average, Total Processes (Stat Panels)
  • Variables: Automatische Bucket- und Host-Auswahl
  • Thresholds: Farbkodierte Warnungen (Grün/Gelb/Rot)

7. Intelligentes Alerting

Der Horror: Alerts um 3 Uhr nachts wegen 0,1% CPU-Anstieg. Die Realität: Nach einer Woche schaltest du alle Alerts ab. Ich zeige dir, wie du Alerts baust, die wirklich wichtig sind.

Alert-Philosophie: „Würde ich dafür nachts aufstehen?“

✅ Gute Alerts
  • Disk 95% voll: In 1-2 Tagen kritisch
  • RAM 90%+ für 5min: OOM-Killer droht
  • Load Average 5+ für 10min: System überlastet
  • Container down: Service nicht erreichbar
❌ Nervige Alerts
  • CPU 70% für 30s: Normal bei Updates
  • Network-Spike: YouTube-Stream startet
  • RAM 80%: Linux nutzt RAM als Cache
  • Disk I/O hoch: Docker-Build läuft

Essential Alerts konfigurieren

Grafana Alerting einrichten

1. Alert Rule erstellen: Alerting → Alert Rules → New Rule

Alert: Disk Space Critical

// Flux Query für Disk Usage
from(bucket: "metrics")
  |> range(start: -5m)
  |> filter(fn: (r) => r["_measurement"] == "disk")
  |> filter(fn: (r) => r["_field"] == "used_percent")
  |> filter(fn: (r) => r["path"] == "/")
  |> mean()

// Condition: IS ABOVE 95
// Evaluation: every 1m for 2m
// No Data: Alerting (wichtig!)
// Execution Error: Alerting

2. Notification Policy: Alerting → Notification Policies

  • Group by: alertname (gleiche Alerts zusammenfassen)
  • Group wait: 10s (kurz warten)
  • Group interval: 5m (nicht spammen)
  • Repeat interval: 12h (alle 12h wiederholen)

Wichtig: Alert-Müdigkeit vermeiden

Problem: Zu viele Alerts = Alle werden ignoriert

Lösung: Maximal 5 Alert-Rules. Lieber weniger, aber wichtige.

Test-Regel: Jeder Alert muss einen konkreten Action-Plan haben

8. Real-World Troubleshooting

Die 8 Probleme, die garantiert auftreten werden. Und wie du sie löst, ohne stundenlang zu googeln.

Problem 1: „No data“ in Grafana

Symptom: Dashboard zeigt „No data“, obwohl Telegraf läuft

Ursache meist: Timestamp-Probleme oder falsche Bucket

Debug-Steps:

# 1. InfluxDB-Daten prüfen
docker exec -it influxdb influx query 'buckets()'
# Bucket "metrics" sollte existieren

# 2. Aktuelle Daten prüfen  
docker exec -it influxdb influx query 'from(bucket:"metrics") |> range(start:-5m) |> limit(n:5)'
# Sollte aktuelle Daten zeigen

# 3. Telegraf-Logs prüfen
docker compose logs telegraf | tail -20
# Auf Fehler prüfen

# 4. Zeitzone-Problem lösen
docker exec -it telegraf date
docker exec -it influxdb date
# Beide sollten gleiche Zeit zeigen

Problem 2: InfluxDB wird langsam

Symptom: Queries dauern nach 2-3 Wochen ewig

Ursache: Zu viele Series, keine Downsampling

Lösung:

# Series-Anzahl prüfen
docker exec -it influxdb influx query 'import "influxdata/influxdb/schema"
schema.measurements(bucket: "metrics")'

# Retention Policy anpassen (in InfluxDB UI)
# Data → Buckets → metrics → Edit
# Retention: 30d statt 365d für Tests

# Downsampling Task erstellen
# Data → Tasks → Create Task
task_example = '''
option task = {name: "downsample_cpu", every: 1h}
from(bucket: "metrics")
  |> range(start: -2h, stop: -1h)
  |> filter(fn: (r) => r._measurement == "cpu")
  |> aggregateWindow(every: 1m, fn: mean)
  |> to(bucket: "metrics_hourly")
''''

Problem 3: Telegraf sammelt keine Docker-Metriken

Symptom: System-Metriken da, Docker-Container fehlen

Ursache meist: Docker-Socket Permissions

Fix:

# User zur docker-Gruppe hinzufügen
sudo usermod -a -G docker $USER

# Telegraf neustarten
docker compose down
docker compose up -d

# Testen ob Docker-Metriken kommen
docker compose logs telegraf | grep docker

# Alternative: Docker-Plugin deaktivieren
# Entferne [[inputs.docker]] aus telegraf.conf

Problem 4: Grafana Alert-Spam

Symptom: Hunderte Alerts wegen temporärer CPU-Spikes

Ursache: Zu niedrige Thresholds, zu kurze Evaluation-Zeiten

Alert-Tuning:

# Intelligente CPU-Alert Query
from(bucket: "metrics")
  |> range(start: -10m)
  |> filter(fn: (r) => r["_measurement"] == "cpu")
  |> filter(fn: (r) => r["_field"] == "usage_idle")
  |> filter(fn: (r) => r["cpu"] == "cpu-total")
  |> map(fn: (r) => ({r with _value: 100.0 - r._value}))
  |> aggregateWindow(every: 1m, fn: mean)
  |> mean()
  
# Condition: IS ABOVE 90 for 5 minutes
# Statt: IS ABOVE 70 for 30 seconds

# Group wait: 10m (statt 30s)
# Repeat interval: 4h (statt 5m)

Problem 5: Container werden nicht erkannt

Symptom: Nur Host-Metriken, keine Container-Details

Lösung: Labels und Container-Namen konfigurieren

Erweiterte Telegraf-Config:

# telegraf.conf erweitern
[[inputs.docker]]
  endpoint = "unix:///var/run/docker.sock"
  gather_services = false
  container_names = []
  container_name_include = ["*"]
  container_name_exclude = ["telegraf", "grafana"]
  timeout = "5s"
  perdevice = true
  total = true
  docker_label_include = ["com.docker.compose.service"]
  docker_label_exclude = []
  tag_env = ["ENVIRONMENT"]

# Container-Labels in docker-compose.yml
services:
  your-app:
    labels:
      - "monitoring=true"
      - "team=backend"
    environment:
      - ENVIRONMENT=production

Problem 6: Hoher Speicherverbrauch

Symptom: InfluxDB braucht nach 1 Monat 8GB+ RAM

Ursache: Zu viele Metriken, keine Limits

Memory-Optimierung:

# docker-compose.yml: Memory-Limits setzen
services:
  influxdb:
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 512M
    environment:
      # InfluxDB Memory-Settings
      - INFLUXD_QUERY_MEMORY_BYTES=1073741824  # 1GB
      - INFLUXD_QUERY_CONCURRENCY=10

  telegraf:
    deploy:
      resources:
        limits:
          memory: 512M

# telegraf.conf: Sampling reduzieren
[agent]
  interval = "30s"           # Statt 10s
  collection_jitter = "5s"   # Jitter hinzufügen
  metric_buffer_limit = 5000 # Buffer kleiner

Problem 7: Dashboards laden langsam

Symptom: Grafana-Dashboard braucht 30+ Sekunden zum Laden

Ursache: Ineffiziente Flux-Queries, zu große Zeiträume

Query-Optimierung:

# ❌ Langsame Query
from(bucket: "metrics")
  |> range(start: -24h)
  |> filter(fn: (r) => r["_measurement"] == "cpu")
  |> yield()

# ✅ Optimierte Query  
from(bucket: "metrics")
  |> range(start: -6h)
  |> filter(fn: (r) => r["_measurement"] == "cpu")
  |> filter(fn: (r) => r["_field"] == "usage_idle")
  |> filter(fn: (r) => r["cpu"] == "cpu-total")
  |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)
  |> map(fn: (r) => ({r with _value: 100.0 - r._value}))

# Dashboard-Settings optimieren:
# - Max data points: 1000 (statt unlimited)
# - Min interval: 1m (statt auto)
# - Relative time: 6h (statt 24h)

Problem 8: Backup & Recovery

Szenario: Server-Crash, alle Monitoring-Daten weg

Lösung: Automatische Backups einrichten

Backup-Strategie:

# backup.sh Script erstellen
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/monitoring"
mkdir -p $BACKUP_DIR

# InfluxDB Backup
docker exec influxdb influx backup /tmp/backup_$DATE -t super-secret-auth-token-change-me
docker cp influxdb:/tmp/backup_$DATE $BACKUP_DIR/

# Grafana Config Backup  
docker cp grafana:/var/lib/grafana $BACKUP_DIR/grafana_$DATE

# Configs sichern
cp -r ~/monitoring/telegraf $BACKUP_DIR/telegraf_$DATE
cp ~/monitoring/docker-compose.yml $BACKUP_DIR/

# Alte Backups löschen (älter als 30 Tage)
find $BACKUP_DIR -name "*" -mtime +30 -delete

# Crontab: Täglich um 2 Uhr
# 0 2 * * * /home/user/monitoring/backup.sh

9. Erweiterte Konfiguration

Wenn das Basis-Setup läuft, kannst du mit diesen Erweiterungen das System auf das nächste Level bringen.

Multi-Server Monitoring

Mehrere Server überwachen

Szenario: Du hast 3 Server (Raspberry Pi, VPS, Homeserver) und willst alle zentral überwachen.

Server 1: Zentrale InfluxDB + Grafana

# docker-compose.yml auf dem Hauptserver
version: '3.8'
services:
  influxdb:
    image: influxdb:2.7-alpine
    ports:
      - "8086:8086"  # Extern erreichbar machen
    environment:
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=central-monitoring-token-2025
    # ... rest der config

  grafana:
    image: grafana/grafana:10.2.2
    ports:
      - "3000:3000"
    # ... rest der config

Server 2+3: Nur Telegraf

# telegraf.conf auf anderen Servern
[global_tags]
  host = "raspberry-pi-4"  # Eindeutiger Name
  location = "homelab"
  role = "nas"

[[outputs.influxdb_v2]]
  urls = ["http://HAUPTSERVER-IP:8086"]
  token = "central-monitoring-token-2025"
  organization = "homelab"
  bucket = "metrics"

# docker-compose.yml (minimal)
version: '3.8'
services:
  telegraf:
    image: telegraf:1.28-alpine
    volumes:
      - ./telegraf.conf:/etc/telegraf/telegraf.conf:ro
    # ... volume mounts für host access

Custom Metriken sammeln

Eigene Metriken hinzufügen

Neben System-Metriken willst du vielleicht Business-Metriken: Website-Besucher, E-Mail-Queue, API-Response-Times, etc.

HTTP-Endpoints überwachen

# telegraf.conf erweitern
[[inputs.http_response]]
  urls = [
    "https://wolfcoder.de",
    "https://api.wolfcoder.de/health",
    "http://localhost:3000"
  ]
  response_timeout = "5s"
  method = "GET"
  follow_redirects = true
  
  # Optional: HTTP Basic Auth
  # username = "monitoring"
  # password = "secret123"

MySQL/PostgreSQL überwachen

# MySQL Monitoring
[[inputs.mysql]]
  servers = ["monitoring:password123@tcp(mysql:3306)/"]
  metric_version = 2
  
  # Welche Metriken sammeln
  gather_process_list = true
  gather_user_statistics = true
  gather_info_schema_auto_inc = true
  gather_innodb_metrics = true
  gather_slave_lag = false

# PostgreSQL Alternative  
[[inputs.postgresql]]
  address = "postgres://monitoring:password123@postgres:5432/postgres?sslmode=disable"
  outputaddress = "postgres"
  databases = ["app_production", "analytics"]

Nginx/Apache Log-Parsing

# Nginx Status-Modul
[[inputs.nginx]]
  urls = ["http://nginx/nginx_status"]
  response_timeout = "5s"

# Log-File parsen (Vorsicht: Performance!)
[[inputs.logparser]]
  files = ["/var/log/nginx/access.log"]
  from_beginning = false
  
  # Common Log Format parsen
  [inputs.logparser.grok]
    patterns = ['''%{COMBINED_LOG_FORMAT}''']
    measurement = "nginx_access"
    timezone = "Europe/Berlin"

Notification-Channels erweitern

Discord, Slack, E-Mail Benachrichtigungen

Standard-Grafana-Notifications sind langweilig. Hier richtig coole Alerts erstellen:

Discord Webhook einrichten

# 1. Discord-Server → Server-Einstellungen → Integrationen → Webhooks
# 2. Webhook erstellen, URL kopieren
# 3. Grafana → Alerting → Contact Points → New Contact Point

# Discord Webhook URL:
# https://discord.com/api/webhooks/123456789/AbCdEfGhIjKlMnOpQrStUvWx

# Message Template:
{
  "embeds": [{
    "title": "🚨 Monitoring Alert",
    "description": "{{ range .Alerts }}{{ .Annotations.summary }}{{ end }}",
    "color": {{ if eq .Status "firing" }}16711680{{ else }}65280{{ end }},
    "fields": [
      {"name": "Server", "value": "{{ .GroupLabels.host }}", "inline": true},
      {"name": "Status", "value": "{{ .Status }}", "inline": true}
    ],
    "timestamp": "{{ .CommonAnnotations.timestamp }}"
  }]
}

E-Mail mit SMTP

# Grafana SMTP in docker-compose.yml
services:
  grafana:
    environment:
      # SMTP-Settings
      - GF_SMTP_ENABLED=true
      - GF_SMTP_HOST=smtp.gmail.com:587
      - GF_SMTP_USER=your-email@gmail.com
      - GF_SMTP_PASSWORD=app-password-hier
      - GF_SMTP_FROM_ADDRESS=monitoring@wolfcoder.de
      - GF_SMTP_FROM_NAME=WolfCoder Monitoring

# Contact Point in Grafana UI:
# Type: Email
# Addresses: admin@wolfcoder.de, team@company.com
# Subject: [{{ .Status }}] {{ .GroupLabels.alertname }}
# Message: Server {{ .GroupLabels.host }} needs attention!

🎯 Zusammenfassung: Dein professionelles Monitoring-System läuft!

Du hast jetzt: Ein professionelles Monitoring-System, das echte Probleme erkennt, bevor sie kritisch werden. Nicht nur bunte Dashboards, sondern ein robustes System mit erweiterten Funktionen und detaillierten Troubleshooting-Lösungen.

✅ Was funktioniert

  • TIG-Stack läuft stabil in Docker
  • System- und Container-Metriken werden gesammelt
  • Grafana zeigt übersichtliche, optimierte Dashboards
  • Intelligente Alerts warnen vor echten Problemen
  • Detaillierte Troubleshooting-Lösungen für 8 häufige Probleme
  • Multi-Server-Monitoring möglich
  • Custom Metriken und erweiterte Benachrichtigungen
  • Backup-Strategie implementiert

🚀 Erweiterte Möglichkeiten

  • Multi-Server-Setup für zentrale Überwachung
  • Custom Metriken (HTTP-Endpoints, Datenbanken, Logs)
  • Discord/Slack/E-Mail-Benachrichtigungen konfiguriert
  • Memory-Optimierung und Performance-Tuning
  • Automatische Backups und Recovery-Strategien
  • Dashboard-Optimierung für bessere Performance
  • Alert-Tuning gegen Spam und False-Positives
  • Container-Monitoring mit Labels und Metadata

💡 Was dieser Guide anders macht

Statt „installiere diese 10 Tools“ zeige ich dir, warum jede Entscheidung Sinn macht,welche Probleme in der Praxis auftreten, und wie du sie löst. Basierend auf 5 Jahren echten Monitoring-Erfahrungen, nicht nur Lab-Setups.

Fragen? Probleme? Diskutiere auf dem Discord oder schau dir weitere Guides an.