news 2026/10/9 10:53:31

kubeadm集群升级全攻略:从控制平面到worker节点的安全实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
kubeadm集群升级全攻略:从控制平面到worker节点的安全实践

1. 升级前的准备工作与版本策略

1.1 先想清楚:为什么升级 kubeadm 集群要卡版本

kubeadm 集群升级,最容易踩的坑就是不看版本路线,直接往新版冲。Kubernetes 官方的支持策略是:kubeadm 只能从一个次版本升级到相邻的下一个次版本,比如 1.28 到 1.29,不支持跨多个次版本直接跳。原因在于 API 资源的废弃节奏、kubelet 与 kube-apiserver 的版本偏差容忍范围都是固定设计的,跨版本跳很容易撞上不兼容的接口和已废弃的 API 资源,一旦撞上,整个集群的稳定性都会受影响。

实际操作中,我的习惯是把升级路线拆成三步走:先确认当前集群版本,再确定目标版本,最后规划每个节点的操作顺序。需要确认的东西包括 etcd 版本和镜像的兼容性、CoreDNS 是否需要同步升级、控制平面与 worker 节点之间镜像拉取策略、以及本地存储 PV/PVC 在节点重启后能否自动恢复。这些信息看起来繁琐,但缺一项都可能在升级过程中变成事故。

还有一点必须提前讲清楚:kubeadm 升级不会自动帮你完成所有事。它负责更新控制平面组件的静态 Pod 清单和集群级配置,但 kubelet 的二进制版本、kubelet.conf 配置、节点的隔离和恢复等操作,都需要手动介入。很多人以为跑一条命令就万事大吉,实际上升级是一个由多个环节组成的过程,任何一个环节被跳过,都会留下隐患。

1.2 环境检查与备份清单

升级前必须做的检查项,我一般列成这样一张清单,逐项打勾:

  • 所有节点状态是否为 Ready,是否有节点处于 NotReady 或内存压力状态
  • 核心插件是否健康,包括 coredns、metrics-server、网络插件(flannel 或 calico)
  • etcd 集群是否有异常,有没有成员掉线或 leader 切换频繁的情况
  • 是否有 Pending 状态的 Pod,是否有大量 CrashLoopBackOff
  • 工作负载的副本数是否达到预期,特别是 Deployment 和 StatefulSet

这些检查做完后,备份是绝对不能跳过的一步。备份至少要做两件事:etcd 快照和 kubeadm 配置备份。etcd 快照命令是:

ETCDCTL_API=3 etcdctl --endpoints=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 /backup/etcd-snapshot-$(date +%Y%m%d).db

kubeadm 配置一般在/etc/kubernetes/kubeadm-config.yaml,直接拷贝备份就行。我建议把备份文件同时放在控制平面节点本地和远端存储,避免节点硬件故障导致备份也丢。

这里有个我踩过坑的细节:如果集群里用了自定义的 admission webhook,升级前一定要确认新版本对admissionregistration.k8s.io/v1API 的兼容性。否则可能出现所有创建请求都被 webhook 拦截的情况,影响范围远比想象的大。检查方式很简单,先看一下 webhook 配置里的 apiVersion 和新旧版本对应关系,再确认 webhook 服务的可用性。

注意:如果集群中有使用PodDisruptionBudget(PDB)的工作负载,drain 节点时会受到 PDB 限制,导致驱逐速度极慢甚至卡住。升级前要评估业务是否允许中断,必要时先调整 PDB 策略。

2. 升级控制平面节点的完整流程

2.1 升级顺序:先控制平面还是先 worker

这个顺序非常关键,我的建议是严格按“控制平面节点优先、worker 节点其次”的顺序来。控制平面升级后,kube-apiserver、kube-controller-manager、kube-scheduler 都会运行在新版本上,而 kubelet 可以暂时停留在旧版本。Kubernetes 官方文档明确说:kubelet 版本不能高于 kube-apiserver 版本,但可以低一个次版本。所以先升控制平面,再逐个升级 worker 节点,是安全且符合规范的路线。

反过来,如果先升 worker 节点,就可能出现 worker 节点的 kubelet 版本比 API Server 还新,导致 kubelet 上报节点状态、Pod 状态时接口不兼容,最直接的现象是节点状态不稳定、Pod 一直卡在 ContainerCreating。我之前在一个测试环境里试过先升级 worker,结果节点间歇性 NotReady,排查了半天才发现是版本顺序的问题。

此外,控制平面内部也有顺序讲究。如果集群里有多个控制平面节点,官方推荐的做法是先升级第一个控制平面节点,然后逐步升级其余控制平面节点。这样能保证在升级过程中集群始终有可用的 API Server 端点,不会出现整个控制面不可用的情况。

2.2 主节点升级实测:kubeadm upgrade 三步

我用 kubeadm 1.28 升级到 1.29 的例子来说明完整流程。第一步,先更新软件源,然后安装目标版本的 kubeadm、kubelet 和 kubectl:

apt update apt install -y kubeadm=1.29.0-00 kubelet=1.29.0-00 kubectl=1.29.0-00

这里要注意:最好一次性把三个包都指定版本装好,不能只装 kubeadm,忘记升级 kubelet。我就犯过这个错误,只升级了 kubeadm,忘记升级 kubelet,最后在kubeadm upgrade node阶段报版本不匹配,额外花了不少时间排查。如果使用的是国内镜像源,注意确认源里确实有对应版本,否则执行安装时会提示找不到包。

第二步,查看升级计划:

kubeadm upgrade plan

这个命令会输出当前集群版本、可升级到的最高版本,以及升级过程中需要拉取的镜像列表。如果输出里显示 “can be upgraded to v1.29.0”,说明升级路径没问题。如果出现 “unsupportedVersion” 之类的提示,说明软件源里没有对应版本,或者当前 kubeadm 版本无法识别目标版本。

第三步,执行升级:

kubeadm upgrade apply v1.29.0

这个命令会自动处理证书轮换、关键的配置更新、控制平面静态 Pod 清单的更新。执行过程中,通常会卡在 “Waiting for the kubelet to boot” 或类似的阶段,这属于正常现象,因为系统在等待静态 Pod 拉起并进入健康状态。看到 “upgrade completed successfully” 才算成功。

注意:执行kubeadm upgrade apply时必须使用 root 权限,而且命令需要在一个空闲终端中执行,过程中如果有其他 kubectl 命令干扰,可能导致验证阶段误判。

2.3 控制平面升级后的收尾动作

升级完成后,手动收尾动作不能省。第一,更新本地 kubeconfig,让 kubectl 能继续访问新的 API Server:

sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config

这一步是为了确保本地客户端的访问凭据是最新的。如果跳过,后续kubectl get nodes可能因为证书或 endpoint 变化而报错。

第二,检查控制平面 Pod 的状态。重点看 kube-apiserver、etcd、kube-controller-manager、kube-scheduler 这些静态 Pod 是否处于 Running 状态。因为这些组件由 kubelet 直接拉起,如果新版本镜像拉不下来,会一直卡在 ImagePullBackOff。建议在升级前就确认镜像仓库的可达性,最好提前用kubeadm config images pull预拉取一遍目标版本镜像:

kubeadm config images pull --kubernetes-version v1.29.0

第三,在第一个控制平面节点上,还要执行:

kubeadm upgrade node

很多人以为这个命令只用于 worker 节点,但控制平面节点在apply之后也需要在本地执行kubeadm upgrade node来更新 kubelet 配置。原因是kubeadm upgrade apply主要负责控制平面组件的更新和集群级配置,而本节点的 kubelet systemd 配置、kubelet.conf 和证书文件不会自动写入,需要通过kubeadm upgrade node触发。

执行完这一步后,重启 kubelet 服务:

systemctl restart kubelet

到这里,第一个控制平面节点才算真正升级完成。

3. worker 节点的升级与业务迁移

3.1 先腾空节点:cordon 和 drain 的正确姿势

worker 节点升级时,最怕的是 Pod 直接在原地被拉起,导致正在处理的业务请求中断。标准做法是先标记节点为不可调度,再把 Pod 驱逐到其他节点:

kubectl cordon node-worker-1 kubectl drain node-worker-1 --ignore-daemonsets --delete-emptydir-data

cordon会标记节点为不可调度,新的 Pod 不会调度到这个节点上。drain会驱逐节点上的 Pod,触发优雅终止流程,等 Pod 迁移到其他节点后再进入维护状态。如果节点上运行的是 StatefulSet,且使用了本地存储,drain可能无法成功,这时候需要评估业务可接受的停机窗口,或者提前在存储层做好迁移方案。实际项目中,我遇到最多的问题是 PVC 绑定在本地节点上的 Pod,驱逐后 PVC 无法 attach 到其他节点,导致 Pod 一直 Pending。

还有一个必须记住的细节:如果节点上有 DaemonSet 的 Pod,drain默认不会驱逐它们,所以要加--ignore-daemonsets;如果某些工作负载使用了 emptyDir 临时存储,需要加--delete-emptydir-data,否则 drain 会因为无法删除 emptyDir 而卡住。这两个参数是高频使用的,建议直接写进操作文档里。

3.2 worker 节点执行升级命令

腾空节点并确认节点上的 Pod 都已经迁移走之后,在 worker 节点上执行升级。先更新软件源并安装目标版本组件:

apt update apt install -y kubeadm=1.29.0-00 kubelet=1.29.0-00 kubectl=1.29.0-00

然后执行:

sudo kubeadm upgrade node sudo systemctl restart kubelet

kubeadm upgrade node会读取本地的 kubelet 配置,并生成新版本的 kubelet.conf 和证书文件。执行完之后必须重启 kubelet,否则新配置不会生效。我见过不少人在这一步忘记重启,然后发现节点的 kubelet 版本还是旧的,节点状态变成 NotReady,最后一通排查才发现只是没重启服务。

这一整套流程做完后,可以执行kubectl get nodes确认该节点的 VERSION 已经变成新版本,同时 STATUS 是 Ready。

3.3 解除维护状态:uncordon

升级完成后,需要解除节点的不可调度标记:

kubectl uncordon node-worker-1

这里有个节奏问题:如果集群里有多个 worker 节点,我建议一台一台来,每台升级完、uncordon、确认业务 Pod 调度回该节点后,再操作下一台。不要把所有 worker 节点一次性全部 drain,那样会让集群调度压力突然增大,甚至出现资源不足导致大量 Pod Pending。

整个升级过程中,集群调度器会重新为被驱逐的 Pod 分配节点,这实际上就是一次集群调度的实战演练。如果集群里配置了 PriorityClass,要注意高优先级 Pod 会抢占其他 Pod 的资源,避免因为短时间内多个节点同时维护引发大规模重调度风暴。生产环境里,跨节点迁移大流量业务时还要特别注意网络带宽和存储性能的瓶颈,必要时提前扩容相关节点资源。

4. 升级后的验证与常见问题排查

4.1 集群健康检查的完整验证清单

升级完成后不能只看控制平面 Pod 状态,还要从多个维度验证。先看节点状态:

kubectl get nodes

所有节点应该显示 Ready,并且 VERSION 列已经变成新版本。然后看核心插件和系统组件:

kubectl get pods -n kube-system -o wide

重点关注 kube-apiserver、kube-controller-manager、kube-scheduler、etcd、coredns、flannel 或 calico 这些 Pod。另外,我习惯再执行两条命令:

kubectl cluster-info kubectl get componentstatuses

componentstatuses这条命令虽然现在已经属于半废弃状态,但很多老运维还是会用它快速评估控制平面组件是否健康,输出结果里 controller-manager、scheduler、etcd 都应该是 Healthy。如果集群里启用了 metrics-server,还可以确认kubectl top nodes是否能正常返回数据,这一步能验证 kubelet 的 metrics 采集链路没有在升级中损坏。

除此之外,建议验证一下工作负载是否真的恢复了。随便挑几个核心业务应用,看一下 Pod 的启动时间和所在节点,确认 Pod 已经迁回目标节点并且 Running 状态稳定。如果业务有自建的监控告警系统,此时要确认数据采集没有中断,告警通道没有因为节点重启而静默。

4.2 常见升级问题速查表

我把升级过程中遇到的高频问题整理成速查表,方便排查:

现象可能原因处理方式
kubeadm upgrade plan 报无法解析镜像软件源未更新先apt update并确认目标版本已安装
升级后 node 一直 NotReadykubelet 未重启查看systemctl status kubelet,重启 kubelet
Pod 一直 ContainerCreating镜像仓库不可达或新版本镜像不存在检查 kubelet 日志,确认镜像 tag 是否匹配目标版本
drain 卡住无法完成有未配置容忍的 Pod 或 PDB 限制用kubectl describe pod查看卡住的 Pod,评估强制驱逐或调整 PDB
API Server 启动失败证书过期或配置不匹配查看/var/log/kube-apiserver日志,检查证书有效期和路径
升级后部分节点网络异常网络插件版本与集群不一致检查 flannel/calico Pod 状态,按插件的升级文档同步更新

遇到问题不要先想着回滚,先看日志。kubelet 日志在 worker 节点上用journalctl -u kubelet -f查看,控制平面组件日志可以直接用kubectl logs -n kube-system查看,如果控制平面组件本身起不来,则需要在对应节点上查看静态 Pod 的容器日志,路径一般是/var/log/pods/kube-system_xxx/。

4.3 关于回滚方案的思考

很多人问升级失败能不能回滚。说实话,kubeadm 集群的升级回滚比升级本身还麻烦,尤其是控制平面已经执行了apply之后,etcd 数据可能已经被新版本写入,旧的二进制版本重新放回去也不一定兼容。我的经验是:如果只是 worker 节点升级失败,直接把 kubelet 和 kubeadm 的二进制版本降回去,重启 kubelet,大概率能恢复;如果控制平面升级失败,就要优先考虑是否有可用的 etcd 快照,用备份做恢复。

所以,升级前的备份不是走流程,而是真正决定你能不能安全回滚的关键。建议把 etcd 快照文件单独存放,并且至少保留升级前和业务稳定后的两份快照,这样即使稳定运行一段时间后发现隐患,也能有一个恢复点。多看几遍官方文档里关于备份 etcd 的章节,比自己临时摸索靠谱得多。

5. 升级kubeadm集群的两个额外实践建议

5.1 小集群练手,再上生产

升级 kubeadm 集群这件事,我做得越多越觉得关键不在命令本身,而在节奏。我实际测试下来最稳的顺序是:先在一套小集群里完整走一遍升级流程,包括验证、回滚、再升级,确认没有意外情况后,再在生产环境动手。小集群的节点少、业务量小,即使操作失误,修复成本也低。生产环境升级前,我会把所有的命令和步骤整理成一份操作单,里面包含每个节点的 IP、操作顺序、预计耗时、回滚入口,然后逐条执行,执行一项就打勾一项。

5.2 操作窗口与告警处理

升级时间尽量安排在业务低峰期。这个不用多说,但一定要提前在运维群同步操作窗口,避免在升级过程中被业务方的告警打扰。升级过程中会有节点重启、Pod 迁移,期间部分服务可能出现短暂不可用,如果业务方不知情,他们可能会误报故障,甚至有人会主动重启 Pod 导致操作动作冲突。

另一个很实用的建议是:在升级前把 kubectl 命令行工具提前下载到本地,并验证其版本与目标集群版本的兼容性。新版 kubectl 通常能兼容旧版 API Server,但反过来不一定成立。我习惯在正式操作前先跑一遍kubectl version --client和kubectl version --server,把版本输出记录下来,再开始动集群。这样做的好处是,一旦升级后出现兼容性问题,能快速判断是 kubectl 的问题还是集群组件的问题。

永远不要在没有备份、没有验证方案的情况下直接升级,记住这一点,很多坑就都绕开了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 10:53:31

Java Web轻量级供求信息网源码解析与实战部署

简介:这是一套基于Java Web技术栈开发的都市供求信息网完整项目源码,面向Java初学者与Web开发入门者,适用于课程设计、毕业设计及小型信息发布平台实践。项目采用JSPServletMySQL架构,前后台功能完备:前台支持信息列表…

作者头像 李华
网站建设 2026/10/9 10:53:15

Agent Skills,一篇就够了:用TaoToken统一Key跑通SKILL.md与MCP上下文

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/9 10:50:30

注意力机制中文聊天机器人:模型加载与直接运行实战指南

简介:面向机器学习与自然语言处理初学者的中文聊天机器人项目,是大学生课程设计作品,基于注意力机制与序列模型构建,能够理解中文语境并生成自然回复。项目已提供预训练模型(.h5),下载后无需重新…

作者头像 李华
网站建设 2026/10/9 10:49:39

二叉树存储结构详解:顺序存储与链式存储选型及遍历实践

1. 为什么二叉树的存储结构值得单独琢磨 很多同学学二叉树,上来就背定义、画图、遍历,一到写代码就卡壳。尤其是期末复习或者准备考研数据结构的时候,翻到“二叉树的存储结构”这一节,感觉不就是数组和链表吗,有什么好…

作者头像 李华
网站建设 2026/10/9 10:48:30

基于SpringBoot2+Vue3的线上教育培训办公系统全栈实战解析

先说说这个项目到底是个啥。简单讲,一套基于 SpringBoot2 Vue3 MyBatis-Plus MySQL8.0 的线上教育培训办公系统,覆盖了在线课程、培训报名、考试测评、审批办公这些核心场景。前后端分离,后端负责业务逻辑和数据接口,前端负责交…

作者头像 李华
网站建设 2026/10/9 10:48:29

Python+Django+Vue:高校学生实习平台全栈开发毕设指南

每年到了毕设季和课设末期,总有一批人会被同一个题目卡住:Python Vue 的高校学生实习综合服务平台。这类项目在网上被翻来覆去地讨论,但真上手时,问题往往出在“知道大概要做什么,却不知道从哪个文件开始写”。这篇文…

作者头像 李华