K8s单节点创建Pod报ImagePullBackOff但docker pull拉取正常
Kubernetes单节点ImagePullBackOff故障排查(手动docker pull正常场景)
以下是按出现概率从高到低排序的排查步骤,逐次验证即可定位根因:
- 先确认故障节点kubelet实际对接的容器运行时
登录故障节点执行crictl info | grep -i runtime检查runtime类型。70%以上的同类问题都是因为集群实际用containerd作为运行时,你手动执行docker pull操作的是独立部署的docker服务,修改docker的daemon.json对kubelet的拉取逻辑完全无效。
如果确认runtime为containerd,直接编辑/etc/containerd/config.toml,找到对应私有镜像仓库的配置段:- 在
[plugins."io.containerd.grpc.v1.cri".registry.configs."<你的私有仓库地址>".tls]下添加insecure_skip_verify = true - 在
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."<你的私有仓库地址>"]下配置正确的endpoint地址为你的仓库访问地址
修改完成后执行systemctl restart containerd生效。
- 在
- 验证kubelet拉取镜像的实际报错
不要只看kubectl describe pod返回的简略报错,在故障节点执行journalctl -u kubelet -f,同时重建故障Pod,直接看kubelet输出的拉取失败详细日志,绝大多数场景下日志会直接标明是证书错误、权限拒绝还是网络超时。
也可以直接用crictl pull <完整镜像地址:tag>模拟kubelet的拉取逻辑,这个命令走的是kubelet对接的runtime通道,和你手动执行docker pull的链路完全独立,命令返回的报错就是实际故障原因。 - 检查镜像拉取的认证权限
如果你手动执行docker pull前做过docker login,认证信息默认存在/root/.docker/config.json里,kubelet默认不会读取这个路径的认证文件:- 如果是docker作为runtime,把认证文件拷贝到kubelet的读取路径:
cp /root/.docker/config.json /var/lib/kubelet/config.json && chmod 600 /var/lib/kubelet/config.json,之后执行systemctl restart kubelet - 如果是containerd作为runtime,需要把认证信息配置到前述的config.toml对应仓库的auth段,或者在Pod定义里配置正确的imagePullSecret。
- 如果是docker作为runtime,把认证文件拷贝到kubelet的读取路径:
- 检查cgroup驱动一致性
如果确认runtime为docker,执行docker info | grep Cgroup查看docker的cgroup驱动,再对比kubelet启动参数里的cgroup-driver配置,两者必须完全一致(要么都是systemd要么都是cgroupfs)。驱动不匹配时kubelet无法正常调用docker接口拉取镜像,手动执行docker命令不受影响。
驱动不一致时,在docker的daemon.json里添加"exec-opts": ["native.cgroupdriver=systemd"](和kubelet配置对齐),重启docker后再重启kubelet即可。 - 检查基础网络与解析配置
对比故障节点和正常节点的私有仓库域名解析结果,确认nslookup <私有仓库地址>返回的IP一致,同时检查故障节点的iptables规则,执行iptables -t nat -L OUTPUT -n | grep <私有仓库IP>确认没有错误的流量转发规则——节点上残留的iptables规则可能把kubelet发起的拉流请求转发到错误地址,手动执行docker pull时如果走了不同的出口链路就不会触发这个问题。
注意:修改完daemon.json或者containerd配置后,一定要重启对应runtime服务和kubelet,很多人改完配置不重启服务,配置自然不会生效。
内容的提问来源于stack exchange,提问作者smiles
相关产品推荐
相关产品推荐

