1. 问题背景与现象分析
最近在部署Kubernetes集群时遇到了一个典型问题:当我尝试通过kubectl创建一个简单的nginx Pod时,Pod状态一直卡在Pending状态。作为一名长期与容器技术打交道的工程师,我决定深入分析这个问题并记录完整的排查过程。
1.1 初始状态观察
执行kubectl get pods命令后,输出显示Pod状态为Pending:
code复制NAME READY STATUS RESTARTS AGE
nginx 0/1 Pending 0 2m
通过describe命令查看详细状态时,发现关键错误信息:
code复制Warning FailedScheduling 100s default-scheduler 0/1 nodes are available: 1 node(s) had taint {node-role.kubernetes.io/master: }, that the pod didn't tolerate.
这个错误表明Pod无法被调度到任何节点上,因为唯一的节点(master节点)被设置了污点(taint),而Pod没有对应的容忍(toleration)设置。
1.2 第一层解决方案:处理节点污点
对于单节点集群或希望在master节点上运行工作负载的情况,最简单的解决方案是移除master节点的污点:
bash复制kubectl taint nodes <node-name> node-role.kubernetes.io/master-
执行后,Pod状态从Pending变成了ImagePullBackOff,这表示调度问题已解决,但出现了新的镜像拉取问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 镜像拉取问题深度排查
2.1 ImagePullBackOff错误分析
查看Pod详细描述,发现如下关键错误:
code复制Warning Failed 41s kubelet Failed to pull image "nginx": rpc error: code = Unknown desc = Get "https://registry-1.docker.io/v2/": dial tcp 199.59.149.235:443: i/o timeout
这个错误明确告诉我们:kubelet无法从Docker Hub(registry-1.docker.io)拉取nginx镜像,原因是网络连接超时。
2.2 常见原因排查
-
网络连通性检查:
- 确认节点能够访问外网
- 测试直接访问registry-1.docker.io的443端口是否通畅
-
Docker配置验证:
检查/etc/docker/daemon.json文件,确认已配置镜像加速器:json复制{ "registry-mirrors": ["https://docker.1ms.run","https://docker-0.unsee.tech"] } -
手动拉取测试:
使用docker pull nginx命令可以成功拉取镜像,这说明:- Docker引擎配置正确
- 网络连接基本正常
- 问题可能出在containerd的配置上
3. Kubernetes与Containerd的镜像拉取机制
3.1 组件关系解析
很多工程师存在一个误解,认为Kubernetes使用Docker来拉取和管理镜像。实际上,从Kubernetes 1.20版本开始,默认容器运行时已改为containerd,Docker只是作为可选组件存在。
关键组件关系:
- kubectl:Kubernetes命令行工具
- kubelet:节点上的主要代理组件
- containerd:实际的容器运行时
- CRI(Container Runtime Interface):kubelet与containerd之间的标准接口
3.2 配置继承问题
Docker和containerd虽然可以共享一些底层组件,但它们的配置是完全独立的。在Docker中配置的镜像加速器不会自动应用到containerd,这就是为什么docker pull能成功而kubectl创建Pod失败的原因。
4. Containerd镜像加速器配置详解
4.1 生成默认配置文件
首先,我们需要生成containerd的默认配置文件:
bash复制containerd config default | sudo tee /etc/containerd/config.toml
4.2 关键配置修改
在生成的config.toml文件中,找到registry配置部分,添加镜像加速器:
toml复制[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://docker.1ms.run", "https://docker-0.unsee.tech"]
配置说明:
docker.io:表示这个配置针对Docker Hub的镜像endpoint:可以配置多个镜像加速器地址,containerd会按顺序
