How to fix 'ImagePullBackOff' without leaving kubectl
Table of Contents
Your pod is stuck in ImagePullBackOff and you don’t know why. Before opening the browser to check the registry, run these three commands.
Step 1: What’s the Actual Error? #
ImagePullBackOff is the retry state - it tells you the kubelet keeps trying and keeps failing. The real error is in the events:
kubectl describe pod my-pod | grep -A 5 Events:
Look for the last line under Warning Failed. That’s the actual cause.
The Four Causes You Usually See #
| Message | Cause |
|---|---|
manifest for X not found | The tag doesn’t exist. Typo, or built but never pushed. |
unauthorized: authentication required | Missing or wrong imagePullSecrets. |
dial tcp: lookup X: no such host | Registry hostname wrong, or DNS is broken. |
pull rate limit exceeded | Docker Hub is rate-limiting anonymous pulls. |
Verify the Image Exists #
If your registry supports it, crane checks the manifest without pulling the layers:
crane manifest my-registry/my-image:my-tag
If that returns JSON, the image exists and your problem is auth or DNS. If it 404s, you’re pushing to a different tag than the pod spec references.
Verify the Pull Secret #
kubectl get secret my-pull-secret -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d
Check the registry hostname in the output matches the image reference in the pod spec exactly. docker.io vs index.docker.io/v1/ vs registry-1.docker.io catches a lot of people.
Force a Retry #
Once you fix the underlying issue, force the pod to re-pull:
kubectl rollout restart deployment my-deployment
or for a bare pod:
kubectl delete pod my-pod
(The Deployment or ReplicaSet will recreate it, and it will pull fresh.)
The One That Wastes the Most Time #
Docker Hub anonymous pull rate limits: 100 pulls per 6 hours per IP. If a hundred nodes all try to pull the same public image at once, you hit it fast. The fix is to mirror the image to your own registry or authenticate the anonymous pulls.