CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Terraform 基础设施即代码/课时/plan 与 apply
RawBlame
课时目录12 节

Terraform 基础设施即代码

  1. 01Terraform 是什么
  2. 02HCL 语法
  3. 03init 与 Provider
  4. 04plan 与 apply
  5. 05State 管理
  6. 06变量与输出
  7. 07Module 复用
  8. 08AWS 资源示例
  9. 09Terraform 与 K8s
  10. 10CI 中的 Terraform
  11. 11Terraform vs Helm
  12. 12综合练习

plan 与 apply

执行计划、审批、destroy 风险。

35 分钟

plan 与 apply

这一课你将能做到

  1. 看懂 plan 输出中的 +、-、~、-/+ 和资源数量汇总
  2. 用 -out 保存计划、用 show 审查、把计划原样 apply,杜绝「计划和执行不一致」
  3. 说出 apply 的执行顺序逻辑,并用 target、replace 处理日常特殊场景

为什么要学

plan 是 Terraform 最有价值的设计:在动任何真实资源之前,先给你一份「变更说明书」。线上事故里,有相当一部分不是 Terraform 本身的问题,而是人没认真看计划:plan 里明明写着要销毁数据库,有人一路回车。学会读 plan、保存 plan、按计划执行,是区分「会用 Terraform」和「敢在生产敲 apply」的分水岭。

人话:plan 像手术前的知情同意书——医生告诉你切哪、缝哪、风险是什么;你不看就签字,出了事不能怪手术刀。

先建立图像

plan 中四种标记:

+  create   新建资源
~  update   原地修改部分属性
-  destroy  删除资源
-/+ replace 删除后重建(或先建后删,取决于参数)

一次变更的汇总行示例:

Plan: 2 to add, 1 to change, 1 to destroy.

执行顺序不是文件顺序,而是 Terraform 根据引用关系画出的依赖图:被依赖的先建(VPC → 子网 → EC2),删除时反过来。

跟着做

步骤 1:准备可反复演练的配置

新建 plan-demo/main.tf:

terraform {
  required_version = ">= 1.7.0"
}

variable "instance_count" {
  type    = number
  default = 1
}

resource "null_resource" "app" {
  count  = var.instance_count
  triggers = {
    index = count.index
    role  = "springboot-app"
  }
}

执行 terraform init。

步骤 2:第一次 plan

terraform plan

输出片段:

Terraform used the selected providers to generate the following execution plan.
...
  # null_resource.app[0] will be created
  + resource "null_resource" "app" {
      + id       = (known after apply)
      + triggers = {
          + index = 0
          + role  = "springboot-app"
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

(known after apply) 表示这个值要等云端创建后才知道,比如 IP、ID。

步骤 3:保存计划并审查

terraform plan -out=tfplan
terraform show tfplan

-out 把计划写成二进制文件,里面锁定了当时的配置、状态和参数。之后 apply 这个文件,执行的内容和你看到的完全一致,不会被中途的代码改动影响。CI/CD 的标准姿势就是「一个 job 生成 plan 供评审,下一个 job apply 该文件」。

步骤 4:按计划执行

terraform apply tfplan

注意:apply 一个保存好的计划文件时(审批在 plan 环节已经完成)。直接 不带参数则会现场重新算一次计划并要求确认——这存在「显示的计划」和「执行的计划」之间配置被改动的风险。

不会再问 yes
terraform apply

步骤 5:体验 update 与 replace

修改配置,把 role 改掉:

  triggers = {
    index = count.index
    role  = "springboot-web"
  }

再 plan:

  ~ triggers = {
      ~ role = "springboot-app" -> "springboot-web"
    }
Plan: 0 to add, 1 to change, 0 to destroy.

~ 表示原地更新。AWS 中有些属性不可变(如 EC2 的 AMI、子网的 CIDR),修改它们会显示 -/+,即销毁重建——这是看 plan 时最需要警惕的信号。

步骤 6:定向操作与强制替换

只想操作某一个资源(应急用,别当日常):

terraform plan -target=null_resource.app[0]
terraform apply -target=null_resource.app[0]

怀疑某个资源在云端状态异常,想强制重建:

terraform plan -replace=null_resource.app[0]

-replace 是 Terraform 1.7 推荐写法(等价旧的 taint 思路),只影响下一次计划。

步骤 7:销毁计划也要审

terraform plan -destroy -out=destroy.plan
terraform show destroy.plan
terraform apply destroy.plan

养成习惯:destroy 前同样先出计划,确认销毁清单里没有「还要留着」的资源(比如忘了加 lifecycle 保护的数据库)。

讲清楚要点

  1. plan 是只读的:它刷新真实资源状态、计算差异,但绝不修改任何东西。可以随时跑、放心跑。
  2. 「计划即执行」要靠 -out 保证:人肉看的是终端输出,apply 现场重算可能不同;用 plan 文件把两者绑定。
  3. 颜色和符号对应:终端里绿色新增、黄色修改、红色删除。色盲或日志场景看 + ~ - 字符即可。
  4. lifecycle 规则能防误删:资源块内加 lifecycle { prevent_destroy = true },任何计划销毁该资源的操作直接报错,数据库等关键资源建议加。
  5. -target 是逃生舱不是常规手段:频繁 target 会让配置整体状态和你的心智模型脱节,用完要尽快做一次完整 plan 收敛。
  6. apply 失败可以安全重试:部分成功后 state 已记录完成项,重新 apply 会从断点继续,不会重复创建已完成资源。

你可能会懵的地方

  • plan 里出现 (known after apply) 正常吗? 正常。资源 ID、自动分配的 IP、RDS 端点这些都是创建后才生成的。但如果下游硬依赖它,会看到一连串 known after apply,属于预期行为。

  • 为什么我改了一行,plan 却显示要重建资源? 那个属性对云平台是不可变的(ForceNew)。plan 的 -/+ 行就是答案;真要避免停机,考虑蓝绿/先建后删(create_before_destroy)。

  • apply 到一半失败了怎么办? 读错误信息修好问题(权限、配额、参数),直接重新 apply。Terraform 按依赖图继续,已完成的资源不会重来。

  • plan 结果会过期吗? plan 文件不感知之后的云端变化。生产上 plan 和 apply 间隔不宜过久,apply 前可重新确认;CI 里通常 plan 审批后立即执行。

  • terraform apply -auto-approve 什么时候能用? 临时/测试环境的自动化流水线可以;任何涉及生产数据的 apply 都应保留人工审批环节。

错法对照

错法问题正解
只看 Plan 汇总行,不看明细汇总 0/1/0 里也可能换了数据库逐个查看 ~ 和 -/+ 的属性
人肉看 plan,却 terraform apply 重算中途配置被改,执行了别的内容plan -out 后 apply 计划文件
用 -target 做日常发布其余资源长期不收敛target 只用于应急,随后全量 apply
数据库不加保护就 destroy数据永久丢失lifecycle.prevent_destroy 或分离策略
apply 失败后手工去控制台补状态与现实进一步分裂修配置/权限后重跑 apply

卡点急救

  1. plan 报凭证/权限错误:plan 也会调用云 API 刷新状态。检查环境变量、aws sts get-caller-identity 确认身份,核对 IAM 权限。
  2. apply 卡住无输出:可能在等锁(远程 state 被占用)或云 API 慢。看是否有 lock 信息,必要时 terraform force-unlock <锁ID>(确认持锁操作真的已死)。
  3. Saved plan is stale:计划生成后配置或 state 已变化,重新 plan 出新文件即可,不要强行执行旧文件。

面试常问

  • Terraform plan 做了什么?为什么生产环境一定要先 plan? 刷新资源真实状态,与配置和 state 对比生成增删改计划,供人工评审。它把「变更」前置成可审计的文本,是防止误操作(尤其是销毁和重建)的关键关卡。

  • 如何保证审批的计划和最终执行的是同一份? terraform plan -out 保存计划文件,评审后 terraform apply 该文件;文件内含状态快照,不可被中途改动,CI 中还可配合指纹/加密存储防篡改。

  • 什么是 tainted / replace?-target 有什么风险? 标记资源为「下次替换」会让 Terraform 销毁重建它(1.7 用 -replace)。-target 只对部分资源操作,会造成整体状态长期偏离配置,只适合应急排障。

自测三问

  1. plan 中的 ~ 和 -/+ 有什么本质区别?对线上服务的影响分别是什么?
  2. 为什么推荐 plan -out + apply 文件,而不是 apply 直接确认?
  3. EC2 的实例类型能原地修改吗?修改 AMI 为什么会触发重建?

小结一句话

plan 是变更说明书:看懂 +/−/~ 和重建信号,用 -out 锁定计划再 apply,是在生产安全使用 Terraform 的核心纪律。

延伸

  • Command: plan 官方文档
  • Command: apply 官方文档
  • Resource Lifecycle 生命周期规则
  • 下一课:State 管理——本地状态、远程后端、锁、import 与 move。
加载本节练习…
← 上一课init 与 Provider下一课 →State 管理