Kubernetes imagePullPolicy Guide
Configure imagePullPolicy correctly: Always, Never, and IfNotPresent behavior. Understand digest pinning and tag mutability implications.
π‘ Quick Answer:
IfNotPresentuses cached images (default for tagged images);Alwayschecks the registry every time (default for:latest);Neveronly uses pre-pulled local images.
The Problem
Misunderstanding imagePullPolicy leads to:
- Running stale images after tag updates (
IfNotPresentwith mutable tags) - Unnecessary registry pulls increasing startup time and bandwidth
- Failed pods on nodes without pre-cached images (
Neverpolicy) - Outages when registries are unreachable (
Alwayspolicy)
The Solution
Explicit Policy Configuration
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
spec:
containers:
- name: app
image: myregistry.io/app:v2.1.0
imagePullPolicy: IfNotPresentDefault Behavior Rules
# Tag specified β defaults to IfNotPresent
image: nginx:1.25.3 # β IfNotPresent
# :latest tag β defaults to Always
image: nginx:latest # β Always
image: nginx # β Always (implicit :latest)
# Digest β defaults to IfNotPresent
image: nginx@sha256:abc... # β IfNotPresentProduction: Digest Pinning
containers:
- name: app
image: myregistry.io/app@sha256:a1b2c3d4e5f6...
imagePullPolicy: IfNotPresent # Safe β digest is immutableAir-Gapped: Never Policy
containers:
- name: app
image: internal-app:v1.0
imagePullPolicy: Never # Only use pre-loaded imagesPre-load images on nodes:
# On each node (or via DaemonSet init)
crictl pull myregistry.io/app:v1.0flowchart TD
A[Pod Scheduled] --> B{imagePullPolicy?}
B -->|Always| C[Check Registry]
B -->|IfNotPresent| D{Image in Local Cache?}
B -->|Never| E{Image in Local Cache?}
C -->|New Digest| F[Pull Image]
C -->|Same Digest| G[Use Cached]
C -->|Registry Down| H[Pod Fails: ErrImagePull]
D -->|Yes| G
D -->|No| F
E -->|Yes| G
E -->|No| I[Pod Fails: ErrImageNeverPull]
F --> J[Start Container]
G --> JCommon Issues
Stale images with mutable tags Using imagePullPolicy: IfNotPresent with tags like v2-latest means nodes with cached old images wonβt pull updates:
# Force re-pull by changing the tag
image: myapp:v2.1.1 # Instead of overwriting v2.1.0ErrImageNeverPull Pod uses Never policy but image isnβt cached on the scheduled node:
kubectl describe pod app | grep -A5 Events
# Pre-pull or switch to IfNotPresentAlways policy causing slow rollouts Every new pod pulls from registry. Use IfNotPresent with immutable tags (semver or digest).
Best Practices
- Use immutable tags (semver like
v1.2.3) withIfNotPresent - Never use
:latestin production β it defaults toAlwaysand is mutable - Pin by digest (
@sha256:...) for maximum reproducibility - Use
Alwaysonly when you intentionally overwrite tags (dev/staging) - Use
Neverfor air-gapped environments with pre-loaded images - Configure
imagePullSecretsfor private registries
Key Takeaways
IfNotPresentis fastest β pulls only on cache missAlwaysverifies the digest with the registry (doesnβt always re-download)Neverfails if the image isnβt already on the node:latesttriggersAlwaysby default β avoid in production- Immutable tags +
IfNotPresentis the production best practice - Digests are the only truly immutable image references

Recommended
Kubernetes Recipes β The Complete Book100+ production-ready patterns with detailed explanations, best practices, and copy-paste YAML. Everything in one place.
Get the Book βLearn by Doing
CopyPasteLearn β Hands-on Cloud & DevOps CoursesMaster Kubernetes, Ansible, Terraform, and MLOps with interactive, copy-paste-run lessons. Start free.
Browse Courses βπ Deepen Your Skills β Hands-on Courses
Courses by CopyPasteLearn.com β Learn IT by Doing
