用 ARC Zonal Shift 做一次 72 小时可用区撤离演练

2026-10-01 30 预计阅读时间: 1 分钟
来源: aws.amazon.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:12 分钟

多可用区部署并不等于已经验证过可用区故障。真正的风险往往藏在剩余容量、连接重试、DNS 缓存、Pod 拓扑约束和数据库故障转移之后。一次持续 48~72 小时的可用区撤离演练,可以覆盖扩缩容、定时任务、发布、备份和流量高峰,比十几分钟的故障测试更容易暴露架构缺口。

AWS Application Recovery Controller(ARC)的 Zonal Shift 可以把受支持资源的流量临时移出指定 Availability Zone。它不会销毁实例,也不是完整的断电模拟,但非常适合验证 Amazon ECS、Amazon EKS、Amazon RDS for PostgreSQL 和 Amazon Aurora PostgreSQL 在失去一个可用区后能否继续服务。

演练前先确认两个事实

第一,Zonal Shift 操作的是 ARC 当前支持并识别的资源,而不是任意 ECS 服务、EKS Pod 或数据库 ARN。负载均衡场景通常需要对 ARC 列出的负载均衡资源执行操作;数据库资源的具体行为则取决于引擎、拓扑和服务支持情况。

运行下面的命令,把 ARC 当前可管理的资源作为事实来源:

export AWS_REGION=us-east-1

aws arc-zonal-shift list-managed-resources \
  --region "$AWS_REGION" \
  --output table

如果预期资源没有出现在结果中,不要手工猜 ARN 后直接演练。应先检查区域、资源类型、负载均衡或数据库配置,以及对应服务是否已启用 Zonal Shift 支持。

第二,撤离一个可用区后,剩余可用区必须有足够容量。建议在演练前逐项确认:

  • ECS 服务在至少两个可用区拥有可调度的容器实例或 Fargate 子网。
  • EKS 节点组、Pod 反亲和性、拓扑分布约束和 PodDisruptionBudget 不会阻止重新调度。
  • 剩余可用区能够承载峰值流量,而不是只够处理平均流量。
  • RDS PostgreSQL 或 Aurora PostgreSQL 已配置合适的多可用区拓扑。
  • 应用使用数据库端点而不是固定 IP,并能处理短暂断连、DNS 更新和事务重试。
  • 运维角色具备 StartZonalShift、UpdateZonalShift、CancelZonalShift、ListManagedResources 和 ListZonalShifts 等必要权限。

还要注意,可用区名称是账户相关的。跨账户协同演练时,应先用 AZ ID 对齐物理可用区,再映射到各账户中的 us-east-1a 一类名称。

把 72 小时演练拆成阶段

不要在没有基线数据的情况下直接开始计时。更稳妥的节奏是:

阶段 建议时长 关注内容
基线采集 30~60 分钟 请求量、错误率、延迟、任务数、Pod 数、数据库连接和复制延迟
启动撤离 15~30 分钟 流量是否离开目标 AZ,是否发生错误尖峰
稳态运行 48~72 小时 高峰流量、自动扩缩容、发布、批处理、备份和节点替换
恢复接入 30~60 分钟 被撤离 AZ 的容量与健康状态,流量回流后的错误和延迟
复盘 演练后 容量缺口、告警盲区、人工步骤和恢复时间

Zonal Shift 是临时操作,必须设置过期时间。48~72 小时的演练应记录 shift ID,并安排负责人检查过期时间,避免操作在无人关注时自动结束。

可复制的启动、续期与取消命令

下面的脚本假设已经安装 AWS CLI v2 和 jq,并且资源出现在 list-managed-resources 的结果中。运行前需要替换区域、可用区和资源 ARN。

#!/usr/bin/env bash
set -euo pipefail

export AWS_REGION="us-east-1"
export AWAY_FROM_AZ="us-east-1a"
export RESOURCE_ARN="arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/app/example/0123456789abcdef"

aws arc-zonal-shift start-zonal-shift \
  --region "$AWS_REGION" \
  --away-from "$AWAY_FROM_AZ" \
  --resource-identifier "$RESOURCE_ARN" \
  --expires-in 72h \
  --comment "72-hour AZ evacuation drill" \
  > zonal-shift.json

SHIFT_ID=$(jq -r '.zonalShiftId' zonal-shift.json)
echo "Started zonal shift: $SHIFT_ID"

aws arc-zonal-shift list-zonal-shifts \
  --region "$AWS_REGION" \
  --output table

如果演练窗口需要延长,可以在原操作过期前更新它:

AWS_REGION="us-east-1"
SHIFT_ID="replace-with-zonal-shift-id"

aws arc-zonal-shift update-zonal-shift \
  --region "$AWS_REGION" \
  --zonal-shift-id "$SHIFT_ID" \
  --expires-in 72h \
  --comment "Extend drill after capacity review"

需要提前终止时,不要等待自动过期:

AWS_REGION="us-east-1"
SHIFT_ID="replace-with-zonal-shift-id"

aws arc-zonal-shift cancel-zonal-shift \
  --region "$AWS_REGION" \
  --zonal-shift-id "$SHIFT_ID" \
  --comment "Cancel drill and restore normal routing"

如果应用由多个 ARC 托管资源共同承载,应为每个资源记录独立的 shift ID。不要把启动命令塞进无人值守的循环;每次操作后都应验证流量、容量和数据库状态,再继续下一个资源。

ECS、EKS 和 PostgreSQL 分别看什么

ECS:任务还在运行,不代表服务仍有容量

重点观察服务的 RunningTaskCount、PendingTaskCount、部署状态,以及负载均衡器的健康目标数。若容量提供者或 EC2 Auto Scaling Group 在各 AZ 分布不均,任务可能长期处于 Pending。使用 Fargate 时,也要确认服务子网覆盖剩余 AZ。

建议同时检查:

  • ALB/NLB 的 HealthyHostCount 和 UnHealthyHostCount。
  • TargetResponseTime、目标 5xx 和连接重置。
  • ECS CPU、内存预留率以及扩容是否成功。
  • 发布期间新旧任务是否都能在剩余 AZ 放置。

EKS:验证的是调度链路,不只是入口流量

入口流量离开一个 AZ 后,已有 Pod 可能仍留在该 AZ。若演练目标包括计算层撤离,可以在经过批准后配合节点隔离或受控驱逐,但这属于额外故障注入,不是 Zonal Shift 本身的行为。

先用只读命令确认分布:

kubectl get nodes -L topology.kubernetes.io/zone
kubectl get pods -A -o wide
kubectl get pdb -A
kubectl get events -A --sort-by=.lastTimestamp | tail -n 50

需要特别关注不可满足的 topology spread constraints、过严的反亲和性、单 AZ 持久卷,以及剩余节点组扩容失败。不要为了让演练通过而临时删除 PodDisruptionBudget;这通常说明生产拓扑本身需要调整。

RDS PostgreSQL 与 Aurora PostgreSQL:把重连当作核心测试项

数据库侧不能只盯着实例是否可用。应用连接池可能保留失效连接,DNS 缓存可能延迟端点更新,长事务也可能放大切换影响。

至少记录以下指标:

  • DatabaseConnections、CPUUtilization 和 FreeableMemory。
  • ReadLatency、WriteLatency、磁盘队列和事务错误率。
  • Aurora 副本延迟,以及 writer、reader 角色变化。
  • 应用端连接超时、重连次数、事务回滚和 p95/p99 延迟。

数据库资源对 Zonal Shift 的响应语义可能不同于负载均衡器,因此应以 list-managed-resources、实际数据库拓扑和当前 AWS 服务支持为准。演练前还应确认客户端重试具有指数退避和随机抖动,避免切换时形成重连风暴。

观测与止损条件必须提前写好

持续多天的演练不能依赖某个人一直盯着仪表盘。应为以下信号设置告警:

  • 业务成功率低于既定 SLO。
  • p99 延迟持续超过基线阈值。
  • 剩余 AZ 的 CPU、内存、连接数或目标容量超过安全水位。
  • ECS Pending 任务或 EKS Pending Pod 持续增加。
  • 数据库连接耗尽、复制延迟持续上升或发生不可接受的事务失败。
  • 无法在预定时间内扩容,或者另一个 AZ 同时出现异常。

止损条件应是可执行的,例如:错误率连续 10 分钟超过 2%,或剩余容量连续 15 分钟高于 80% 时立即取消 shift。阈值需要按照实际 SLO 和容量模型调整,不能照搬示例。

可用一个简单的外部探针持续记录用户路径:

while true; do
  timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ)
  result=$(curl -sS -o /dev/null \
    -w 'status=%{http_code} total=%{time_total}' \
    --connect-timeout 3 \
    --max-time 10 \
    https://api.example.com/health || echo 'request_failed')
  echo "$timestamp $result"
  sleep 30
done | tee az-drill-canary.log

运行前应把地址改成能覆盖真实依赖的轻量级业务探针,而不是只返回固定文本的进程存活接口。

恢复不是简单执行 cancel

取消 Zonal Shift 前,先确认被撤离 AZ 中的目标、节点和数据库组件已经健康,并且容量足以接收流量。最好选择低流量时段恢复,然后执行取消命令,持续观察至少一个完整的扩缩容和部署周期。

恢复清单可以保持简短但明确:

  1. 确认目标 AZ 的计算、网络和数据库健康检查通过。
  2. 检查 ECS 任务、EKS 节点和 Pod 是否达到预期分布。
  3. 确认数据库副本延迟和连接状态恢复正常。
  4. 取消每一个已记录的 zonal shift。
  5. 验证流量回流、错误率、延迟和目标健康数。
  6. 导出演练时间线、告警、人工操作和容量曲线。

一次成功演练不应只得到“系统没有宕机”的结论。更有价值的产物是明确的剩余容量下限、可验证的数据库重试策略、自动化的停止条件,以及下一次可以直接复用的运行手册。ARC Zonal Shift 提供了撤离开关,但多可用区架构是否真的可靠,仍取决于调度、容量、客户端恢复能力和持续观测是否形成闭环。


相关推荐