ImagePullBackOff means Kubernetes tried to pull your container image, failed, and is now retrying with exponential backoff. The pod will never start until the pull succeeds — but the fix is usually one of five causes, and kubectl describe tells you which within seconds.
Table of Contents
- See the real error
- Cause 1 — Wrong image name or tag
- Cause 2 — Private registry auth
- Cause 3 — Rate limits and network
- Cause 4 — Platform/architecture mismatch
- Cause 5 — Tag exists but was overwritten
- When it's actually ErrImagePull
See the real error
Don't guess — get the event:
kubectl describe pod <pod-name> -n <namespace> Scroll to Events at the bottom. The Failed to pull image line carries the real reason verbatim:
Failed to pull image "myregistry/app:v2": rpc error: code = NotFound desc = failed to pull and unpack image: failed to resolve reference: myregistry/app:v2: not found Each cause below maps to a distinct event message.
Cause 1 — Wrong image name or tag
Event says: not found, manifest unknown, or does not exist.
The image name or tag doesn't exist in the registry. Check for typos first — ngnix vs nginx is embarrassingly common — then verify the tag actually exists:
# For Docker Hub, check the tag exists crane ls myrepo/myimage # or check the registry UI docker pull myregistry/app:v2 # test the pull from your machine Watch for latest — it only exists if someone pushed it, and on some registries it means nothing at all. Pin explicit tags in the manifest.
Cause 2 — Private registry auth
Event says: unauthorized, 401, access denied, no basic auth credentials.
Kubernetes can't authenticate to your registry. Fix: create an image pull secret and reference it:
kubectl create secret docker-registry regcred \ --docker-server=myregistry.example.com \ --docker-username=robot_user \ --docker-password=<token> \ -n my-namespace spec: imagePullSecrets: - name: regcred containers: - name: app image: myregistry.example.com/app:v2 For ECR/GCR/ACR, prefer workload identity or node-level IAM over static secrets — cloud registries rotate tokens. Gotcha: the secret must be in the same namespace as the pod, and default service accounts can carry it cluster-wide via imagePullSecrets on the SA.
Cause 3 — Rate limits and network
Event says: toomanyrequests, connection refused, i/o timeout, context deadline exceeded.
- Docker Hub rate limits — anonymous pulls are capped per IP; a busy cluster NATs all pulls through one egress IP and hits the ceiling fast. Fix: authenticate pulls (higher limit) or mirror images to your own registry.
- Corporate proxy/firewall — nodes can't reach the registry. Test from a node:
crictl pull <image>bypasses Kubernetes entirely. - DNS —
lookup myregistry on 10.96.0.10:53: no such hostmeans CoreDNS can't resolve it; checkkube-dnspods.
Cause 4 — Platform/architecture mismatch
Event says: no matching manifest for linux/arm64 (or amd64).
The image was built for the wrong CPU architecture — common when developers build on Apple Silicon and deploy to amd64 nodes. Fix: build multi-arch images:
docker buildx build --platform linux/amd64,linux/arm64 \ -t myregistry/app:v2 --push . Cause 5 — Tag exists but was overwritten
Event says: pull succeeds but the container is wrong, or pull used to work and silently changed.
Someone repushed the tag with different content. imagePullPolicy: Always pulls every restart; IfNotPresent caches whatever it first pulled — a moving latest tag gives different nodes different images. Pin digests for reproducibility:
image: myregistry/app@sha256:abc123... When it's actually ErrImagePull
ErrImagePull is the initial failure state; ImagePullBackOff is the retry state — same root causes. If the pod later shows CreateContainerConfigError or CrashLoopBackOff, the pull succeeded and your problem moved elsewhere — see Fixing CrashLoopBackOff for the next tier of debugging.
The one-line summary: describe the pod, read the event, fix the named cause. ImagePullBackOff is never the disease — it's the symptom.
Related Articles
Author: CloudOpsGuide Team


