imagePullPolicy 是什么
imagePullPolicy 决定 kubelet 启动容器时是否去镜像仓库拉取镜像,取值为 Always、IfNotPresent、Never。它有一条容易忽略的默认规则:不显式声明时,镜像 tag 为 latest 或干脆不写 tag,默认就是 Always;写了具体版本 tag 或以 digest 引用,默认变成 IfNotPresent。生产上「镜像重新推了但节点还在跑旧的」与「每次重启都去仓库拉导致启动变慢」这两个高频问题,根子都在这个字段。
取值与默认规则
| 取值 | 行为 | 何时成为默认 |
|---|---|---|
| IfNotPresent | 节点本地已有同名镜像就不再拉取 | 镜像 tag 为具体版本号或以 digest 引用时 |
| Always | 每次启动容器都向仓库查询并拉取 | 镜像 tag 为 latest 或省略 tag 时 |
| Never | 只用节点本地镜像,没有就启动失败 | 从不会默认,必须显式声明 |
典型使用场景
- 固定版本发布:写明确 tag 并声明 IfNotPresent,启动快且不依赖仓库可用性
- 开发环境快速迭代:用 latest 并声明 Always,重启容器即可拿到最新构建产物
- 离线或隔离节点:镜像先手工导入节点(crictl pull 或离线包),配合 Never 阻止 kubelet 访问外网仓库超时
- 仓库故障应急:把策略临时改为 Never,节点上有缓存时 Pod 仍能重建,争取恢复时间
- 合规审计:用 image@sha256 形式锁定唯一内容,避免同名 tag 被重新推送后内容漂移
声明方式
声明方式
containers:
- name: app
image: registry.example.com/app:1.26.0 # 具体版本 tag,不写策略时默认 IfNotPresent
imagePullPolicy: IfNotPresent # 生产建议显式声明,不依赖隐含默认值核对是否真的更新了
核对是否真的更新了
kubectl get deploy web -o jsonpath='{.spec.template.spec.containers[*].imagePullPolicy}'
kubectl describe pod web-x | grep -i -E 'Image:|Image ID:' # 对比声明地址与实际运行的摘要
kubectl get events --field-selector reason=Failed --sort-by=.lastTimestamp | tail -5
crictl images | grep app # 节点侧看本地镜像的 tag 与 IDdescribe 输出读法
| 字段 | 含义 | 正常/异常 |
|---|---|---|
| Image | 清单声明的镜像地址 | 应带具体版本 tag,与本次发布一致 |
| Image ID | 容器实际运行的镜像摘要 | 与 Image 的 tag 对不上说明跑的是旧镜像 |
| State | 容器当前状态 | Waiting + ImagePullBackOff、ErrImagePull 指向拉取失败 |
| Events | 调度与拉取过程中的事件 | 拉取失败会给出仓库地址、鉴权或网络错误原文 |
Always 并不意味着「跳过仓库」:kubelet 仍要访问仓库做鉴权与 manifest 查询,因此仓库不可达时容器起不来。这正是「节点上明明有镜像却报拉取失败」的原因,此时改用 IfNotPresent 或 Never 即可吃本地缓存。
私有仓库拉取失败按顺序排查:imagePullSecrets 是否建在 Pod 所在命名空间、Secret 的 dockerconfigjson 是否覆盖该 registry 域名、节点到仓库的网络与证书是否可信,最后才怀疑镜像名或 tag 写错。