K8s镜像拉取失败排查:事件、凭据与仓库

遇到 Pod 一直 Pending 或 ImagePullBackOff 时,先别急着重建应用。本篇按事件、Secret、镜像地址、仓库连通性和节点运行时逐层排查,帮助快速定位 K8s镜像拉取失败原因。

K8s镜像拉取失败时,Pod 可能停在 `ErrImagePull`、`ImagePullBackOff` 或长时间 `Pending`。最快的排查入口不是反复删除 Pod,而是先看 Pod events:事件会告诉你是镜像不存在、认证失败、仓库超时,还是节点运行时无法拉取。

下面这组命令可以先建立现场,不要一开始就改 YAML;这些检查围绕 Pod 事件、镜像字段和私有仓库凭据展开<sup>[1]</sup><sup>[2]</sup><sup>[3]</sup>:

kubectl describe pod <pod-name> -n <namespace>
kubectl get events -n <namespace> --sort-by=.lastTimestamp
kubectl get secret -n <namespace>
kubectl get pod <pod-name> -n <namespace> -o yaml

K8s镜像拉取失败排查决策树

图1:从 Pod 事件进入 K8s 镜像拉取失败排查的决策树

先用事件区分 ErrImagePull 和 ImagePullBackOff

Kubernetes 在 Pod 生命周期中会记录容器创建和镜像拉取相关事件;当镜像拉取失败时,Pod 状态和事件会显示失败原因与后续退避重试<sup>[1]</sup>。`ErrImagePull` 更像首次拉取失败信号,`ImagePullBackOff` 表示 kubelet 已进入退避重试阶段。

事件或状态 常见含义 优先检查
`ErrImagePull` 镜像首次拉取失败 镜像名、tag、仓库地址、认证
`ImagePullBackOff` 多次失败后退避重试 上一次失败事件、Secret、网络
`manifest unknown` tag 或 digest 不存在 镜像是否已推送、tag 是否写错
`unauthorized` 私有仓库认证失败 imagePullSecrets、账号权限
`i/o timeout` 仓库网络不可达或响应慢 节点网络、DNS、代理、仓库状态

不要只看 Pod 状态

Pod 状态只告诉你当前卡住了,事件才告诉你为什么卡住。排障时应复制完整事件文本,尤其是仓库返回的状态码、错误短语和失败镜像名。很多问题并不是 Kubernetes 调度失败,而是 kubelet 在目标节点上无法完成镜像拉取。

站内“容器镜像安全怎么做”“Kubernetes安全怎么做”等内容可在发布前确认正式 URL 后作为延伸阅读;本文聚焦拉取失败排障,不展开镜像治理的完整体系。

镜像名、tag 和拉取策略是第一层

Kubernetes 镜像字段支持 registry、repository、tag 或 digest 组合;如果不写 tag,默认行为和镜像策略可能导致环境间结果不一致。Kubernetes 官方文档建议生产环境避免依赖可变 tag,并说明了 `imagePullPolicy` 的影响<sup>[2]</sup>。

先核对这些字段:

  • 镜像地址是否包含正确 registry 域名和 namespace。
  • tag 是否已推送,大小写是否一致。
  • 是否应该使用 digest 固定不可变镜像版本。
  • `imagePullPolicy` 是否与发布策略一致。
  • 节点是否能解析仓库域名并访问镜像层。
containers:
  - name: app
    image: registry.example.com/team/app:1.2.3
    imagePullPolicy: IfNotPresent

如果团队使用同一个 tag 覆盖发布,节点缓存可能导致旧镜像继续运行;如果每次都 `Always` 拉取超大镜像,又可能放大发布窗口的仓库压力。策略要和镜像版本治理一起设计。

私有仓库要检查 imagePullSecrets 和 ServiceAccount

私有镜像仓库认证通常通过 Docker registry Secret 或 ServiceAccount 绑定 `imagePullSecrets` 实现。Kubernetes 官方任务文档提供了为私有仓库配置 pull secret 的方式<sup>[3]</sup>。

事件 Secret 仓库信号关系图

图2:Pod 事件、imagePullSecrets、Serv

认证排查顺序:

  1. Secret 是否存在于 Pod 所在 namespace。
  2. Secret 类型是否为 `kubernetes.io/dockerconfigjson`。
  3. Pod 或 ServiceAccount 是否引用了正确 `imagePullSecrets`。
  4. Secret 中 registry 地址是否与镜像地址完全匹配。
  5. 仓库账号是否有目标项目、仓库和 tag 的拉取权限。

Secret namespace 经常被忽略

Secret 是 namespace 级资源。把 Secret 创建在 `default`,但 Pod 部署在业务 namespace,是常见错误。还有一种情况是 ServiceAccount 绑定了旧 Secret,新 Secret 创建成功但 Pod 并没有引用它。下面的检查应与私有仓库凭据文档一起核对<sup>[3]</sup>。

kubectl get serviceaccount <sa-name> -n <namespace> -o yaml
kubectl get secret <secret-name> -n <namespace> -o yaml

如果事件显示 `unauthorized` 或 `authentication required`,应优先检查 Secret、ServiceAccount 和仓库权限,而不是重启节点。

节点网络和运行时决定能否真正拉取

即使镜像名和 Secret 都正确,节点也可能因为 DNS、代理、防火墙、证书、镜像仓库不可用或容器运行时配置导致拉取失败。Kubelet 负责在节点上拉取镜像并启动容器,因此节点侧网络和运行时状态同样重要<sup>[2]</sup>。

节点侧常见检查方向:

  • 节点是否能解析 registry 域名。
  • 节点到仓库的出站网络是否允许。
  • 私有仓库 TLS 证书是否被节点信任。
  • containerd 或 CRI-O 是否配置了镜像加速、代理或私有仓库。
  • 仓库是否限制并发、频率或 IP 白名单。

在无法 SSH 到节点的环境中,可以使用平台提供的诊断工具或临时调试 Pod 检查网络连通性;涉及生产节点命令时,应按主流程授权执行,不在草稿中假定可直接远程操作。

修复后要验证新 Pod 和旧缓存

镜像拉取失败修复后,不要只看 Secret 已创建或仓库已恢复。要重新触发 Pod 创建,并观察新 Pod 的事件、镜像 ID 和容器启动状态。

K8s镜像拉取修复验证时间线

图3:从发现镜像拉取失败到修复 Secret、仓库和新 Pod

验证步骤建议:

  1. 记录原始失败事件和镜像地址。
  2. 修复镜像 tag、Secret、仓库权限或节点网络。
  3. 重新创建 Pod 或触发 Deployment rollout。
  4. 观察新 Pod events 是否还出现拉取失败。
  5. 确认容器进入 Running,镜像 ID 与期望版本一致。
  6. 检查业务探针、日志和服务访问是否正常。

旧缓存可能掩盖问题

如果节点已经缓存了某个镜像,`IfNotPresent` 可能让 Pod 看起来启动正常,但其他节点仍然拉取失败。排查私有仓库或镜像权限问题时,最好验证至少一个未缓存该镜像的节点,或使用明确的新 tag / digest。

小结

K8s镜像拉取失败要从事件开始,而不是从猜测开始。先区分 `ErrImagePull` 和 `ImagePullBackOff`,再按镜像名、tag、拉取策略、imagePullSecrets、ServiceAccount、仓库权限、节点网络和运行时逐层排查。修复后一定要通过新 Pod 事件和镜像 ID 验证,避免节点缓存掩盖问题。

参考资料

常见问题

ImagePullBackOff 和 ErrImagePull 有什么区别?

`ErrImagePull` 通常表示镜像拉取动作失败,`ImagePullBackOff` 表示 kubelet 多次失败后进入退避重试。排查时应看事件里的上一条具体错误,而不是只看最终状态名。

K8s镜像拉取失败一定是 Secret 错了吗?

不一定。Secret 错误很常见,但镜像 tag 不存在、仓库地址错误、节点网络不可达、证书不受信任、仓库限流或节点运行时配置异常,也会导致拉取失败。事件文本通常能帮助缩小范围。

修改 imagePullSecrets 后为什么 Pod 还是失败?

可能是 Secret 不在同一 namespace,Pod 使用的 ServiceAccount 没有引用新 Secret,或者旧 Pod 没有重新创建。建议检查 ServiceAccount、重新触发 Pod 创建,并观察新 Pod events 是否使用了正确凭据。

原创声明:本文为 CNBPA 云原生社区原创技术内容,非商业转载须注明出处:https://www.cloudnative-tech.com/p/9482/。文中原创图示、架构图和文章内容未经许可不得用于商业转载、培训课件、营销材料或二次分发。
(0)
上一篇 2天前
下一篇 2小时前

相关推荐