前几天帮一个朋友排查问题,他哭丧着脸说“我删不掉自己创建的S3桶了”。问了半天搞清楚,他写Pulumi脚本创建桶的时候,随手开了个“防止删除”的开关,后来这个桶没用了,怎么删都删不掉——他试了阿里云控制台删,提示有保护;试Pulumi命令删,也报错;甚至想直接删Pulumi状态文件,又怕搞坏整个项目。
一、从一个“删不掉的桶”说起
朋友当时在做一个测试项目,用Pulumi写代码创建S3桶存运行日志,写完代码就顺手把控制删除的开关开了,觉得这样以后不会误删这个桶。后来项目功能迭代后,这个测试日志桶早就没用了,他想一次性删掉所有资源释放空间,结果这个S3桶成了拦路虎。他试了各种常规方法都没用,就卡在这了,甚至差点想重新搭整个项目环境。
二、DeletionProtection到底是啥?
你可以把Pulumi管理的云资源想象成自己的柜子:DeletionProtection就像给这个柜子装了个密码锁的外罩——平时没解锁的话,别人或者Pulumi想直接把整个柜子抱走(删除资源)是不行的,得先输密码(关闭保护)才行。这个功能的核心初衷是防止开发者手滑删错重要资源,比如把生产环境的桶误删,所以本质是个“安全闸”,不是坑,是有用的。
2.1 它的作用原理
当你给某个云资源(比如S3桶、阿里云OSS、AWS EC2实例)开启DeletionProtection后,Pulumi会同步两个地方的状态:一是自己记录的项目状态文件,二是云服务商那边的资源配置。任何涉及删除该资源的操作,都会先检查这个开关,要是没关,就会直接拦截操作,返回“无法删除”的报错。
2.2 踩坑的真实案例
朋友踩坑的代码很简单,他创建S3桶的时候,随手加了deletion_protection=True,这段代码运行后,Pulumi就把这个桶的保护开关开到了AWS那边。后来他执行pulumi destroy删项目时,Pulumi检测到这个桶的保护状态,直接弹出报错:“Cannot delete test-log-bucket because deletion protection is enabled”,连带着整个项目的资源都没法删了。
技术栈:Pulumi + Python 误开删除保护的示例代码:
import pulumi
import pulumi_aws as aws
# 创建S3桶并开启删除保护
test_log_bucket = aws.s3.Bucket("test-log-bucket",
deletion_protection=True, # 随手开启的删除保护,后来忘了
tags={"Name": "test-log-bucket", "env": "test"})
# 输出桶名方便后续查看和排查
pulumi.export("target_bucket", test_log_bucket.bucket)
三、破解“删不了”僵局的两种方法
既然坑是因为保护开关没关,那破解的核心就是先关掉保护,再操作删除。这里有两种常用方法,按需选用:
3.1 先关保护再正常删除(推荐)
这是最稳妥的方法,不会打乱Pulumi的状态,也不会留下后续隐患。步骤是先修改代码关掉保护,同步到云服务商,再执行删除。 修改后的代码示例:
import pulumi
import pulumi_aws as aws
# 修改:将删除保护从True改为False,准备删除
test_log_bucket = aws.s3.Bucket("test-log-bucket",
deletion_protection=False, # 关键修改:关闭保护
tags={"Name": "test-log-bucket", "env": "test"})
pulumi.export("target_bucket", test_log_bucket.bucket)
操作步骤:
- 把旧代码替换成上面的修改版本,保存;
- 运行
pulumi up命令,Pulumi会自动检测到桶的配置变化,提示“更新test-log-bucket的deletion_protection从True到False”,输入yes确认; - 等更新完成后,保护就已经在AWS侧关掉了,这时候运行
pulumi destroy,Pulumi就能顺利删掉这个桶和项目里其他所有资源。 这里要注意顺序:必须先关保护、同步状态,再执行删除,要是跳过同步直接destroy,Pulumi还是会用之前的保护状态拦截操作。
3.2 强制删除绕开保护(紧急情况用)
要是已经等不及要删资源,或者Pulumi状态已经乱了,也可以用这两个临时方案:
第一个是手动在云服务商控制台删除,比如去AWS S3控制台找到目标桶,手动删除。但删完后必须运行pulumi refresh命令,这个命令会把Pulumi记录的状态和AWS实际资源对上,把已经删除的桶从Pulumi状态里删掉,不然下次创建同名资源会报错,Pulumi还会继续尝试删除已经没了的桶,导致后续混乱。
第二个是用Pulumi的--force参数,比如运行pulumi destroy --force,但这个参数对大部分云资源的删除保护没用,还是得先确认保护开关关闭,所以只适合资源已经从云侧删除,Pulumi状态还没同步的情况。
四、避坑指南:优缺点和注意事项
DeletionProtection不是坏功能,只是用的时候要懂分寸: 优点:确实能防误删,尤其是项目刚上线的阶段,临时测试资源开保护,万一有人手滑删错,能及时止损。 缺点:灵活性差,一旦确定要删除,就必须多一步关保护的操作,而且开关藏在代码的某个参数里,很容易忘,等删的时候才发现,陷入僵局。 注意事项:
- 开保护前先想:这个资源是长期用还是临时测试?临时用的别开,省得删的时候麻烦;
- 给资源加明确的标签,比如加
need_protection: yes/no,排查的时候一目了然,朋友后来给所有资源都加了这个标签,删的时候专门筛掉不需要保护的,再也没卡过; - 手动删云资源后,一定要执行
pulumi refresh同步状态,这是避免状态混乱的关键; - 要是项目资源多,定期(比如每周)检查一次Pulumi代码,把已经没用的资源的保护关掉,提前规划资源生命周期。
五、总结
那个朋友最后用了先关保护再删除的方法,顺利解决了问题。这个坑本质是“随手设置的参数”导致的,不是Pulumi的bug——很多开发者写代码的时候,只顾着实现功能,不会留意这类安全开关,直到要删的时候才后悔。用Pulumi的时候,除了写核心功能代码,还要多关注资源的生命周期配置:开保护要想好什么时候关,删之前确认所有资源的状态,遇到删不掉的情况先找保护开关,别慌。只要提前规划好,就能避开这个常见陷阱,高效管理云资源。
评论
围绕“Pulumi 资源删除保护机制的应用陷阱:误开启 DeletionProtection 后无人能删的僵局破解”参与讨论