Newsletter

    Newsletter abonnieren

    Neue Infrastruktur-Guides, Vergleichsberichte und Migrationshinweise direkt ins Postfach.

    Infrastruktur-Notizen, Guides und neue Tools. Jederzeit abbestellbar.

    Zurück zum Blog
    Prometheus
    Cardinality
    SRE
    Monitoring

    Wie ein Team den Prometheus-Speicherverbrauch von 60 GB auf 20 GB gesenkt hat – und die stille Cardinality-Krise aufdeckte

    22. Januar 2026
    5 Min. Lesezeit

    Es gibt diesen Moment, den irgendwann jeder Prometheus-Betreiber erlebt.

    Die UI wird träge.

    Scrapes fangen an zu scheitern.

    PromQL-Queries laufen in ein Timeout.

    Dashboards hängen gerade lange genug, um einen an den eigenen Lebensentscheidungen zweifeln zu lassen.

    Dann prüft man den Speicher.

    Und Prometheus frisst sich lässig durch 50 bis 60 GB RAM.

    Das ist nicht „leicht überdimensioniert". Das ist „das hier wird gleich der größte Incident des Jahres".

    Ein Engineer schilderte genau dieses Szenario. Ein Cluster, in dem Prometheus auf rund 60 GB angeschwollen war. Die Scrape-Zuverlässigkeit sank. Queries liefen in Timeouts. Die Stabilität bröckelte.

    Das war kein theoretisches Tuning.

    Das war Überleben.

    Und die Lösung war nicht exotisch.

    Sie war gnadenlos.


    Die wahren Übeltäter: drei vorhersehbare Killer

    Die Untersuchung deckte drei klassische Prometheus-Speicherfallen auf:

    1. Doppeltes Scraping
    2. Histogramm-Überlastung
    3. Label-Explosion

    Wer Prometheus in Kubernetes lange genug betreibt, ist wahrscheinlich schon mindestens einmal davon gebissen worden.

    Die meisten Teams trifft es bei allen dreien.


    1. Doppeltes Scraping: der versehentliche 2x-Multiplikator

    Prometheus scrapte Ingress-Metriken sowohl von den Pods als auch von einem ServiceMonitor.

    Klingt harmlos.

    Ist es nicht.

    Jeder doppelte Scrape verdoppelt:

    • Anzahl der Time Series
    • Speicherverbrauch
    • WAL-Druck
    • Head-Block-Churn

    Und sofern man nicht explizit nachgelagert dedupliziert, hat man die Cardinality für dieses gesamte Metrik-Set gerade verdoppelt.

    Das ist das stille Multiplikator-Problem.

    Man merkt es nicht sofort. Aber es summiert sich über Cluster hinweg.

    Ein kleines Config-Versehen kann einen zig Gigabyte kosten.

    Die Lösung?

    Unnötiges Scraping auf Pod-Ebene deaktivieren.

    Einfach. Brutal. Effektiv.


    2. Histogramm-Überlastung: Tod durch Buckets

    Histogramme sind mächtig.

    Sie sind auch teuer.

    Metriken wie *_duration_seconds_bucket können Hunderttausende Time Series erzeugen, wenn:

    • Sie viele Buckets haben.
    • Sie viele Label-Kombinationen haben.
    • Sie viele Replicas haben.

    Buckets × Labels × Pods × Cluster multiplizieren.

    Das jetzt noch mit der Retention im Head-Block multiplizieren.

    Plötzlich sieht der Speicherverlauf aus wie ein Hockeyschläger.

    Histogramme sind in Exportern oft standardmäßig aktiviert. Teams prüfen selten noch einmal, ob sie wirklich alle Buckets brauchen. Oder ob High-Cardinality-Labels daran hängen.

    Das Ergebnis?

    Prometheus wird zum Histogramm-Lagerhaus.


    3. Label-Explosion: das Cardinality-Monster

    Das ist der gefährlichste von allen.

    Labels wie:

    • replicaset
    • path
    • container_id

    erzeugten über 10.000 eindeutige Werte.

    Das ist nicht „ein bisschen viel".

    Das ist eine Cardinality-Bombe.

    Jede eindeutige Label-Kombination entspricht einer eigenen Time Series.

    Wenn path rohe URLs mit eingebetteten IDs enthält?

    Wenn sich container_id bei jedem Deploy ändert?

    Wenn replicaset sich ständig dreht?

    Dann erzeugt man Tausende neuer Time Series pro Rollout.

    Prometheus hält sie im Speicher.

    Nicht, weil es kaputt ist.

    Weil es genau so funktioniert.


    Die Lösung war nicht raffiniert — sie war diszipliniert

    Die Abhilfemaßnahmen waren unkompliziert:

    • Ungenutzte Metriken entfernen (nach Prüfung von Dashboards und Alerts)
    • Redundantes Scraping deaktivieren
    • High-Cardinality-Labels entfernen, die gar nicht genutzt wurden
    • Skripte schreiben, um zu prüfen, was gefahrlos entfernt werden konnte

    Der letzte Punkt ist wichtig.

    Labels blind zu entfernen kann Ingestion-Fehler verursachen.

    Ein Moderator meldete sich mit einer entscheidenden Warnung: labeldrop entfernt das Label — nicht die Series.

    War dieses Label für die Eindeutigkeit erforderlich, kann seine Entfernung zu Kollisionen doppelter Series und zu Ingestion-Fehlern führen.

    Genau diese Art von subtilem Prometheus-Verhalten bringt Leute zu Fall.

    Man löscht keine Series.

    Man führt sie zusammen.

    Und gedankenloses Zusammenführen führt ins Chaos.

    Der Autor aktualisierte seinen Beitrag nach dieser Korrektur entsprechend.

    Schon dieser Austausch zeigt etwas Wichtiges:

    Prometheus-Tuning ist kein Rätselraten.

    Es ist Präzisionsarbeit.


    Das Ergebnis: 60 GB → 20 GB

    Nach dem Aufräumen sank der Speicherverbrauch von rund 60 GB auf etwa 20 GB.

    Und die Stabilität kehrte zurück.

    Scrapes normalisierten sich.

    Die UI-Reaktionsfähigkeit verbesserte sich.

    PromQL lief nicht mehr in Timeouts.

    Derselbe Cluster.

    Dieselben Workloads.

    Andere Disziplin.

    Dieses Delta — 40 GB — war keine magische Komprimierung.

    Es war das Entfernen von Verschwendung.


    Das unangenehme Muster, das sich durch alle Teams zieht

    Die Kommentare zeigen etwas Vielsagendes.

    Mehrere Teams berichteten von ähnlichen Problemen.

    Jemand witzelte: „Laughs in VictoriaMetrics."

    Ein anderer meinte: „NetData ;)"

    Das ist der übliche Kreislauf:

    1. Prometheus wächst.
    2. Der Speicherverbrauch explodiert.
    3. Die Leute geben der Datenbank die Schuld.
    4. Alternative TSDB-Anbieter betreten die Bühne.

    Aber hier ist die unbequeme Wahrheit:

    Die meisten Prometheus-Speicherexplosionen sind nicht die Schuld von Prometheus.

    Sie sind architektonisch bedingt.

    Doppeltes Scraping.

    Unbegrenzte Label-Cardinality.

    Übereifrige Histogramme.

    Überladung durch Kubernetes-Standardmetriken.

    Tatsächlich lautete eine starke Empfehlung, die Standard-action: drop-Regeln in kube-prometheus-stack zu überprüfen, weil Metriken vom Kubernetes-apiserver und von cAdvisor kleine Setups überfordern können.

    Kubernetes sendet jede Menge Metriken.

    Wer sie alle blind aufnimmt, meldet sich freiwillig für eine Speicherkrise.


    Die eigentliche Lektion: Prometheus verzeiht keine Faulheit

    Prometheus ist brutal ehrlich.

    Es speichert genau das, was man ihm zu speichern aufträgt.

    Es komprimiert schlechte Labeling-Entscheidungen nicht einfach weg.

    Es schützt einen nicht automatisch vor Cardinality-Explosionen.

    Es warnt einen nicht, wenn sich Histogramme mit Replicas vervielfachen.

    Es geht davon aus, dass man weiß, was man tut.

    Das ist Macht.

    Und Gefahr.

    Wenn Leute sagen „Prometheus skaliert nicht", meinen sie oft eigentlich:

    „Wir haben die Cardinality nicht im Griff gehabt."


    Wenn Sie gerade bei 40 GB+ RAM liegen

    Hier ist die unbequeme Checkliste:

    • Scrapen Sie denselben Endpoint doppelt?
    • Brauchen Sie wirklich Pod-Ebenen-Metriken für jeden Service?
    • Wie viele Histogramm-Buckets exportieren Sie?
    • Hängen Sie User- oder Path-Level-Labels an High-Volume-Metriken?
    • Stecken Container-IDs oder Replica-Hashes in Ihren Labels?
    • Haben Sie kürzlich ungenutzte Metriken geprüft?
    • Überprüfen Sie die Drop-Regeln in kube-prometheus-stack?

    Wenn Sie sich diese Fragen noch nicht gestellt haben, wartet Ihr Speicherverlauf nur auf seinen Auftritt.


    Prometheus mit 20 GB ist nicht klein. Es ist einfach kontrolliert.

    Die Erkenntnis lautet nicht „weniger betreiben".

    Sie lautet „bewusst betreiben".

    Eine Prometheus-Instanz, die für einen großen Kubernetes-Cluster verantwortungsvoll 20 GB nutzt, kann vollkommen gesund sein.

    Eine Prometheus-Instanz, die 60 GB verbraucht, weil sie Ingress-Metriken dupliziert und jede jemals erzeugte Container-ID mitverfolgt?

    Das ist Verschwendung.

    Der Unterschied ist Disziplin.

    Und in der Observability skaliert Disziplin besser als Hardware.

    Jedes Mal.