K8s 1.28 从 Docker 切换到 Containerd 后,如何正确配置 Harbor 私有镜像仓库(保姆级避坑指南) K8s 1.28 全面拥抱 ContainerdHarbor 私有仓库深度配置实战手册当 Kubernetes 1.24 版本宣布弃用 Docker 运行时整个容器生态迎来了重大转折。作为一线运维人员我在最近升级到 K8s 1.28 时深刻体会到从 Docker 到 Containerd 的转变不仅仅是简单的运行时替换更是一次操作范式和管理思维的全面革新。本文将分享如何在这种变革中正确配置 Harbor 私有镜像仓库的全套解决方案。1. 理解运行时变革从 Docker 到 ContainerdKubernetes 放弃 Docker 转而采用 Containerd 作为默认容器运行时这一决定背后有着深层次的技术考量。Docker 作为一个完整的容器解决方案包含了太多 Kubernetes 不需要的组件而 Containerd 则是一个更轻量、更专注的容器运行时。关键差异点对比特性DockerContainerd架构层级高层封装底层运行时镜像管理docker CLIctr/nerdctl CLI默认命名空间docker.iok8s.io配置文件位置/etc/docker/daemon.json/etc/containerd/config.toml日志系统独立日志驱动集成到 Kubernetes 日志在实际迁移过程中最大的挑战来自于操作习惯的改变。我们不能再依赖熟悉的docker pull或docker login命令而是需要掌握新的工具链# 传统 Docker 方式 docker login registry.example.com docker pull registry.example.com/myapp:v1.0 # Containerd 新方式 ctr images pull --user username:password registry.example.com/myapp:v1.02. Containerd 核心配置config.toml 深度解析Containerd 的所有行为都由/etc/containerd/config.toml文件控制。在配置 Harbor 私有仓库前建议先生成默认配置sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml关键配置项说明镜像加速配置适用于国内环境[plugins.io.containerd.grpc.v1.cri.registry.mirrors] [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io] endpoint [https://registry-1.docker.io] [plugins.io.containerd.grpc.v1.cri.registry.mirrors.registry.example.com] endpoint [https://registry.example.com]私有仓库认证配置[plugins.io.containerd.grpc.v1.cri.registry.configs] [plugins.io.containerd.grpc.v1.cri.registry.configs.registry.example.com.auth] username your_username password your_passwordHTTP 仓库支持Harbor 默认使用 HTTP 时需要[plugins.io.containerd.grpc.v1.cri.registry.configs.registry.example.com.tls] insecure_skip_verify true重要提示修改配置后必须重启 containerd 服务才能生效sudo systemctl restart containerd3. Harbor 私有仓库实战配置3.1 基础环境准备假设我们已经有一个运行中的 Harbor 实例地址为harbor.example.com接下来需要在所有 Kubernetes 节点上进行配置。多节点配置策略在主节点完成 config.toml 配置使用 Ansible 批量同步到所有工作节点ansible k8s_nodes -m copy -a src/etc/containerd/config.toml dest/etc/containerd/ ansible k8s_nodes -m service -a namecontainerd staterestarted3.2 镜像操作全流程Containerd 提供了ctr和nerdctl两个命令行工具。ctr是 Containerd 原生工具而nerdctl提供了更接近 Docker 的体验。完整镜像生命周期示例# 从 Docker Hub 拉取镜像 ctr image pull docker.io/library/nginx:alpine # 查看可用镜像注意默认命名空间是 default ctr image ls # 为镜像打标签准备推送到 Harbor ctr image tag docker.io/library/nginx:alpine harbor.example.com/my-project/nginx:alpine # 推送镜像到 HarborHTTP 仓库需要特殊参数 ctr image push --plain-httptrue harbor.example.com/my-project/nginx:alpineKubernetes 专用命名空间操作Kubernetes 使用特殊的k8s.io命名空间管理镜像所有操作需要指定-n k8s.io参数# 查看 Kubernetes 使用的镜像 ctr -n k8s.io image ls # 将镜像导入到 Kubernetes 命名空间 ctr -n k8s.io image import myapp.tar4. Kubernetes 工作负载集成4.1 镜像拉取密钥配置即使 Containerd 已经配置了仓库认证Kubernetes 仍然需要单独的 Secret 来拉取私有仓库镜像kubectl create secret docker-registry harbor-creds \ --docker-serverharbor.example.com \ --docker-usernameadmin \ --docker-passwordHarbor12345 \ --namespacedefault4.2 工作负载配置示例在 Deployment 中引用私有仓库镜像和拉取密钥apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: template: spec: containers: - name: myapp image: harbor.example.com/my-project/nginx:alpine imagePullSecrets: - name: harbor-creds镜像拉取策略对比策略描述适用场景Always总是尝试拉取最新镜像持续交付环境IfNotPresent本地不存在时才拉取开发测试环境默认策略Never只使用本地镜像不尝试拉取离线环境或特殊场景5. 高级技巧与故障排查5.1 多架构镜像支持Containerd 对多架构镜像如同时支持 amd64 和 arm64有更好的支持# 拉取多架构镜像 ctr image pull --platform linux/amd64,linux/arm64 docker.io/library/nginx:latest # 查看镜像支持的平台 ctr image inspect docker.io/library/nginx:latest | grep Platform5.2 常见问题解决方案问题1ErrImagePull 错误可能原因和解决方案认证失败检查 config.toml 和 Kubernetes Secret 配置网络不通验证节点到 Harbor 的网络连接镜像不存在确认镜像路径和标签正确问题2x509 证书错误对于自签名证书的 Harbor需要在所有节点添加 CA 证书sudo mkdir -p /etc/containerd/certs.d/harbor.example.com sudo cp harbor-ca.crt /etc/containerd/certs.d/harbor.example.com/ca.crt问题3镜像同步策略在混合环境中部分节点能访问外网部分不能可以采用以下策略在外网节点拉取镜像导出为 tar 包在内网节点导入# 在外网节点 ctr image export nginx.tar docker.io/library/nginx:alpine # 在内网节点 ctr -n k8s.io image import nginx.tar从 Docker 到 Containerd 的转变确实带来了短期的适应成本但长期来看这种更轻量、更专注的架构设计为 Kubernetes 带来了更好的性能和更简单的维护。在实际生产环境中建议建立完善的镜像缓存策略和节点配置管理方案以充分发挥 Containerd 的优势。