Kubernetes ImagePullBackOff:不是注册表(是 IAM)
Source: Dev.to
请提供您希望翻译的完整文本内容,我将按照要求保留源链接、格式和技术术语,仅翻译正文部分。
ImagePullBackOff – 为什么它通常是身份问题,而不是注册表问题
到 2026 年,当你的 pod 进入 ImagePullBackOff 状态时,注册表通常是没有问题的。
镜像标签存在,仓库正常运行,且没有任何错误。
真正的罪魁祸首往往是 Kubernetes 节点。
ImagePullBackOff 实际意味着什么
“我尝试拉取镜像,但没有成功,现在我会在再次尝试之前等待更长的时间。”
Kubelet 并 不会 告诉你拉取失败的 原因。
最常见的隐藏原因是:你的身份验证令牌已悄然过期。
常见调试路径(以及为何会失败)
| 看到的情况 | 你的想法 |
|---|---|
ImagePullBackOff | “可能是镜像标签错误。” |
ImagePullBackOff | “可能是注册表宕机了。” |
ImagePullBackOff | “可能是 Docker Hub 对我进行速率限制。” |
如果注册表真的宕机,你会看到 连接超时。
ImagePullBackOff 通常意味着 连接成功,但 身份验证握手失败。
真正的问题出在 凭证提供程序
自从 Kubernetes 移除了内置云提供程序(即“伟大的解耦”)后,kubelet 依赖外部的 Kubelet Credential Provider 来获取云镜像仓库(ECR、ACR 等)的短期认证令牌。
拉取流程概览
- 请求 – Kubelet 看到一个镜像,例如
12345.dkr.ecr.us-east-1.amazonaws.com/app:v1。 - 交换 – Kubelet 向 Credential Provider 插件请求令牌(AWS IAM、Azure Entra ID,……)。
- 验证 – 云端检查节点的 IAM 角色是否被授权。
- 拉取 – 在令牌有效的情况下,kubelet 将请求交给镜像仓库。
如果 第 3 步 失败(令牌过期、时钟漂移、IMDS 不可用、缺少 IAM 策略),镜像仓库会返回 401 Unauthorized,而 kubelet 则报告通用的 ImagePullBackOff。
快速定位根本原因
1. 获取真实错误信息
kubectl describe pod <pod-name>
查找类似以下的行:
rpc error: code = Unknown desc = failed to authorize: failed to fetch anonymous token: unexpected status: 401 Unauthorized
或
no basic auth credentials
这些表明是身份验证失败,而不是网络或注册表故障。
2. 绕过 Kubernetes 直接在节点上测试
大多数现代集群使用 containerd(Docker shim 已不再使用)。请使用
crictl,而不是docker。
# SSH to the node
crictl pull <image>
| 结果 | 解释 |
|---|---|
| 成功 | 节点 IAM 正常 → 问题出在 ServiceAccount / imagePullSecrets。 |
| 失败 | 节点本身配置错误 → IAM、网络或时钟问题。 |
如果失败,请深入查看容器运行时日志:
journalctl -u containerd --no-pager | grep -i "failed to pull"
常见 IAM 相关原因与解决方案
| 云平台 | 症状 | 常见原因 | 解决办法 |
|---|---|---|---|
| AWS | 某些节点随机出现 401 错误 | 节点的实例配置文件缺少 AmazonEC2ContainerRegistryReadOnly(或 ecr:GetAuthorizationToken / ecr:BatchGetImage)。 | 将该策略附加到节点角色。 |
| Azure | 集群创建后 Pod 卡在 ImagePullBackOff | AcrPull 角色尚未传播(可能需要约 10 分钟)。 | 等待或使用以下命令验证:az aks show -n <cluster> -g <rg> --query "identityProfile.kubeletidentity.clientId" |
| GCP | 即使 ServiceAccount 正确仍返回 403 Forbidden | 节点使用默认的 Storage Read‑Only 访问范围创建 → 无法访问 Artifact Registry API。 | 使用 Workload Identity,或使用 cloud-platform 范围重新创建节点池。 |
令牌过期与时钟漂移
- AWS EKS 令牌每 12 小时 过期一次。
- GCP 元数据令牌每 1 小时 过期一次。
如果节点的时钟漂移(NTP 故障)或 实例元数据服务 (IMDS) 被限流,kubelet 将无法刷新令牌 → 在一段稳定运行后出现 ImagePullBackOff。
检测:监控 node-problem-detector 以获取 NTP/IMDS 警报。
网络相关检查
如果您锁定出站流量(PrivateLink、Private Endpoints、VPC Endpoint 策略),配置错误的端点可能会悄悄丢弃流量。
在节点上测试:
curl -v https://<registry-host>/v2/
| 响应 | 含义 |
|---|---|
| 超时 / 卡住 | 网络问题(Security Group、PrivateLink、VPC Endpoint)。 |
| 401 Unauthorized | IAM 问题(网络正常)。 |
| 200 OK | 注册表可访问 → 可能是镜像标签拼写错误。 |
推荐的加固检查清单
- 使用工作负载身份 – 将 IAM 角色绑定到 Kubernetes ServiceAccount,而不是节点范围的实例配置文件。
- 启用 VPC 端点 / Private Link – 将注册表流量保持在公共互联网之外。
- 监控 IMDS 健康 – 当节点无法访问云元数据服务时发出警报。
- 对 401 错误进行警报 – 配置 Prometheus/Alertmanager 在
ImagePullBackOff或注册表返回 401 响应时触发。 - 每周轮换节点 – 防止配置漂移和僵尸进程。
- 优先使用 containerd – 使用
crictl测试拉取,而不是 Docker。
TL;DR
ImagePullBackOff 很少是 Docker‑registry 问题。
它 几乎总是 是 身份(IAM / 凭证)问题。
停止盯着 Docker Hub UI 看——关注节点的凭证提供者、IAM 策略、时钟同步和网络路径。只要这些确认无误,Pod 就能顺利拉取镜像。
目的地
开始审计握手。
第 2 部分:调度器卡住了
调试待定的 Pod
不是 DNS(而是 MTU)
调试 Ingress
存储有重力
调试 PVC