Observability: Was Loki + Grafana für uns tun

Observability: Was Loki + Grafana für uns tun

Ein konkreter Blick auf die Observability-Stack-Entscheidungen, die unser Debug-Leben leichter gemacht haben.

Logs sind das Stiefkind vieler Systeme. Man braucht sie selten, aber dann dringend. In Kubernetes-Clustern mit dutzenden Services und flüchtigen Pods wird das Log-Management schnell zum Albtraum — es sei denn, man investiert in ein passendes Tooling.

Warum nicht Elasticsearch

Wir haben lange mit einem Elasticsearch-basierten Stack gelebt. ES ist mächtig, hat aber zwei Probleme im Alltag: Es ist teuer (RAM-hungrig, skaliert linear mit Datenvolumen), und es lädt Teams ein, komplexe Index-Strategien zu bauen, deren Wartung irgendwann keiner mehr übernimmt.

Für ein mittelgroßes Setup (unsere Größenordnung: ~50 GB Logs pro Tag bei 20 Services) war ES überdimensioniert. Jede Suche bedeutete Volltext-Indexing im Hintergrund, und die resultierenden Indexe verbrauchten dreimal so viel Platz wie die Rohdaten.

Wie Loki anders funktioniert

Loki ist grundlegend anders: Es indiziert nur Metadaten (Labels), nicht den Log-Inhalt. Das macht Loki kompakt und günstig — ein Cluster, der mit 8 GB RAM auskommt, wo ES 64 GB brauchte.

Der Tradeoff: Volltext-Suche ist langsamer. In der Praxis ist das akzeptabel, weil gute Label-Hygiene (nach Service, Namespace, Severity) die Suche meistens schon eingrenzt, bevor Volltext ins Spiel kommt.

Unser Label-Schema

Wir haben uns auf fünf Standard-Labels festgelegt, die jeder Service ausspielen MUSS:

  • service — Name des Service (z.B. web-core-gateway)
  • namespace — Kubernetes-Namespace
  • env — prod/staging/dev
  • level — debug/info/warn/error
  • request_id — nur bei Service-Logs mit Request-Kontext

request_id ist der wichtigste. Er ermöglicht Cross-Service-Korrelation: Eine Anfrage trifft das Gateway, geht weiter an den Orchestrator, dann an drei Agents. Alle Logs zu dieser Anfrage tragen dieselbe request_id und können in Grafana zu einer Timeline zusammengeführt werden.

Der "LogQL-Moment"

LogQL ist Lokis Query-Sprache. Sie orientiert sich an PromQL und fühlt sich für Prometheus-Nutzer vertraut an. Der entscheidende Moment im Team war, als wir gelernt haben, | json und | unwrap zu nutzen — JSON-Logs können in LogQL direkt geparst und gefiltert werden.

Eine typische Query bei uns:

{service="web-core-gateway"} | json | duration > 1s

Das gibt uns in Sekunden alle langsamen Requests im Gateway. Ohne Index-Vorbereitung, ohne Aggregations-Pipeline.

Grafana als Cockpit

Wir haben sieben Dashboards, die wir täglich nutzen:

  1. Cluster-Gesundheit: CPU/Memory/Disk pro Node
  2. Service-Health: Up/Down, Latenz p50/p95/p99 pro Service
  3. Error-Rate: 5xx-Rate pro Endpoint, Fehler-Top-10
  4. RAG-Pipeline: Retrieval-Latenz, LLM-Latenz, Token-Verbrauch
  5. Auth-Events: Login-Erfolge/Fehler, Token-Rotationen
  6. Content-Pipeline: Indexer-Durchsatz, Index-Aktualität
  7. Business-KPIs: Aktive Sessions, Conversion-Rates

Der Schlüssel: Jedes Dashboard beantwortet eine spezifische Frage. Keine Dashboards, in denen "alles mögliche" steht.

Alerting: Weniger ist mehr

Wir haben bewusst nur wenige Alerts. Die Regel: Ein Alert muss einen klaren Handlungs-Hinweis geben. Ein Alert, der nur "irgendwas ist komisch" sagt, wird innerhalb von zwei Wochen gemutet und nie wieder angeschaut.

Unsere Alert-Liste:

  • Service down > 2 Minuten → Slack + PagerDuty
  • 5xx-Rate > 1% über 5 Minuten → Slack
  • Disk > 85% → Slack + Ticket
  • Cert-Expiry in < 7 Tagen → Slack

Das war's. Alle anderen Auffälligkeiten findet man in den Dashboards.

Ausblick

Nächster Schritt ist OpenTelemetry Traces, um Service-übergreifende Latenzen besser zu verstehen. Loki + Tempo + Mimir (alles Grafana-Stack) sollen das liefern, ohne dass wir einen zweiten Observability-Provider dazubekommen.

SOVAIA (Ein Produkt der KIINNO AG)

Baarerstrasse 52
6300 Zug
Schweiz


plus 4 1 4 1 5 1 0 0 6 7 5