8.2 K8s 生产运维:集群升级最佳实践
预计阅读时间:19 分钟
📖 目录
Kubernetes 版本迭代快(约每 3 个月发布小版本),生产集群需要定期升级以获取安全补丁和新功能。本文以 kubeadm 部署的集群为例,介绍安全的升级流程,涵盖从规划、备份、执行到验证的完整生命周期。
升级是一个高风险操作,必须严格遵循规范流程。错误的升级方式可能导致集群不可用、数据丢失或业务中断。下面按「备份 → 升级 kubeadm → 升级节点 → 验证」四步拆解每一步的原理和注意事项。
学习目标
- 掌握 Kubernetes 小版本升级的完整流程(控制面 + 工作节点)
- 理解逐节点排空(drain)与恢复调度(uncordon)的必要性
- 能够独立完成从升级规划、备份、执行到验证的端到端操作
- 识别升级过程中的常见故障并具备排查能力
前置知识
- 熟悉 Kubernetes 集群组件:kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、kube-proxy
- 了解 kubeadm 的集群部署方式及静态 Pod 管理机制
- 具备 Linux 包管理基础(apt/yum),了解版本锁定(apt-mark hold)机制
- 已完成 etcd 备份操作(升级前必须备份 etcd)
- 了解 kubectl drain / uncordon 命令的含义与作用
升级原则
- 一次跳一个小版本(如 1.28 → 1.29,不要 1.28 → 1.30)
- 先升级控制面,再升级工作节点
- 逐个节点升级(工作节点逐台排空再升级)
- 升级前必须备份 etcd
- 阅读版本变更日志(CHANGELOG),注意不兼容变更
- 在低峰期执行升级,预留足够的回滚窗口
- 确保 PodDisruptionBudget 满足最低可用要求,避免排空时违反 PDB
版本兼容性说明
Kubernetes 对组件版本有严格要求:
- kube-apiserver 只允许比 etcd 新一个小版本,或与 etcd 同版本
- kubelet 不能比 kube-apiserver 新,最多落后两个小版本
- kube-proxy 与 kubelet 版本要求一致
- CoreDNS 版本随 K8s 版本自动升级,无需手动指定
- etcd 版本通常随 kubeadm 一起升级,无需单独处理
升级前准备
# 1. 查看当前版本
kubectl version --short
kubeadm version
# 2. 查看可升级版本
kubeadm upgrade plan
# 输出示例:
# Components that must be upgraded:
# + kube-apiserver 1.28.0 -> 1.29.0
# + kube-controller-manager 1.28.0 -> 1.29.0
# + kube-scheduler 1.28.0 -> 1.29.0
# + kube-proxy 1.28.0 -> 1.29.0
# + CoreDNS 1.10.1 -> v1.11.1
# + etcd 3.5.9 -> 3.5.12
# 3. 备份 etcd(关键!)
sudo etcdctl snapshot save /backup/etcd-preupgrade-$(date +%F-%H%M).db
# 4. 确保集群健康
kubectl get nodes
kubectl get pods -A | grep -v Running | grep -v Completed
# 5. 检查所有节点的就绪状态
kubectl get nodes -o custom-columns=NAME:.metadata.name,STATUS:.status.conditions[-1].type,VERSION:.status.nodeInfo.kubeletVersion
# 6. 确认 PDB 不会阻止排空
kubectl get pdb -A
版本仓库配置
在升级前需要配置正确的 Kubernetes 包仓库:
# Debian/Ubuntu 系统
# 添加 Kubernetes 官方 GPG 密钥
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 添加仓库
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
# RHEL/CentOS 系统
cat <
升级控制面节点
第一步:升级 kubeadm
# 在第一个控制面节点执行
# 确认目标版本存在
sudo apt-cache madison kubeadm
# 选择目标版本
sudo apt-mark unhold kubeadm && \
sudo apt install -y kubeadm=1.29.0-1.1 && \
sudo apt-mark hold kubeadm
# 验证
kubeadm version
第二步:升级控制面
# 预检查(dry-run,不实际执行)
sudo kubeadm upgrade plan v1.29.0
# 执行升级(第一个控制面节点)
sudo kubeadm upgrade apply v1.29.0
# 其他控制面节点使用 upgrade node
sudo kubeadm upgrade node
第三步:升级 kubelet 和 kubectl
# 排空当前节点(除非只有一个控制面节点)
kubectl drain master --ignore-daemonsets --delete-emptydir-data
# 更新 kubelet 和 kubectl
sudo apt-mark unhold kubelet kubectl && \
sudo apt install -y kubelet=1.29.0-1.1 kubectl=1.29.0-1.1 && \
sudo apt-mark hold kubelet kubectl
# 重启 kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet
# 恢复节点调度
kubectl uncordon master
# 验证
kubectl get nodes
kubelet --version
第四步:升级其他控制面节点(如果有多台)
# 在第二、第三个控制面节点执行
sudo apt-mark unhold kubeadm kubelet kubectl && \
sudo apt install -y kubeadm=1.29.0-1.1 kubelet=1.29.0-1.1 kubectl=1.29.0-1.1 && \
sudo apt-mark hold kubeadm kubelet kubectl
sudo kubeadm upgrade node
sudo systemctl daemon-reload
sudo systemctl restart kubelet
升级工作节点
控制面升级完成后,逐台升级工作节点:
# 在控制面节点排空工作节点
kubectl drain worker1 --ignore-daemonsets --delete-emptydir-data
# 在工作节点上执行
sudo apt-mark unhold kubeadm kubelet kubectl && \
sudo apt install -y kubeadm=1.29.0-1.1 kubelet=1.29.0-1.1 kubectl=1.29.0-1.1 && \
sudo apt-mark hold kubeadm kubelet kubectl
sudo kubeadm upgrade node
sudo systemctl daemon-reload
sudo systemctl restart kubelet
# 在控制面节点恢复调度
kubectl uncordon worker1
# 等待工作节点 Ready,再排空下一台
kubectl wait --for=condition=Ready node/worker1 --timeout=60s
批量升级工作节点
对于大规模集群(50+ 节点),建议使用脚本批量升级以提高效率和一致性。批量升级时需要注意控制并行度,避免同时排空过多节点导致业务不可用。
# upgrade-workers.sh
#!/bin/bash
TARGET_VERSION="1.29.0-1.1"
SSH_USER="ubuntu"
SSH_KEY="~/.ssh/id_rsa"
# 获取所有工作节点
WORKERS=$(kubectl get nodes -l '!node-role.kubernetes.io/control-plane' -o jsonpath='{.items[*].metadata.name}')
for worker in $WORKERS; do
echo "=== 升级节点: $worker ==="
# 排空节点
kubectl drain "$worker" --ignore-daemonsets --delete-emptydir-data --timeout=120s
# SSH 到工作节点执行升级
ssh -i "$SSH_KEY" "$SSH_USER@$worker" "
sudo apt-mark unhold kubeadm kubelet kubectl
sudo apt install -y kubeadm=$TARGET_VERSION kubelet=$TARGET_VERSION kubectl=$TARGET_VERSION
sudo apt-mark hold kubeadm kubelet kubectl
sudo kubeadm upgrade node
sudo systemctl daemon-reload
sudo systemctl restart kubelet
"
# 恢复调度
kubectl uncordon "$worker"
# 等待节点 Ready
kubectl wait --for=condition=Ready "node/$worker" --timeout=120s
echo "=== 节点 $worker 升级完成 ==="
done
echo "所有工作节点升级完成"
升级后验证
# 版本确认
kubectl version --short
kubeadm version
# 节点状态
kubectl get nodes -o wide
# 核心组件运行状态
kubectl get pods -n kube-system
# 运行一个测试 Pod
kubectl run test-nginx --image=nginx --restart=Never
kubectl delete pod test-nginx
# 检查 etcd 集群
kubectl -n kube-system exec etcd-master -- etcdctl endpoint health
# 确认旧版本 manifest 已更新
ls -la /etc/kubernetes/manifests/
# 检查 API 废弃版本警告
kubectl get --raw /metrics | grep apiserver_requested_deprecated_apis
# 验证 CoreDNS 正常
kubectl -n kube-system get deployment coredns -o yaml | grep image
回滚方案
如果升级后出现严重问题,需要回滚。Kubernetes 不支持直接版本回滚,通常需要恢复升级前的 etcd 快照并重新安装旧版本二进制。
回滚前评估:确认是否确实需要回滚,还是可以通过修复配置解决。回滚操作本身也有风险,需要在维护窗口内执行。
# 控制面回滚(无法直接回滚,需要恢复 etcd 快照)
# 1. 停止所有控制面组件
sudo mv /etc/kubernetes/manifests/*.yaml /tmp/
# 2. 恢复旧版本二进制
sudo apt-mark unhold kubelet kubectl kubeadm
sudo apt install -y kubelet=1.28.0-1.1 kubectl=1.28.0-1.1 kubeadm=1.28.0-1.1
# 3. 恢复 etcd 快照
sudo ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-preupgrade.db \
--data-dir=/var/lib/etcd-restore
# 4. 替换数据目录并恢复 manifest
sudo mv /var/lib/etcd /var/lib/etcd.new
sudo mv /var/lib/etcd-restore /var/lib/etcd
sudo mv /tmp/*.yaml /etc/kubernetes/manifests/
# 5. 重启 kubelet
sudo systemctl restart kubelet
版本兼容矩阵详解
Kubernetes 官方版本偏差策略(Version Skew Policy)对控制面各组件的版本差有硬性规定,违反它会导致集群行为异常。升级规划的第一步就是对照这张矩阵检查目标版本组合:
| 组件 | 与 kube-apiserver 的关系 | 允许的偏差 |
|---|---|---|
| kube-apiserver | 基准组件 | 必须最先升级,其他组件以它为准 |
| kube-controller-manager / kube-scheduler / kube-proxy | 与控制面同节点运行 | 最多比 apiserver 旧一个小版本 |
| kubelet | 工作节点代理 | 最多比 apiserver 旧两个小版本(1.28 起允许落后 3 个) |
| etcd | 数据存储 | 不比 apiserver 新,最多比 apiserver 旧一个小版本 |
| kubectl | 客户端工具 | 比 apiserver 新/旧均不超过一个小版本 |
upgrade plan 只允许一次跨越一个小版本(1.28 → 1.29),这是 kubeadm 的硬性检查;而版本偏差策略描述的是"升级完成后混合版本运行期"的容忍度。两者是两个层面的规则,不要混淆。举例:集群 apiserver 为 1.29,那么工作节点 kubelet 可以暂时停留在 1.28 甚至 1.27,但新版本 1.30 的 kubelet 绝对不允许先于 apiserver 加入集群。这也是为什么标准流程必须是"先控制面、后工作节点"。
排空节点:drain 的完整语义
kubectl drain 不是简单的"把 Pod 踢走",它的执行序列值得完整理解:
- 给节点打上
unschedulable污点(NoSchedule),阻止新 Pod 调度上来 - 逐 Pod 检查是否受 PDB(PodDisruptionBudget)保护——受保护且 PDB 不满足"最小可用"时,驱逐会被拒绝
- 对可驱逐的 Pod 执行优雅终止(先发 SIGTERM,等待
terminationGracePeriodSeconds,超时才 SIGKILL) - DaemonSet 管理的 Pod 默认不驱逐(除非
--ignore-daemonsets) - 无属主副本的裸 Pod、带本地存储(emptyDir)的 Pod 默认不驱逐(除非
--delete-emptydir-data)
# 排空前检查:这个节点上的 Pod 是否都能被驱逐
kubectl get pod -n production -o wide | grep worker1
kubectl get pdb -A | grep -v "AGE"
# 注意看 MIN AVAILABLE / MAX UNAVAILABLE 字段
# 带完整参数的排空
kubectl drain worker1 \
--ignore-daemonsets \
--delete-emptydir-data \
--timeout=180s
# 排空被 PDB 卡住时的处理
# 1. 查看被拒绝的 Pod
kubectl describe pod <pod-name> | grep -A 5 "Failed to evict"
# 2. 评估:临时提高 PDB 的 maxUnavailable(维护窗口内可接受)
kubectl patch pdb my-pdb -n production --type=merge \
-p '{"spec":{"maxUnavailable":1}}'
terminationGracePeriodSeconds 设为 30-60s,应用应监听 SIGTERM 完成存量请求后退出。若应用不处理 SIGTERM,排空会变成"等待 30 秒后强杀",流量中断不可避免。升级失败处理流程
升级失败按发生阶段可分为三类,处理策略完全不同:
| 失败阶段 | 典型症状 | 处理策略 |
|---|---|---|
| 预检失败(升级前) | upgrade plan 报 unsupported version、节点 NotReady | 修复问题后重试,无风险 |
| 升级中断(执行中) | kubeadm upgrade apply 卡住或报错 | 先诊断修复,必要时重新执行 apply(幂等) |
| 升级后异常(执行完) | 组件 CrashLoop、API 不可用 | 按下方流程评估,可能触发回滚 |
升级中断的标准处理步骤
# 1. 停止一切操作,先观察(静态 Pod 会自动重启,给 2-3 分钟)
kubectl get pods -n kube-system
kubectl get nodes
# 2. 收集诊断信息
journalctl -u kubelet -n 100
kubectl get events -A --sort-by=.lastTimestamp | tail -30
crictl ps -a | grep -E "apiserver|etcd|scheduler"
# 3. 常见中断原因与处理
# 3.1 镜像拉取失败(网络问题)→ 手动拉取镜像后等待重启
crictl pull registry.k8s.io/kube-apiserver:v1.29.0
# 3.2 证书过期 → 重新生成后重启 kubelet
sudo kubeadm certs renew all
sudo systemctl restart kubelet
# 3.3 manifest 语法错误 → 检查并修正后重试
sudo kubeadm upgrade apply v1.29.0 --config /tmp/kubeadm-upgrade.yaml --force
# 4. 确认 etcd 健康(控制面升级失败最常见的原因是 etcd 未就绪)
kubectl -n kube-system exec etcd-master -- etcdctl endpoint health
# 5. 检查 etcd 集群成员(多控制面场景)
kubectl -n kube-system exec etcd-master -- etcdctl member list -w table
补充一点:如果升级中断发生在"静态 Pod 已替换但未就绪"的窗口期,kubelet 会自动尝试重启新版本组件——给它 2-3 分钟观察期是合理的,不要一看到异常就立刻手动干预,避免与 kubelet 的重启逻辑互相打架。
铁律:升级过程中出现任何异常,先停止后续步骤(不要继续升级工作节点),把控制面恢复到稳定状态,再决定继续还是回滚。
另一个容易被忽略的点:kubeadm upgrade apply 本身是幂等的——修复阻塞问题后可以原命令重跑,不需要"先降级再升级"。但重跑前务必确认上一次执行没有产生半完成的证书或 manifest 变更(kubeadm upgrade plan 重新输出应为一致的升级路径)。
回滚决策树与风险评估
K8s 不支持二进制级别的平滑降级,回滚本质上是一次"反向升级",同样伴随风险。先决策,再动手:
升级后发现严重问题?
├── 控制面组件异常(apiserver 频繁重启)?
│ ├── 是 → 评估修复成本:
│ │ ├── 配置类问题 → 修配置,不回滚
│ │ └── 版本类问题 → 恢复 etcd 快照 + 安装旧版本二进制
│ └── 否 ↓
├── 工作节点异常(NotReady、Pod 失联)?
│ ├── 单个节点 → 单独回滚该节点(重装旧版本 kubelet)
│ └── 全部节点 → 检查 kubelet 版本与 apiserver 偏差是否超限
├── 业务功能异常?
│ ├── 与 K8s 版本无关 → 查应用,不回滚
│ └── 依赖废弃 API → 迁移 API(看 apiserver 废弃日志),不回滚
└── 数据问题?
└── 必须回滚 → 恢复升级前 etcd 快照(会丢失快照之后的所有变更)
回滚风险清单
- 数据回退:恢复 etcd 快照会丢弃快照之后的所有写入——升级窗口内的业务数据可能丢失
- 存储卷兼容性:新版本 apiserver 可能升级了 CRD/存储 schema,旧版本读不回新 schema(如 CronJob 从 batch/v1beta1 迁移到 v1 后不可逆)
- 证书时效:回滚后部分证书可能不匹配,需要
kubeadm certs renew - 回滚窗口:建议在升级后 2 小时内决定是否回滚,超过 48 小时几乎不可回滚
多控制面与大规模集群升级要点
多控制面节点的升级顺序
多控制面集群(HA)的升级顺序与单节点不同,核心差异在于"第一个节点用 apply、其余节点用 upgrade node":
# 1. 第一个控制面节点
sudo kubeadm upgrade apply v1.29.0
# 2. 其余控制面节点(逐个执行)
sudo apt-mark unhold kubeadm kubelet kubectl
sudo apt install -y kubeadm=1.29.0-1.1 kubelet=1.29.0-1.1 kubectl=1.29.0-1.1
sudo apt-mark hold kubeadm kubelet kubectl
sudo kubeadm upgrade node
# 3. 等所有控制面节点就绪后,才允许开始升级工作节点
kubectl get nodes -l node-role.kubernetes.io/control-plane
# 4. 若控制面节点位于不同可用区,每个可用区各留一台最后升级,
# 避免单可用区故障时整个控制面同时不可用
大规模集群的批次规划
- 50 节点以下:一次性脚本串行升级(本文的 upgrade-workers.sh),总耗时约 30-60 分钟
- 50-200 节点:按业务分组(网关层、中间件层、业务层),每组内串行、组间留观察窗口
- 200 节点以上:引入节点池管理,按节点池滚动升级,每个池升级后运行自动化冒烟测试再继续
- 每次升级批次之间观察 10-15 分钟,重点看错误事件(
kubectl get events -A | grep Failed)与节点 Ready 状态
升级完成后的维护事项
- 更新集群版本记录(Wiki/CMDB):当前版本、升级时间、升级路径、遗留问题
- 把本次升级踩到的坑与耗时写入 SOP,作为下次升级的预估依据
- 保留升级期间的所有日志(终端输出、kubelet 日志片段)至少一个升级周期
- 检查旧版本镜像是否清理:
crictl images | grep 1.28,确认无残留占用磁盘
升级前健康基线检查
升级前记录集群健康基线,升级后对照差异——这是判断"升级是否引入问题"最客观的方法。以下检查项建议输出到文件存档:
# 健康基线快照(升级前执行,保存为 pre-upgrade.txt)
{
echo "=== 节点状态 ==="
kubectl get nodes -o wide
echo "=== 组件状态 ==="
kubectl get pods -n kube-system -o wide
echo "=== 异常 Pod(非 Running/Completed)==="
kubectl get pods -A | grep -v -E "Running|Completed"
echo "=== 容器运行时长(重启次数异常高的先处理)==="
kubectl get pods -A -o custom-columns=NS:.metadata.namespace,POD:.metadata.name,RESTARTS:.status.containerStatuses[0].restartCount | sort -k3 -n | tail -10
echo "=== 存储状态 ==="
kubectl get pv -o wide
echo "=== CRD 数量(升级后可能因版本迁移变化)==="
kubectl get crd | wc -l
} > pre-upgrade.txt
升级前必须清零的问题
- 任何节点处于 NotReady 状态(升级会放大既有问题)
- 核心组件(coredns、kube-proxy)存在 CrashLoopBackOff
- etcd 集群不健康(
endpoint health非 all healthy) - 大量 Pod 反复重启(先定位原因,而不是带病升级)
升级窗口与变更管理
技术操作之外,升级是一次变更管理事件。生产集群的升级窗口至少要覆盖以下要素:
| 要素 | 内容 | 说明 |
|---|---|---|
| 窗口时间 | 低峰期 + 预留 2 倍预期时长 | 控制面 30-60 分钟 + 节点每台 5-10 分钟 |
| 干系人 | 业务方、DB 管理员、值班人 | 业务方需知晓可能的 PDB 驱逐影响 |
| 通信渠道 | 专用群/频道 + 升级前中后三次通告 | 异常时业务方能第一时间反馈 |
| 回滚预案 | 已备份 etcd + 旧版本包可获取 | apt 缓存旧包或自建镜像仓库留存版本 |
| 停止变更 | 窗口内冻结其他变更 | 避免与发布系统、配置系统打架 |
# 升级通告模板
# 【变更通告】K8s 集群 1.28.0 → 1.29.0 升级
# 窗口:2026-08-02 02:00 - 05:00 (UTC+8)
# 影响:节点逐台排空,POD 将迁移;预计单 Pod 中断 < 2 分钟
# 风险:低(已演练 2 次);回滚:可(保留升级前 etcd 快照)
# 联系人:运维值班 @oncall
升级后的性能与稳定性回归
功能验证通过不等于升级完成,性能回归同样要纳入验收。特别是 kube-proxy 从 iptables 模式升级到 IPVS、或网络组件(CNI)随版本更新时,转发路径的变化需要量化确认:
# 1. 基础连通与延迟抽样(跨节点 Pod 间)
kubectl run perf-test --image=nicolaka/netshoot -- -c 10 -t 5 <svc-ip>:80 2>/dev/null || true
# 用 ping 抽样跨节点延迟,与升级前基线对比
kubectl exec perf-test -- ping -c 20 -q <remote-pod-ip>
# 输出 rtt min/avg/max/mdev,与升级前存档对比
# 2. 控制面 API 延迟(apiserver 响应是升级后最常劣化的指标)
kubectl get --raw "/metrics" | grep apiserver_request_duration_seconds | head -5
# 关注 apiserver_request_duration_seconds_sum/count 的 P99 变化
# 3. 节点负载对比
kubectl top nodes
# 升级后 24 小时内对比升级前基线:CPU/内存应基本持平,
# 若某节点明显升高,优先检查该节点 kubelet/kube-proxy 版本与日志
# 4. 长期观察项(升级后 1 周)
kubectl get events -A --sort-by=.lastTimestamp | grep -i -E "error|fail" | tail -20
# 废弃 API 使用量(为下个版本规划做准备)
kubectl get --raw /metrics | grep apiserver_requested_deprecated_apis | grep -v "^#"
常见错误
| 问题 | 原因 | 解决方案 |
|---|---|---|
| kubeadm upgrade plan 显示 "unsupported version" | 一次只能跳一个小版本,需要先升级到中间版本 | 分步升级,如 1.27 → 1.28 → 1.29 |
| apiserver 升级后旧版 controller-manager 异常 | 控制面组件版本必须一致或接近 | 确保所有控制面组件同时升级,不要跳过步骤 |
| 节点升级后 NotReady | kubelet 未正确启动或配置不兼容 | kubectl describe node 查看原因,journalctl -u kubelet -f 检查日志 |
| 升级后 Pod 无法调度 | 节点有污点或 kubelet 版本不匹配 | 检查 kubectl describe node | grep Taints,确认 kubelet 版本 |
| etcd 数据不兼容 | etcd 降级需要恢复备份 | 确认版本兼容性矩阵,必要时恢复升级前的 etcd 快照 |
| 排空节点超时 | 存在无法驱逐的 Pod(DaemonSet、PDB 限制) | 使用 --ignore-daemonsets --delete-emptydir-data --force,检查 PDB |
| 升级后 CoreDNS 崩溃循环 | DNS 配置与新版本不兼容 | kubectl logs -n kube-system coredns-xxx 查看日志,确认 CoreDNS 版本 |
最佳实践
- 升级前在 staging 集群验证整个流程
- 使用
--dry-run=client预检查,确认无误后再执行 - 为升级操作创建详细的 SOP 文档,包括回滚步骤和联系方式
- 升级过程中保持
kubectl get nodes -w持续监控节点状态 - 为每个工作节点设置升级间隔,避免同时排空过多节点导致服务中断
- 升级完成后运行一轮端到端测试,验证核心业务功能正常
- 保留升级前后的 etcd 快照至少 7 天,以便快速回滚
- 升级完成后更新运维文档,记录新版本的已知问题和特殊配置
- 升级前通知相关团队,避免在升级窗口内进行其他变更操作
- 为大规模集群配置节点升级并发数,避免同时排空过多节点导致服务降级
练习题
- 版本规划:假设当前集群版本为 1.27.3,目标版本为 1.30.1。列出完整的升级步骤序列(每一步的版本号),并说明为什么不能直接从 1.27 跳到 1.30。
- 自动化升级脚本:编写一个 Bash 脚本,实现单个工作节点的自动升级流程,包括:版本检查 → 排空 → 安装新版本 → 重启 kubelet → 恢复调度 → 验证。加入错误处理,任一步骤失败时回滚并输出错误信息。
- 升级监控:在升级过程中,如何使用
kubectl get events和kubectl top nodes实时监控集群健康状态?列出你认为在升级过程中需要关注的 5 个关键指标。
学习检查点
学完本章后,请检验自己是否掌握以下内容:
| 检查项 | 自测问题 | 验证方法 |
|---|---|---|
| 概念理解 | 能用自己的话解释 K8s 集群升级的控制平面和工作节点升级顺序 | 尝试向他人讲解 |
| 命令操作 | 能不查文档完成 kubeadm upgrade plan 和 apply 操作 | 在终端实际执行 |
| 原理掌握 | 能说出 K8s 集群升级的 API 兼容性和组件协调原理 | 画出流程图 |
| 故障排查 | 能独立排查集群升级后组件版本不兼容的问题 | 模拟故障并修复 |
| 最佳实践 | 能说明为什么需要在升级前进行集群健康检查和备份 | 对比不同方案 |
本章总结
集群升级应遵循"小步快跑":一次只跳一个小版本,先备份 etcd、确认集群健康,再按控制面先行、工作节点逐台排空的顺序执行,每台验证 Ready 后才继续下一台。K8s 不支持直接版本回退,回滚依赖升级前的 etcd 快照与旧版本二进制,因此保留快照至少 7 天、预留回滚窗口是升级成功的关键保障。
延伸阅读
- 6.2:Kubernetes 入门 Kubernetes 容器编排入门——集群搭建
- 6.15:HA 集群 Linux 高可用集群——多控制面节点配置
- Kubernetes 官方升级指南:https://kubernetes.io/docs/tasks/administer-cluster/cluster-upgrade/
- kubeadm 官方文档:https://kubernetes.io/docs/reference/setup-tools/kubeadm/
- Kubernetes CHANGELOG:https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/
- Kubernetes 版本偏差策略:https://kubernetes.io/releases/version-skew-policy/