从 Pulumi 程序中删除一个资源,通常也会删除底层云基础设施:这正是期望状态模型的作用。但有时你想要相反的结果——让 Pulumi 停止管理某项资源,同时让真实资源保持不变。
常见原因包括:将资源移交给另一个团队的堆栈;撤销一次过早进行的 pulumi import;或者退役一个项目,但它创建的数据库或 DNS 区域仍在其他地方提供服务。
Pulumi 用两种互补工具支持这一需求:pulumi state delete 适用于一次性的交互式移除;retainOnDelete 资源选项,适用于希望写进程序、并在 CI 中安全重复执行的变更。两者都让云资源保持原样,只改变 Pulumi 跟踪的内容。
这是“导入资源”的反向操作:导入将现有基础设施纳入 Pulumi 管理。它也不同于在工具外部删除资源后,再将状态与实际情况协调一致;后一种情况,请参考漂移检测和 pulumi refresh。
使用 pulumi state delete 移除资源
要立即从命令行移除堆栈状态中的单个资源,先找到它的 URN,然后传给 pulumi state delete:
$ pulumi stack --show-urns
$ pulumi state delete 'urn:pulumi:prod::my-project::aws:s3/bucket:Bucket::my-bucket'
pulumi state delete 只编辑状态文件,不会调用资源提供方,因此 AWS 中的存储桶仍然存在,只是 Pulumi 不再记得它。移除完成后,还要从程序中删除相应资源声明,以免后续执行 pulumi up 时尝试重新创建它。
默认存在两项保护措施。
依赖资源。 如果其他资源依赖于目标资源,或者以它为父资源,Pulumi 会拒绝移除。否则,这些依赖资源就会继续引用一个状态已不再跟踪的资源:
error: urn:...::demo-pet can't be safely deleted because the following resources depend on it:
* "demo-password" (urn:...::demo-password)
Delete those resources first or pass --target-dependents.
可以传入 --target-dependents,在一次操作中移除目标资源及所有依赖它的资源;或者,如果希望它们继续受到管理,先分别处理依赖资源的移除。
受保护资源。 设置了 protect 选项的资源,不能在没有明确覆盖的情况下从状态中移除,就像 pulumi up 不能删除它一样:
error: urn:...::demo-protected can't be safely deleted because it is protected. Re-run this command with --force to force deletion
可以传入 --force,或者先执行 pulumi state unprotect,再按正常方式移除。如果你还希望从程序中删除 protect: true,先执行 pulumi state unprotect 是更好的选择,因为它会留下明确的变更记录。
pulumi state delete 也支持在一次调用中传入多个 URN,以及使用 --all 清空堆栈中的全部资源状态。如果要退役整个堆栈,同时让其中的资源继续在 Pulumi 管理之外存在,这会很有用。
使用 retainOnDelete 声明式移除资源
pulumi state delete 很适合一次性的手动清理,但不适合交给 CI 流水线替你调用:URN 输入错误,或者过期的流水线运行,都可能在无人注意时移除错误资源的状态。
如果移除应当作为正常 pulumi up 的一部分发生,改为设置 retainOnDelete 资源选项。
TypeScript
const bucket = new aws.s3.Bucket("my-bucket", {}, { retainOnDelete: true });
Python
bucket = aws.s3.Bucket("my-bucket", opts=pulumi.ResourceOptions(retain_on_delete=True))
Go
bucket, _ := s3.NewBucket(ctx, "my-bucket", &s3.BucketArgs{}, pulumi.RetainOnDelete(true))
C#
var bucket = new Aws.S3.Bucket("my-bucket", new Aws.S3.BucketArgs(),
new CustomResourceOptions { RetainOnDelete = true });
Java
var bucket = new Bucket("my-bucket",
BucketArgs.Empty,
CustomResourceOptions.builder()
.retainOnDelete(true)
.build());
YAML
resources:
bucket:
type: aws:s3:Bucket
options:
retainOnDelete: true
HCL
resource "aws_s3_bucket" "my_bucket" {
# ...
pulumi {
retain_on_delete = true
}
}
如果你来自 Terraform,可能首先想到 removed 块,但它在这里不能完成任务。Pulumi HCL 要求 removed 块中包含 lifecycle { destroy = true },并直接拒绝 Terraform 的 destroy = false“忘记资源”行为,转而提示使用 pulumi state delete。应先设置 retain_on_delete,执行 pulumi up,让该选项进入状态,然后再移除声明。
设置 retainOnDelete 后,从程序中移除资源声明,再执行 pulumi up。Pulumi 预览会将该资源标为保留式删除,更新时会将它从状态中移除,绝不会调用提供方的删除操作:
- aws:s3:Bucket my-bucket delete[retain]
因为整个变更都存在于程序里,所以它会经过与其他更新相同的审核、预览和 CI 流程。当多人可能操作该资源,或者移除需要无人值守执行时,这种方法更安全。
资源以这种方式从状态中移除后,程序或状态里已经没有可以切换 retainOnDelete 的对象:资源声明已消失,Pulumi 也不再跟踪资源。
如果后来决定确实要从云提供方删除资源,可以直接通过提供方自己的控制台或 CLI 删除;或者重新将它导入 Pulumi,恢复管理,把 retainOnDelete 设为 false,然后移除声明、执行 pulumi up,通过 Pulumi 删除。
如果只是想继续让 Pulumi 管理资源,但不希望将来删除时再保留它,应在资源仍声明于程序中时设置 retainOnDelete: false,并执行 pulumi up。这样会清除保留标记,但不会删除任何资源;以后移除声明时,便会照常从云提供方删除资源。
如何选择
在键盘前进行一次性交互式清理、希望立即获得结果时,使用 pulumi state delete,例如撤销意外导入,或在重组堆栈时移除少量资源。
当移除由代码变更驱动、应经过正常审核和部署流程,尤其是在 CI 中执行时,使用 retainOnDelete。如果希望操作意图保留在程序历史中,而非只存在于执行过一次的命令里,也应选择它。
给 Terraform 用户的说明
Pulumi 中对应 terraform state rm 的命令是 pulumi state delete:它们都把资源从工具状态中移除,同时让底层基础设施保持不变。
Pulumi 还允许通过 retainOnDelete 资源选项表达相同意图,使移除经过程序正常的审核与部署路径。
相关页面
- 编辑状态文件:涵盖各类
pulumi state子命令,以及什么时候适合手动编辑状态文件。 - 导入资源:逆向操作,将现有基础设施纳入 Pulumi 管理。
- 防止意外变更:介绍
protect和前文提到的其他生产保护措施。 - 在堆栈之间移动资源:使用
pulumi state move将资源状态转移到另一个堆栈,而不是直接移除。
来源:Removing resources without deleting them,Pulumi Corp.,读取于2026年10月3日。Copyright © 2026 Pulumi Corp. 中文翻译,代码与错误输出保留原文,未执行任何状态变更。文档仓库许可:Apache License 2.0,完整许可副本随交接包的 sources/APACHE-2.0.txt 提供。按原许可,材料按现状提供,不附带明示或默示担保。示例不是完整可直接运行的程序,省略的上下文不得理解为已核验的实际基础设施。











暂无评论内容