第一次在CentOS 7.9上部署Kubernetes 1.15.1集群时,我遇到了那个经典的红色警告——"error execution phase preflight"。屏幕突然卡在这个报错界面,就像开车时突然亮起的发动机故障灯。这个报错其实是kubeadm在初始化集群前的自检机制,它会检查系统环境是否符合运行Kubernetes的基本要求。
preflight检查就像机场登机前的安检,主要验证三个方面:系统配置(比如内存、CPU)、依赖服务(比如容器运行时)和网络设置。我遇到的报错信息显示有两个致命问题:Swap未关闭和Docker版本不兼容。这就像安检时同时发现携带了违禁品和护照过期,必须全部解决才能继续。
当时的生产环境已经部署了部分中间件,回滚成本很高。我不得不保持冷静,按照报错信息的指引开始排查。首先用free -h确认了Swap分区确实处于激活状态,又用docker version查看到当前安装的是18.03.1社区版,而Kubernetes 1.15.1官方验证的最新版本是18.09。
第一次看到要求禁用Swap时,我和很多运维同学一样困惑。毕竟Swap是Linux系统的安全网,可以在物理内存不足时防止OOM(Out Of Memory)。但Kubernetes的设计理念恰恰相反——它希望精确控制Pod的内存使用,如果部分内存被交换到磁盘,会导致调度器无法准确评估节点负载。
这就好比物流公司要求所有货物必须放在仓库货架上(内存),不允许临时堆放在过道(Swap),因为这样会干扰仓库容量计算。Kubernetes需要确保Pod申请的资源就是实际获得的资源,Swap的介入会打破这个保证。
临时关闭Swap很简单:
bash复制sudo swapoff -a
但重启后又会恢复,需要修改/etc/fstab永久生效。我建议的操作流程:
blkid找到Swap分区UUID:bash复制sudo blkid | grep swap
bash复制sudo cp /etc/fstab /etc/fstab.bak
code复制UUID=12345678-1234-1234-1234-1234567890ab none swap sw 0 0
在行首添加#注释掉,或者直接删除该行。
bash复制sudo mount -a # 重新挂载文件系统
free -h # 应该显示Swap为0
注意:如果服务器物理内存确实不足,可以考虑调整kubelet参数
--fail-swap-on=false,但这会影响调度准确性,不建议生产环境使用。
当看到"Docker version is not on the list of validated versions"警告时,我意识到掉进了版本兼容性的坑。Kubernetes每个版本都有官方验证过的Docker版本列表,比如1.15.x推荐的是18.09系列。这就像iPhone系统升级后,某些老版本APP可能会闪退。
通过查阅Kubernetes官方文档,我发现版本兼容性涉及三个维度:
在CentOS 7上完整升级Docker的步骤比想象中复杂:
bash复制sudo yum remove docker* containerd runc
sudo rm -rf /var/lib/docker
sudo rm -rf /etc/docker
bash复制sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
bash复制yum list docker-ce --showduplicates | sort -r
bash复制sudo yum install docker-ce-18.09.9 docker-ce-cli-18.09.9 containerd.io
bash复制sudo mkdir /etc/docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
bash复制sudo systemctl enable --now docker
验证安装时,建议运行docker info | grep Cgroup确认驱动是systemd,否则后续kubelet会报错。
执行初始化时,我原本使用的命令包含--experimental-upload-certs参数,结果收到"Flag has been deprecated"警告。这种参数废弃在Kubernetes版本迭代中很常见,就像手机APP的界面改版。
正确的替代方案是使用--upload-certs,完整初始化命令应该像这样:
bash复制sudo kubeadm init \
--config=kubeadm-config.yaml \
--upload-certs \
| tee kubeadm-init.log
建议总是通过kubeadm config print init-defaults获取最新配置模板,而不是复制老教程的命令。
即使解决了Swap和Docker问题,集群初始化仍可能被防火墙阻断。在CentOS 7上需要:
bash复制sudo firewall-cmd --permanent --add-port={6443,2379-2380,10250,10251,10252}/tcp
sudo firewall-cmd --reload
bash复制sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
跨节点时间不同步会导致证书验证失败等诡异问题。务必在所有节点安装chrony:
bash复制sudo yum install -y chrony
sudo systemctl enable --now chronyd
chronyc sources # 验证时间源
当终于看到"Your Kubernetes control-plane has initialized successfully!"时,别急着庆祝,还需要完成这些关键步骤:
bash复制mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
bash复制kubectl get pods -n kube-system
应该看到coredns、kube-proxy等组件都是Running状态。
bash复制kubectl taint nodes --all node-role.kubernetes.io/master-
bash复制kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
最后用kubectl get nodes看到节点状态为Ready,才算是真正的成功。整个过程就像组装一台精密仪器,每个零件都必须严丝合缝。记录下所有操作步骤和参数选择,它们会成为你宝贵的排障知识库。