深色模式
Terraform 工作流:plan / apply / destroy
摘要:Terraform 的正确姿势不是写完就 apply。本文给出一条可放进 CI 的标准流水线:格式化、校验、生成 plan 存档、人工评审、按存档执行,以及 destroy 前的必做检查。
适用环境
- 已安装 Terraform,项目已配置远程 backend
- 团队协作或接入 CI(GitLab CI / GitHub Actions 均可套用)
- 至少两个环境(dev / prod)用于演练
操作步骤
1. 生成 plan 存档(关键)
bash
terraform fmt -check -recursive # CI 门禁:格式不符就失败
terraform validate # 语法与类型校验,不需要凭证
terraform plan -out=prod.tfplan
terraform show -json prod.tfplan > prod.tfplan.json1
2
3
4
2
3
4
用 -out 后 apply,能保证评审的内容 == 执行的内容。
2. 评审 plan 输出
bash
terraform show prod.tfplan1
text
+ create
~ update in-place
-/+ destroy and then create replacement ← 最危险,必须逐个确认1
2
3
2
3
任何 -/+ 都要问:这个资源能中断吗?数据会丢吗?
3. 按存档执行
bash
terraform apply prod.tfplan # 不再交互确认
terraform apply -auto-approve # CI 中使用,本地不推荐1
2
2
危险
生产环境 apply -auto-approve 等于放弃最后一道确认。更稳妥的做法是只接受已评审的 -out 存档。
4. 安全 destroy
bash
terraform plan -destroy -out=destroy.tfplan
terraform show destroy.tfplan # 先看清楚会删什么
terraform apply destroy.tfplan
terraform destroy -target=aws_instance.demo # 仅删单个资源1
2
3
4
2
3
4
5. 多环境与典型 CI
环境差异仅为变量 → 用 terraform workspace;资源结构不同或需独立审批 → 独立目录 + 独立 backend key(生产推荐)。
yaml
stages: [validate, plan, apply]
validate:
script: [terraform fmt -check -recursive, terraform init -backend=false, terraform validate]
plan:
script: [terraform init, terraform plan -out=$CI_COMMIT_SHORT_SHA.tfplan]
artifacts: { paths: ["*.tfplan"] }
apply:
when: manual # 人工点按钮才执行
script: [terraform init, terraform apply $CI_COMMIT_SHORT_SHA.tfplan]1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
验证
bash
terraform plan -detailed-exitcode; echo $? # 0 无变更 / 1 报错 / 2 有变更1
- [ ] CI 中 apply 是手动触发,且使用 plan 存档
- [ ]
plan -detailed-exitcode返回 0 说明无漂移 - [ ] destroy 前已确认备份与快照
常见坑
plan 存档和环境不匹配
prod.tfplan 只能在同一个 workspace/backend 下 apply。
-target 会留下半成品状态
依赖资源仍在 state 中形成悬空引用。仅用于救急,事后跑一次全量 plan 校正。
workspace 忘了切换
在 default workspace 上误 apply 到生产是常见事故。执行前用 terraform workspace show 确认。