使用Terraform在分支合并后销毁资源的最佳实践
GitLab分支合并后自动销毁Terraform资源的最佳实践
核心思路:依托目标分支(dev)的流水线完成销毁
因为分支合并后原分支无法再触发流水线,所以转而利用dev分支的合并触发流水线,在其中嵌入针对被合并分支的销毁逻辑。
方案1:迁移远程状态存储(优先推荐)
当前状态文件存在Runner本地的隐患极大——Runner实例重启、扩容或更换都会导致状态丢失,彻底无法完成销毁。先把状态迁到GitLab内置的Terraform状态存储或其他远程后端:
- 修改Terraform配置的backend为gitlab,用分支名区分状态文件:
terraform { backend "gitlab" { project = "你的项目路径" name = "terraform-state-${var.branch_name}" } } - 每个分支的状态文件会通过
var.branch_name作为标识,统一存储在GitLab项目的状态仓库中。
然后在dev分支的.gitlab-ci.yml中添加销毁job:
destroy-branch-resources: stage: cleanup only: - merge_requests # 可选设为manual,先手动验证再自动执行 script: - export SOURCE_BRANCH=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME - terraform init -backend-config="name=terraform-state-${SOURCE_BRANCH}" - terraform destroy -var-file="terraform-${SOURCE_BRANCH}.tfvars" -auto-approve tags: - 你的terraform-runner标签
当MR合并到dev时,这个job会自动触发,通过CI_MERGE_REQUEST_SOURCE_BRANCH_NAME拿到原分支名,加载对应的状态和tfvar文件完成销毁。
方案2:在dev流水线中通过Git日志获取被合并分支(适配本地状态场景)
如果暂时无法迁移远程状态,需确保所有Runner共享同一个状态存储目录(比如用NFS挂载到所有Runner节点),然后在dev的流水线中添加:
destroy-branch-resources: stage: cleanup only: - dev script: # 获取最后一次合并的源分支 - LAST_MERGE_COMMIT=$(git log --merges -1 --pretty=format:"%H") - SOURCE_BRANCH=$(git show --pretty=format:"%P" $LAST_MERGE_COMMIT | awk '{print $1}' | xargs git name-rev --name-only | sed 's/remotes\/origin\///') - cd /共享状态目录/${SOURCE_BRANCH} - terraform destroy -var-file="/tfvars目录/terraform-${SOURCE_BRANCH}.tfvars" -auto-approve tags: - 你的共享runner标签
这个方法依赖Runner共享状态目录,且Git日志能正确解析源分支,适合临时过渡,但长期仍推荐迁移到远程状态。
方案3:MR合并前触发销毁(提前清理)
在MR创建阶段,添加一个“预合并销毁”的job,并设为MR合并的前置条件:
pre-merge-destroy: stage: pre-cleanup only: - merge_requests except: - dev script: - terraform destroy -var-file="terraform-${CI_COMMIT_BRANCH}.tfvars" -auto-approve when: manual rules: - if: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "dev"
要求合并前必须执行该销毁job,从根源上避免合并后再处理资源的麻烦。
内容的提问来源于stack exchange,提问作者AR98
相关产品推荐
相关产品推荐

