kubeadm镜像拉取失败主因是dns解析失败、证书错误或认证问题,而非配置错误;需先用kubectl describe pod查看events中的具体错误类型,再针对性解决。

镜像拉取失败不是配置写错了,而是环境没对上——国内节点直连 k8s.gcr.io、gcr.io 或私有 Harbor 时,90% 的问题出在 DNS、证书、认证这三环里,不是改个 imagePullPolicy 就能绕过去。
查清错误类型再动手,别一上来就改配置
先用 kubectl describe pod <pod-name></pod-name> 看 Events 区域,重点关注最后一行错误描述:
-
manifest unknown→ 镜像标签根本不存在,比如写了v1.25.999却没推送到仓库 -
pull access denied→ 认证失败,常见于私有仓库未配imagePullSecrets或 token 过期 -
connection refused/no such host→ DNS 解析失败或仓库地址拼错(注意k8s.gcr.io不是k8s.grc.io) -
x509: certificate signed by unknown authority→ 节点时间偏差 >5 分钟,或私有仓库用了自签名证书但 Docker 未信任
错误信息里带 rpc error: code = DeadlineExceeded,基本可断定是网络不通或超时,不是镜像问题。
国内拉不到 k8s.gcr.io?换源 + 手动打标是最稳解法
官方镜像仓库在国内多数节点无法直连,kubeadm init 失败时显示一堆 Failed to pull image "k8s.gcr.io/...",别硬等重试。直接本地拉取镜像并重打 tag:
- 用国内镜像源替代:比如
registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.26.0 - 或用社区镜像:
mirrorgooglecontainers/kube-controller-manager:v1.26.0 - 拉完后必须执行
docker tag k8s.gcr.io/kube-controller-manager:v1.26.0,否则 kubeadm 不认 - 确认无误后,用
kubeadm config images list核对所需镜像列表,再逐个补全
别依赖 registry-mirrors 全局配置——它只对 Docker daemon 生效,而 kubeadm 初始化阶段走的是 containerd 或 CRI-O,不走这个路径。
私有仓库(如 Harbor)拉取失败,重点检查三处
Harbor 报 repository does not exist or may require 'docker login',不是密码错了,而是凭证没落到节点上:
-
docker login <harbor-url></harbor-url>只影响当前 shell 的 Docker CLI,不影响 kubelet 拉取行为 - 必须把凭证做成 Kubernetes Secret:
kubectl create secret docker-registry regcred --docker-server=<harbor-url> --docker-username=<user> --docker-password=<pass></pass></user></harbor-url> - Pod spec 中要显式引用:
imagePullSecrets: [{name: regcred}],ServiceAccount 默认不自动挂载 - Harbor 项目若设了 “机器人账号” 权限,得确认该账号有
pull权限,且镜像路径前缀匹配项目名(如harbor.example.com/myproj/nginx)
如果用的是 containerd,还得额外检查 /etc/containerd/config.toml 是否启用了 auths 配置块——默认不读 ~/.docker/config.json。
镜像存在、认证也对,还是拉不动?盯住节点级细节
很多问题卡在“看起来都对”,实则被底层运行时忽略:
- 节点时间不同步:用
timedatectl status确认,偏差超过 5 分钟会导致 TLS 握手失败 - DNS 配置被覆盖:检查
/etc/resolv.conf是否被 NetworkManager 或 systemd-resolved 改写,尤其在云主机上 - containerd 的
plugins."io.containerd.grpc.v1.cri".registry.configs下没配私有仓库的 TLS skip 配置,而 Harbor 用的是 HTTP 或自签 HTTPS - 防火墙规则:确认节点出向 443/80 端口没被
iptables或nftablesDROP,curl -v https://harbor.example.com/v2/能通不代表 kubelet 能通——它用的是 containerd 的 netns
最常被跳过的一步:用 crictl pull <image></image> 在节点上手动试拉。它走的路径和 kubelet 完全一致,比 docker pull 更能暴露真实问题。











