云资源销毁为什么要逆序:一次依赖反转的清理设计
云资源销毁为什么要逆序:一次依赖反转的清理设计
引子
创建云资源时,顺序通常是“网络 → 安全组 → 计算 → 存储”,因为有依赖关系:实例要挂在子网里,子网要属于 VPC。但销毁时如果照搬创建顺序,往往会失败——子网里还有实例、安全组还被引用、磁盘还挂着。正确的做法是按依赖关系逆序销毁。
一、依赖图:先把关系画清楚
把资源看成有向图:A 依赖 B,就画一条 A → B 的边。销毁顺序应当是“没有出边”的资源先删,也就是拓扑排序的逆序。
VPC
└── Subnet
└── ECS ── EVS
└── EIP
SecurityGroup ── ECS
销毁顺序示例:EIP → ECS(含解绑)→ EVS → SecurityGroup → Subnet → VPC。
如果直接先删 VPC,会收到“资源仍在使用中”的报错;很多脚本在这里用“强制删除”绕过,结果留下孤儿资源持续计费。
二、先解绑,再删除
不少资源之间是绑定关系而非父子关系,例如 EIP 绑定 ECS、磁盘挂载到实例、网卡挂到实例。删除前必须先解绑:
unbind_eip(instance)
detach_volume(volume, instance)
delete_instance(instance)
顺序错了会出现两类问题:
- 删除失败:资源被占用;
- 隐式删除:某些平台删除实例时会连带释放绑定资源,导致误删共享资源。
因此要明确哪些是“独占资源”(可随实例释放),哪些是“共享资源”(必须显式保留)。
三、清理脚本的三层保护
1. 计划预览(Dry Run)
先输出“将要删除什么、按什么顺序”,人工确认后再执行:
plan = build_destroy_plan(resources)
print_plan(plan) # 仅打印,不执行
execute(plan) if confirm else None
2. 资源归属校验
只删除本次创建、且带有明确标签的资源,避免误删同账号下其他业务:
if resource.tags.get("project") != project_id:
skip(resource)
3. 幂等与容错
删除操作本身应当幂等:资源不存在视为成功;删除中状态要轮询等待,而不是立即重试。
if not exists(resource):
return OK
delete(resource)
wait_until(lambda: not exists(resource), timeout=600)
四、常见坑与处理
- 删除是异步的:接口返回成功不代表已删完,必须轮询状态;
- 依赖是隐式的:安全组规则、路由表关联、终端节点等都可能阻止删除;
- 计费资源残留:EIP、磁盘、快照、负载均衡最容易遗留;
- 并发删除:并行删同一层资源可以提速,但跨层必须串行;
- 失败中断:脚本中断后要能从“剩余资源”继续,而不是从头再来。
五、把销毁做成可重入流程
推荐的做法是:每一轮都重新扫描“现存资源”,计算当前可删除集合,删除后再次扫描,直到清空或达到上限:
for round in range(20):
remaining = list_resources(project)
if not remaining:
return SUCCESS
ready = [r for r in remaining if no_dependents(r)]
for r in ready:
delete(r)
sleep(10)
return TIMEOUT
这种“扫描—计算—删除”的循环天然可重入:中途失败,下次运行会自动从当前状态继续,不需要记录复杂的进度。
六、小结
云资源销毁的核心不是“删得快”,而是“删得干净且不误伤”:
- 按依赖关系逆序销毁;
- 先解绑后删除,区分独占与共享资源;
- 用 Dry Run、标签校验、幂等与轮询构建三层保护;
- 用可重入的扫描循环替代一次性脚本。
把清理当成与创建同等重要的工程能力,才能真正做到“用完即走、不留账单”。
- 点赞
- 收藏
- 关注作者
评论(0)