K8s 1.28 从Harbor拉镜像总失败?别慌,containerd的config.toml配置保姆级教程来了
K8s 1.28 从Harbor拉镜像总失败别慌containerd的config.toml配置保姆级教程来了最近在Kubernetes 1.28集群中从Harbor私有仓库拉取镜像时频繁遇到ErrImagePull错误这很可能是因为你还在用Docker时代的配置思路来处理containerd。自从K8s 1.24版本弃用Docker后containerd成为了默认的容器运行时而它的认证配置方式与Docker有着本质区别。本文将带你深入理解containerd的config.toml配置文件特别是mirrors和configs这两个关键部分彻底解决Harbor镜像拉取失败的问题。1. 为什么Docker时代的配置不再适用很多从Docker迁移到containerd的用户会发现明明在节点上能用docker login成功登录Harbor但在K8s中却始终无法拉取镜像。这是因为认证配置位置不同Docker将仓库认证信息存储在~/.docker/config.json中而containerd需要直接在/etc/containerd/config.toml中配置运行时隔离K8s通过CRI容器运行时接口与containerd交互不会读取Docker的认证信息命名空间差异containerd默认使用k8s.io命名空间管理K8s容器与Docker的默认命名空间隔离常见错误现象Failed to pull image harbor.example.com/library/nginx:latest: rpc error: code Unknown desc failed to pull and unpack image harbor.example.com/library/nginx:latest: failed to resolve reference harbor.example.com/library/nginx:latest: failed to authorize: failed to fetch anonymous token: unexpected status: 401 Unauthorized2. containerd核心配置文件解析containerd的主配置文件/etc/containerd/config.toml采用TOML格式与Docker的JSON配置不同。我们需要重点关注以下两个部分2.1 镜像仓库镜像(mirrors)mirrors部分用于定义仓库镜像和访问策略相当于Docker中的registry-mirrors。对于Harbor仓库典型配置如下[plugins.io.containerd.grpc.v1.cri.registry] [plugins.io.containerd.grpc.v1.cri.registry.mirrors] [plugins.io.containerd.grpc.v1.cri.registry.mirrors.harbor.example.com] endpoint [http://harbor.example.com]关键参数说明harbor.example.com你的Harbor仓库地址endpoint指定仓库访问协议和地址支持http/https2.2 仓库认证配置(configs)configs部分用于配置私有仓库的认证信息这是解决401未授权错误的关键[plugins.io.containerd.grpc.v1.cri.registry.configs] [plugins.io.containerd.grpc.v1.cri.registry.configs.harbor.example.com] [plugins.io.containerd.grpc.v1.cri.registry.configs.harbor.example.com.auth] username admin password Harbor12345安全提示生产环境中建议将密码存储在K8s Secret中而不是直接写在配置文件里3. HTTP与HTTPS场景下的完整配置示例根据Harbor使用的协议不同配置方式也有所差异。3.1 HTTP仓库配置对于测试环境的HTTP Harbor仓库需要额外配置跳过TLS验证[plugins.io.containerd.grpc.v1.cri.registry] [plugins.io.containerd.grpc.v1.cri.registry.mirrors] [plugins.io.containerd.grpc.v1.cri.registry.mirrors.harbor.example.com] endpoint [http://harbor.example.com] [plugins.io.containerd.grpc.v1.cri.registry.configs] [plugins.io.containerd.grpc.v1.cri.registry.configs.harbor.example.com] [plugins.io.containerd.grpc.v1.cri.registry.configs.harbor.example.com.tls] insecure_skip_verify true [plugins.io.containerd.grpc.v1.cri.registry.configs.harbor.example.com.auth] username admin password Harbor123453.2 HTTPS仓库配置生产环境推荐使用HTTPS配置更简洁但需要确保证书可信[plugins.io.containerd.grpc.v1.cri.registry] [plugins.io.containerd.grpc.v1.cri.registry.mirrors] [plugins.io.containerd.grpc.v1.cri.registry.mirrors.harbor.example.com] endpoint [https://harbor.example.com] [plugins.io.containerd.grpc.v1.cri.registry.configs] [plugins.io.containerd.grpc.v1.cri.registry.configs.harbor.example.com] [plugins.io.containerd.grpc.v1.cri.registry.configs.harbor.example.com.auth] username admin password Harbor123454. 多节点配置与验证在K8s集群中所有节点都需要相同的containerd配置。以下是推荐的配置分发流程在主节点上编辑并验证config.toml使用以下命令分发到所有工作节点# 使用scp scp /etc/containerd/config.toml rootk8s-worker-01:/etc/containerd/ scp /etc/containerd/config.toml rootk8s-worker-02:/etc/containerd/ # 或者使用Ansible ansible k8s-workers -m copy -a src/etc/containerd/config.toml dest/etc/containerd/在每个节点上重启containerd服务systemctl daemon-reload systemctl restart containerd验证配置是否生效ctr -n k8s.io images pull --plain-http harbor.example.com/library/nginx:latest5. 高级排错技巧当配置完成后仍然遇到问题时可以尝试以下排错方法5.1 检查containerd日志journalctl -u containerd -f常见错误日志分析错误信息可能原因解决方案failed to authorize认证信息错误检查config.toml中的auth配置certificate signed by unknown authority证书问题添加CA证书或设置insecure_skip_verifyno such hostDNS解析失败检查网络和DNS配置5.2 使用nerdctl测试nerdctl是containerd的CLI工具语法与docker相似nerdctl --insecure-registry login harbor.example.com -u admin -p Harbor12345 nerdctl --insecure-registry pull harbor.example.com/library/nginx:latest5.3 K8s层面的检查如果Pod仍然无法拉取镜像检查ImagePullSecrets是否配置正确节点上的containerd是否正常运行网络策略是否阻止了到Harbor的连接kubectl describe pod pod-name | grep -i pull kubectl get nodes -o wide6. 从Docker到containerd的思维转变对于长期使用Docker的用户需要特别注意以下差异点镜像管理containerd使用命名空间隔离镜像K8s专用镜像存储在k8s.io命名空间ctr -n k8s.io images ls认证机制不再依赖~/.docker/config.json所有认证必须在config.toml中显式配置CLI工具ctr和nerdctl替代了docker命令但功能略有不同常用命令对照表Docker命令containerd等效命令docker pullctr images pulldocker imagesctr -n k8s.io images lsdocker runnerdctl rundocker login需配置config.toml在实际使用containerd管理K8s集群半年后我发现其稳定性和性能确实优于Docker只是初期配置需要一些适应。最常遇到的坑是忘记在多节点集群上同步配置导致部分节点无法拉取镜像。建议将config.toml纳入配置管理系统确保集群一致性。