从上个月开始,我负责的这套 K8S 1.28 集群就开始不断出现节点 NotReady 告警。一开始我们怀疑是机房网络抖动,排了一圈又一圈,直到某个运维老哥在周会上甩出一句:“CentOS 7 已经 EOL 了,我们是不是该动了?”会议室瞬间安静。说实话,从 CentOS 7 迁移到 Rocky Linux 9.4 这个想法我们拖了大半年,总觉得不到最后一刻不用慌。但当你真正面对 K8S 1.28 集群里几十个节点、一堆本地数据盘、还有跑在 GPU 节点上的训练任务时,就会发现这不是“重装个系统再 kubeadm join”那么简单。
这套集群承载了线上核心 API、日志采集、部分 AI 推理服务,业务方只关心别停,不关心你用的是什么发行版。于是我花了两个月时间,用滚动替换的方式把 K8S 1.28 集群从 CentOS 7 平滑迁到了 Rocky Linux 9.4,整个过程中业务没有出现过超过 5 分钟的连续中断。这篇文档不是什么官方迁移教程,而是我在实际操作中整理出来的完整实施手册,适合和我一样需要“在不重建集群、不迁移业务的前提下更换节点操作系统”的团队参考。
1. 迁移前要搞清的三个问题:风险、兼容性、目标状态
网上很多文章会把“系统迁移”写成一堆命令的堆砌,但真正动手前,必须先把三个问题想清楚:为什么要迁、用什么方案迁、迁完之后要得到什么。这三个问题没捋明白,后续每一步都会踩坑。
1.1 CentOS 7 的 EOL 到底影响了什么
CentOS 7 停止维护后,最直接的问题就是 yum 源和漏洞补丁不再更新。尤其是 K8S 1.28 这种对 kubelet、containerd 运行时有较新依赖的版本,底层操作系统如果长期停留在 3.10 内核,很多新特性根本用不上。比如 cgroups v2、io_uring、更完善的 nftables 机制,这些在 CentOS 7 上要么不支持,要么需要额外打补丁。
Rocky Linux 9.4 作为 RHEL 9 的兼容发行版,内核版本通常在 5.14 以上,且默认启用 cgroups v2。Kubernetes 从 1.25 开始就已经支持 cgroups v2,1.28 版本在 Rocky 9.4 上运行是完全没有问题的。但要注意,容器运行时如果还用 Docker 的话,需要评估 cri-dockerd 的兼容性,我这边一开始就是 containerd,反而省了运行时迁移这一步。
1.2 迁移方案的取舍:原地升级、新建集群、滚动替换
我在社区里看到不少人推荐“原地升级”,也就是在 CentOS 7 节点上直接替换 yum 源,然后通过升级安装包的方式把系统变成 Rocky Linux。这个思路听起来省事,但实际上风险极高。CentOS 7 和 Rocky Linux 9.4 的 glibc、systemd、内核模块加载机制差异太大,跨大版本原地升级非常容易把 kubelet、containerd 甚至 SSH 服务搞挂。一旦中途失败,系统处于半坏状态,回滚成本极高。
新建集群再迁移业务是很多正规企业会选的方式,但前提是业务允许重新发布、重新挂载存储,而且你有充足的时间做数据同步。我这边业务方明确要求不能重建 Service 和 PVC,所以这条路也被否掉了。
最终我选择的是“滚动替换节点”方案:保持现有控制面和 API Server 不变,新装一批 Rocky Linux 9.4 节点,通过 kubeadm 方式加入现有集群,逐批把旧节点上的业务排空后下线。这样集群的 etcd 数据、Service、PVC 全部得以保留,只是承载这些对象的节点发生了替换。整个过程中,集群视角始终存在,不会出现“集群整体不可用”的窗口。
1.3 迁移前必须摸清的盘点清单
这个环节很多人会省略,但恰恰是迁移成败的关键。你需要对集群现有状态做一次彻底盘点,把这四类信息记录在案:
- 控制平面架构:是单 Master 还是高可用?etcd 是内嵌还是外部部署?如果内嵌 etcd,节点替换时要额外处理 etcd member 的增删。
- CNI 类型及 CIDR:Calico 还是 Flannel?Pod CIDR、Service CIDR、IPIP 模式还是 VXLAN 模式?
- 存储方案:用了 Local PV 还是 NFS?如果是 Local PV,节点替换后原节点数据无法跟随,必须在迁移前确认哪些 PVC 可以重建,哪些必须提前备份。
- 工作负载分布:哪些节点有专用标签、污点或节点亲和性?GPU 节点有多少个业务 Pod 在跑?
我当时的排查命令大概是这样的:
bash复制# 查看所有节点及角色
kubectl get nodes -o wide
# 查看节点上的标签和污点
kubectl get nodes --show-labels
kubectl get node <node-name> -o yaml | grep -A5 taints
# 查看 CNI 配置
kubectl get pods -n kube-system -o wide | grep -i calico
# 或者
kubectl get ds -n kube-system calico-node -o yaml
# 查看 StorageClass
kubectl get sc
这些信息在后面滚动替换的时候会反复用到。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 迁移前的备份与红线的设立
备份做得好不好,决定了你出问题时是“回滚”还是“回天乏术”。K8S 集群迁移过程中,最核心的数据是 etcd,其次是 PVC 数据、kubeadm 生成的配置、以及自定义的 CRD 资源。
2.1 etcd 快照:唯一能救命的底牌
不管集群规模多大,迁移前一定要做 etcd 快照。K8S 1.28 如果用 kubeadm 部署的集群,etcd 通常以静态 Pod 方式运行在控制平面节点上,直接进入 etcd 容器执行快照命令即可:
bash复制# 进入 etcd 容器
kubectl exec -n kube-system etcd-master01 -- sh -c \
"ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
snapshot save /var/lib/etcd/snapshot-$(date +%F).db"
# 将快照拷贝到迁移服务器或对象存储
kubectl cp kube-system/etcd-master01:/var/lib/etcd/snapshot-2025-01-20.db /backup/
快照文件不要只存在本地,建议同时上传到异地位置,比如内网备份服务器和对象存储各一份。我之前见过一个事故,etcd 快照和原集群在同一台存储上,存储坏了快照也跟着没了,那才是真正的灾难现场。
2.2 kubeadm 配置与 RBAC 资源备份
kubeadm 的配置文件和证书路径也需要提前备份。虽然滚动替换节点不会轻易改动控制面,但万一新节点加入时证书不匹配,就需要用原始 kubeadm-config 重新生成。
``
