Blog · 8. Juli 2025 · Aktualisiert am 7. September 2026 · 10 Min. Lesezeit

Kubernetes Autoscaling mit HPA

Bildschirm zeigt ein Liniendiagramm mit deutlich ansteigender Kurve
Foto: AlphaTradeZone / Pexels

Der Horizontal Pod Autoscaler, kurz HPA, ist der eingebaute Mechanismus von Kubernetes, um die Anzahl der Pods eines Deployments automatisch an die aktuelle Last anzupassen. Überschreitet zum Beispiel die CPU-Auslastung einen Schwellwert, erzeugt der HPA neue Pods, sinkt die Last wieder, baut er sie ab. Kubernetes Autoscaling bedeutet in der Praxis meistens genau das: horizontale Skalierung über den HPA, nicht das Hinzufügen von mehr Rechenleistung pro Pod.

Ich betreibe Kubernetes-Cluster in Produktion und habe das Kubernetes-Praxisbuch bei Rheinwerk geschrieben (2024). Der HPA gehört in fast jedem dieser Cluster zur Grundausstattung, gerade weil er ohne Cloud-spezifischen Autoscaler auskommt und auf Hetzner genauso funktioniert wie in einer Cloud mit Managed Kubernetes. Alle meine Beiträge rund um den Betrieb von Kubernetes-Clustern findest du auf der Seite Kubernetes.

Der HPA braucht zwei Dinge, bevor er überhaupt arbeitet: eine Metrikquelle im Cluster und gesetzte Ressourcen-Requests am Container. Fehlt eines davon, bleibt er still, und genau daran scheitern die meisten Einrichtungen.

Was der Kubernetes HPA macht

Der HPA ist eine Kontrollschleife, die in einem festen Intervall läuft, standardmäßig alle 15 Sekunden, und dabei eine oder mehrere Metriken eines Deployments mit einem Zielwert vergleicht. Liegt die gemessene CPU-Auslastung über dem Zielwert, berechnet der HPA die passende neue Pod-Anzahl und erhöht spec.replicas des Deployments entsprechend. Sinkt die Last, verringert er die Anzahl wieder, allerdings vorsichtiger und mit eingebauter Verzögerung, damit er nicht bei jedem kurzen Ausschlag hoch- und runterschaltet.

Wichtig für das Verständnis: Der HPA erzeugt keine Pods direkt. Er ändert nur die gewünschte Anzahl im Deployment, und das Deployment kümmert sich wie gewohnt darum, die passende Zahl an Pods über sein ReplicaSet zu erzeugen oder abzubauen. Deshalb funktioniert der HPA nur mit Objekten, die eine Replica-Anzahl kennen, also Deployments, ReplicaSets und StatefulSets, nicht mit einzelnen Pods oder DaemonSets.

Skalieren kann nur, was auch skalierbar gebaut ist. Eine Anwendung, die lokalen Zustand im Arbeitsspeicher hält oder Sitzungen an einen bestimmten Pod bindet, verhält sich bei mehreren Replikas unvorhersehbar. Der HPA eignet sich deshalb vor allem für zustandslose Dienste: APIs, Web-Frontends, Worker, die Nachrichten aus einer Queue verarbeiten.

Voraussetzung: metrics-server und gesetzte Requests

Bevor der HPA überhaupt etwas skalieren kann, braucht er eine Datenquelle für die aktuelle Auslastung. Diese Rolle übernimmt der metrics-server, ein leichtgewichtiger Dienst, der die Ressourcennutzung jedes Pods vom Kubelet abfragt und über die Metrics API bereitstellt. Ohne laufenden metrics-server zeigt kubectl top pods nichts an, und der HPA bleibt handlungsunfähig.

Die zweite Voraussetzung wird oft übersehen: Der HPA rechnet die CPU-Auslastung in Prozent vom gesetzten resources.requests.cpu des Containers aus. Fehlt dieser Wert, kann der HPA keine sinnvolle Prozentzahl bilden und meldet den Zielwert als unbekannt. Wie du Requests und Limits für deine Container sinnvoll setzt, habe ich ausführlich in Kubernetes Requests und Limits erklärt beschrieben, das ist die Grundlage, auf der jede HPA-Konfiguration aufbaut.

Eine erste HPA-Definition mit CPU

Nimm an, du betreibst ein Deployment namens shop-api mit gesetzten CPU-Requests. Der HPA aus dem folgenden Manifest hält die Anwendung zwischen zwei und acht Replikas und zielt auf eine durchschnittliche CPU-Auslastung von 60 Prozent der jeweiligen Requests.

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: shop-api
  namespace: shop
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: shop-api
  minReplicas: 2
  maxReplicas: 8
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60

Das Feld scaleTargetRef verweist auf das Deployment, das skaliert werden soll. minReplicas und maxReplicas stecken den Rahmen ab, innerhalb dessen der HPA arbeiten darf, und verhindern sowohl einen kompletten Ausfall bei niedriger Last als auch ein unkontrolliertes Wachstum bei einem Lastspitzen-Bug. Unter metrics steht die eigentliche Regel: Hier ist es die durchschnittliche CPU-Auslastung relativ zum Request, du kannst aber auch einen absoluten Wert in Millicores angeben.

Rolle das Manifest mit kubectl apply -f hpa.yaml aus und prüfe den Zustand mit kubectl get hpa shop-api und, bei Problemen, mit kubectl describe hpa shop-api. Die Ausgabe von describe zeigt dir unten in den Events, ob der HPA erfolgreich skaliert hat oder aus welchem Grund nicht, etwa weil die Zielmetrik fehlt.

Mehrere Metriken und ein ruhigeres Skalierungsverhalten

Die einfache Version mit einer CPU-Metrik reicht für viele Fälle, doch die aktuelle HPA-Version erlaubt deutlich mehr. Du kannst mehrere Metriken gleichzeitig angeben, etwa CPU und Memory, und der HPA berechnet für jede Metrik die nötige Replica-Zahl und wählt am Ende das Maximum. Damit reagiert er auf den jeweils dringlicheren Engpass. Zusätzlich lässt sich über den behavior-Block steuern, wie aggressiv oder zurückhaltend der HPA hoch- und runterskaliert.

  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 60
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 75
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300
    scaleUp:
      stabilizationWindowSeconds: 0

Das stabilizationWindowSeconds beim Herunterskalieren sorgt dafür, dass der HPA die letzten fünf Minuten an Messwerten betrachtet und sich am jeweils größten Bedarf orientiert, statt sofort auf einen kurzen Rückgang zu reagieren. Die beiden Werte im Beispiel sind zugleich die Standardwerte von Kubernetes, 300 Sekunden beim Herunterskalieren und 0 beim Hochskalieren; der Block schreibt sie erst einmal nur sichtbar hin, damit du sie danach gezielt verändern kannst.

Interessant wird der Block erst, wenn du bewusst von den Standardwerten abweichst. Voreingestellt darf der HPA laut Kubernetes-Dokumentation zum HPA je 15 Sekunden bis zu 100 Prozent der laufenden Replikas abbauen und beim Hochskalieren zusätzlich vier Pods je 15 Sekunden hinzufügen. Das folgende Beispiel bremst den Abbau deutlich und deckelt gleichzeitig den Aufbau:

  behavior:
    scaleDown:
      stabilizationWindowSeconds: 600
      policies:
        - type: Percent
          value: 50
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Pods
          value: 2
          periodSeconds: 30
      selectPolicy: Max

Beim Herunterskalieren schaut der HPA hier zehn Minuten zurück und darf je Minute höchstens die Hälfte der aktuell laufenden Pods abbauen. Beim Hochskalieren reagiert er weiterhin ohne Verzögerung, kommt aber nur in Schritten von zwei Pods je 30 Sekunden nach oben, was einer Anwendung mit längerer Startzeit Luft lässt. Beim Hochskalieren lohnt sich meist genau diese Richtung: schnell reagieren, wenn die Last tatsächlich steigt, und vorsichtig wieder abbauen. Diese Feinjustierung ist der Unterschied zwischen einem HPA, der ruhig arbeitet, und einem, der bei jeder kleinen Schwankung Pods hoch- und runterfährt.

Warum der HPA nicht skaliert: die häufigsten Fehler

In meinen Projekten tauchen immer wieder dieselben drei Ursachen auf, wenn ein HPA scheinbar nichts tut. Erstens fehlt der metrics-server oder liefert veraltete Werte, dann zeigt kubectl get hpa in der Spalte TARGETS ein <unknown> an. Zweitens fehlen Requests am Container, dann kann der HPA keine Prozentzahl berechnen, selbst wenn der metrics-server einwandfrei läuft. Drittens ist maxReplicas zu niedrig gesetzt, sodass der Cluster zwar skalieren möchte, aber gegen die eigene Obergrenze läuft, ohne dass das auf den ersten Blick auffällt.

Ein vierter, subtilerer Fehler ist das sogenannte Flattern: Der HPA skaliert im Minutentakt hoch und wieder runter, weil der Schwellwert zu nah an der normalen Schwankungsbreite der Last liegt. Ein zu niedriges stabilizationWindowSeconds oder ein zu enger Zielwert wie 90 Prozent Auslastung begünstigen das. Setze den Zielwert lieber konservativ, etwa bei 60 bis 70 Prozent, und beobachte über ein paar Tage, ob die Anzahl der Replikas ruhig bleibt.

HPA, VPA und Cluster Autoscaler im Vergleich

Alle drei Mechanismen lösen unterschiedliche Skalierungsprobleme, und in der Praxis werden sie oft verwechselt oder unnötig kombiniert. Die folgende Tabelle fasst zusammen, wofür jeder gedacht ist.

Merkmal Horizontal Pod Autoscaler Vertical Pod Autoscaler Cluster Autoscaler
Was skaliert wird Anzahl der Pods Ressourcen (CPU, Memory) je Pod Anzahl der Nodes
Reagiert auf Last über einer Metrik dauerhaft falsch bemessene Requests Pods, die nicht eingeplant werden können
Voraussetzung metrics-server, gesetzte Requests eigener Controller und CRDs Cloud-API oder Node-Provisioning
Typischer Einsatz zustandslose Dienste mit schwankender Last Anwendungen mit unklarem Ressourcenbedarf Cluster mit stark variabler Gesamtlast

Den Vertical Pod Autoscaler habe ich in einem Projekt für Prometheus selbst eingesetzt, um die Ressourcenanforderungen automatisch anzupassen, ohne mehrere Replikas synchron halten zu müssen. Kritisch daran fand ich, dass Requests und Limits im Git-Repository dann nicht mehr dem entsprachen, was tatsächlich im Cluster lief. Für die meisten Anwendungen bevorzuge ich deshalb den HPA: Er verändert nur die Anzahl der Pods, die im Manifest sichtbar bleibt, statt heimlich an den Ressourcen einzelner Pods zu drehen. Den Cluster Autoscaler brauchst du zusätzlich nur, wenn dein Cluster selbst Nodes hinzufügen oder entfernen kann, was auf einem selbst betriebenen Hetzner-Cluster in der Regel manuell oder über Infrastructure as Code geschieht statt automatisch.

Ausblick: Skalierung nach eigenen Metriken

CPU und Memory sind nicht immer die passende Grundlage für eine Skalierungsentscheidung. Ein Worker, der Nachrichten aus einer Queue verarbeitet, sollte eher nach der Warteschlangenlänge skalieren als nach seiner CPU-Auslastung, die bei wartenden Prozessen niedrig bleibt, obwohl Arbeit ansteht. Für solche Fälle unterstützt der HPA sogenannte Custom Metrics und External Metrics, die typischerweise über einen Adapter aus Prometheus in die Kubernetes Metrics API gespiegelt werden.

Ein wachsender Teil dieser Aufgabe wird inzwischen von KEDA übernommen, einem Projekt, das viele fertige Skalierer für Queues, Themen und andere externe Systeme mitbringt und darunter einen ganz normalen HPA erzeugt und verwaltet. Ich beobachte KEDA in eigenen Projekten, ohne es bisher flächendeckend produktiv zu betreiben, weil sich klassische CPU- und Memory-Skalierung für die meisten meiner Anwendungen als ausreichend erwiesen hat. Wer eigene Metriken braucht, sollte sich das Projekt aber genauer ansehen, bevor er einen eigenen Adapter baut.

Häufige Fragen

Was ist der Unterschied zwischen HPA und VPA?

Der HPA verändert die Anzahl der Pods eines Deployments, der VPA verändert die Ressourcenanforderungen einzelner Pods. Beide lassen sich technisch kombinieren, in der Praxis führt das aber leicht zu widersprüchlichen Anpassungen, deshalb setze ich meist auf einen der beiden Mechanismen pro Anwendung.

Warum skaliert mein HPA nicht?

Am häufigsten fehlt der metrics-server, fehlen Requests am Container, oder maxReplicas ist bereits erreicht. Ein Blick auf kubectl describe hpa zeigt in den Events fast immer den konkreten Grund, oft schneller als jede Vermutung.

Kann der HPA nach eigenen Metriken skalieren?

Ja, über Custom Metrics und External Metrics, die meist per Adapter aus Prometheus stammen, oder über Projekte wie KEDA, die diese Anbindung fertig mitbringen. Für Standardfälle mit CPU und Memory brauchst du das nicht, für Queue-basierte Worker ist es fast Pflicht.

Wie schnell reagiert der HPA auf eine Lastspitze?

Die Kontrollschleife läuft standardmäßig alle 15 Sekunden, dazu kommt die konfigurierte Stabilisierungszeit vor dem eigentlichen Skalieren. Für eine Anwendung, die harte Sekundenbruchteile braucht, ist der HPA also zu langsam, für die meisten Web- und API-Lasten reicht die Reaktionszeit gut aus.

Brauche ich zusätzlich einen Cluster Autoscaler?

Nur, wenn deine Nodes selbst automatisch mitwachsen sollen. Auf einem selbst betriebenen Cluster ohne Cloud-Autoscaler bleibt die Node-Anzahl fest, und der HPA verteilt die Last innerhalb der vorhandenen Kapazität, bis die Nodes voll sind.

Wie du weitermachst

Ein HPA ist nur so gut wie die Requests, auf denen er rechnet: Lies dazu Kubernetes Requests und Limits erklärt, wenn du diesen Schritt noch nicht sauber gelöst hast. Willst du sehen, wie viel deine Pods tatsächlich verbrauchen, bevor du Schwellwerte festlegst, hilft dir Kubernetes Monitoring mit Prometheus. Und wenn du wissen willst, was ein Cluster mit automatischer Skalierung am Ende kostet, findest du das in Kubernetes Kosten: was ein Cluster kostet.

Mein Vorschlag: Setz den HPA zuerst mit einer einzigen CPU-Metrik und einem konservativen Zielwert auf, beobachte eine Woche lang das Skalierungsverhalten, und ergänze erst danach Memory oder eigene Metriken. Die offizielle Anleitung dazu findest du im Kubernetes-Dokumentationsbeispiel zum HPA, Details zu Custom Metrics stehen in der Dokumentation zum HPA mit eigenen Metriken.

Ausführlich mit allen Beispielen, inklusive VPA und Cluster Autoscaler, steht das in Kapitel 8.3 meines Kubernetes-Praxisbuchs bei Rheinwerk.

Kevin Welter

Kevin Welter

Entwickler, IT-Architekt, Fachbuchautor (Kubernetes, Cloud-Infrastrukturen) und Speaker. Betreibt sein Business mit einer KI-Belegschaft aus acht KI-Mitarbeitern und zeigt Selbstständigen in seiner Community, wie sie ihren ersten KI-Mitarbeiter einstellen.

Mehr über KI-Mitarbeiter

Kubernetes von den Grundlagen bis zum produktionsreifen Cluster

Zum Buch