Image Pull and Registry Auth
How does the Kubelet get a container image onto the Node before the container can run? It reads imagePullPolicy, which when you leave it unset defaults to Always for :latest or an untagged image and to IfNotPresent for any other tag or a digest, finds credentials through imagePullSecrets, and pulls only the layers the Node does not already hold by sha256 digest. A failed pull surfaces as ErrImagePull and retries on an exponential ImagePullBackOff.
Play the animation 5 steps, animated, best on a wide screen
Image Pull and Registry Auth, step by step
-
Kubelet reads spec.containers[0].imagePullPolicy. Left unset, the default follows the image reference: :latest or no tag at all gives Always, which re-resolves the digest on every container start, and any other tag (v2 here) or a pinned digest gives IfNotPresent. The explicit value Never disables pulling, so the image has to be preloaded on the Node or the container fails with ErrImageNeverPull. Pull is per-container, not per-Pod.
Play from step 1 -
A private registry needs credentials, so Kubelet reads Pod.spec.imagePullSecrets, which the ServiceAccount admission plugin fills from the Pod ServiceAccount when the Pod names none of its own. Each Secret of type kubernetes.io/dockerconfigjson holds a docker config, and Kubelet hands a matching entry to the runtime in the CRI PullImage request. For ECR, GCR or ACR a credential provider plugin can mint credentials instead.
Play from step 2 -
Kubelet asks the runtime, through the CRI ImageStatus call, whether this exact image is on the Node. Its layer store is keyed by sha256 digest and shared by every Pod on the Node. Only 2 of the 4 app:v2 layers came in with earlier images, so ImageStatus reports no image and the pull goes ahead. A present image the Kubelet pulled with credentials is still pulled again unless this Pod holds the same ones (KubeletEnsureSecretPulledImages, beta, on by default).
Play from step 3 -
The runtime fetches the manifest first, then issues GET /v2/app/blobs/sha256:{digest} for each of the 2 missing layers, carrying the assembled Authorization header. The 2 layers already in the store are reused, so a partial cache hit shrinks the wire transfer. On error the container goes Waiting with reason ErrImagePull and Kubelet retries on an exponential backoff (10s, 20s, 40s, capped at 300s), which surfaces as ImagePullBackOff.
Play from step 4 -
All 4 layers are in the store. With the default overlayfs snapshotter the container rootfs is an overlay filesystem: every layer mounts read-only under one top read-write layer that takes whatever the container writes outside its volumes. Only that upper layer is per-container, so a second Pod on the same image shares the lower ones. Kubelet then calls CreateContainer to bind that rootfs and the mounts, and StartContainer to exec PID 1.
Play from step 5