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
Top comments (0)