华为云CLI批量改资源翻车后的回滚

举报
yd_292017662 发表于 2026/10/22 10:33:16 2026/10/22
【摘要】 我们没上 Terraform,靠华为云 CLI 和一份 state-prod.json 批量改 ECS 与 EIP。一次合并冲突把映射写乱,7 台机器公网绑定被错误改动。我把那晚的报错、恢复动作、耗时和返工后的防呆改造都记了下来。

事情失控和回滚过程

9 月 18 日我值夜班,变更脚本跑在堡垒机 s7n.xlarge.2(4 vCPU / 8 GiB),Ubuntu 22.04.4 LTS。环境我当时重新核过一遍,huaweicloud-cli 3.1.96、jq 1.6、Python 3.11.9,区域固定 cn-north-4,目标是 34 台 ECS 和 19 个 EIP 的映射对齐。脚本默认参数是 --workers 8 --interval 0 --retry 1,这个并发是我前一天自己提上去的,单次从 4 分 52 秒压到 4 分 11 秒,省了 41 秒,后面证明这 41 秒不值。

这个方案我一开始是拒绝的。

20:05 我把同事分支 feature/eip-reconcile 合到主分支,冲突文件就一个 state-prod.json,但冲突块有 11 行。我手工解冲突时把 7 条映射抄错了,典型一条是把 server_id=9f21d6... 配成了 publicip_id=6aa2bd...,正确应该是 3d7b4a...。20:11 跑 ./reconcile_eip.sh prod --workers 8 --interval 0,终端不是单一错误,是 400、409、429 交替刷。20:13 到 20:15 两分钟里日志里一共打了 126 行异常,最快一秒 9 条,基本看不出先后关系。

$ huaweicloud --version
huaweicloud-cli 3.1.96

$ ./reconcile_eip.sh prod --workers 8 --interval 0
[20:11:08] detach eip 3d7b4a.. from ecs 9f21d6..
[20:11:09] attach eip 6aa2bd.. to ecs 9f21d6..
ServiceResponseException:
  status_code: 400
  request_id: 2f7a9bb6c0d9470ab7c2a9f97f1e11a4
  error_code: ECS.0005
  error_msg: The server status does not satisfy the operation requirements.

ServiceResponseException:
  status_code: 409
  request_id: e137f0f5f4de4a5f90b8fd9a8ef26f61
  error_code: EIP.0105
  error_msg: The public IP is in use.

ServiceResponseException:
  status_code: 429
  request_id: 1b6d4d2f8f594de2a1c0d3f8a6d77e3c
  error_code: APIG.3002
  error_msg: Request throttled due to too many requests.

我当时手心是凉的。

20:14 Prometheus 上网关 5xx 从 0.3% 抬到 18.7%,支付回调和短信网关同时告警。Nginx 的 /api/pay/callback 在 20:13 到 20:35 统计到 183 次 502,P95 从 42ms 拉到 1.9s,峰值 2.6s。业务群直接问“公网是不是被你动了”,我没有回避,直接认了是我这边变更引发,先停自动流程再说。

20:19 我做过一次失败的抢救,我以为把 7 条映射改回去重跑就会自动修。那次我直接 vim state-prod.json,改完执行 ./reconcile_eip.sh prod --workers 12 --retry 3。这里我又犯了一个低级错误,workers 还从 8 提到了 12,想靠速度把窗口缩短。脚本老逻辑是“无条件 detach,再 attach”,不是幂等;第二次运行把两台已经恢复正确的 ECS 再次解绑,20:19:41 到 20:20:41 这一分钟里,APIG.3002 新增 61 次,CTS 里同一个 AK 的调用速率冲到 23 req/s。我在 20:20:47 按了 Ctrl+C,进程 PID 28741 退出码 130。

# 老逻辑关键段,问题就在这里
for pair in state:
  detach(pair.server_id)   # 不看当前绑定
  attach(pair.server_id, pair.publicip_id)

20:22 我先做冻结,crontab -l > /tmp/cron.bak 后把每 5 分钟执行的一行注释,仓库里加 .ops-freeze,CI 的 deploy job 手动 disable。三步做完 2 分钟出头。然后去 CTS 用 request_id 反查,确认调用人是堡垒机 AK,源 IP 10.23.6.14,不是外部账号误操作,这一步把方向定住了,不然会在权限和网络上白查半小时。

# 拉取实时状态,不再信任本地 state
huaweicloud ECS ListServersDetails --region cn-north-4 --limit 100 > ecs-live.json
huaweicloud VPC ListPublicips --region cn-north-4 --limit 200 > eip-live.json
python3 diff_state.py --state state-prod.json --ecs ecs-live.json --eip eip-live.json --out patch.json
python3 apply_patch.py --file patch.json --region cn-north-4 --workers 1 --interval 2 --retry 6 --retry-backoff 8

diff_state.py 我当场补了两个参数校验,不传 region 就直接退出码 17,资源数量和目标不一致就退出码 19。patch.json 最后只生成 7 条修复,按顺序串行打。第 4 条又撞 ECS.0005,我查实例详情是 REBOOT,那台机在系统盘扩容后的重启窗口。我把重试从 --retry 1 改成 --retry 6 --retry-backoff 8,实际重试 4 次,睡眠 8+16+32+40 秒,共等了 96 秒,第 5 次 attach 成功。21:02 全部映射回正,从 20:14 告警出现到恢复 48 分钟。那晚我临时新建 3 个按量 EIP 做冒烟和切流,规格 5M 共享带宽,账单是 1.74 元;短信补发 230 条,多 0.46 元。

返工后我改了什么和还没做完的事

返工我没再写“改了一下”,每一条都落成代码。状态文件拆成 desired-state.json 和 live-state.json,仓库只存前者;后者每次执行前现拉,且脚本里加了只读校验,发现 live 文件有 Git 变更就终止,退出码 23,报错写死 LIVE_STATE_MUTATED。状态文件挪到 OBS 桶 ops-state-cn-north-4,版本控制打开,生命周期 30 天。我查了 9 月账单,这部分 0.18 元。

{
  "version": 3,
  "region": "cn-north-4",
  "generated_at": "2026-09-18T21:10:44+08:00",
  "resources": 34,
  "max_change": 2,
  "sha256": "9f4c8d..."
}

入口也改了,从一把梭变两阶段。plan 只出计划,不做真实解绑;apply 必须带审批哈希,哈希不匹配直接退出码 31。命令从 ./reconcile_eip.sh prod 变成:

python3 reconcile.py plan  --desired desired-state.json --region cn-north-4 --max-change 2 --out plan-20260918.json
python3 reconcile.py apply --plan plan-20260918.json --approve 6b7d9f --workers 1 --interval 2

我还把幂等补齐了。apply 前会先查 live 绑定,current_publicip_id == target_publicip_id 就记一条 SKIP_ALREADY_MATCHED,不会再 detach。单次计划里如果 detach_count > 2 直接失败,错误文本固定成 EIP_CHANGE_GUARD: planned detach 3 exceeds max_change 2。这个报错是给值班看的,避免他们把 guard 误解成接口抖动。

并发从 8 降到 1,平均执行时长从 4 分 12 秒涨到 5 分 03 秒,慢了 51 秒,但过去三周跑了 9 次,没有再出现误解绑。CI 里我补了两个 gate:资源数量不等于 34 拒绝合并,sha256 不匹配拒绝部署;这两个 gate 分别在 9 月 26 日和 10 月 2 日拦过一次错误提交,没再进生产。

还没解决的是互斥锁,现在两个人同时在堡垒机执行还是会打架;我下周准备把锁放到 DCS Redis,用 SET ops:eip:lock $HOSTNAME:$PID NX PX 600000,再加 fencing token,锁过期后旧进程继续写的问题我还没验证完。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。