CentOS 7.9上k8s v1.15.1初始化踩坑实录:从preflight报错到成功启动集群
CentOS 7.9上部署Kubernetes v1.15.1的实战避坑指南
那天下午三点二十七分,当我在CentOS 7.9服务器上第5次执行kubeadm init命令时,熟悉的红色报错再次无情地出现在终端上——"error execution phase preflight"。作为一个经历过多次k8s部署的老手,我没想到会在一个看似简单的旧版本部署上耗费整整两天时间。本文将还原这次充满戏剧性的排错历程,带你穿越那些官方文档没写的暗坑。
1. 环境准备:那些容易被忽视的细节
在开始讲述具体报错之前,有必要先交代下这次部署的特殊背景。客户的生产环境由于历史原因必须使用Kubernetes v1.15.1这个相对陈旧的版本,而服务器操作系统则是CentOS 7.9。这种"新系统+旧k8s"的组合本身就埋下了不少隐患。
1.1 系统基础配置检查
首先确认系统基本信息,这步很关键但很多人会跳过:
# 查看系统版本
cat /etc/redhat-release
# 内核版本
uname -r
# 内存和CPU
free -h
lscpu
我的环境输出如下:
- CentOS Linux release 7.9.2009 (Core)
- 内核版本:5.4.259-1.el7.elrepo.x86_64
- 8核CPU,16GB内存
特别注意:虽然官方建议使用3.10内核,但实际测试发现5.x内核也能正常工作。不过如果你遇到奇怪的cgroup问题,可能需要降级内核。
1.2 必要的系统参数调整
在CentOS 7上部署k8s前,必须调整几个关键系统参数:
# 关闭SELinux
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 加载br_netfilter模块
modprobe br_netfilter
echo 'br_netfilter' > /etc/modules-load.d/br_netfilter.conf
# 设置网络参数
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
这些配置看似基础,但任何一个遗漏都可能导致后续出现难以诊断的问题。特别是网络相关参数,如果不设置正确,后面安装网络插件时会出现各种连接问题。
2. 第一个拦路虎:Swap分区问题
当我第一次执行kubeadm init时,遇到了最经典的swap报错:
[ERROR Swap]: running with swap on is not supported. Please disable swap
2.1 为什么k8s要禁用swap?
这个设计决策源于k8s的资源管理机制。Swap会干扰kubelet对Pod内存使用的准确评估,可能导致:
- 内存压力判断失准,影响调度决策
- 性能下降(内存换入换出开销)
- QoS保障失效(重要Pod可能被换出)
2.2 彻底禁用swap的完整步骤
大多数教程只告诉你swapoff -a,但在生产环境中这远远不够:
# 临时关闭所有swap分区
swapoff -a
# 永久禁用 - 需要修改fstab
sed -i '/swap/d' /etc/fstab
# 检查是否还有swap设备
blkid | grep swap
# 如果有输出,需要进一步处理对应的设备
# 重启后验证
reboot
free -h
特别注意:某些云平台的CentOS镜像会使用特殊的swap配置方式,仅修改fstab可能不够。如果重启后发现swap又回来了,需要检查是否有systemd-swap服务在运行。
3. Docker版本的地雷阵
解决swap问题后,我遇到了第二个报错:
WARNING SystemVerification: this Docker version is not on the list of validated versions: 18.03.1-ce
3.1 k8s v1.15.1的Docker版本兼容性
查阅官方文档发现,v1.15.x验证过的Docker版本是18.09.x系列。而CentOS 7默认仓库中的Docker版本(18.03.1)确实不在支持列表中。
版本兼容性对照表:
| Kubernetes版本 | 已验证Docker版本 |
|---|---|
| v1.15.x | 18.09.x |
| v1.16.x | 18.09.x, 19.03.x |
| v1.17.x | 19.03.x |
3.2 彻底清理和安装指定Docker版本
在CentOS上处理Docker版本问题需要格外小心,以下是完整流程:
# 完全卸载现有Docker
sudo yum remove -y docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-selinux \
docker-engine-selinux \
docker-engine
# 清理残留文件和配置
sudo rm -rf /var/lib/docker
sudo rm -rf /etc/docker
# 安装必要依赖
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加Docker官方仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 列出可用版本
yum list docker-ce --showduplicates | sort -r
# 安装特定版本(这里选择18.09.9)
sudo yum install -y docker-ce-18.09.9 docker-ce-cli-18.09.9 containerd.io
# 配置Docker
mkdir /etc/docker
cat <<EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
EOF
# 启动服务
systemctl enable --now docker
关键提示:cgroup驱动必须设置为systemd以与kubelet保持一致,否则后续会引发cgroup不一致问题。
4. kubeadm的版本陷阱
当Docker问题解决后,我以为胜利在望,却遇到了第三个坑:
Flag --experimental-upload-certs has been deprecated, use --upload-certs instead
4.1 kubeadm命令的版本差异
这个报错揭示了k8s版本管理中的一个重要事实:不同小版本间的CLI参数可能有变化。v1.15.x确实已经弃用了--experimental-前缀的参数。
正确的初始化命令应该是:
kubeadm init \
--config=kubeadm-config.yaml \
--upload-certs \
| tee kubeadm-init.log
4.2 推荐的kubeadm配置文件
为了避免命令行参数的各种版本兼容问题,最佳实践是使用配置文件:
apiVersion: kubeadm.k8s.io/v1beta2
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: "192.168.1.100" # 替换为实际IP
bindPort: 6443
nodeRegistration:
criSocket: "/var/run/dockershim.sock"
name: "k8s-master"
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: "v1.15.1"
controlPlaneEndpoint: "192.168.1.100:6443"
networking:
podSubnet: "10.244.0.0/16" # 根据选择的网络插件调整
apiServer:
extraArgs:
runtime-config: "storage.k8s.io/v1=true"
controllerManager:
extraArgs:
node-cidr-mask-size: "24"
scheduler:
extraArgs:
address: "0.0.0.0"
这个配置文件不仅解决了参数弃用问题,还能统一集群的初始配置,方便后续维护。
5. 最后的障碍:镜像拉取问题
当所有配置都调整正确后,kubeadm init还是卡在了镜像拉取阶段。这是因为旧版本k8s的镜像仓库已经发生了变化。
5.1 手动拉取镜像的解决方案
对于v1.15.1,需要手动拉取镜像并重新打标签:
# 列出需要的镜像
kubeadm config images list --kubernetes-version v1.15.1
# 从可用的镜像源拉取
images=(
k8s.gcr.io/kube-apiserver:v1.15.1
k8s.gcr.io/kube-controller-manager:v1.15.1
k8s.gcr.io/kube-scheduler:v1.15.1
k8s.gcr.io/kube-proxy:v1.15.1
k8s.gcr.io/pause:3.1
k8s.gcr.io/etcd:3.3.10
k8s.gcr.io/coredns:1.3.1
)
for image in "${images[@]}"; do
docker pull registry.aliyuncs.com/google_containers/${image#k8s.gcr.io/}
docker tag registry.aliyuncs.com/google_containers/${image#k8s.gcr.io/} $image
done
5.2 验证集群状态
成功初始化后,执行以下命令验证集群状态:
# 配置kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# 检查节点状态
kubectl get nodes
# 检查各组件状态
kubectl get pods -n kube-system
如果一切正常,你应该能看到控制平面组件全部处于Running状态。至此,这个历经多重考验的k8s v1.15.1集群终于成功启动。回顾整个过程,最大的教训就是:部署旧版本k8s时,必须仔细研究该版本特定时期的文档和已知问题,不能简单套用最新版本的经验。
更多推荐
所有评论(0)