K8s集群初始化:从kubeadm init报错到成功,我的完整排错记录与心得分享
凌晨三点,屏幕上的红色报错信息格外刺眼——这是我第七次在虚拟机里执行kubeadm init失败。作为有三年K8s使用经验的运维工程师,这次集群搭建却让我栽了跟头。本文将完整还原这段从盲目重装系统到精准定位"镜像拉取失败"问题的全过程,重点分享系统性排错方法论和国内环境适配技巧。
1. 初遇报错:那些年我们踩过的"重装大法"坑
"虚拟机环境有问题?"这是看到[ERROR ImagePull]时的第一反应。和大多数初学者一样,我立即执行了以下操作:
# 典型错误示范 - 盲目重装 sudo kubeadm reset rm -rf ~/.kube sudo apt purge kubeadm kubelet kubectl重装三次后,相同的错误再次出现:
failed to pull image "k8s.gcr.io/kube-apiserver:v1.20.9": rpc error: code = Unknown desc = Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled...关键教训:当遇到镜像拉取失败时,立即检查以下三个要素:
- 网络连通性(能否访问目标仓库)
- DNS解析(nslookup k8s.gcr.io)
- 本地Docker配置(特别是代理和镜像加速设置)
提示:使用
kubeadm config images list可预览需要拉取的镜像列表,提前发现潜在问题
2. 深度排查:从日志分析到配置解剖
2.1 日志分析三板斧
执行journalctl -xeu kubelet发现关键线索:
Oct 15 03:22:11 master kubelet[1087]: E1015 03:22:11.123456 1087 kuberuntime_image.go:51] Pull image "k8s.gcr.io/pause:3.2" failed: rpc error...此时应该采用分层排查法:
网络层验证:
curl -I https://k8s.gcr.io/v2/ ping registry.aliyuncs.com容器运行时检查:
docker pull registry.aliyuncs.com/google_containers/pause:3.2 crictl imagesK8s组件状态:
systemctl status kubelet -l kubectl get pods -n kube-system
2.2 配置重构实战
通过kubeadm config print init-defaults生成的默认配置存在两个关键问题:
| 配置项 | 默认值 | 问题 | 修正方案 |
|---|---|---|---|
| imageRepository | k8s.gcr.io | 国内无法访问 | registry.aliyuncs.com/google_containers |
| kubernetesVersion | latest | 版本模糊 | v1.20.9 |
修正后的配置示例:
apiVersion: kubeadm.k8s.io/v1beta2 kind: ClusterConfiguration imageRepository: registry.aliyuncs.com/google_containers kubernetesVersion: v1.20.9 networking: podSubnet: 192.168.0.0/163. 国内环境适配方案对比
3.1 镜像加速方案选型
经过实测对比三种主流方案:
Docker镜像加速(修改
/etc/docker/daemon.json):{ "registry-mirrors": ["https://<你的ID>.mirror.aliyuncs.com"], "exec-opts": ["native.cgroupdriver=systemd"] }优点:全局生效
缺点:仍需手动拉取K8s系统镜像Kubeadm指定仓库:
kubeadm init --image-repository=registry.aliyuncs.com/google_containers优点:一键解决
缺点:阿里云仓库可能存在版本延迟离线镜像打包:
docker save $(kubeadm config images list) -o k8s-images.tar docker load -i k8s-images.tar适用场景:完全离线的内网环境
3.2 网络插件选择建议
国内常见CNI插件性能对比:
| 插件类型 | 平均Pod启动时间 | 网络吞吐量 | 适合场景 |
|---|---|---|---|
| Calico | 1.2s | 8Gbps | 生产环境 |
| Flannel | 0.8s | 5Gbps | 开发测试 |
| Cilium | 1.5s | 10Gbps | 云原生应用 |
注意:选择
podSubnet时需确保与公司内网无冲突,常见配置:
- 10.244.0.0/16(Flannel默认)
- 192.168.0.0/16(Calico推荐)
4. 终极解决方案:分步操作指南
4.1 预检流程
系统配置检查:
swapoff -a sed -i '/ swap / s/^/#/' /etc/fstab sysctl net.bridge.bridge-nf-call-iptables=1容器运行时配置:
cat > /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" } } EOF
4.2 集群初始化完整命令
分步执行以下操作:
# 1. 拉取镜像 kubeadm config images pull \ --image-repository=registry.aliyuncs.com/google_containers \ --kubernetes-version=v1.20.9 # 2. 初始化控制平面 kubeadm init \ --apiserver-advertise-address=192.168.1.100 \ --control-plane-endpoint=cluster-endpoint \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.20.9 \ --service-cidr=10.96.0.0/16 \ --pod-network-cidr=192.168.0.0/16 # 3. 配置kubectl mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config4.3 常见问题应急处理
当遇到kubelet持续崩溃时:
检查日志时间戳:
journalctl -u kubelet --since "10 minutes ago" | grep -i error重置集群状态:
kubeadm reset --force iptables -F && iptables -t nat -F ipvsadm --clear rm -rf /etc/cni/net.d重试初始化:
systemctl restart docker kubeadm init --v=5 # 显示详细日志
5. 集群调优与维护心得
5.1 关键参数调优表
| 参数 | 默认值 | 推荐值 | 作用 |
|---|---|---|---|
| kubelet--max-pods | 110 | 150 | 单节点最大Pod数量 |
| kube-api--audit-log-maxage | 0 | 30 | 审计日志保留天数 |
| kube-controller--node-monitor-period | 5s | 2s | 节点状态检测间隔 |
5.2 日常维护检查清单
每周执行:
kubectl get nodes -o wide kubectl get pods -A | grep -v Running df -h /var/lib/docker每月执行:
kubeadm upgrade plan etcdctl endpoint health calicoctl node status
在经历这次排错后,我的集群已经稳定运行了六个月。最深刻的体会是:90%的K8s问题都能通过journalctl和kubectl describe找到线索。建议每次遇到报错时,先喝杯咖啡,仔细阅读日志前20行——这往往比盲目重装节省更多时间。