K8s 集群拉取 Harbor 镜像失败怎么排错
K8s 集群拉取 Harbor 镜像失败,绝大多数情况不是 Harbor 本身挂了,而是节点没配好域名解析、证书信任或登录凭据。
这篇按报错顺序带你排查,每一步都给出命令和预期结果,照着做即可定位。
先看现象,把问题缩小到具体节点
在 Master 上执行:
kubectl get pods -A | grep -Ev "Running|Completed"
kubectl describe pod -n <命名空间> | tail -30
重点看 describe 输出里的 Events。
常见三类:
Failed to pull image ... x509: certificate signed by unknown authority:证书问题。dial tcp: lookup harbor.example.com: no such host:DNS 问题。401 Unauthorized或pull access denied:认证问题。
确认是哪个节点在拉镜像:kubectl get pod -o wide 看 NODE 列,然后 SSH 到该节点继续排查。
节点侧排查:DNS、证书、认证逐项过
检查域名解析
在出问题的节点执行:
cat /etc/hosts | grep harbor
nslookup harbor.example.com
如果 Harbor 用的是内网域名,最稳的做法是在每台节点 /etc/hosts 里写死:
192.168.1.100 harbor.example.com
改完不需要重启,但已有 Pod 不会自动重试,删掉重建即可。
配置 containerd 信任自签证书
Harbor 默认用自签或内部 CA 证书时,containerd 不认。
先确认 Harbor 证书 SAN 里包含你访问用的域名。
然后在节点上创建目录并放入 CA:
mkdir -p /etc/containerd/certs.d/harbor.example.com
cp harbor-ca.crt /etc/containerd/certs.d/harbor.example.com/ca.crt
编辑 /etc/containerd/config.toml,
在 [plugins."io.containerd.grpc.v1.cri".registry] 下增加:
config_path = "/etc/containerd/certs.d"
保存后重启:
systemctl restart containerd
如果 Harbor 用 HTTP 而非 HTTPS,
还需在 certs.d/harbor.example.com/hosts.toml 里写明 server = "http:,
//harbor.example.com"
否则默认走 HTTPS 会报连接错误。
验证节点能否直接拉取
crictl pull harbor.example.com/library/nginx:latest
能拉下来说明节点侧通了,问题在 K8s 的 Secret 配置;
仍报错则回到 DNS 或证书继续查。
认证凭据:imagePullSecret 没配或配错
私有 Harbor 项目需要登录。
先在节点用 docker 或 crictl 手动登录验证账号可用:
docker login harbor.example.com
然后在 K8s 里创建 Secret:
kubectl create secret docker-registry harbor-secret \
--docker-server=harbor.example.com \
--docker-username=admin \
--docker-password='你的密码' \
-n default
在 Deployment 里引用:
spec:
template:
spec:
imagePullSecrets:
- name: harbor-secret
容易踩的坑:Secret 必须和 Pod 在同一个 namespace;
改了 Secret 后要重建 Pod 才生效。
避坑与验证清单
- Harbor 证书 SAN 必须包含实际访问域名,只写 IP 会报 x509 错误。
- containerd 改配置后必须重启服务,否则不生效。
/etc/hosts改了要删 Pod 重建,别等它自己恢复。- 防火墙需放行 Harbor 的 443/80 端口,节点侧用
telnet harbor.example.com 443验证。 - 集群节点多时逐台检查,别只修 Master。
修复后重新部署并观察:
kubectl get pods -w
Pod 从 ImagePullBackOff 变为 Running 即成功。
常见疑问
为什么 Master 能拉镜像,Worker 不行?
每台节点的 containerd 配置、hosts 文件和证书是独立的,需要逐台配置,不会自动同步。
改了 containerd 配置一定要重启吗?
是的,containerd 不支持热加载 registry 配置,systemctl restart containerd 后新拉取才会用新配置。
Secret 建了还是 401 怎么办?
检查 Secret 是否在 Pod 所在 namespace,用户名密码是否含特殊字符需转义,以及 Harbor 里该账号是否有目标项目的拉取权限。
按 DNS → 证书 → 认证 → 网络这个顺序排查,基本能覆盖 K8s 集群拉取 Harbor 镜像失败的常见场景。
先确认现象和出错节点,再逐项验证,比盲目改配置快得多。