自建 Kubernetes 安全升级 Hands-on

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。
本文缩写(英文全称与中文含义)
缩写 英文全称/名称 中文含义
API Application Programming Interface 应用程序编程接口
AZ Availability Zone 可用区
CNI Container Network Interface 容器网络接口
CPU Central Processing Unit 中央处理器
CRD Custom Resource Definition Kubernetes 自定义资源定义
CRI Container Runtime Interface 容器运行时接口
CSI Container Storage Interface 容器存储接口
DNS Domain Name System 域名系统
GitOps GitOps 以 Git 保存期望状态、由自动化持续协调实际状态的运维方式
GPU Graphics Processing Unit 图形处理器
HA High Availability 高可用
IaC Infrastructure as Code 基础设施即代码
IAM Identity and Access Management 身份与访问管理
IP Internet Protocol 网际协议;IP 地址是网络寻址标识
LB Load Balancer 负载均衡器
OS Operating System 操作系统
PDB Pod Disruption Budget Pod 中断预算,约束自愿驱逐
PKI Public Key Infrastructure 公钥基础设施
PV Persistent Volume 持久卷
PVC Persistent Volume Claim 持久卷申领
RKE2 Rancher Kubernetes Engine 2 Rancher Kubernetes 发行版
SLO Service Level Objective 服务等级目标
SSH Secure Shell 安全远程登录协议

适用:kubeadm、Ubuntu/Debian、systemd、containerd、3 个控制面节点。单控制面需接受 API 中断;RKE2、k3s、Kubespray 等应使用各自升级工具,不能直接套用 kubeadm。命令使用 Bash,逐段执行,不能整篇一键运行。

1. 先确定升级路径#

类型 做法
补丁:1.N.a → 1.N.b 同一 minor,可直接到已验证的目标 patch;仍检查变更记录、备份并滚动升级
次版本:1.N → 1.(N+1) 先补齐当前 minor 的稳定补丁,再完成一次完整升级与验收
跨多个次版本 N → N+1 → N+2,每一跳都完成控制面、插件、节点、备份与观察;禁止控制面跳级
真正主版本:1.x → 2.x 另查届时迁移政策,本手册不假设兼容
严重落后、依赖断档 优先新建受支持集群,迁移应用与数据,再切流

通常口语里的“跨大版本”指 minor 升级。HA API Server 最多相差一个 minor;kubelet 不能比它可能访问的 API Server 更新;kubectl 保持在服务端前后一个 minor 内。本文采用更保守顺序:全部控制面完成 → 控制面 kubelet → worker。版本偏差规则

2. 开始前必须通过的检查#

检查 放行条件
环境 确认 context、节点名/IP、LB、部署工具版本;有主机 SSH、sudo 和备用管理入口
API 查目标版本移除项;扫描 Git、Helm 渲染结果、审计日志、Operator/CRD 和 webhook;只看 api-resources 不够
兼容 列出 CNI、CSI、CoreDNS、kube-proxy、Ingress、监控、安全组件、Service Mesh 的当前/目标版本和支持矩阵
主机 核对 OS、内核、CRI/containerd、cgroup、证书到期、时间同步、磁盘空间、镜像仓库连通性
可用性 核心服务多副本且跨节点/可用区;PDB 允许一次驱逐;readiness、优雅退出和 LB 摘流已验证
容量 少一台节点仍可调度;检查 requests、亲和性、污点、GPU、卷所在 AZ、卷挂载数量及 IP 余量
数据 etcd 快照和异机副本校验通过;PKI、配置、加密密钥可恢复;PV/数据库另备份,隔离恢复演练成功
变更 测试环境完成同路径升级;冻结应用/Schema 变更,防止 GitOps、自动缩容与升级冲突;指定负责人和恢复时限

按API 迁移指南逐跳检查。插件尽量先升级到同时支持新旧 Kubernetes 的版本;没有兼容交集时,按供应商迁移步骤拆分操作。不要同时换 OS、CNI 和 CPU 架构。

以下从管理机采集基线;保存输出到受限目录,不能把 Secret/etcd 快照提交 Git:

kubectl config current-context
kubectl version
kubectl get nodes -o wide
kubectl get pods -A -o wide
kubectl get pdb -A
kubectl get pvc -A
kubectl get events -A --sort-by=.metadata.creationTimestamp
kubectl get --raw='/readyz?verbose'

在控制面检查 sudo kubeadm certs check-expiration,并按 etcd 运维与灾备执行全成员健康检查、快照和恢复演练。etcd 备份不包含 PV 业务数据;外部 etcd 必须另有符合其版本政策的滚动升级方案。

升级前写下停止阈值:例如关键交易连续失败、5xx 超 SLO、p95 持续高于基线、DNS/PVC 异常、节点超过约定时间不 Ready。阈值和观察时间按业务调整,不能只验收 Pod Running。

每一跳升级先填写 变更执行记录,明确节点/业务超时阈值、恢复负责人及最晚决策时间;回退资格以本篇恢复章节和当次平台查询结果为准。

3. 每台主机准备精确版本#

先从目标 minor 的官方 kubeadm 文档确认路径。下面的 1.N 等是占位符,必须替换;包版本从仓库查询,不能猜测后缀。每换一台主机重新设置变量。

export TARGET_MINOR='1.N'
export TARGET_VERSION='1.N.P'

# 已采用 pkgs.k8s.io 的主机;先备份并检查现有源,避免重复配置。
cat /etc/apt/sources.list.d/kubernetes.list
sudo cp -a /etc/apt/sources.list.d/kubernetes.list /etc/apt/sources.list.d/kubernetes.list.before-upgrade
sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL "https://pkgs.k8s.io/core:/stable:/v${TARGET_MINOR}/deb/Release.key" -o /tmp/kubernetes-release.key
sudo gpg --dearmor --yes -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg /tmp/kubernetes-release.key
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v${TARGET_MINOR}/deb/ /" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
apt-cache madison kubeadm kubelet kubectl

确认签名与仓库更新成功,再设置查询到的精确包版本并安装 kubeadm;此时不升级 kubelet:

export PKG_VERSION='1.N.P-1.1' # 替换为查询结果,三包均须存在
sudo apt-mark unhold kubeadm
sudo apt-get install -y "kubeadm=$PKG_VERSION" && sudo apt-mark hold kubeadm
kubeadm version
sudo kubeadm config images pull --kubernetes-version "v$TARGET_VERSION"

任一命令失败即停下修复;不要在下载或安装失败后继续。离线集群先同步目标镜像和软件包。

4. 顺序升级控制面#

一次只操作一台,始终保持 etcd 多数派。先在第一台控制面执行:

sudo kubeadm upgrade plan
# 人工核对目标、etcd/CoreDNS/kube-proxy 变化后执行,保留交互确认。
sudo kubeadm upgrade apply "v$TARGET_VERSION"

检查本机静态 Pod、API/LB 与 etcd 健康;必要时先从 LB 摘除故障 API 后端。确认恢复正常,再在其余控制面逐台完成第 3 节并执行:

sudo kubeadm upgrade node

每台都验收后再继续下一台。不要在其他控制面重复 upgrade apply,也不要并行重启控制面。kubeadm 的较新版本会等控制面全部升级后处理 CoreDNS/kube-proxy;旧集群要查对应版本行为。CNI 按兼容计划单独升级。kubeadm 升级流程

确认每个 API Server 静态 Pod 镜像都已到目标版本,并检查各后端健康;不能只经 LB 查询一次 kubectl version 就认定全部完成。

5. 逐台升级 kubelet 与 worker#

先控制面节点,再一台普通 worker 试点,最后其余 worker。每台重复以下过程;控制面已执行 upgrade node/apply,无需再执行。

在管理机:

export NODE='替换为一个节点名'
kubectl get pods -A --field-selector "spec.nodeName=$NODE" -o wide
kubectl drain "$NODE" --ignore-daemonsets --timeout=15m

drain 失败就停止:先处理 PDB、容量、裸 Pod、local PV/hostPath/emptyDir。不要默认加 --force、--disable-eviction 或 --delete-emptydir-data;后者会丢弃临时卷数据,必须先确认可丢弃。DaemonSet、静态 Pod 不会像普通 Pod 一样迁走。安全排空节点

在当前节点:worker 先执行第 3 节安装 kubeadm,再执行 sudo kubeadm upgrade node。随后所有节点执行:

sudo apt-mark unhold kubelet kubectl
sudo apt-get install -y "kubelet=$PKG_VERSION" "kubectl=$PKG_VERSION" && sudo apt-mark hold kubelet kubectl
sudo systemctl daemon-reload
sudo systemctl restart kubelet
sudo systemctl is-active kubelet
sudo journalctl -u kubelet -n 60 --no-pager

没有安装 kubectl 的 worker 只升级 kubelet。若主机确需重启,在排空状态逐台进行,不能顺带批量升级 OS。

回管理机,确认新版本、Ready、CNI/CSI DaemonSet 健康后恢复调度:

kubectl get node "$NODE" -o wide
kubectl wait --for=condition=Ready "node/$NODE" --timeout=5m
kubectl uncordon "$NODE"
kubectl get pods -A -o wide

在试点节点实际调度测试 Pod,验证 DNS、Service、外网/私网、NetworkPolicy、PVC 读写、业务身份及外部 LB 请求。通过后逐台推进,避免只是看到旧节点上的业务还正常。

每批可执行检查#

在管理机选定本批新节点上的实际业务 Pod,不要拿旧节点健康结果代替。先核对 Pod 的 NODE 列,再填写变量;命令只读,需 kubectl 权限。

export CHECK_NS='orders'
export CHECK_DEPLOYMENT='orders-api'
kubectl -n "$CHECK_NS" get pods -o wide
export CHECK_POD='REPLACE_POD_ON_UPGRADED_NODE'
kubectl -n "$CHECK_NS" wait --for=condition=Ready "pod/$CHECK_POD" --timeout=5m
kubectl -n "$CHECK_NS" rollout status "deployment/$CHECK_DEPLOYMENT" --timeout=5m
kubectl -n "$CHECK_NS" get pod "$CHECK_POD" -o jsonpath='{.spec.nodeName}{"\n"}{range .status.containerStatuses[*]}{.name}{" ready="}{.ready}{" restarts="}{.restartCount}{" last="}{.lastState}{"\n"}{end}'
kubectl -n "$CHECK_NS" get events --field-selector "involvedObject.kind=Pod,involvedObject.name=$CHECK_POD" --sort-by=.metadata.creationTimestamp

预期:Pod 位于本批节点、Ready、发布完成;观察窗口内无新增异常重启或挂载/网络事件。然后执行该应用既有业务验收,并通过日志/追踪确认请求确实命中新节点副本;涉及数据库、消息和卷时必须覆盖实际读写。任一失败不推进下一批;仅上述命令成功仍不构成业务验收。

6. 验收与故障处置#

现象 行动
单个 worker 异常 保持 cordon,暂停下一台;查 kubelet/runtime/CNI/CSI 日志;修复或按当前控制面兼容版本重建节点
一个控制面异常 停止继续升级,保护剩余 etcd 多数派;修复本机配置/证书/磁盘,可按原计划重试失败的 kubeadm 操作
API/etcd 大面积失效 启动预演过的灾备流程,隔离旧控制面并评估数据回退损失;不能往运行中集群随意塞入旧快照
应用不兼容 优先恢复兼容应用/插件;控制面降级不是 kubeadm 支持的通用回滚方案

kubeadm 生成的 manifest/etcd 临时备份只用于对应故障恢复,不能代替灾备。不要直接把 kubelet、API Server 和 etcd 二进制统一降级来“回滚”。

结束前确认:所有节点目标版本且无遗留 cordon;控制面/etcd、插件、PVC 正常;业务读写和异步任务通过;监控稳定覆盖代表性流量及定时任务。保存版本清单、结果、耗时和新备份,更新 IaC/GitOps,再恢复暂停的自动化。完成本跳观察后才开始下一 minor。

跨度过大采用新集群迁移:还原对象与数据 → 验证 IAM/网络/存储 → 小流量验证 → 停写并完成最终同步 → 切 LB/DNS → 保留旧集群观察。防止两边同时写入;DNS 缓存和切流后的新增数据必须纳入回切方案。

核对日期:2026-09-23。本文命令未在真实集群执行;落地前必须在与你生产相同的版本与插件组合上演练。

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭