How to fix Failed to pull image, ImagePullBackOff, ErrImagePull in Kubernetes
Deployment image pull fails due to invalid image references, missing credentials, network issues, or registry problems. Fix by verifying image name/tag, checking imagePullSecrets, testing network connectivity, and validating registry access.
Quick fix
Fixes IMAGE_PULL_ERROR
# Check pod status:
kubectl describe pod -n <namespace> <pod-name>
# Look for:
# - Failed to pull image ...
# - Error response from daemon
# - Reason: ImagePullBackOff
# Check image reference in deployment:
kubectl get deployment -n <namespace> <name> -o yaml | grep -A 3 "image:"
# Check which registry is being used:
kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.spec.containers[0].image}'- Check pod image pull status
- Verify image exists in registry
- Fix image reference in deployment
- Create imagePullSecret for private registries
# Check pod status:kubectl describe pod -n <namespace> <pod-name># Look for:# - Failed to pull image ...# - Error response from daemon# - Reason: ImagePullBackOff# Check image reference in deployment:kubectl get deployment -n <namespace> <name> -o yaml | grep -A 3 "image:"# Check which registry is being used:kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.spec.containers[0].image}'Failed to pull image, ImagePullBackOff, ErrImagePull
What this error means
When Kubernetes tries to create a pod, the kubelet must pull the container image from a registry. Image pull errors occur when: 1. **Wrong image reference**: Image doesn't exist or tag is incorrect 2. **No credentials**: Private registry requires authentication 3. **Network blocked**: Firewall or DNS prevents reaching registry 4. **Registry unavailable**: Registry is down or rate-limiting 5. **Wrong platform**: Image is for different CPU architecture The pod enters ErrImagePull (error) or ImagePullBackOff (temporary retry) state, preventing the deployment from progressing.
Typical symptoms
- Pod status shows ErrImagePull or ImagePullBackOff
- Deployment replicas show 0/N ready (N = desired replicas)
- kubectl describe pod shows 'Failed to pull image'
- Pods stay in Pending or ContainerCreating state
- Pull error appears for all replicas of an image
- Works in one cluster but fails in another
- Works before upgrade, fails after upgrade
Common causes
- Image name or tag is incorrect or doesn't exist
- Image has been deleted from registry
- Private registry requires imagePullSecret not configured
- imagePullSecret credentials are wrong or expired
- Network firewall blocking registry access
- DNS can't resolve registry hostname
- CPU architecture mismatch (e.g., ARM image on Intel node)
How to fix "Failed to pull image, ImagePullBackOff, ErrImagePull"
Get detailed error information:
# Check pod status:
kubectl describe pod -n <namespace> <pod-name>
# Look for:
# - Failed to pull image ...
# - Error response from daemon
# - Reason: ImagePullBackOff
# Check image reference in deployment:
kubectl get deployment -n <namespace> <name> -o yaml | grep -A 3 "image:"
# Check which registry is being used:
kubectl get pod -n <namespace> <pod-name> -o jsonpath='{.spec.containers[0].image}'Check if the image actually exists:
# For Docker Hub:
curl -s https://hub.docker.com/v2/repositories/<user>/<image>/tags | jq '.results[].name'
# For Docker Hub with specific tag:
docker pull <username>/<image>:<tag>
# For private registry:
podman login <registry>
podman pull <registry>/<image>:<tag>
# Or test from pod:
kubectl run -it --rm debug --image=alpine -- sh
apk add curl
curl -u <user>:<token> https://registry/v2/<image>/manifests/<tag>Correct the image name if it's wrong:
# Find the correct image reference:
# Format: [registry/]image:tag
# Common examples:
# - nginx:latest (Docker Hub)
# - gcr.io/project/image:v1.0
# - registry.example.com:5000/myapp:latest
# Update deployment:
kubectl set image deployment/<name> <container>=<correct-image> -n <namespace>
# Or edit directly:
kubectl edit deployment -n <namespace> <name>
# Change container.image field
# Verify the change:
kubectl get deployment -n <namespace> <name> -o yaml | grep image:New pods will pull the corrected image.
If using a private registry, set up authentication:
# Create Docker config credentials:
kubectl create secret docker-registry myregistry \
--docker-server=<registry> \
--docker-username=<user> \
--docker-password=<token> \
--docker-email=<email> \
-n <namespace>
# Or for Kubernetes API token:
kubectl create secret docker-registry myregistry \
--docker-server=gcr.io \
--docker-username=_json_key \
--docker-password="$(cat ~/key.json)" \
-n <namespace>Then add to deployment:
spec:
template:
spec:
imagePullSecrets:
- name: myregistry
containers:
- name: app
image: registry.example.com/app:v1Check if credentials are working:
# Get secret contents:
kubectl get secret <secret-name> -n <namespace> -o jsonpath='{.data..dockerconfigjson}' | base64 -d | jq .
# Test credentials manually:
kubectl run -it --rm debug \
--image-pull-policy=Never \
--image=alpine \
--overrides='{"spec":{"serviceAccount":"default"}}' \
-- sh
# Inside pod, test registry:
apk add curl
curl -u <user>:<password> https://<registry>/v2/_catalogIf credentials are wrong, delete and recreate the secret.
Verify network can reach the registry:
# From a node, test:
ping <registry-host>
nslookup <registry-host>
curl -v https://<registry>/v2/
# From a pod:
kubectl run -it --rm debug --image=alpine -- sh
apk add curl
curl -v https://docker.io/v2/
curl -v https://<private-registry>/v2/
# Check firewall rules:
# - Port 443 (HTTPS) must be open
# - No corporate proxies blocking
# - DNS must resolve registry hostnameIf connectivity fails, contact network team to unblock registry.
Ensure image matches node architecture:
# Check node architecture:
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.architecture}'
# Check image architecture:
docker image inspect <image> | jq '.Architecture'
# Or for multi-arch images:
docker manifest inspect <image>:tag | jq '.manifests[].platform'
# If mismatch, use platform-specific image:
# AMD64: ubuntu:latest
# ARM64: ubuntu:latest-arm64
# ARM32: ubuntu:latest-arm32v7
# Update deployment with correct architecture:
kubectl set image deployment/<name> <container>=<image>-arm64Confirm the image pulls successfully:
# Force pod recreation:
kubectl rollout restart deployment -n <namespace> <name>
# Watch for image pull:
kubectl get pods -n <namespace> -w
# Check pod events:
kubectl describe pod -n <namespace> <new-pod-name> | tail -20
# Verify pod is Running:
kubectl get pods -n <namespace> | grep <deployment>
# Check actual image used:
kubectl get pods -n <namespace> <pod-name> -o jsonpath='{.spec.containers[0].image}'Pod should transition from ContainerCreating โ Running.
Advanced notes
### Image Pull Policies
Control when images are pulled:
imagePullPolicy: Always # Always pull (default for latest)
imagePullPolicy: IfNotPresent # Only pull if not cached
imagePullPolicy: Never # Never pull (local only)For reproducibility, explicit tags with IfNotPresent work well.
### Private Registry Setup
For self-hosted registries (Harbor, Nexus):
# Create secret with base64 auth:
echo -n user:password | base64
# Creates: dXNlcjpwYXNzd29yZA==
# Use in deployment:
imagePullSecrets:
- name: private-registry### Multi-arch Images
Modern best practice is multi-arch images:
FROM --platform=${BUILDPLATFORM} golang:latest as builder
# ... build code ...
FROM ubuntu:latest
COPY --from=builder /app /appBuild with: docker buildx build --platform linux/amd64,linux/arm64
### Rate Limiting
Docker Hub limits pulls (100/6h for anonymous):
# Solution: Authenticate even for public images
kubectl create secret docker-registry dockerhub \
--docker-server=docker.io \
--docker-username=<user> \
--docker-password=<token>Or use private registry mirror.
### Image Pull Timeout
Slow registries may timeout:
spec:
template:
spec:
containers:
- name: app
image: slow.registry.com/image:v1
imagePullPolicy: IfNotPresent # Reduces frequencyAlso check network bandwidth and latency.
Frequently asked questions
- What does "IMAGE_PULL_ERROR" mean?
- When Kubernetes tries to create a pod, the kubelet must pull the container image from a registry. Image pull errors occur when: 1. Wrong image reference: Image doesn't exist or tag is incorrect 2.
- How do I fix "IMAGE_PULL_ERROR"?
- Deployment image pull fails due to invalid image references, missing credentials, network issues, or registry problems. Fix by verifying image name/tag, checking imagePullSecrets, testing network connectivity, and validating registry access.
- What causes "IMAGE_PULL_ERROR"?
- Image name or tag is incorrect or doesn't exist Image has been deleted from registry Private registry requires imagePullSecret not configured
- Is the "IMAGE_PULL_ERROR" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.
Official resources & further reading
- ๐Kubernetes Official Documentation
- ๐Images - Kubernetes Docs(Official Docs)
- ๐Pull an Image from a Private Registry - Kubernetes Docs(Official Docs)
- ๐