Jenseits von einfachem Monitoring
Es gibt einen bedeutsamen Unterschied zwischen Monitoring und Observability. Monitoring sagt Ihnen, wann etwas nicht stimmt. Observability sagt Ihnen warum. Ein produktionsreifer Observability-Stack verbindet Metriken, Logs und Traces zu einer einheitlichen Sicht, die Ihrem Team erlaubt, Probleme in Minuten statt Stunden zu diagnostizieren.
In diesem Leitfaden gehen wir den Stack durch, den wir bei DevOpsVibe am häufigsten deployen: Prometheus für Metriken, Grafana für Visualisierung, Alertmanager für Benachrichtigungen und Loki für Log-Aggregation. Alles laufend auf Kubernetes.
Architektur-Übersicht
Der Stack besteht aus vier Hauptkomponenten:
- Prometheus -- scraped und speichert Zeitreihen-Metriken aus Ihren Services und Ihrer Infrastruktur
- Grafana -- bietet Dashboards, Explorations-Tools und eine einheitliche Query-Oberfläche
- Alertmanager -- handhabt Alert-Routing, Deduplizierung, Gruppierung und Silencing
- Loki -- ein horizontal skalierbares Log-Aggregationssystem, das für den Einsatz mit Grafana konzipiert ist
Zusammen liefern diese Tools die drei Säulen der Observability: Metriken, Logs und (mit Tempo) Traces.
Den Stack mit Helm deployen
Der schnellste Weg in die Produktion ist das kube-prometheus-stack-Helm-Chart, das Prometheus, Grafana, Alertmanager sowie eine Reihe vorkonfigurierter Recording Rules und Dashboards bündelt:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--values custom-values.yaml
Custom Values
Hier eine produktiv abgestimmte custom-values.yaml:
# custom-values.yaml
prometheus:
prometheusSpec:
retention: 30d
retentionSize: "50GB"
storageSpec:
volumeClaimTemplate:
spec:
storageClassName: gp3
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 100Gi
resources:
requests:
memory: 4Gi
cpu: "2"
limits:
memory: 8Gi
scrapeInterval: 30s
evaluationInterval: 30s
grafana:
adminPassword: "${GRAFANA_ADMIN_PASSWORD}"
persistence:
enabled: true
size: 10Gi
dashboardProviders:
dashboardproviders.yaml:
apiVersion: 1
providers:
- name: custom
orgId: 1
folder: "Custom"
type: file
disableDeletion: false
editable: true
options:
path: /var/lib/grafana/dashboards/custom
alertmanager:
alertmanagerSpec:
storage:
volumeClaimTemplate:
spec:
storageClassName: gp3
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 5Gi
Service Discovery konfigurieren
Prometheus erkennt Targets in Kubernetes automatisch über ServiceMonitor- und PodMonitor-Custom-Resources. Um eine neue Anwendung zu überwachen, erstellen Sie einen ServiceMonitor:
# servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: my-api
namespace: monitoring
labels:
release: monitoring
spec:
selector:
matchLabels:
app: my-api
namespaceSelector:
matchNames:
- production
endpoints:
- port: metrics
interval: 15s
path: /metrics
scrapeTimeout: 10s
Das entscheidende Detail, das viele Teams übersehen: Das Label release: monitoring muss mit dem Namen des Helm-Releases übereinstimmen. Ohne es nimmt Prometheus Ihren ServiceMonitor nicht auf.
Effektive Dashboards bauen
Ein häufiger Fehler ist, Dashboards mit Dutzenden Panels zu erstellen, die niemand ansieht. Orientieren Sie sich stattdessen an den Methoden RED und USE:
Die RED-Methode (für Services)
- Rate -- Requests pro Sekunde
- Errors -- Fehlerrate in Prozent
- Duration -- Latenz-Perzentile (p50, p95, p99)
Die USE-Methode (für Ressourcen)
- Utilization -- genutzter Anteil der Ressourcenkapazität
- Saturation -- Umfang der in der Warteschlange befindlichen Arbeit
- Errors -- Anzahl von Fehlerereignissen
Hier eine Grafana-Dashboard-Panel-Definition für API-Latenz mit PromQL:
{
"title": "API Latency (p99)",
"type": "timeseries",
"targets": [
{
"expr": "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket{service=\"my-api\"}[5m])) by (le))",
"legendFormat": "p99"
},
{
"expr": "histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{service=\"my-api\"}[5m])) by (le))",
"legendFormat": "p95"
},
{
"expr": "histogram_quantile(0.50, sum(rate(http_request_duration_seconds_bucket{service=\"my-api\"}[5m])) by (le))",
"legendFormat": "p50"
}
]
}
Alerting, das keine Ermüdung erzeugt
Alert-Fatigue ist der Hauptgrund, warum Monitoring-Investitionen scheitern. Engineers beginnen, Alerts zu ignorieren, und dann bleibt ein echter Incident unbemerkt. So konfigurieren wir Alertmanager, um das zu verhindern:
# alertmanager-config.yaml
global:
resolve_timeout: 5m
slack_api_url: "${SLACK_WEBHOOK_URL}"
route:
receiver: "default"
group_by: ["alertname", "namespace", "service"]
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- match:
severity: critical
receiver: "pagerduty-critical"
repeat_interval: 15m
- match:
severity: warning
receiver: "slack-warnings"
repeat_interval: 4h
receivers:
- name: "default"
slack_configs:
- channel: "#alerts-default"
title: '{{ .GroupLabels.alertname }}'
text: '{{ range .Alerts }}{{ .Annotations.description }}{{ end }}'
- name: "pagerduty-critical"
pagerduty_configs:
- service_key: "${PAGERDUTY_SERVICE_KEY}"
severity: critical
- name: "slack-warnings"
slack_configs:
- channel: "#alerts-warnings"
inhibit_rules:
- source_match:
severity: critical
target_match:
severity: warning
equal: ["alertname", "namespace"]
Gute Alert-Rules schreiben
Jeder Alert sollte handlungsleitend sein. Wenn ein Engineer einen Alert erhält und nicht weiß, was zu tun ist, sollte der Alert nicht existieren.
# alert-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: api-alerts
namespace: monitoring
spec:
groups:
- name: api.rules
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
> 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.service }}"
description: "{{ $labels.service }} is returning 5xx errors at {{ $value | humanizePercentage }} over the last 5 minutes."
runbook: "https://wiki.example.com/runbooks/high-error-rate"
- alert: HighLatency
expr: |
histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service))
> 2.0
for: 10m
labels:
severity: warning
annotations:
summary: "High p99 latency on {{ $labels.service }}"
description: "p99 latency for {{ $labels.service }} is {{ $value }}s, exceeding 2s threshold."
Log-Aggregation mit Loki hinzufügen
Deployen Sie Loki neben Ihrem Prometheus-Stack, um Metriken und Logs in Grafana zu vereinen:
helm install loki grafana/loki-stack \
--namespace monitoring \
--set promtail.enabled=true \
--set loki.persistence.enabled=true \
--set loki.persistence.size=50Gi \
--set loki.persistence.storageClassName=gp3
Fügen Sie Loki dann als Data Source in Grafana hinzu. Die Stärke dieses Setups liegt darin, mit Grafanas Split-View und Label-Matching direkt von einer Metrik-Spitze zu den entsprechenden Logs zu springen.
Eine typische LogQL-Abfrage, um Fehler zu finden:
{namespace="production", app="my-api"} |= "error" | json | level="error" | line_format "{{.timestamp}} {{.message}}"
SLO-basiertes Monitoring
Statt auf willkürlichen Schwellwerten zu alarmieren, definieren Sie Service Level Objectives und alarmieren auf Burn Rates:
- SLI: Das Verhältnis erfolgreicher Requests zu Gesamt-Requests
- SLO: 99,9 % der Requests sollen in einem 30-Tage-Fenster erfolgreich sein
- Error Budget: 0,1 % der Requests dürfen fehlschlagen (ca. 43 Minuten Downtime pro Monat)
Alarmieren Sie, wenn Ihr Error Budget zu schnell verbrannt wird:
- alert: ErrorBudgetBurnRate
expr: |
(
sum(rate(http_requests_total{status=~"5.."}[1h])) by (service)
/
sum(rate(http_requests_total[1h])) by (service)
) > (14.4 * 0.001)
for: 5m
labels:
severity: critical
annotations:
summary: "Error budget burning fast for {{ $labels.service }}"
Tipps für den Betrieb
- Retention richtig dimensionieren. 30 Tage hochauflösende Daten mit heruntergesampelter Langzeitspeicherung über Thanos oder Cortex.
- Recording Rules nutzen, um teure Abfragen vorzuberechnen. Das verbessert die Ladezeiten von Dashboards dramatisch.
- Alerting-Prometheus vom Dashboarding-Prometheus trennen in großen Umgebungen, damit Abfragelast die Alert-Auswertung nicht stört.
- Dashboards als Code speichern in der Versionskontrolle, z. B. über Grafanas Provisioning-System oder Tools wie Grafonnet.
- Alerts testen. Nutzen Sie
promtool, um Alert-Rules vor dem Deployment per Unit-Test zu prüfen.
Fazit
Ein gut gebauter Observability-Stack ist kein Luxus -- er ist das Fundament, das alles andere möglich macht. Ohne ihn ist Incident Response Ratespiel, Kapazitätsplanung ein Glücksspiel und Performance-Optimierung ein Schuss ins Dunkle.
Bei DevOpsVibe designen und deployen wir Observability-Plattformen, die auf Ihre Infrastruktur zugeschnitten sind. Vom initialen Setup über Custom Dashboards bis zu SLO-Frameworks sorgen wir dafür, dass Ihr Team die Sichtbarkeit hat, die es braucht. Melden Sie sich, um Ihre Monitoring-Anforderungen zu besprechen.