Blog · 28. Oktober 2026 · 14 Min. Lesezeit

ImagePullBackOff: Ursachen und Lösung

Grafische Titelkarte zum Beitrag „ImagePullBackOff: Ursachen und Lösung“ mit einem stilisierten Motiv: ein Container-Symbol, dessen Pfeil zur Registry an einer Sperre endet, daneben eine Uhr für die Wartezeit.
Grafik: HumanITy

ImagePullBackOff bedeutet, dass der kubelet das Container-Image für deinen Pod nicht ziehen konnte und jetzt mit wachsender Pause auf den nächsten Versuch wartet. Der Container startet gar nicht erst. Die Ursache steht fast immer in den Events von kubectl describe pod, in der Meldung „Failed to pull image“. Die häufigsten Gründe: falscher Image-Name oder Tag, private Registry ohne imagePullSecrets, das Pull-Limit von Docker Hub, Netzwerk oder DNS auf dem Node, ein Image ohne passende Prozessorarchitektur und ein Registry-Zertifikat, dem der Node nicht vertraut. ErrImagePull ist der einzelne gescheiterte Versuch, ImagePullBackOff die Wartezeit danach.

Ich betreibe seit 2017 Kubernetes-Cluster, heute vor allem k3s auf Hetzner Cloud, bin Kubestronaut der CNCF und habe das Kubernetes-Praxisbuch bei Rheinwerk geschrieben. Alle Beiträge zum Thema findest du auf der Seite Kubernetes.

Was ImagePullBackOff in Kubernetes bedeutet

Ein Container hat laut Kubernetes-Dokumentation drei mögliche Zustände: Waiting, Running und Terminated. Solange das Image fehlt, ist er im Zustand Waiting, und das Feld Reason sagt dir, warum, hier eben ImagePullBackOff. Der Pod bleibt in der Phase Pending, denn dazu zählt laut Dokumentation auch die Zeit, in der Images geladen werden. Mehr zu Phasen und Zuständen steht in Kubernetes Pod: was ist ein Pod?.

Anders als beim CrashLoopBackOff ist dein Code noch gar nicht gelaufen. Logs gibt es deshalb keine, kubectl logs hilft nicht. Die Antwort liegt in den Events.

ErrImagePull und ImagePullBackOff: der Unterschied

Beide Meldungen beschreiben dasselbe Problem zu zwei Zeitpunkten. Im Quellcode des kubelet ist ErrImagePull als allgemeiner Fehler beim Ziehen eines Images definiert, du siehst ihn direkt nach einem gescheiterten Versuch. Danach startet eine Wartezeit. Fragt der kubelet in dieser Zeit erneut nach dem Image, meldet er ImagePullBackOff und schreibt die Fehlermeldung des letzten Versuchs in das Feld Message des Containers, in kubectl describe pod unter State: Waiting. Deshalb wechselt die STATUS-Spalte von kubectl get pods zwischen beiden Werten.

Die Kubernetes-Dokumentation nennt als Obergrenze der Wartezeit 300 Sekunden, also 5 Minuten. Im Quellcode beginnt sie bei 10 Sekunden und verdoppelt sich mit jedem Fehlschlag. Ein Pod, der schon länger hängt, versucht es also nur noch alle paar Minuten.

Dazu kommen weitere Gründe aus derselben Familie:

Grund Was er bedeutet
ErrImagePull ein Versuch, das Image zu ziehen, ist gescheitert
ImagePullBackOff der kubelet wartet nach einem Fehlschlag auf den nächsten Versuch
InvalidImageName der Image-Name lässt sich nicht auswerten, meist ein Tippfehler im Format
ErrImageNeverPull imagePullPolicy: Never, und das Image liegt nicht auf dem Node
RegistryUnavailable die Container-Laufzeit meldet, dass die Registry nicht erreichbar ist

Diagnose: kubectl describe und die Events lesen

Für die Diagnose reichen drei Befehle:

kubectl get pods -n shop
kubectl describe pod api-7d9c6b5f8-x2k4q -n shop
kubectl events --for pod/api-7d9c6b5f8-x2k4q -n shop

In kubectl describe pod steht im Abschnitt des Containers State: Waiting mit Reason: ImagePullBackOff. Ganz unten folgen die Events. Schematisch, gekürzt und mit einem Beispiel-Image sieht die Abfolge so aus:

Events:
  Type     Reason   Message
  ----     ------   -------
  Normal   Pulling  Pulling image "registry.example.com/shop/api:1.4.2"
  Warning  Failed   Failed to pull image "registry.example.com/shop/api:1.4.2": <Fehler der Container-Laufzeit>
  Warning  Failed   Error: ErrImagePull
  Normal   BackOff  Back-off pulling image "registry.example.com/shop/api:1.4.2"
  Warning  Failed   Error: ImagePullBackOff

Entscheidend ist der Text nach „Failed to pull image“: Dort steht, was die Container-Laufzeit von der Registry zurückbekommen hat, etwa ein unbekanntes Image, eine verweigerte Anmeldung, ein Zeitlimit oder ein Zertifikatsfehler. Ordne ihn einer der Ursachen unten zu. Weitere Befehle stehen in kubectl Befehle: die wichtigsten im Alltag.

Einen Punkt übersehen viele: Das Image zieht nicht dein Pod, sondern die Container-Laufzeit auf dem Node, zum Beispiel containerd, mit Netzwerk, DNS und Zertifikaten des Nodes. Ein Test aus einem anderen Pod sagt deshalb wenig. Mit Node-Zugang prüfst du direkt dort mit crictl pull <image>, meist mit Root-Rechten, in k3s als k3s crictl pull <image>. Für eine private Registry nutzt crictl das imagePullSecret nicht, du gibst die Zugangsdaten mit --creds <benutzer>:<token> mit, sonst scheitert der Test auch bei gesunder Registry. Ohne Node-Zugang ist docker pull <image> auf deinem Rechner der erste Test, den auch die Kubernetes-Dokumentation vorschlägt.

Die häufigsten Ursachen und ihr Fix

Ursache Typischer Hinweis in den Events Fix
falscher Name oder Tag Image oder Tag wird nicht gefunden Name, Tag und Registry prüfen, Image wirklich gepusht?
private Registry ohne Zugangsdaten Anmeldung verweigert, oder FailedToRetrieveImagePullSecret Secret anlegen und als imagePullSecrets eintragen
Pull-Limit von Docker Hub „You have reached your pull rate limit“ angemeldet ziehen, eigener Mirror
Netzwerk, DNS, Proxy Zeitüberschreitung, Host nicht auflösbar vom Node aus testen, Proxy und Firewall prüfen
falsche Prozessorarchitektur „no match for platform in manifest“ Image für die Architektur des Nodes bauen
Zertifikat der Registry TLS-Fehler beim Verbindungsaufbau Zertifizierungsstelle auf jedem Node hinterlegen

Falscher Image-Name oder Tag

Die Kubernetes-Dokumentation nennt ein gescheitertes Ziehen des Images als häufigste Ursache für Pods im Zustand Waiting und gibt drei Prüfpunkte vor: Stimmt der Name, wurde das Image gepusht, lässt es sich von Hand ziehen? Achte auf die stillen Ergänzungen: Aus busybox wird docker.io/library/busybox:latest. Fehlt der Registry-Teil, fragt Kubernetes also Docker Hub.

Für Produktion rät die Dokumentation von :latest ab und empfiehlt einen sprechenden Tag wie v1.42.0 oder einen Digest. Ein Digest ist ein Hash über den Inhalt und ändert sich nie, ein Tag kann später auf ein anderes Image zeigen.

Private Registry ohne imagePullSecrets

Für eine private Registry braucht der kubelet Zugangsdaten. Die Dokumentation empfiehlt ein Secret vom Typ kubernetes.io/dockerconfigjson, das du im Pod als imagePullSecrets einträgst:

kubectl create secret docker-registry regcred -n shop \
  --docker-server=registry.example.com \
  --docker-username=<benutzer> \
  --docker-password=<token>
spec:
  imagePullSecrets:
    - name: regcred
  containers:
    - name: api
      image: registry.example.com/shop/api:1.4.2

Das Secret muss im selben Namespace liegen wie der Pod. Zeigen die Events den Grund FailedToRetrieveImagePullSecret, findet Kubernetes kein Secret mit diesem Namen. Zugangsdaten auf der Kommandozeile landen laut Dokumentation womöglich in deiner Shell-Historie. Leg das Secret deshalb lieber aus einer Datei an (kubectl create secret generic regcred --from-file=.dockerconfigjson=<pfad> --type=kubernetes.io/dockerconfigjson, so beschrieben auf derselben Doku-Seite), und nimm statt deines Passworts ein Token mit reinen Leserechten. Nutzen alle Pods eines Namespace dieselbe Registry, hängst du das Secret an den ServiceAccount der Pods, meist default. Neue Pods mit diesem ServiceAccount bekommen es automatisch, bestehende nicht. Mehr in ConfigMap und Secret in Kubernetes.

Pull-Limit von Docker Hub

Laut Docker-Dokumentation (Stand 28.10.2026) erlaubt Docker Hub nicht angemeldeten Nutzern 100 Pulls in 6 Stunden je IPv4-Adresse oder IPv6-/64-Subnetz, angemeldeten Nutzern mit Personal-Konto 200. Die bezahlten Pläne haben kein Pull-Limit, aber eine Fair-Use-Regel. Alle Nodes, die ohne Anmeldung über dieselbe öffentliche IPv4-Adresse ziehen, teilen sich also ein Kontingent, und ein Image mit mehreren Architekturen zählt als ein Pull je gezogener Architektur.

Ist das Limit erreicht, antwortet Docker Hub mit Statuscode 429 und „You have reached your pull rate limit“. Den Stand zeigen die Header ratelimit-limit und ratelimit-remaining einer HEAD-Anfrage, die laut Docker nicht als Pull zählt. Abhilfe: angemeldet ziehen mit einem imagePullSecret für https://index.docker.io/v1/, ein eigener Mirror, und feste Tags mit imagePullPolicy: IfNotPresent.

Netzwerk, DNS und Proxy

Erreicht der Node die Registry nicht, nennt die Fehlermeldung meist Host und Netzwerkfehler. Typisch sind eine Firewall, ein Proxy, den die Container-Laufzeit nicht kennt, oder ein Name, den der DNS-Server des Nodes nicht auflöst. In meinen Schulungen passiert das auf Firmenrechnern oft: Der Cluster startet, die Pods bleiben in ImagePullBackOff, und fast immer steckt ein Proxy oder eine Firewall dahinter, die den Download der Images blockiert. Wie du das lokal angehst, steht in Kubernetes lokal: Cluster auf dem Rechner. Prüf zuerst vom Node aus, dann im Cluster.

Falsche Prozessorarchitektur

Eine Registry kann laut Kubernetes-Dokumentation einen Image-Index mit einem Image je Architektur ausliefern. Fehlt die Architektur des Nodes, etwa linux/arm64 auf einem Raspberry Pi, bricht containerd mit „no match for platform in manifest“ ab. Welche Plattformen ein Image hat, zeigt docker buildx imagetools inspect <image>. Ist ein Image dagegen falsch gekennzeichnet, lädt der Node es, der Container beendet sich aber sofort, und du landest im CrashLoopBackOff. Mehr in Kubernetes auf dem Raspberry Pi.

Zertifikat der Registry

Nutzt deine Registry ein Zertifikat einer internen Zertifizierungsstelle, scheitert der Pull am TLS-Handshake. Die Zertifizierungsstelle gehört auf jeden Node: bei containerd als Feld ca in einer hosts.toml unter /etc/containerd/certs.d/<registry-host>/, was nur greift, wenn in der containerd-Konfiguration config_path = "/etc/containerd/certs.d" gesetzt ist, in k3s als ca_file unter tls in /etc/rancher/k3s/registries.yaml, danach laut Dokumentation k3s auf jedem Node neu starten. Die Prüfung abzuschalten (insecure_skip_verify bzw. skip_verify) ist höchstens ein kurzer Test.

Nach dem Fix: warten oder neu starten?

Nach dem Fix versucht es der kubelet von selbst wieder, im ungünstigsten Fall erst nach 5 Minuten. Im Quellcode hängt die Wartezeit am einzelnen Pod und Image, ein neuer Pod beginnt ohne Wartezeit. Lag der Fehler außerhalb des Manifests (Image nachgepusht, Secret angelegt, Netzwerk repariert), lösch den Pod, wenn ein Deployment ihn neu anlegt, oder starte das Deployment mit kubectl rollout restart deployment api -n shop neu. Hast du das Manifest geändert, rollt Kubernetes ohnehin neue Pods aus. Wie Rollouts ablaufen, steht in Rolling Update und Rollback in Kubernetes.

So vermeidest du ImagePullBackOff

Vier Gewohnheiten verhindern die meisten Fälle:

  1. Feste Tags oder Digests statt :latest, damit Nodes nicht ohne Grund neu ziehen.
  2. Zugangsdaten am ServiceAccount, damit niemand das imagePullSecret im Manifest vergisst.
  3. Eigene Registry oder Mirror für Basis-Images, unabhängig vom Pull-Limit von Docker Hub.
  4. Builds für alle Architekturen deiner Nodes und eine Prüfung in der Pipeline, dass das Image mit genau diesem Tag existiert. Wie so eine Pipeline aussieht, steht in CI/CD für Kubernetes: die Pipeline.

Häufige Fragen

Was bedeutet ImagePullBackOff?

Der kubelet konnte das Image nicht aus der Registry ziehen und wartet vor dem nächsten Versuch, mit wachsender Pause bis höchstens 5 Minuten. Der Container läuft nicht, der Pod bleibt Pending.

Was ist der Unterschied zwischen ErrImagePull und ImagePullBackOff?

ErrImagePull meldet einen gescheiterten Versuch, ImagePullBackOff die Wartezeit danach. Die Ursache ist dieselbe und steht in den Events von kubectl describe pod.

Wie behebe ich ImagePullBackOff bei einer privaten Registry?

Leg mit kubectl create secret docker-registry ein Secret im Namespace des Pods an und trag es unter imagePullSecrets ein. Bei FailedToRetrieveImagePullSecret stimmt der Name oder der Namespace nicht.

Warum funktioniert docker pull bei mir, aber nicht im Cluster?

Weil dein Rechner und der Node verschiedene Zugangsdaten, Netzwerke und Zertifikate haben, oft auch eine andere Architektur. Teste deshalb auf dem Node selbst, zum Beispiel mit crictl pull und bei privater Registry mit --creds.

Wie du weitermachst

ImagePullBackOff tritt vor dem Start des Containers auf. Läuft das Image, stürzt der Container aber ab, hilft CrashLoopBackOff: Pods richtig debuggen. Beendet der Kernel ihn wegen Speichermangels, lies Kubernetes OOMKilled: erkennen und beheben.

Mein Vorschlag für den nächsten Fall: kubectl describe pod, den Text nach „Failed to pull image“ lesen, die Ursache in der Tabelle oben suchen. Die Grundlagen zu Pods und zur Kommandozeile stehen in meinem Kubernetes-Praxisbuch bei Rheinwerk.

Kevin Welter

Kevin Welter

Entwickler, IT-Architekt, Fachbuchautor (Kubernetes, Cloud-Infrastrukturen) und Speaker. Betreibt sein Business mit einer KI-Belegschaft aus vierzehn 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