Amazon EKS 新增了 Kubernetes 版本回滚能力:集群控制平面升级后,如果出现兼容性或稳定性问题,团队可以在 7 天内退回升级前的 Kubernetes 版本。这项能力降低了原地升级的恢复成本,但它不是跳过测试、备份和工作负载验证的理由。
回滚窗口改变了什么
过去,托管 Kubernetes 的控制平面版本升级通常被视为单向操作。应用、准入控制器或平台组件一旦在新版本下出现问题,团队往往需要修复兼容性问题,或者把工作负载迁移到另一套集群。
EKS 提供 7 天回滚窗口后,升级流程多了一条快速恢复路径。它尤其适合处理这些情况:
- 控制器依赖的 Kubernetes API 行为发生变化;
- admission webhook 在新版本中超时或拒绝请求;
- 网络、存储或可观测性组件升级后表现异常;
- 生产流量暴露了预发布环境未覆盖的问题。
需要注意的是,摘要明确提到的是集群控制平面版本回滚。不要据此假设节点组、插件、CRD、应用数据库或升级期间修改的资源也会自动恢复。控制平面回到旧版本,不等于整个系统回到升级前的状态。
把 7 天当成故障预算,而不是观察周期
七天看似充裕,但生产问题经常具有延迟性:定时任务可能每周才执行一次,证书轮换、节点扩缩容和故障转移也未必会在升级当天触发。因此,升级后的验证应集中在前几个小时完成,并明确设置“继续观察”与“立即回滚”的边界。
可以为升级建立以下门槛:
| 阶段 | 建议检查项 | 失败后的动作 |
|---|---|---|
| 升级前 | API 弃用、插件兼容性、节点版本、备份状态 | 阻止升级 |
| 升级后 30 分钟 | Pod、节点、系统组件、Webhook、核心接口 | 评估立即回滚 |
| 升级后 24 小时 | 错误率、延迟、扩缩容、批处理任务 | 修复或回滚 |
| 窗口关闭前 | 遗留告警和业务验收 | 明确接受新版本风险 |
回滚决策最好由指标驱动。例如,当关键接口错误率持续超过阈值、集群级控制器无法完成 reconcile,或者新 Pod 无法稳定调度时,不要把大部分窗口消耗在没有明确截止时间的排查上。
可以这样实践:保存升级基线并执行健康检查
下面的脚本不会发起升级或回滚。它使用 AWS CLI 和 kubectl 保存集群版本与运行状态,可直接改造成 CI/CD 流水线的升级前后检查。运行前需要配置 AWS 凭证,并把 CLUSTER_NAME 和 AWS_REGION 改成实际值。
#!/usr/bin/env bash
set -euo pipefail
CLUSTER_NAME="my-eks-cluster"
AWS_REGION="ap-southeast-1"
SNAPSHOT_DIR="eks-upgrade-snapshot-$(date -u +%Y%m%dT%H%M%SZ)"
mkdir -p "$SNAPSHOT_DIR"
aws eks describe-cluster \
--name "$CLUSTER_NAME" \
--region "$AWS_REGION" \
--output json > "$SNAPSHOT_DIR/cluster.json"
aws eks list-addons \
--cluster-name "$CLUSTER_NAME" \
--region "$AWS_REGION" \
--output json > "$SNAPSHOT_DIR/addons.json"
aws eks list-nodegroups \
--cluster-name "$CLUSTER_NAME" \
--region "$AWS_REGION" \
--output json > "$SNAPSHOT_DIR/nodegroups.json"
aws eks update-kubeconfig \
--name "$CLUSTER_NAME" \
--region "$AWS_REGION"
kubectl version -o yaml > "$SNAPSHOT_DIR/kubernetes-version.yaml"
kubectl get nodes -o wide > "$SNAPSHOT_DIR/nodes.txt"
kubectl get pods -A -o wide > "$SNAPSHOT_DIR/pods.txt"
kubectl get events -A --sort-by=.lastTimestamp > "$SNAPSHOT_DIR/events.txt"
kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations \
-o yaml > "$SNAPSHOT_DIR/webhooks.yaml"
if ! kubectl wait --for=condition=Ready nodes --all --timeout=120s; then
echo "ERROR: one or more nodes are not Ready" >&2
exit 1
fi
FAILED_PODS=$(kubectl get pods -A \
--field-selector=status.phase!=Running,status.phase!=Succeeded \
--no-headers 2>/dev/null | wc -l | tr -d ' ')
if [ "$FAILED_PODS" -gt 0 ]; then
echo "ERROR: found $FAILED_PODS pods outside Running/Succeeded states" >&2
exit 1
fi
echo "Health checks passed. Snapshot: $SNAPSHOT_DIR"
这个示例中的 Pod 判断比较严格,生产环境可能存在正常的 Pending Job 或已知异常 Pod。可以改为检查指定命名空间,或维护允许列表,避免无关工作负载阻塞升级。
升级前后分别执行一次脚本,并把输出作为流水线制品保存。比较 cluster.json、插件清单、事件和 Webhook 配置,通常比只看控制平面版本更容易定位回归。
回滚时不要遗漏数据面
来源摘要没有给出具体的回滚 API、CLI 参数或控制台步骤,因此不应凭空构造命令。实际操作时,应使用当前区域和集群页面中 EKS 提供的受支持回滚入口,并在执行前核对目标版本、7 天截止时间以及 AWS 返回的前置条件。
控制平面回滚后,还需要逐项确认:
- 托管节点组和自管节点的 kubelet 版本是否仍在支持范围内;
- VPC CNI、CoreDNS、kube-proxy 等插件是否兼容回滚后的版本;
- 升级期间应用的 CRD 和对象是否仍能被旧版本 API 正确读取;
- Webhook、Operator 和 GitOps 控制器是否恢复正常 reconcile;
- 业务数据库、消息队列和外部状态是否需要独立恢复。
尤其要避免在回滚窗口内删除旧 API 仍然依赖的数据,或者同时进行节点、插件和控制平面的多层升级。变更叠加后,即使控制平面能够回滚,也很难判断故障来自哪一层。
采用建议
把新能力接入现有升级机制时,可以从一套简单规则开始:升级前记录基线,升级后立即运行自动化检查,为关键指标设置回滚阈值,并在变更单中记录 7 天窗口的准确截止时间。大规模平台还应先升级低风险集群,再逐步推进到生产集群。
EKS 的版本回滚能力缩短了控制平面升级失败后的恢复路径,却无法替代兼容性测试、备份和多集群容灾。最稳妥的做法,是把它视为升级流程中的紧急制动器,而不是恢复整个 Kubernetes 平台状态的万能撤销按钮。