Kubernetes Requests und Limits legen fest, wie viel CPU und Memory Kubernetes für einen Container fest einplant und wo dessen Obergrenze liegt. Ohne diese Angaben verbraucht ein Container so viel, wie er will, und kann anderen Containern auf derselben Node die Ressourcen wegnehmen. Mit Requests und Limits im Manifest gibst du Kubernetes die Information, die es für Planung und Schutz braucht.
Ich betreibe Kubernetes-Cluster in Produktion und habe das Kubernetes-Praxisbuch bei Rheinwerk geschrieben. Requests und Limits gehören zu den Einstellungen, bei denen zu knappe und zu großzügige Werte gleichermaßen Ärger machen, beides mit im Betrieb spürbaren Folgen. Eine Übersicht zu allen meinen Kubernetes-Beiträgen findest du auf der Seite Kubernetes.
Kubernetes Requests und Limits: der Unterschied in zwei Sätzen
Die Request ist nicht der gemessene Verbrauch, sondern der Wert, den du für die Planung festlegst. Der Scheduler sucht eine Node, auf der die Summe der bereits angeforderten Requests plus deiner neuen Request noch in die verfügbare (allocatable) Kapazität passt, und führt deine Request dort als belegt. Wie viel Arbeitsspeicher auf der Node in diesem Moment tatsächlich frei ist, spielt für diese Entscheidung keine Rolle. Grundlage für den Wert selbst ist der gemessene Normalbedarf plus eine Sicherheitsmarge. Ob ein Container darüber hinausgehen kann, entscheidet nicht die Request, sondern die Ressource und das gesetzte Limit (Kubernetes-Dokumentation zum Ressourcenmanagement, Stand September 2026).
Das Limit ist die Obergrenze, und sie wirkt je Ressource unterschiedlich. Bei CPU wird der Container gedrosselt, sobald er sie erreicht; das ist ein hartes Limit. Bei Memory greift der Kernel erst ein, wenn er Speicherdruck feststellt, und beendet den Container dann mit einem Out-of-Memory-Fehler. Setzt du kein Limit, kann ein Container theoretisch die ganze Node für sich beanspruchen. Setzt du ein Limit über der Request, erlaubst du dem Container, kurzzeitig mehr zu verbrauchen, ohne dass er dafür fest eingeplant wird.
Ein Beispiel aus der Praxis: Eine Anwendung liegt im gemessenen Normalbetrieb bei etwa 0,4 CPU-Kernen und 450 MiB Memory. Mit etwas Marge setzt du die Request auf 0,5 Kerne und 512 MiB. Bei einem kurzen Lastpeak darf sie auf 1 CPU-Kern hochgehen. Das ist dein Limit. Kubernetes plant den Pod anhand der 0,5 Kerne ein, erlaubt ihm im Bedarfsfall aber den doppelten Verbrauch.
Was bei Überschreitung passiert: CPU-Throttling gegen Out-of-Memory
CPU und Memory verhalten sich an ihrem Limit unterschiedlich, und dieser Unterschied entscheidet oft über die richtige Fehlersuche. Überschreitet ein Container sein CPU-Limit, wird er nicht beendet, sondern gedrosselt: Der Kernel lässt ihm für den Rest eines Zeitfensters keine weitere Rechenzeit. Deine Anwendung läuft weiter, wird aber spürbar langsamer, ohne dass ein Fehler oder ein Neustart sichtbar wird.
Bei Memory gibt es diese sanfte Bremse nicht. Auch ein gesetztes Memory-Limit ist aber kein vorab reservierter Speicherbereich und keine Sperre, die im Moment der Überschreitung zugreift: Die Kubernetes-Dokumentation nennt Memory-Limits ausdrücklich reaktiv durchgesetzt. Ein Container kann zeitweise mehr Speicher belegen als sein Limit erlaubt, und der Kernel beendet ihn erst, wenn er Speicherdruck feststellt (Kubernetes-Dokumentation zum Ressourcenmanagement, Stand September 2026). Genau deshalb muss der Kill nicht exakt in dem Moment sichtbar werden, in dem der Container sein Limit überschreitet. Der Speicherdruck, auf den der Kernel reagiert, kann dabei im cgroup des Containers selbst entstehen; die Node muss dafür nicht insgesamt voll sein. kubectl describe pod zeigt das als OOMKilled im letzten Zustand des Containers, danach startet Kubernetes ihn entsprechend seiner Restart Policy neu, bei wiederholten Abstürzen mit wachsendem Abstand.
Für die Fehlersuche bedeutet das: Wird eine Anwendung ohne erkennbaren Fehler langsam, prüfe zuerst das CPU-Limit. Startet sie dagegen wiederholt neu, prüfe zuerst das Memory-Limit und die Events des Pods.
QoS-Klassen: was Requests und Limits über dein Eviction-Risiko sagen
Aus deinen Requests und Limits leitet Kubernetes automatisch eine Quality-of-Service-Klasse ab. Sie entscheidet nicht direkt darüber, wer bei einem Engpass weichen muss, sie sagt aber viel über das Risiko.
Wenn eine Node unter Speicherdruck gerät, räumt das Kubelet Pods, um die Node stabil zu halten. Sortiert wird dabei aber nicht nach QoS-Klasse: Laut Kubernetes-Dokumentation zur Node-pressure Eviction (Stand September 2026) zählt zuerst die Nutzung oberhalb der Requests, dann die Pod Priority, dann die Nutzung relativ zu den Requests. Die Klasse wirkt indirekt, weil ein Guaranteed-Pod seine Requests im Normalfall nicht überschreitet und ein BestEffort-Pod keine Requests hat, über denen er liegen könnte. Guaranteed senkt also das Risiko einer Verdrängung. Ein Ausfallschutz ist es nicht, und es kostet dich die Flexibilität eines Limits über der Request.
Die richtigen Werte finden statt raten
Requests und Limits aus dem Bauch heraus zu setzen, führt fast immer zu einem von zwei Fehlern: entweder zu großzügig, was Ressourcen auf der Node verschwendet, oder zu knapp, was zu Throttling und OOM-Kills führt. Beide Fehler lassen sich mit denselben Werkzeugen vermeiden.
Läuft in deinem Cluster ohnehin Prometheus, ist die P95-Nutzung von CPU und Memory über einen längeren Zeitraum die belastbarste Grundlage für deine Requests. Der Vertical Pod Autoscaler kann dieselbe Beobachtung automatisieren und Werte vorschlagen. Ich setze ihn trotzdem nur im Notfall ein, und dafür gibt es harte Gründe in seiner eigenen Dokumentation: Ändert er die Ressourcen eines Pods, wird der Pod neu erstellt, und damit starten alle Container darin neu. Garantieren kann er nicht, dass ein verdrängter Pod auch wieder hochkommt. Zusammen mit dem Horizontal Pod Autoscaler auf derselben Metrik, also CPU oder Memory, soll er ausdrücklich nicht laufen (bekannte Einschränkungen des VPA, Stand September 2026). In meinen Clustern ist der Horizontal Pod Autoscaler der deutlich stabilere Weg: Er ändert die Zahl der Replikate statt die Ressourcen eines laufenden Pods. Beide lösen verschiedene Probleme, der eine skaliert in die Breite, der andere in die Höhe. Wenn du den VPA nur zum Messen nutzen willst, gibt es dafür einen Modus, in dem er ausschließlich Empfehlungen schreibt und laufende Pods nicht anfasst.
Eine einzelne Messung reicht dabei nicht. Beobachte deine Anwendung über mehrere Tage und über einen echten Lasttest, denn eine ruhige Nacht sagt nichts über den Verbrauch am Monatsende.
CPU-Limits setzen oder weglassen?
In der Praxis hat sich eine Diskussion etabliert, die ich in meinen eigenen Clustern differenziert löse: CPU-Limits sind der Grund für viel Throttling, das auf den ersten Blick nicht erklärbar wirkt, weil kubectl top es nicht direkt anzeigt. Wer kein CPU-Limit setzt, riskiert dafür, dass eine einzelne Anwendung bei einem Bug die ganze Node für sich beansprucht. Eine allgemeingültige Antwort gibt es hier nicht: Wie stark sich ein CPU-Limit auswirkt, hängt vom Lastprofil ab, und wer den generellen Verzicht empfiehlt, verallgemeinert eine Beobachtung aus latenzkritischen Diensten auf alle Workloads.
Meine eigene Linie: Requests setze ich so gut wie überall, weil der Scheduler darüber plant. Memory-Limits setze ich grundsätzlich, ohne Ausnahme. CPU-Limits setze ich situativ, abhängig davon, wie gut der Cluster ausgestattet und wie kritisch die Anwendung ist. Für weniger kritisch als Memory-Limits halte ich sie ohnehin, weil ein gedrosselter Prozess weiterläuft und ein Prozess über dem Memory-Limit stirbt. Als Empfehlung daraus: Ein CPU-Limit lohnt sich vor allem dort, wo mehrere Teams sich einen Namespace teilen und eine Anwendung die anderen ausbremsen kann. Auf isolierten, gut überwachten Workloads ist der Verzicht eine vertretbare Entscheidung, solange die Request passt.
So sieht ein Pod-Manifest mit Requests und Limits für beide Ressourcen aus:
apiVersion: v1
kind: Pod
metadata:
name: checkout-service
spec:
containers:
- name: checkout-service
image: registry.example.com/checkout-service:stable
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "256Mi"
Die Angabe 250m steht für 250 Millicpu, also ein Viertel eines CPU-Kerns. Memory gibst du in Mebibyte (Mi) oder Gibibyte (Gi) an, denn Bytes würden das Manifest nur unleserlich machen. In diesem Beispiel darf der Container doppelt so viel CPU nutzen wie angefordert, bekommt beim Memory aber keinen Spielraum. Der Pod landet damit in der Klasse Burstable: Beim Speicher sind Request und Limit gleich, bei der CPU bleibt Luft nach oben.
LimitRange und ResourceQuota: Grenzen für den ganzen Namespace
Requests und Limits im einzelnen Pod zu setzen, ist die eine Hälfte der Aufgabe. Die andere Hälfte ist, dafür zu sorgen, dass niemand sie vergisst oder zu großzügig wählt. Dafür gibt es zwei Objekte auf Namespace-Ebene.
Eine LimitRange setzt Standardwerte für Requests und Limits, falls ein Manifest keine mitbringt, und kann zusätzlich Minimal- und Maximalwerte je Container erzwingen. Eine ResourceQuota begrenzt die Summe aller Requests und Limits im gesamten Namespace, zum Beispiel auf maximal 10 GiB Memory für alle Pods zusammen. Als Standard empfiehlt es sich, beide Objekte in jedem neuen Namespace anzulegen, damit ein vergessenes Limit nicht zum Problem für den ganzen Cluster wird. Ehrlich dazu: Ich ziehe das selbst nicht überall durch, sondern dort, wo mehrere Parteien auf einem Cluster arbeiten. Wer diese Vorgaben zusätzlich technisch erzwingen will, etwa mit einer Policy-Engine wie Gatekeeper, verhindert von vornherein, dass ein Manifest ohne Requests überhaupt in den Cluster gelangt.
Häufige Fragen
Was ist der Unterschied zwischen Requests und Limits in Kubernetes?
Die Request ist der Wert, den Kubernetes zur Planung gegen die verfügbare Kapazität einer Node einrechnet und dort als belegt führt. Das Limit ist die Obergrenze für den tatsächlichen Verbrauch: Bei CPU greift eine Drosselung, bei Memory ein Abbruch des Prozesses, sobald der Kernel Speicherdruck feststellt. Zwischen Request und Limit darf ein Container frei schwanken.
Sollte ich für jeden Container CPU-Limits setzen?
Das kommt auf den Cluster an. In geteilten Namespaces mit mehreren Teams verhindert ein CPU-Limit, dass eine Anwendung die anderen ausbremst. Auf isolierten, gut überwachten Workloads ist der Verzicht auf ein CPU-Limit eine bewusste Entscheidung, die etwas Flexibilität bei Lastpeaks erlaubt.
Was bedeutet OOMKilled und wie vermeide ich es?
OOMKilled bedeutet, dass der Kernel den Container wegen Speichermangels beendet hat. Das passiert in zwei Fällen: wenn der Container mehr Speicher belegt als sein Limit erlaubt, oder wenn dem Node insgesamt der Speicher ausgeht, dann auch bei Containern ohne eigenes Limit. Durchgesetzt wird das reaktiv, also nicht zwingend im selben Moment, in dem das Limit überschritten wird. Vermeiden lässt sich das durch ein Memory-Limit aus einem realistischen Lasttest statt aus einer Schätzung, durch genug Luft auf den Nodes, und durch die Frage, ob die Anwendung den Speicher überhaupt braucht oder ihn nur nicht wieder freigibt.
Wie finde ich die richtigen Werte für Requests und Limits?
Am belastbarsten sind gemessene Werte aus Prometheus über mehrere Tage und ein echter Lasttest. Der Vertical Pod Autoscaler kann Werte vorschlagen, greift in seinen aktiven Modi aber in laufende Pods ein; ich nutze ihn nur im Notfall. Eine einzelne Momentaufnahme reicht in keinem Fall aus.
Reichen Requests und Limits allein als Ressourcen-Steuerung im Namespace?
Nein. Für den ganzen Namespace ergänzt eine LimitRange Standardwerte und Grenzen je Container, während eine ResourceQuota die Summe aller Requests und Limits im Namespace begrenzt. Beide zusammen verhindern, dass ein einzelner vergessener Wert den ganzen Cluster belastet.
Wie du weitermachst
Requests und Limits sind die Grundlage für zwei Themen, die direkt daran anschließen: Skalierst du deine Anwendung automatisch, rechnet Kubernetes Autoscaling mit HPA mit genau diesen Requests. Und ob dein Pod überhaupt merkt, dass er unter Last leidet, entscheiden Liveness und Readiness Probes erklärt. Wer mehrere Teams in einem Cluster trennt, findet die passende Grundlage dazu in Kubernetes Namespaces richtig nutzen.
Mein Vorschlag für heute: Prüfe in einem deiner Namespaces mit kubectl describe pod, ob Requests und Limits überhaupt gesetzt sind, und vergleiche sie mit dem tatsächlichen Verbrauch über kubectl top pod. Die offizielle Referenz dazu findest du in der Kubernetes-Dokumentation zum Ressourcen-Management.
Ausführlich mit Rechenbeispiel, Overcommitment-Grafik und Fehlersuche steht das in Kapitel 8 meines Kubernetes-Praxisbuchs bei Rheinwerk.