imagePullPolicy 的默认值是怎么来的?Always 是不是每次都下载整个镜像?仓库挂了时哪些 Pod 会受影响?同一个 tag 一定是同一份镜像吗?这篇用一个连不上的仓库和一个被改指向的 tag,把三种策略的行为都跑一遍。
image: busybox → imagePullPolicy=Always image: busybox:latest → imagePullPolicy=Always image: busybox:1.36 → imagePullPolicy=IfNotPresent image: busybox@sha256:aaaaaaaaaaaaaaaaaaaaaaaaa → imagePullPolicy=IfNotPresent image: registry.example.com/team/app → imagePullPolicy=Always 规则:没写 tag 或 tag 是 latest → Always;指定了别的 tag 或 digest → IfNotPresent(由 API Server 的准入补上)
不写 imagePullPolicy 时,API Server 的准入按镜像引用补默认值:busybox(没写 tag)、busybox:latest、registry.example.com/team/app(没写 tag)是 Always;busybox:1.36(指定了别的 tag)和 busybox@sha256:…(digest)是 IfNotPresent。默认值是在创建对象时由准入写进 Pod spec 的,读出来就能看到。
ifnp-present(localhost:5999/app:1.0 本地已有):容器状态 running;''
never-present(localhost:5999/app:1.0 本地已有):容器状态 running;''
always-present(localhost:5999/app:1.0 本地已有):容器状态 waiting/ErrImagePull;'failed to pull and unpack image "localhost:5999/app:1.0": failed to resolve reference "localhost:5999/app:1.0": failed to do request: Head "https://lo'
always-present 的事件:['Pulling: Pulling image "localhost:5999/app:1.0"', 'Failed: Failed to pull image "localhost:5999/app:1.0": failed to pull and unpack image "localhost:5999/app:1.0": failed to resolve reference "localhost:5999/a', 'Failed: Error: ErrImagePull', 'BackOff: Back-off pulling image "localhost:5999/app:1.0"']
对照:busybox:1.36(docker.io 的镜像,节点上有,但访问 docker.io 的连接不通也不拒绝)+ Always,过了 60 秒:容器状态 waiting/ImagePullBackOff,事件 ['Pulling: Pulling image "busybox:1.36"', 'Failed: Failed to pull image "busybox:1.36": rpc error: code = DeadlineExceeded desc = failed to pull and unpack image "docker.io/library/busybox:1.36": faile'](连接既不通也不被拒绝,要等超时才报错:DeadlineExceeded)镜像 localhost:5999/app:1.0 在节点上已有,但这个仓库地址没有服务:IfNotPresent 和 Never 的 Pod 直接 Running;Always 的 Pod 容器状态是 ErrImagePull(failed to pull and unpack image … failed to resolve reference … Head "https://localhost:5999/…"),事件依次 Pulling、Failed、ErrImagePull、BackOff(Back-off pulling image),随后是 ImagePullBackOff。Always 并不是每次都下载整个镜像,但每次创建容器都要访问仓库确认 digest,仓库故障时这样的 Pod 起不来。对照 docker.io 的 busybox:1.36(节点上有,但连不通 docker.io)+ Always,60 秒后也是 ImagePullBackOff,事件里是 DeadlineExceeded——连接不通也不拒绝时要等超时才报错。
ifnp-missing(IfNotPresent + 本地没有):容器状态 waiting/ErrImagePull;message='failed to pull and unpack image "localhost:5999/missing:1.0": failed to resolve reference "localhost:5999/missing:1.0": failed to do request: Head "https://localhost:5999/v2/missing/manifests/1.0": di' never-missing(Never + 本地没有):容器状态 waiting/ErrImageNeverPull;message='Container image "localhost:5999/missing:1.0" is not present with pull policy of Never' 对照:never-missing 的事件里没有 Pulling(Never 不会尝试拉取);ifnp-missing 的事件:['Pulling: Pulling image "localhost:5999/missing:1.0"', 'Failed: Failed to pull image "localhost:5999/missing:1.0": failed to pull and unpack image "localhost:5999/missing:1.0": failed to resolve reference "localhos', 'Failed: Error: ErrImagePull']
镜像 localhost:5999/missing:1.0 本地没有:IfNotPresent 会尝试拉取,失败 → ErrImagePull;Never 不拉取,直接 ErrImageNeverPull,message 是 Container image "localhost:5999/missing:1.0" is not present with pull policy of Never,事件里也没有 Pulling。
节点上 demo:v1 原本是 busybox:第一个 Pod first 的 imageID=2b865bd036cfddd518839204 在节点上把 demo:v1 这个 tag 改指向 nginx 镜像:docker.io/library/demo:v1 第二个 Pod second 同样写 demo:v1 + IfNotPresent:imageID=8ba7c98b61c2a856a22b826a(不同:True)——没有拉取事件:无 Pulling first 里是 BusyBox v1.36.1 (2023-05-18 22;second 里是 nginx version: nginx/1.27.5——同一个 tag,同一个节点,两个 Pod 跑的是不同的镜像 这就是为什么生产环境推荐固定 digest 或不可变 tag,而不是依赖 latest + Always 去“刷新”
节点上 demo:v1 原本是 busybox,Pod first 的 imageID 以 …2b865bd036cfddd518839204 结尾;用 ctr images tag --force 把节点上的 demo:v1 改指向 nginx 镜像后,第二个 Pod second 同样写 demo:v1 + IfNotPresent,没有任何拉取事件,imageID 是 …8ba7c98b61c2a856a22b826a。first 里是 BusyBox v1.36.1,second 里是 nginx/1.27.5。IfNotPresent 只看 tag 在不在,不比较内容;tag 是可变的,固定 digest 才能保证“跑的是同一份”。