应先查 kubelet 日志中 "failed to pull" 前 3–5 行的上下文错误:x509 证书问题需检查 containerd registry 的 ca_file 配置;connection refused 或 context deadline exceeded 说明网络不通,须用 crictl pull 和 curl -v 复现验证;unauthorized 则表明认证缺失,需确认 imagePullSecrets 或 containerd auth 配置已生效且重启了服务。

直接看 kubelet.log 里的 “failed to pull” 行,但别只盯这一句——真正卡点往往在它前面几行的网络或证书错误。
查日志前先确认日志位置和格式
不同发行版/部署方式下,kubelet.log 路径和格式不统一:
- 标准 systemd 环境(如 kubeadm 部署):日志走 journal,
journalctl -u kubelet -n 200 --no-pager是首选,/var/log/messages里也会有副本,但时间戳可能不准 - K3s 默认写入
/var/log/kubelet.log,且是纯文本格式;而多数上游 Kubernetes 发行版默认用 JSON 格式输出到 journald - JSON 日志需用
jq过滤才高效,例如:journalctl -u kubelet -n 100 --no-pager | jq 'select(.log | contains("pull"))' - 如果启用了 logrotate,注意
/var/log/kubelet.log.1.gz可能含更早的失败记录
重点过滤“pull”失败前的上下文错误
failed to pull and unpack image 是表象,真正原因藏在它之前 3–5 行。常见前置错误类型:
-
x509: certificate signed by unknown authority→ 私有仓库 TLS 证书未被 containerd 或 kubelet 信任,检查/etc/containerd/config.toml中registry段是否配置了ca_file -
context deadline exceeded或connection refused→ 网络不通,优先用crictl pull <image></image>复现,再curl -v https://<registry>/v2/</registry>验证连通性与 HTTP 状态码 -
unauthorized: authentication required→ registry 认证缺失,确认imagePullSecrets已挂载到 Pod,或containerd的auth配置已生效(改完必须systemctl restart containerd) -
failed to resolve reference→ 镜像名拼写错误、tag 不存在,或 DNS 解析失败(检查节点/etc/resolv.conf和systemd-resolved状态)
区分是 kubelet 报错还是 containerd 实际执行失败
很多人误以为 kubelet 自己拉镜像,其实它只调用 CRI 接口,真正在干活的是 containerd。所以:
- 若
journalctl -u kubelet里只有模糊报错(如ImagePullBackOff),必须进一步查crictl logs或ctr -n k8s.io images list - 用
crictl info确认 containerd 当前使用的 registry 配置是否加载成功(尤其关注registry.configs字段) - 手动触发一次拉取:
sudo crictl pull harbor.example.com/app:v1.2,结果和 kubelet 日志一致,说明问题不在 kubelet 启动参数,而在底层运行时 - 如果
crictl pull成功但 Pod 仍失败,大概率是imagePullSecrets作用域不对(比如建在 default namespace 却用于其他 ns)
最容易被忽略的是:kubelet 日志里看到的错误,常常是上一次失败的残留;真正的当前失败可能已被滚动日志覆盖。务必结合 journalctl -u kubelet --since "2 minutes ago" 或 tail -f /var/log/kubelet.log 实时观察,而不是只翻旧记录。


















