Jedes Kubernetes-Deployment kann vier Zahlen tragen: einen Request und ein Limit, für CPU und für Arbeitsspeicher. Ich habe das Beispiel aus dem Microsoft-Learn-Modul auf seinem eigenen Cluster mit einem Node laufen lassen und dann Pods absichtlich über ihre Limits getrieben. Kubernetes hat drei verschiedene Dinge getan, und nur eines davon erschien als Fehler.
Dieser Explainer zeigt, was Requests und Limits wirklich tun und was hinter jedem Limit passiert, mit der echten Ausgabe aus meinem eigenen Azure-Kubernetes-Service-Cluster (AKS). Das Video ist auf Englisch.
Das Wichtigste
- Ein Request ist eine Buchung. Der Scheduler addiert die Requests der Pods auf einem Node und setzt einen neuen Pod nur dort hin, wo sein Request noch passt. Wie ausgelastet der Node wirklich ist, schaut er nie an, und Limits addiert er nie. Ein Pod, der nicht passt, bleibt Pending.
- Ein Node gibt Pods weniger, als er hat. Auf einem Node mit zwei CPUs behält AKS 100 Millicores für sich (1.900 sind allocatable), und die System-Pods hatten bereits 927 gebucht. Das Beispiel des Moduls verlangt 1.000 pro Pod: Keiner seiner beiden Pods ist gestartet.
- Über dem CPU-Limit wartet ein Container. Der Kernel gibt ihm seinen Anteil an jedem 100-ms-Abschnitt. Dieselbe Arbeit dauerte 3,09 s statt 1,64 s, und der Pod blieb Running, ohne einen einzigen Neustart.
- Über dem Speicher-Limit wird der Container beendet. OOMKilled, Exit-Code 137, danach startet Kubernetes ihn neu. Der Grund steht im letzten Zustand des Containers, nicht in den Events, und sein eigenes Log bricht einfach ab. Ein Limit ohne Request wird zum Request.
Der Request ist eine Buchung
Ein Request ist das, was Kubernetes für Ihren Container auf einem Node bucht: so viel CPU, so viel Speicher. Der Scheduler, der Teil von Kubernetes, der für jeden neuen Pod einen Node auswählt, addiert diese Buchungen, bevor er etwas platziert. CPU wird in Millicores gezählt: 1.000m sind eine ganze CPU.
Das Beispiel des Moduls verlangt zwei Pods mit je 1 CPU und 2 GiB:
resources:requests: # booked by the schedulercpu: "1000m"memory: "2Gi"limits: # enforced by the kernelcpu: "2000m"memory: "4Gi"
Der Cluster der Übung hat einen Node; meiner war ein Standard_D2s_v5 mit zwei CPUs und 8 GB. Ich habe das Beispiel angewendet und beide Pods eine Minute lang mit einem kleinen eigenen Skript beobachtet (wie kubectl get pods --watch, mit den Sekunden):
> python watch.py pods api-big --secs 600.4s api-big-6dd546c879-ftqhh Pending 0/10.4s api-big-6dd546c879-q52gv Pending 0/160.3s time is up
Beide Pending von der ersten bis zur letzten Sekunde: kein Node zugewiesen, kein Neustart, kein Absturz. kubectl describe nodes zeigt, warum:
> kubectl describe nodesCapacity:cpu: 2Allocatable:cpu: 1900mResource Requests Limitscpu 927m (48%) 9642m (507%)
Allocatable sind 1.900 Millicores, nicht 2.000: AKS behält auf einem Node dieser Größe 100 für sich. Die System-Pods, die AKS auf jedem Cluster betreibt (DNS, Netzwerk, Metriken), hatten bereits 927 gebucht. Bleiben 973, und jeder Pod verlangt 1.000. Nicht einmal der erste Pod bekommt einen Platz. Arbeitsspeicher hätte für beide gereicht, CPU für keinen.
Dieselbe Ausgabe zeigt die andere Hälfte der Regel: Die Limits auf diesem Node ergaben zusammen 507 % seiner CPU. Der Scheduler addiert nur Requests. Limits können weit mehr versprechen, als der Node hat, und die tatsächliche Auslastung zählt ebenfalls nicht.
Eine Buchung bleibt außerdem bestehen, solange ihr Pod existiert, auch wenn der Pod nie läuft. Während ich das vorige Video aufgenommen habe, waren meine früheren Test-Pods noch auf dem Node, einer davon hing an seinem Image fest und ist nie gestartet. Ein weiterer Pod verlangte nur 50 Millicores und blieb ebenfalls Pending:
> kubectl describe pod -l app=api-crashRequests:cpu: 50mFailedScheduling … 0/1 nodes are available: 1 Insufficient cpu. …
Wenn ein Pod Pending ist, beschreiben Sie zuerst den Pod und dann den Node. Fordern Sie weniger an, löschen Sie Pods, die Sie nicht brauchen, oder fügen Sie einen Node hinzu.
Über dem CPU-Limit
Ein Limit ist die Obergrenze: das Maximum, das Ihr Container nutzen darf. Die praktische Übung des Moduls setzt ein CPU-Limit von 500m, also eine halbe CPU. Meine Demo-App hat einen /work-Endpunkt, eine Schleife, die eine CPU etwa anderthalb Sekunden lang beschäftigt. Ich habe sie zweimal bereitgestellt: mit den Limits der Übung (api-mem) und mit einem CPU-Limit von 2 (api-fast), und in jedem Pod dieselbe Anfrage ausgeführt:
> kubectl exec deploy/api-fast -- python get.py http://localhost:8000/work200 {"pod": "api-fast-…", "wall_s": 1.64, "cpu_s": 1.63}> kubectl exec deploy/api-mem -- python get.py http://localhost:8000/work200 {"pod": "api-mem-…", "wall_s": 3.09, "cpu_s": 1.54}
Mit einem Limit von zwei hatte die Arbeit die ganze Zeit eine ganze CPU: 1,64 Sekunden auf der Uhr. Mit einer halben CPU fast doppelt so lange, bei etwa derselben CPU-Zeit. Ein zweiter Versuch ergab 1,62 und 3,11.
Das ist Throttling. In jeder Scheduling-Periode (standardmäßig 100 ms) gibt der Kernel dem Container seinen Anteil, 50 ms bei einer halben CPU, und lässt ihn dann auf den nächsten Abschnitt warten. Die Arbeit wird trotzdem erledigt, nur in doppelt so vielen Abschnitten. Und Kubernetes bemerkt es nicht:
> kubectl get pods -l app=api-memNAME READY STATUS RESTARTS AGEapi-mem-666bbc8499-kdp82 1/1 Running 0 17s
Über seinem CPU-Limit wird ein Container nie beendet. Er wartet. Nichts im Status verrät es; Sie sehen es nur an langsameren Antworten.
Über dem Speicher-Limit
Derselbe Pod, dieselben Einstellungen der Übung: Er fordert 256Mi Arbeitsspeicher an, sein Limit liegt bei 512Mi (Mi = Mebibyte, die binäre Art von Megabyte). Ein zweiter Endpunkt belegt Speicher in Schritten von 50 MB, hält ihn fest und schreibt nach jedem Schritt eine Zeile. Ich habe 700 angefordert.
Das Modul sagt, ein zu niedrig gesetzter Request verursache diese Abbrüche. Wo stirbt der Container also, am Request oder am Limit? Am Limit, und er wird vorher nicht langsamer:
> kubectl exec deploy/api-mem -- python get.py "http://localhost:8000/alloc?mb=700"command terminated with exit code 137
137 ist 128 + 9: Signal 9, SIGKILL, ein Abbruch, den kein Programm abfangen oder hinter sich aufräumen kann. Der Kernel kann einen Prozess auf die CPU warten lassen, aber er kann keinen Speicher zurücknehmen, den die App bereits hält. Geht der Container über sein Speicher-Limit, beendet ihn der Out-of-Memory-Killer des Kernels. Wo Kubernetes das sagt:
> kubectl describe pod -l app=api-memState: RunningLast State: TerminatedReason: OOMKilledExit Code: 137Restart Count: 1Limits:memory: 512MiRequests:memory: 256MiNormal Started 46s (x2 over 63s) … Container started
Die Events am Ende der Ausgabe sagten nichts dazu. Der Grund steht im letzten Zustand des Containers, und Kubernetes hatte den Container bereits in derselben Sekunde neu gestartet. Was die App vor ihrem Ende ausgegeben hat:
> kubectl logs deploy/api-mem --previousaks-api v1 listening on :8000holding 50 MBholding 100 MB…holding 400 MBholding 450 MB
Dann nichts mehr: kein Fehler, kein Abschied. Die nächsten 50 plus der eigene Speicher der App überschritten 512. Hier funktionierte --previous, weil der neue Container schon lief; der vorige war also der beendete (der vorige Explainer dieser Reihe zeigt, wann es scheitert).
Und der Request: 256Mi. Die App hielt 450, weit darüber, ohne Probleme. Ein Request ist keine Obergrenze; das Limit ist es.
| Über dem … | Was passiert | Neustarts | Wo Sie es sehen |
|---|---|---|---|
| Request (Speicher oder CPU) | nichts, solange der Node Platz hat | 0 | — |
| CPU-Limit | Throttling: wartet auf seinen Anteil an jedem 100-ms-Abschnitt | 0 | langsamere Antworten |
| Speicher-Limit | OOMKilled, Exit-Code 137, Neustart | +1 | describe pod → Last State |
Ein Limit allein
Wie kann ein Limit allein einen Pod am Starten hindern? Ich habe einem Pod ein CPU-Limit von 3 gegeben und gar keinen Request, dann Kubernetes gefragt, welche Ressourcen es gespeichert hat:
> kubectl get pod -l app=api-limits -o jsonpath='{.items[0].spec.containers[0].resources}'{"limits":{"cpu":"3"},"requests":{"cpu":"3"}}
Diesen Request habe ich nie geschrieben. Ohne Request kopiert Kubernetes das Limit und bucht es: drei CPUs auf einem Node, der Pods 1,9 gibt.
> kubectl describe pod -l app=api-limitsFailedScheduling … 0/1 nodes are available: 1 Insufficient cpu. …
Pending für die ganzen 30 Sekunden, die ich zugesehen habe. Setzen Sie also beides: einen Request für das, was Ihr Pod zum Laufen braucht, und ein Limit für das, was er nie überschreiten darf.
Was passierte, als ich es ausgeführt habe
Getestet am 26. Oktober 2026 in meinem eigenen Azure-Abonnement (AKS 1.36 in westeurope, Azure CLI 2.88.0, kubectl 1.36); anschließend wurde alles gelöscht. Ein AKS-Cluster diente vier Videos dieser Reihe; diese Seite nutzt seine Ressourcen-Schritte. Der Cluster hatte einen Standard_D2s_v5-Node (2 vCPU, 8 GB) und den Free-Tarif; die App ist eine kleine Python-API nach dem Vorbild der Übung (Port 8000), ohne das Modell der Übung in Microsoft Foundry, plus zwei Endpunkte für diesen Test: /work (eine CPU-Schleife) und /alloc (hält Speicher in 50-MB-Schritten; ihre MB sind binär, wie die Mi des Limits).
- Der Node: Kapazität 2 CPUs und 8.126.896 KiB Speicher, allocatable 1.900m und 5.927.344 KiB; 14 System-Pods hatten 927m CPU (48 %) und 994Mi Speicher (17 %) angefordert.
- Das Beispiel des Moduls: beide Pods 60 Sekunden lang Pending,
Node: <none>,PodScheduled: False. - Der OOM-Abbruch: Der Container startete um 15:01:19 und wurde um 15:01:36 beendet; der neue startete in derselben Sekunde.
Was das Video weglässt
- QoS-Klassen (beide Pods hier waren Burstable: Requests unter den Limits) und Eviction bei Ressourcendruck auf dem Node, bei der Pods, die mehr als ihre Requests nutzen, zuerst verdrängt werden.
- Wie man Throttling direkt misst (die CPU-Statistiken des Containers),
kubectl top, LimitRange und ResourceQuota (Standardwerte bei der Zulassung), der Vertical Pod Autoscaler.
Weiterlesen
- Microsoft-Learn-Modul: Deploy applications to Azure Kubernetes Service
- Resource management for pods and containers (Kubernetes-Dokumentation)
- Node resource reservations in AKS
- Troubleshoot OOMKilled errors in AKS



