Ich habe vier Pods auf Azure Kubernetes Service absichtlich kaputt gemacht. Zwei meldeten ImagePullBackOff, einer CreateContainerConfigError, und einer stürzte in anderthalb Minuten viermal ab. Jedes Mal dieselbe Frage: Welcher Befehl zeigt, warum?
Dieser Explainer folgt dem Weg, den jeder Pod geht, bevor Ihr Code läuft, zeigt, wo jeder Status ihn anhält, und mit welchem Befehl Sie an jeder Station den Grund finden, mit der echten Ausgabe aus meinem eigenen Cluster. Das Video ist auf Englisch.
Das Wichtigste
- Der Status nennt die Station. Das Kubelet zieht das Image, füllt die Einstellungen des Containers aus (Umgebungsvariablen und Secrets) und startet dann den Container. ImagePullBackOff hält an der ersten Station, CreateContainerConfigError an der zweiten, CrashLoopBackOff nach der dritten: Ihre App lief und ist abgestürzt.
- BackOff heißt warten, nicht aufgeben. Kubernetes versucht es weiter, und die Pause zwischen zwei Versuchen wächst bis auf fünf Minuten. Eine Korrektur (ein nachgeschobener Tag, Registry-Zugriff, ein angelegtes Secret) greift beim nächsten Versuch, ohne neues Deployment.
- Bevor Ihre App läuft, kennt nur Kubernetes den Grund.
kubectl describe podendet mit den Events. Lesen Sie den ersten Fehler: Auch ein falscher Tag meldet401 Unauthorized, weil AKS zusätzlich immer einen anonymen Pull versucht. - Nachdem Ihre App lief, haben ihre eigenen Logs die Antwort. In einer Crash-Schleife zeigt das einfache
kubectl logsden gerade abgestürzten Container;--previoushilft erst, wenn der Container wieder läuft. Die Spalte RESTARTS wählt den Befehl: null und nicht laufend → describe, mehr als null → logs.
Hängt am Image
Ein Pod ist die kleine Hülle, in der Kubernetes Ihren Container ausführt. Bevor Ihr Code läuft, zieht das Kubelet, der Agent auf jeder Maschine des Clusters, das Container-Image aus der Registry, füllt die Einstellungen des Containers aus und startet ihn. Der Status in kubectl get pods nennt die Station, an der der Pod wartet.
Mein erster Fehler war ein Tippfehler: der Tag v1.0, der Tag aus dem Beispiel des Microsoft-Learn-Moduls, während meine Registry nur v1 hatte. Ein kleines Skript von mir zeigte jede Statusänderung mit der Sekunde, in der sie passierte, wie kubectl get pods --watch mit Zeitstempeln:
> python watch.py pods api-typo --secs 750.4s api-typo-… ContainerCreating 0/11.1s api-typo-… ErrImagePull 0/116.4s api-typo-… ImagePullBackOff 0/127.4s api-typo-… ErrImagePull 0/139.0s api-typo-… ImagePullBackOff 0/1
ErrImagePull heißt, ein Versuch ist gerade gescheitert; ImagePullBackOff heißt, Kubernetes wartet vor dem nächsten Versuch, und jede Pause ist länger als die letzte (bis zu fünf Minuten). Neuneinhalb Minuten später meldete der Pod immer noch ImagePullBackOff, mit null Neustarts. Die Versuche hören nie auf.
Ihre App lief nie, also hat sie nichts zu sagen. Kubernetes schon: kubectl describe pod endet mit den Events, was das Kubelet getan hat und was gescheitert ist:
> kubectl describe pod -l app=api-typoStatus: PendingReason: ImagePullBackOffRestart Count: 0Failed to pull image "…/aks-api:v1.0": … not found, … 401 Unauthorized
Unauthorized heißt hier nicht fehlende Berechtigung. Der erste Fehler ist der echte: not found. AKS versucht immer zusätzlich einen Pull ohne Anmeldedaten, und dieser Versuch bekommt die 401 (Microsofts Troubleshooting-Leitfaden beschreibt das für falsche Image-Namen). Prüfen Sie Image-Namen und Tag gegen Ihre Registry; korrigieren Sie den Tag im YAML und wenden Sie es erneut an, oder schieben Sie den fehlenden Tag nach, den Kubernetes beim nächsten Versuch übernimmt.
Mein zweiter Fehler nutzte dasselbe Image in einer zweiten Registry, auf die der Cluster nie Zugriff bekommen hatte. Jetzt hatte das Event die 401 und sonst nichts:
> kubectl describe pod -l app=api-privateReason: ErrImagePullRestart Count: 0Failed to pull image "otherregistry…": … 401 Unauthorized
Das Modul nennt den Registry-Zugriff „meist automatisch“. Das ist er nicht: Der Cluster zieht Images mit seiner eigenen Identität (der Managed Identity des Kubelets), und diese Identität braucht die Rolle AcrPull auf jeder Registry. Meine erste Registry hatte sie nur, weil ich sie beim Anlegen des Clusters angehängt hatte. Für einen bestehenden Cluster:
az aks update -g rg-demo -n aks-demo --attach-acr otherregistry
Das dauerte 106 Sekunden. Ich habe weder neu deployt noch den Pod angefasst; 32 Sekunden nachdem ich mit dem Beobachten begann, lief die App.
Hängt an den Einstellungen
Das Manifest des Moduls liest einen API-Schlüssel aus einem Secret, einem Kubernetes-Objekt für Schlüssel und Passwörter:
env:- name: MODEL_NAMEvalue: "gpt-5-mini"- name: API_KEYvalueFrom:secretKeyRef:name: api-secrets # never createdkey: api-key
Das Modul führt Secrets unter CrashLoopBackOff auf, als würde ein fehlendes Secret die App abstürzen lassen. Das tut es nicht: Das Kubelet füllt die Einstellungen aus, bevor der Container existiert, und ein fehlendes Pflicht-Secret hält es genau dort an. Der Status war nach einer halben Sekunde CreateContainerConfigError, und dann nichts mehr: kein Absturz, kein Neustart. Der Container wurde nie angelegt, also gibt es keine Logs:
> kubectl logs deploy/api-secretError from server (BadRequest): container "api" in pod "…"is waiting to start: CreateContainerConfigError
Der Grund steht wieder in den Events:
> kubectl describe pod -l app=api-secretReason: CreateContainerConfigErrorRestart Count: 0API_KEY: <set to the key 'api-key' in secret 'api-secrets'>Failed (x5 over 42s) Error: secret "api-secrets" not found
Die Lösung ist das Secret selbst (kubectl create secret generic api-secrets --from-literal=api-key=demo). Neun Sekunden später lief derselbe Pod, ohne neues Deployment und ohne Neustart.
Die App lief und ist abgestürzt
Meine App braucht eine Einstellung, MODEL_NAME; ohne sie gibt sie einen Fehler aus und beendet sich mit Code 1. Ich habe sie ohne diese Einstellung deployt und hundert Sekunden lang beobachtet:
> python watch.py pods api-crash --secs 1001.2s api-crash-… Running 1/11.9s api-crash-… Error 0/12.6s api-crash-… Running 1/1 restarts 14.1s api-crash-… Error 0/1 restarts 118.0s api-crash-… CrashLoopBackOff 0/1 restarts 194.2s api-crash-… Running 1/1 restarts 4
Diesmal ist der Container gestartet, also startet Kubernetes ihn neu: Der erste Neustart kommt sofort, danach verdoppelt sich die Pause (10 s, 20 s, 40 s, bis zu fünf Minuten; nach zehn Minuten ohne Probleme beginnt sie von vorn). Meine Neustarts kamen etwas später, aber immer weiter auseinander. CrashLoopBackOff heißt: Kubernetes sitzt gerade eine dieser Pausen aus.
Diesmal lief Ihre App, also hat sie etwas zu sagen:
> kubectl logs deploy/api-crasherror: MODEL_NAME is not set
Die meisten Anleitungen, auch das Modul, sagen: Bei einer Crash-Schleife fragen Sie nach den Logs des vorherigen Containers. Direkt nach den einfachen Logs brachte mir das einen eigenen Fehler:
> kubectl logs deploy/api-crash --previousunable to retrieve container logs for containerd://74a2e527a39d…
kubectl describe pod zeigt, warum: Der Pod hatte zwei beendete Container, den aktuellen und den davor.
State: TerminatedExit Code: 1Last State: TerminatedExit Code: 1Restart Count: 4
Solange ein abgestürzter Container auf seinen Neustart wartet, ist er noch der neueste Container des Pods, also zeigt ihn das einfache kubectl logs. --previous fragt nach dem davor, und den hatte das Kubelet schon aufgeräumt (es entfernt beendete Container per Garbage Collection). Nutzen Sie --previous, sobald der Container wieder läuft, wenn der Absturz hinter ihm liegt.
Die eine Spalte, die den Befehl wählt
kubectl get pods hat eine Spalte RESTARTS. Am Ende meines Laufs:
> kubectl get podsNAME READY STATUS RESTARTS AGEapi-crash-565c6974d4-r5xzq 0/1 Error 4 (116s ago) 2m37s
Die Pods, deren App nie lief, hatten bei jeder Prüfung null Neustarts. Null Neustarts und nicht laufend: Ihre App lief nie, also fragen Sie Kubernetes mit kubectl describe pod. Mehr als null: Sie lief und ist abgestürzt, also fragen Sie Ihre App mit kubectl logs.
| Status | Wo er anhält | Neustarts | Lesen |
|---|---|---|---|
| ErrImagePull / ImagePullBackOff | beim Ziehen des Images | 0 | describe → Events (der erste Fehler) |
| CreateContainerConfigError | beim Ausfüllen der Einstellungen (fehlendes Secret oder ConfigMap) | 0 | describe → Events |
| CrashLoopBackOff | nach dem Start: die App hat sich beendet | > 0 | logs (zuerst einfach, --previous, sobald er wieder läuft) |
Was passiert ist, als ich es ausprobiert habe
Getestet am 26. Oktober 2026 in meinem eigenen Azure-Abonnement (AKS 1.36 in westeurope, Azure CLI 2.88.0, kubectl 1.36); danach wurde alles gelöscht. Ein AKS-Cluster diente vier Videos dieser Serie; diese Seite nutzt seine Schritte zu den Pod-Status. Der Cluster hatte einen Knoten Standard_D2s_v5 und den Free-Tier; die App ist eine kleine Python-API nach dem Vorbild der Übungs-API des Moduls (Port 8000, MODEL_NAME als Pflicht), ohne das Modell der Übung in Microsoft Foundry.
- Während die zweite Registry angehängt wurde, ersetzte Kubernetes den wartenden Pod durch einen neuen desselben ReplicaSets (ein neuer Pod-Name; der Lauf zeigt nicht, warum). Ein neues Deployment war so oder so nicht nötig: Die App lief 31,7 Sekunden nach dem Start des Beobachters.
- Mein erster Versuch der Crash- und Secret-Schritte kam gar nicht so weit: Beide Pods blieben Pending mit
0/1 nodes are available: 1 Insufficient cpu, weil meine eigenen früheren Deployments die CPU-Requests des Knotens gefüllt hatten. Das ist das Thema des nächsten Videos (Requests und Limits); nach dem Aufräumen zeigte der zweite Lauf die Status oben. - In der Crash-Schleife kamen die Neustarts bei 2,6, 18,7, 40,4 und 94,2 Sekunden des Beobachters.
Was das Video weglässt
- Pending-Pods und
Insufficient cpu(Requests und Limits: das nächste Video). - Image-Pull-Secrets (
imagePullSecrets), ABAC-fähige Registries (bei denen--attach-acrnicht die passende Rolle vergibt) und falsche Image-Architekturen, die ebenfalls401 Unauthorizedmelden (Microsofts Troubleshooting-Leitfaden behandelt sie). - Liveness-Probes als Ursache von Neustarts,
kubectl get eventsundkubectl debug.
Weiterführende Links
- Microsoft-Learn-Modul: Deploy applications to Azure Kubernetes Service
- Troubleshoot AKS image pull errors from Azure Container Registry
- Integrate Azure Container Registry with AKS
- Pod lifecycle and container restarts (Kubernetes-Dokumentation)



