Container-Monitoring
Container-Monitoring mit Prometheus, Grafana und Alertmanager
Einleitung
In einer modernen Cloud-Infrastruktur mit dutzenden Docker-Containern ist proaktives Monitoring unverzichtbar. Niemand möchte nachts von einem ausgefallenen Service überrascht werden – oder schlimmer noch, erst von Benutzern darauf hingewiesen werden. In diesem Artikel zeige ich, wie wir ein vollständiges Monitoring-System für unsere matzka.cloud-Infrastruktur aufgebaut haben.
Warum Monitoring?
Unsere Infrastruktur besteht aus über 40 Docker-Containern, die verschiedene Services bereitstellen:
- Mailcow (E-Mail-Server)
- Nextcloud (File-Sharing)
- Authentik (SSO)
- Directus CMS
- n8n (Workflow-Automation)
- PostgreSQL-Datenbanken
- Redis-Cache-Systeme
Ohne Monitoring würden wir erst bemerken, dass etwas schiefgelaufen ist, wenn Benutzer sich beschweren. Mit einem durchdachten Monitoring-System erkennen wir Probleme, bevor sie kritisch werden.
Die Monitoring-Stack-Komponenten
1. Prometheus – Die Datensammlung
Prometheus ist das Herzstück unseres Monitoring-Systems. Es sammelt kontinuierlich Metriken von allen unseren Containern und speichert diese in einer Zeitreihen-Datenbank.
Was wird überwacht?
- CPU-Auslastung pro Container
- Speicherverbrauch (RAM)
- Container-Status (Running/Stopped)
- Netzwerk-Traffic
- Festplatten-I/O
Konfiguration:
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
cluster: 'matzka-cloud'
environment: 'production'
scrape_configs:
- job_name: 'docker-exporter'
static_configs:
- targets: ['docker-exporter:9417']
Prometheus scrapt alle 15 Sekunden die Metriken und wertet Alert-Regeln aus.
2. Grafana – Die Visualisierung
Grafana verwandelt die Rohdaten von Prometheus in aussagekräftige Dashboards. Unser Haupt-Dashboard zeigt:
- Container-Übersicht: Alle Container mit ihrem aktuellen Status
- Ressourcen-Auslastung: CPU und RAM pro Container als farbcodierte Balken
- Zeitreihen-Diagramme: Entwicklung der Auslastung über die Zeit
- Echtzeit-Updates: Automatische Aktualisierung alle 30 Sekunden
Dashboard-Features:
- Sortierung nach CPU-Auslastung (höchste zuerst)
- Farbcodierung: Grün (OK), Gelb (Warning), Rot (Critical)
- Gauge-Visualisierung für schnelle Übersicht
- Drill-Down zu einzelnen Container-Details
3. Alertmanager – Die intelligente Benachrichtigung
Der Alertmanager ist das Gehirn hinter unseren Benachrichtigungen. Er empfängt Alerts von Prometheus und entscheidet intelligent, wann und wie Benachrichtigungen versendet werden.
Routing-Strategie:
route:
receiver: 'email-admin'
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s # Warte 30s, um ähnliche Alerts zu gruppieren
group_interval: 5m # Aktualisiere Gruppierung alle 5 Minuten
repeat_interval: 4h # Wiederhole Benachrichtigung alle 4 Stunden
routes:
# Kritische Infrastruktur – Sofortige Benachrichtigung
- match:
severity: critical
receiver: 'email-critical'
group_wait: 10s
repeat_interval: 1h
- Verhindert E-Mail-Spam bei mehreren gleichzeitigen Alerts
- Kritische Alerts werden priorisiert (nur 10s Wartezeit)
- Wiederkehrende Alerts alle 4 Stunden als Reminder
Alert-Regeln: Was wird überwacht?
Wir haben 12 verschiedene Alert-Regeln definiert, die in drei Kategorien fallen:
Kritische Alerts (Immediate Action Required)
1. Container Down
- alert: ContainerDown
expr: docker_container_state{state="running"} == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Container {{ $labels.container_name }} is down"
Wenn ein Container länger als 2 Minuten gestoppt ist, wird sofort eine Benachrichtigung gesendet.
2. Critical Infrastructure Down
- alert: CriticalContainerDown
expr: |
docker_container_state{
container_name=~"traefik|postgres-.*|redis-.*|authentik-server|nextcloud|mailserver"
} == 0
for: 1m
labels:
severity: critical
Kerninfrastruktur wie Traefik (Reverse Proxy) oder PostgreSQL-Datenbanken lösen bereits nach 1 Minute einen Alert aus.
3. Critical Memory Usage
- alert: ContainerCriticalMemory
expr: (docker_container_memory_usage_bytes / docker_container_memory_limit_bytes) * 100 > 95
for: 2m
labels:
severity: critical
Wenn ein Container mehr als 95% seines verfügbaren RAM nutzt, besteht die Gefahr eines OOM-Kills (Out of Memory).
Warning Alerts (Requires Attention)
4. High CPU Usage
- alert: ContainerHighCPU
expr: docker_container_cpu_usage_percent > 80
for: 5m
labels:
severity: warning
Dauerhafte CPU-Auslastung über 80% für 5 Minuten deutet auf ein Performance-Problem hin.
5. High Memory Usage
- alert: ContainerHighMemory
expr: (docker_container_memory_usage_bytes / docker_container_memory_limit_bytes) * 100 > 90
for: 5m
labels:
severity: warning
90% RAM-Auslastung ist ein Warnsignal, bevor es kritisch wird.
Info Alerts (Awareness)
6. Container Count Changed
- alert: ContainerCountChanged
expr: abs(count(docker_container_state) - count(docker_container_state offset 10m)) > 5
for: 2m
labels:
severity: info
Wenn sich die Anzahl der Container um mehr als 5 ändert, ist das ein Hinweis auf Deployments oder Probleme.
E-Mail-Benachrichtigungen
SMTP-Integration mit Mailcow
Für E-Mail-Benachrichtigungen nutzen wir unseren eigenen Mailcow-Server:
global:
smtp_smarthost: 'mail.matzka.cloud:587'
smtp_from: 'alerts@matzka.cloud'
smtp_auth_username: 'alerts@matzka.cloud'
smtp_auth_password: 'SECURE_PASSWORD'
smtp_require_tls: true
- Volle Kontrolle über E-Mail-Zustellung
- Keine externen Dienste oder API-Limits
- TLS-verschlüsselte Verbindung
- Eigener Mailserver verhindert Spam-Filter-Probleme
HTML-E-Mail-Templates
Wir verwenden zwei verschiedene E-Mail-Vorlagen:
Critical Alerts:
<div class="critical">
<h1>🚨 CRITICAL ALERT</h1>
<p>Immediate action required for matzka.cloud infrastructure!</p>
</div>
<div class="alert">
<h2>{{ .Labels.alertname }}</h2>
<p><span class="label">Severity:</span>
<span style="color: #dc2626;">CRITICAL</span></p>
<p><span class="label">Container:</span> {{ .Labels.container_name }}</p>
<p><span class="label">Started:</span> {{ .StartsAt }}</p>
</div>
Features:
- Farbcodierung nach Schweregrad (Rot für Critical, Orange für Warning)
- Übersichtliche Darstellung aller betroffenen Container
- Resolved-Alerts werden grün markiert
- Direktlink zu Prometheus für Details
Deployment mit Docker Compose
Das gesamte Monitoring-System läuft in Docker-Containern:
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
networks:
- monitoring
- frontend
volumes:
- prometheus_data:/prometheus
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./prometheus/alerts:/etc/prometheus/alerts:ro
ports:
- "127.0.0.1:9090:9090"
alertmanager:
image: prom/alertmanager:latest
container_name: alertmanager
restart: unless-stopped
networks:
- monitoring
environment:
- ALERTMANAGER_SMTP_PASSWORD=${ALERTMANAGER_SMTP_PASSWORD}
volumes:
- alertmanager_data:/alertmanager
- ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
ports:
- "127.0.0.1:9093:9093"
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
networks:
- monitoring
- frontend
environment:
- GF_SERVER_ROOT_URL=https://monitor.${DOMAIN}
- GF_AUTH_GENERIC_OAUTH_ENABLED=true
- GF_AUTH_GENERIC_OAUTH_CLIENT_ID=${AUTHENTIK_GRAFANA_CLIENT_ID}
volumes:
- grafana_data:/var/lib/grafana
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=Host(`monitor.${DOMAIN}`)"
- "traefik.http.routers.grafana.entrypoints=websecure"
- "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
- Alle Ports sind nur auf
127.0.0.1gebunden (localhost-only) - Externer Zugriff erfolgt über Traefik (Reverse Proxy mit SSL)
- Persistente Datenvolumes für Prometheus und Grafana
- Automatische SSL-Zertifikate via Let's Encrypt
- SSO-Integration mit Authentik für Grafana
Lessons Learned
1. SMTP-Authentifizierung mit Sonderzeichen
Problem: Base64-encodierte Passwörter mit / und = verursachten Probleme.
Lösung:
- Einfache Passwörter ohne Sonderzeichen verwenden
- Oder: Doppelte Anführungszeichen in YAML nutzen:
smtp_auth_password: "password"
2. Alertmanager Environment Variables
Problem: ${VARIABLE} in YAML wird nicht automatisch ersetzt.
Lösung: Passwort direkt in die Konfigurationsdatei schreiben (Datei ist readonly und hat 644 Permissions).
3. Alert-Gruppierung verhindert Spam
Problem: Bei einem Ausfall mehrerer Container kamen 20+ E-Mails auf einmal.
Lösung:
group_by: ['alertname', 'cluster', 'service']
group_wait: 30s
Alerts werden gruppiert und als eine E-Mail versendet.
4. Repeat Interval für Reminders
Problem: Einmalige Benachrichtigung wurde manchmal übersehen.
Lösung:
repeat_interval: 4h # Für Warnings
repeat_interval: 1h # Für Critical
Solange der Alert aktiv ist, wird alle 4h (bzw. 1h) erneut benachrichtigt.
Best Practices
1. Alert-Schwellwerte richtig setzen
Zu niedrig: E-Mail-Spam bei normalen Schwankungen
Zu hoch: Probleme werden zu spät erkannt
Unsere Empfehlung:
- CPU: > 80% für 5 Minuten
- Memory: > 90% für 5 Minuten (Warning), > 95% für 2 Minuten (Critical)
- Container Down: 2 Minuten für reguläre Container, 1 Minute für kritische Infrastruktur
2. Separate Alerts für kritische Infrastruktur
Container wie Traefik, PostgreSQL oder Redis sind essenziell. Diese erhalten:
- Kürzere Wartezeit (1 Minute statt 2 Minuten)
- Höhere Wiederholungsfrequenz (1 Stunde statt 4 Stunden)
- Separate E-Mail-Vorlage mit höherer Dringlichkeit
3. Inhibition Rules nutzen
inhibit_rules:
# Unterdrücke Warning wenn Critical Alert aktiv ist
- source_match:
severity: 'critical'
target_match:
severity: 'warning'
equal: ['container_name', 'instance']
Verhindert doppelte Benachrichtigungen für denselben Container.
4. Dashboards für verschiedene Zielgruppen
- Operations Dashboard: Alle Container, sortiert nach CPU
- Service-spezifische Dashboards: z.B. nur Datenbanken oder nur Web-Services
- Executive Dashboard: Nur kritische Metriken, vereinfachte Darstellung
Monitoring in Aktion: Ein Beispiel
Szenario: Der Docling-Container zeigt dauerhaft hohe CPU-Auslastung.
Timeline:
- T+0min: Prometheus erkennt CPU > 80%
- T+5min: Alert-Regel triggert (5 Minuten Schwellwert erreicht)
- T+5min30s: Alertmanager sendet E-Mail (nach 30s group_wait)
- T+6min: E-Mail kommt an: "Container docling has high CPU usage (82.5%)"
- Sofortige Reaktion: SSH auf Server,
docker stats docling→ Analyse - Lösung: Container-Limits erhöhen oder Workload optimieren
- T+15min: CPU sinkt unter 80%, Alert resolves
- T+16min: Resolve-E-Mail: "✅ Alert resolved: ContainerHighCPU"
Problem würde unbemerkt bleiben, bis der Container abstürzt oder Benutzer sich beschweren.
Kosten und Ressourcen
| Komponente | RAM | CPU |
|---|---|---|
| Prometheus | 200-300 MB | Minimal |
| Grafana | 150-200 MB | Minimal |
| Alertmanager | 50-100 MB | Minimal |
| Gesamt | < 1 GB RAM | Minimal |
0€ (Open Source, läuft auf vorhandener Infrastruktur)
Fazit
Mit Prometheus, Grafana und Alertmanager haben wir ein professionelles Monitoring-System aufgebaut, das:
- ✅ Proaktiv überwacht: Probleme werden erkannt, bevor sie kritisch werden
- ✅ Intelligent benachrichtigt: Keine E-Mail-Spam durch clevere Gruppierung
- ✅ Visuell darstellt: Grafana-Dashboards zeigen den Systemzustand auf einen Blick
- ✅ Open Source ist: Keine Lizenzkosten, volle Kontrolle
- ✅ Skaliert: Von 40 auf 400+ Container ohne Probleme
Das System läuft jetzt produktiv auf matzka.cloud und überwacht 67 Container rund um die Uhr. Die E-Mail-Benachrichtigungen haben uns bereits mehrfach vor Ausfällen bewahrt.
Weiterführende Links
- Prometheus Documentation: https://prometheus.io/docs/
- Grafana Dashboards: https://grafana.com/grafana/dashboards/
- Alertmanager Configuration: https://prometheus.io/docs/alerting/latest/alertmanager/
- Docker Metrics: https://docs.docker.com/config/daemon/prometheus/
Dieser Artikel beschreibt die reale Implementierung des Monitoring-Systems für matzka.cloud, einer self-hosted Cloud-Infrastruktur mit Mailcow, Nextcloud, Authentik, Directus CMS und weiteren Services.
Tags: #Monitoring #Prometheus #Grafana #Alertmanager #Docker #DevOps #SelfHosted #CloudInfrastructure