如果项目级“删除保护”已开启,Terraform destroy 会报什么错误?

解读

在国内金融、政企云项目中,**“项目级删除保护”**是客户合规必选项,目的是防止整套环境被误删。Terraform 作为基础设施即代码的主流工具,其 destroy 操作本质上是调用 Google Cloud API 依次删除资源。当该保护开关打开时,Cloud SQL 实例会被打上 deletionProtection=true 的系统标签,任何删除 API(包括 terraform-provider-google 内部调用的 sqladmin.instances.delete)都会被 googleapis 层直接拒绝,Terraform 在收到 400 响应后立即中断执行流,并把谷歌返回的 googleapi: Error 400: The instance 'xxx' has deletion protection enabled 原样抛给 CLI。因此面试时要抓住“API 层拒绝 → Terraform 插件透传 → 运行期失败”这一链路,才能体现对云厂商实现细节的掌握。

知识点

  1. 项目级删除保护与实例级 deletionProtection 字段是正交关系:前者在组织策略 constraint/sql.restrictNonProtectedInstances 中统一强制,后者是单实例布尔值;两者任一开启均会触发保护。
  2. Terraform google provider 4.50+ 支持读取该策略,但不会自动跳过,而是直接报错;需要显式设置 lifecycle { prevent_destroy = false } 并关闭保护后才能 destroy。
  3. 错误码固定为 400 Bad Request,reason 字段 "deletionProtectionEnabled",中文控制台提示 “实例已开启删除保护”
  4. 国内多云框架下,该错误会被审计平台捕获并强制阻断 CI/CD,需走工单审批流临时关闭策略,再重跑 pipeline。
  5. 若使用 Private Service Connect + VPC-SC 环境,错误信息会被审计日志封装到 data_access 类型日志中,需开启 LOG_BUCKET 才能查看明文。

答案

Terraform destroy 会立即失败并回滚状态,CLI 标准错误输出为:

Error: Error, failed to delete instance because deletion protection is enabled at the project level
  on main.tf line 23, in resource "google_sql_database_instance" "default":
  23: resource "google_sql_database_instance" "default" {

谷歌 API 原始报文为 googleapi: Error 400: The instance 'prod-order-mysql' has deletion protection enabled., deletionProtectionEnabled;Terraform provider 仅做字符串透传,不会自动重试或优雅跳过。

拓展思考

  1. 如何在零停机前提下做销毁演练?
    先通过 gcloud resource-manager org-policies disable-constraint sql.restrictNonProtectedInstances --project=PROJECT_ID 临时关闭项目级策略,再执行 terraform destroy -target,最后立即恢复策略;整个过程用 Cloud Build + Approval 通知保证双人复核,满足国内等保变更管理要求。
  2. 如果实例同时开启CMEK 加密与删除保护,关闭顺序是什么?
    必须先禁用 CMEK(需等待密钥版本清理完成,约 4 小时),再关闭删除保护,否则 KMS 密钥仍在使用中,terraform destroy 会抛出 KMS_KEY_IN_USE 错误,形成二次阻断。
  3. Terraform 1.6 的“计划阻塞”特性下,可提前通过 terraform plan -detailed-exitcode 捕获保护状态,把错误左移到 MR 阶段,避免夜间批量跑管道时才发现删除失败,导致状态文件被锁、影响次日发布窗口。