Zurück zum Blog

Container-Monitoring

Container-Monitoring mit Prometheus, Grafana und Alertmanager

DevOps & Infrastructure | 28. Dezember 2024 | 8 Minuten Lesezeit

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
Warum diese Gruppierung?
  • 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
Vorteile dieser Lösung:
  • 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"
Wichtige Aspekte:
  • Alle Ports sind nur auf 127.0.0.1 gebunden (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:

  1. T+0min: Prometheus erkennt CPU > 80%
  2. T+5min: Alert-Regel triggert (5 Minuten Schwellwert erreicht)
  3. T+5min30s: Alertmanager sendet E-Mail (nach 30s group_wait)
  4. T+6min: E-Mail kommt an: "Container docling has high CPU usage (82.5%)"
  5. Sofortige Reaktion: SSH auf Server, docker stats docling → Analyse
  6. Lösung: Container-Limits erhöhen oder Workload optimieren
  7. T+15min: CPU sinkt unter 80%, Alert resolves
  8. T+16min: Resolve-E-Mail: "✅ Alert resolved: ContainerHighCPU"
Ohne Monitoring:

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
Kosten:

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


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