7.6 Deepdive
Inhalt
- Inhalt
- Intro
- Recording Rules
- Staleness
- Kardinalität
- Histogram (deutsch Histogramm)
- Summary
- on() vs. without()
- Relabeling
- Spezielle Metriken
- Spezielle Labels
- Subqueries
- Interpolation
Intro
In diesem Kapitel beschäftigen wir uns mit fortgeschrittenen Themen rund um Prometheus.
Recording Rules
Recording Rules in Prometheus bieten die Möglichkeit, komplexe oder häufig berechnete Abfragen vorab zu aggregieren und zu speichern. Sie helfen, die Leistung zu verbessern und die Auslastung von Prometheus zu reduzieren, indem sie vordefinierte Metriken generieren.
Als Beispiel wird in einem Dashboard folgendes Query ausgeführt:
histogram_quantile(
0.9,
sum by(le, path, method) (
rate(demo_api_request_duration_seconds_bucket[5m])
)
)
Das Dashboard wird einmal pro Minute aktualisiert und stellt das Resultat über 7 Tage dar. Prometheus berechnet damit das Resultat dieses Queries jede Minute neu, obschon sich der Grossteil der Daten nicht verändert hat. Wir können Recording Rules nutzen, um dieses Query im Voraus zu berechnen. Dazu erstellen wir folgende Rule:
|
|
Im Dashboard sowie im Prometheus Expression Browser kann die Metrik nun über den Namen job:demo_api_request_duration_seconds_bucket:rate5m
verwendet werden.
Erklärung der Parameter
groups
: Eine Sammlung von Regeln, die gemeinsam verarbeitet werden.name
: Name der Gruppe.interval
: (Optional) Gibt das Intervall an, in dem die Regeln ausgeführt werden.rules
: Liste der Regeln.record
: Der Name der neuen Metrik.expr
: Die PromQL-Abfrage, deren Ergebnis gespeichert wird.labels
: (Optional) Zusätzliche Labels für die aufgezeichnete Metrik.
Unterschied zu Alerting Rules
- Recording Rules speichern berechnete Metriken für spätere Abfragen.
- Alerting Rules lösen Alarme aus, wenn eine Bedingung erfüllt ist.
Staleness
Wenn du in der Tabellenansicht von Prometheus ein Query auf einen Instant vector ausführst, bekommst du als Resultat jeweils den letzten/neusten Wert der jeweiligen Metrik zurück. Wenn Prometheus ein bestimmtes Target um 14:00 scraped und du um 14:01 ein Query ausführst, erhältst du den Wert von 14:00 zurück. Prometheus sucht in der Standardkonfiguration die Samples der Metriken innerhalb der letzten 5 Minuten. Existiert für eine bestimmte Time Series innerhalb der letzten 5 Minuten kein Sample, wird kein Resultat zurückgegeben. Das kann z.B. vorkommen, wenn ein Target aus der Prometheus Konfiguration entfernt wurde oder wenn das scrape_interval
auf mehr als 5 Minuten gesetzt ist. Es ist daher wichtig, das scrape_interval
auf deutlich unter 5 Minuten zu setzen (meist wird ein Wert zwischen 30s und 60s angestrebt).
Kardinalität
Die Kardinalität in Prometheus bezieht sich auf die Anzahl der eindeutigen Zeitreihen, die durch verschiedene Kombinationen von Labels entstehen. Je mehr verschiedene Werte ein Label annehmen kann, desto höher ist die Kardinalität einer Metrik. Beispiel für hohe Kardinalität:
http_requests_total{method="GET", status="200", user_id="12345"}
http_requests_total{method="GET", status="200", user_id="67890"}
http_requests_total{method="POST", status="500", user_id="54321"}
Hier führt das Label user_id
zu vielen verschiedenen Kombinationen, was die Anzahl der gespeicherten Zeitreihen erhöht und die Ressourcennutzung von Prometheus stark belasten kann.
Warum ist hohe Kardinalität problematisch?
- Speicherverbrauch: Jede Kombination von Labels erzeugt eine neue Zeitreihe, was die Speicheranforderungen erhöht.
- Leistungseinbussen: Abfragen über viele Zeitreihen sind langsamer und belasten das System stärker.
- Skalierungsprobleme: Ein zu hoher Anstieg der Kardinalität kann Prometheus instabil machen oder zu Out-of-Memory Fehlern führen.
Best Practices zur Vermeidung hoher Kardinalität:
- Vermeide Labels mit hoher Variabilität (z. B.
user_id
,request_id
). - Nutze aggregierte Metriken, statt einzelne Events mit feingranularen Labels zu speichern.
Histogram (deutsch Histogramm)
Ein Histogram ist ein spezieller Metriktyp in Prometheus, der zur Messung von Verteilungen numerischer Werte genutzt wird. Typischerweise wird ein Histogram verwendet, um Latenzen/Antwortzeiten oder Grössen von Anfragen zu analysieren. Aufgrund der oben beschriebenen Problematik mit der Kardinalität, können wir aber nicht jede Latenz oder Grösse einzeln messen. Wir unterteilen daher die Messungen in verschiedene Bereiche (im Folgenden Buckets genannt):
0s - 0.01s
0.01s - 0.1s
0.1s - 0.5s
0.5s - 1s
1s - 5s
5s - +Inf
In den letzten Bucket fallen sämtliche Messungen, welche länger als 5 Sekunden gedauert haben. Für jeden Bucket wird eine separate Metrik erstellt. Diese Metriken haben ein spezielles le
Label, wobei le
für “less than” steht. Die Buckets sind also kumulativ, jedes Bucket beinhaltet somit sämtliche Messungen der vorhergehenden Buckets. In Prometheus sehen spezielle Funktionen zur Verfügung, welche diese Histogram-Metriken auswerten können. Eine dieser Funktionen ist histogram_quantile()
:
histogram_quantile(0.95, spf_resolver_latency_seconds_bucket)
Damit messen wir die Latenz einer bestimmten Applikation. Der erste Parameter der Funktion (0.95
) ist das gesuchte Quantil, welches einen Wert zwischen 0
(0%) und 1
(100%) annehmen kann. In unserem Fall verwenden wir 0.95
, was 95% entspricht. Im Resultat sehen wir somit, innerhalb welcher Zeit 95% der Anfragen beantwortet wurden. Erhalten wir als Wert beispielsweise 0.152
bedeutet das, dass 95% der Anfragen innerhalb von 152 Millisekunden beantwortet wurden. Die restlichen 5% dauerten länger als 152 Millisekunden.
Die Genauigkeit des Resultats, hängt u.A. davon ab, wie viele Buckets die Metrik besitzt. Mit zunehmender Anzahl Buckets steigt auch die Genauigkeit. Da aber für jeden Bucket eine separate Time Series geschrieben werden muss, sollte die Zahl eher tief gehalten werden. Meist kommen zwischen 10 und 20 Buckets zum Einsatz.
Summary
Ein Summary ist ein Metriktyp in Prometheus, der ähnlich wie ein Histogram verwendet wird, um Verteilungen numerischer Werte zu erfassen. Im Gegensatz zu Histograms erfolgt die Aggregation (die Berechnung der Quantile) bereits in der Applikation und nicht erst beim Aufruf eines entsprechenden PromQL Queries. Der grosse Nachteil dieser Metriken ist, dass sie sich beim Abfragen über PromQL nur noch schlecht aggregieren lassen . Aus diesem Grund wirst du Summaries nur noch selten antreffen. In den allermeisten Fällen werden Histograms verwendet.
on() vs. without()
Im Kapitel 5 haben wir gesehen, wie wir mithilfe des by()
Keywords in Aggregationen bestimmte Labels beibehalten können. Als Parameter übergeben wir dabei die Labels, welche wir behalten möchten. Diese Logik lässt sich mit without()
aber auch umkehren. Anstatt dass wir definieren, welche Labels wir behalten möchten, definieren wir mit without()
welche Labels wir nicht behalten möchten.
Relabeling
Relabeling in Prometheus ist ein Mechanismus, mit dem Labels von Metriken, Targets oder Alerts vor der Speicherung oder Weiterverarbeitung modifiziert, gefiltert oder entfernt werden können. Dies geschieht mithilfe von Relabeling-Regeln, welche in der Prometheus Konfiguration definiert werden.
Liefert eine Applikation z.B. ein Label mit zu hoher Kardinalität, kann dieses Label über eine entsprechende Relabel Rule entfernt werden.
Spezielle Metriken
up
Die up
Metrik in Prometheus ist eine Statusmetrik, die anzeigt, ob ein bestimmtes Scrape-Target erfolgreich abgefragt werden konnte. Sie wird von Prometheus automatisch für jedes Target erstellt und hilft dabei, die Verfügbarkeit von überwachten Systemen und Services zu prüfen.
Die up
Metrik nimmt nur einen der folgenden zwei Werte an:
1
: Das Target wurde erfolgreich gescraped.0
: Das Scraping ist fehlgeschlagen (z. B. weil das Target nicht erreichbar ist oder ein Fehler aufgetreten ist).
Mit dem PromQL Query up == 0
können wir sehr einfach alle Targets anzeigen lassen, welche nicht erreichbar sind.
ALERTS
Die ALERTS
Metrik in Prometheus enthält den aktuellen Zustand aller definierten Alerts. Sie hilft dabei, den Status und die Details aktiver oder vergangener Alerts anzuzeigen.
Mit dieser Metrik lässt sich z.B. herausfinden, wie lange sich ein Alert in einem bestimmten Status (inactive
, pending
oder firing
) befunden hat.
Spezielle Labels
__name__
In Prometheus ist name ein spezielles Label, das den Namen einer Metrik enthält. Das Abfragen der Metrik prometheus_http_requests_total
kann damit über zwei unterschiedliche Queries erfolgen:
prometheus_http_requests_total
oder
{__name__="prometheus_http_requests_total"}
Das __name__
Label verhält sich dabei wie jedes andere Label, wir können somit auch über entsprechende Label Selectors nach Metriken suchen:
{__name__=~"prometheus_.+"}
Dieses Query sucht nach allen Time Series, welche mit prometheus_
beginnen.
le
Das le
Label kommt bei Histogram-Metriken zum Einsatz und enthält die Boundaries des jeweiligen Buckets. Wichtig ist, dass dieses Label in Aggregationen (z.B. sum
) nicht weg aggregiert wird. Ansonsten können Histogram-Funktionen wie z.B. histogram_quantile
die Metriken nicht mehr verarbeiten:
histogram_quantile(
0.9,
sum by(le, path, method) ( # das by(le, ...) stellt sicher, dass wir nicht über Bucket Boundaries hinweg aggregieren
rate(demo_api_request_duration_seconds_bucket[5m])
)
)
Subqueries
Subqueries in Prometheus ermöglichen es, eine Abfrage über einen festgelegten Zeitraum und mit einer definierten Auflösung wiederholt auszuführen. Dadurch lassen sich komplexe zeitbasierte Analysen durchführen, die über das einfache Abfragen von Momentaufnahmen (Instant Queries) hinausgehen.
Subquery-Syntax:
Ein Subquery wird mit der Syntax
<query>[<range>:<resolution>]
geschrieben.
<query>
: Die innere Abfrage, deren Ergebnisse du weiterverarbeiten möchtest.<range>
: Der Zeitraum, über den die innere Abfrage wiederholt ausgeführt wird (z. B. 10m für 10 Minuten).<resolution>
: Die Schrittweite, mit der diese Wiederholungen durchgeführt werden (z. B. 1m für 1 Minute).
Das Subquery evaluiert die innere Abfrage mehrfach, wobei für jeden Schritt innerhalb des angegebenen Zeitraums ein eigener Wert berechnet wird. Das Resultat ist eine Time Series, die du dann in weiteren Funktionen (z. B. Aggregationen) weiter verarbeiten kannst.
Beispiel
Stell dir vor, du möchtest den gleitenden Durchschnitt der Änderungsrate einer Metrik http_requests_total
berechnen. Eine mögliche Abfrage könnte so aussehen:
avg_over_time(rate(http_requests_total[5m])[10m:1m])
rate(http_requests_total[5m])
berechnet die Änderungsrate über ein 5-Minuten-Fenster. Das Subquery [10m:1m]
sorgt dafür, dass diese Berechnung über einen Zeitraum von 10 Minuten in Schritten von 1 Minute wiederholt wird. avg_over_time(...)
bildet anschliessend den Durchschnitt der so gewonnenen Werte.
Vorteile von Subqueries
Flexibilität in der Zeitreihenanalyse:
Mit Subqueries kannst du Daten über einen grösseren Zeitraum analysieren und dabei die Auflösung der inneren Abfragen kontrollieren.
Feinere Steuerung der Datenpunkte:
Du bestimmst explizit, wie oft (durch die Schrittweite) die innere Abfrage wiederholt wird. Das ermöglicht genauere und kontrolliertere Berechnungen als bei herkömmlichen Range Vectors.
Komplexe Berechnungen in einem Schritt:
Anstatt mehrere getrennte Abfragen zu schreiben, kannst du mit Subqueries komplexe zeitbasierte Berechnungen direkt in einer einzigen PromQL Anweisung durchführen.
Interpolation
Bei Queries wie rate(http_requests_total[5m])
berechnest du Raten über HTTP Requests. Die diesen Berechnungen zugrundeliegenden Daten sind immer ganzzahlig (es gibt schliesslich keine halben Requests). Als Resultat wirst du aber oft Gleitkommazahlen erhalten. Der Grund dafür ist, dass rate()
die Samples linear an die Grenzen des Range vector selectors interpoliert.
(Quelle: Julis Volz, https://www.youtube.com/watch?v=7uy_yovtyqw
)
In diesem Beispiel verwenden wir einen Range Vector selector von 5 Minuten. Das scrape_interval
beträgt 30 Sekunden, wir führen das Query ca. zum Zeitpunkt 7:35 aus. Die Scrapes stimmen aber nicht genau mit dem scrape window überein (das letzte Sample war bei Minute 7:30). Wir haben also eine Differenz von ca. 5 Sekunden und auch in die andere Richtung haben wir eine Differenz von einigen Sekunden.
Prometheus wendet nun eine lineare Interpolation an und fügt so virtuelle Samples (in grün) an den Grenzen des Range windows ein:
(Quelle: Julis Volz, https://www.youtube.com/watch?v=7uy_yovtyqw
)
Die so interpolierten virtuellen Samples sind nun nicht mehr zwingend ganzzahlig und damit kann auch das Resultat aus Gleitkommazahlen bestehen.