
集群升级前的核对清单把生产环境的 Kubernetes 集群大版本升级例如从 1.28 升级到 1.30是所有云原生运维团队每年最头疼的硬仗。很多团队以为在测试环境点一下控制台升级成功了就万事大吉结果一到生产环境升级 API Server 或 Drain 节点时故障瞬间爆发有的应用因为调用了已被移除的v1beta1API 直接丢失了控制器有的节点因为 PodDisruptionBudget (PDB) 设置过于严格导致 Drain 命令无限期卡死甚至引发集群脑裂。集群升级绝不是简单的执行kubeadm upgrade apply命令。升级前必须逐项核验 API 弃用契约、PDB 约束死锁并构建按节点池分流的金丝雀升级与自动止损机制。弃用 API 扫描别让废弃 Group/Version 成为线上隐形炸弹Kubernetes 在版本演进过程中会定期移除老旧的 API 组如extensions/v1beta1、autoscaling/v2beta2。如果你的 GitOps 仓库或 Helm Chart 中依然残留着这些 API 声明一旦 Control Plane 升级到新版本旧 API 端点被彻底关闭ArgoCD 或 kubectl 将再也无法解析这些 Manifest导致应用无法变更或部署直接报错。升级前的第一项确认就是利用确定性扫描工具如 Pluto 或 Kubent对集群内运行的所有 live 资源以及 GitOps 仓库中的静态 Manifest 进行全量扫描。PDB 死锁陷阱为什么kubectl drain永远卡在 99%第二项极其致命但经常被忽略的确认是PodDisruptionBudget (PDB) 配置冲突。运维人员在升级 Node 节点前必须对 Node 执行kubectl drain --ignore-daemonsets驱逐 Pod。如果某个核心业务仅部署了 2 个 Replicas但开发团队配置了minAvailable: 2的 PDB 规则或者配置了maxUnavailable: 0apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: critical-service-pdb spec: minAvailable: 2 # 致命陷阱集群中总共只有 2 个 PodDrain 时禁止任何 1 个 Pod 离线 selector: matchLabels: app: critical-service在执行 Drain 时K8s Eviction API 发现驱逐任何一个 Pod 都会破坏 PDB 规则于是 Drain 命令被无期限阻塞。如果自动化升级脚本没有设置 Timeout升级进程将卡在半山腰进而导致后续节点无法继续升级造成集群状态不一致。金丝雀节点池升级与 PodReady 自动回滚策略集群 Node 节点的升级绝对不能“一轰而上”。必须采用金丝雀节点池 (Canary Node Pool)逐批递进的方式进行。先挑选 1-2 台非核心 Node 作为金丝雀节点执行 CNI/Kubelet 升级与节点重构。随后引入自动化健康度巡检如果在金丝雀节点上调度运行的应用连续 10 分钟出现Unhealthy或CrashLoopBackOff自动化升级控制面必须立即暂停并将该节点设置为NoSchedule触发回滚流程。生产级升级巡检与节点驱逐 Bash 脚本为了实现上述确认逻辑的自动化在升压控制脚本中必须包含确定性的预检与安全 Drain 逻辑。以下是生产环境集群升级预检 Bash 脚本示例#!/usr/bin/env bash set -euo pipefail TARGET_K8S_VERSIONv1.30.0 LOG_PREFIX[K8s-Upgrade-Precheck] echo ${LOG_PREFIX} 1. 正在使用 Pluto 扫描静态 Helm/GitOps 部署清单... if ! pluto detect-files -d ./deployments --target-versions k8s${TARGET_K8S_VERSION} | grep -q No deprecated APIs found; then echo ${LOG_PREFIX} ERROR: 发现当前部署清单中存在与 ${TARGET_K8S_VERSION} 不兼容的废弃 API阻断升级 exit 1 fi echo ${LOG_PREFIX} 2. 正在检查集群内冲突的 PDB 策略... # 提取 minAvailable 等于 replicas 导致永远无法 Drain 的潜在危险 PDB BLOCKING_PDBS$(kubectl get pdb -A -o json | jq -r .items[] | select(.status.disruptionsAllowed 0) | \(.metadata.namespace)/\(.metadata.name) ) if [ -n ${BLOCKING_PDBS} ]; then echo ${LOG_PREFIX} WARNING: 以下 PDB 当前允许的中断数为 0 (DisruptionsAllowed0)Drain 节点时将被卡死 echo ${BLOCKING_PDBS} echo ${LOG_PREFIX} 请先修正上述 PDB 的 minAvailable/maxUnavailable 设置后再试。 exit 1 fi echo ${LOG_PREFIX} 3. 正在安全驱逐金丝雀节点 (Canary Node)... CANARY_NODEnode-prod-canary-01 # 标记节点不可调度 kubectl cordon ${CANARY_NODE} # 执行带超时保护的 Drain if ! kubectl drain ${CANARY_NODE} \ --ignore-daemonsets \ --delete-emptydir-data \ --grace-period30 \ --timeout300s; then echo ${LOG_PREFIX} ERROR: Node ${CANARY_NODE} Drain 失败触发超时保护取消升级 kubectl uncordon ${CANARY_NODE} exit 1 fi echo ${LOG_PREFIX} 金丝雀节点预检与驱逐成功允许进入 Kubelet 升级阶段。核心升级验证命令汇总在进行集群大版本升级的前中后各个阶段运维架构师需要熟练掌握以下 CLI 排障命令# 检查 API Server 暴露的废弃 API 审计指标 kubectl get --raw /metrics | grep apiserver_requested_deprecated_apis # 查看特定节点的 Pod 驱逐阻止日志 kubectl get events -n default --field-selector reasonFailedToEvictPod # 查看金丝雀节点上的 Kubelet 服务日志 journalctl -u kubelet -n 100 --no-pager | grep -i error # 一键解除节点 Cordon 锁定紧急回滚时使用 kubectl uncordon -l node-role.kubernetes.io/workertrue把 Kubernetes 集群升级看作是一项严密的安全手术。在正式替换二进制组件前把 API 废弃检测、PDB 死锁拦截和金丝雀自动回滚这三把锁锁紧才能做到万无一失。