声明式基础设施描述期望结果,再由工具计算变更。命令式脚本同样可以查询已有资源、实现幂等性;重复创建不是脚本天生无法避免的命运。Terraform 的价值,在于把配置、资源身份、依赖关系和拟执行操作放进一个共同模型,让评审者能够一起检查。
需要把配置与拟执行操作放在一起评审:改变地址可能改变身份关系,而外部修改也可能让完全没动过的配置产生计划。文件可追踪,并不自动等于所有操作都安全。
计划是提案,不是事务保证
普通 plan 通过 provider 读取受管理对象,把刷新后的观察结果与配置比较,再提出创建、更新、替换或删除操作。未知值、provider 的实现、执行权限,以及计划到执行之间发生的变化,都使它无法保证成功,也不能把输出理解成未来所有 API 调用的完整逐条清单。
保存计划可以让 apply 使用被评审的那份提案,而不是自动重算另一份,但并不会冻结远端系统。状态发生变化可能使保存的计划失效,执行也可能在完成部分操作后报错。计划文件和状态可能包含敏感信息,应作为受控产物保存,不要为了排错就把完整内容贴到公开日志里。
成功 apply 之后,如果输入、配置和外部环境稳定,通常应当不再出现新的变更。若持续有差异,就要检查外部控制器、计算属性、provider 缺陷和不断变化的输入。一个干净的计划只说明此次受管理范围内没有拟执行差异,不能证明云账户里所有资源都已被纳入清单,也不能保证业务服务健康。
状态保存的是身份关系
状态把配置地址绑定到真实对象,并保存 Terraform 需要的其他信息。丢失映射不会立刻删除远端资源;之后的计划可能提议创建新对象,而 apply 究竟会建出重复资源,还是遇到名称冲突,取决于 provider 和服务本身。不能把某一次 already exists 错误推广成所有资源的必然结果。
恢复时应先检查后端历史版本与可用快照。当恢复快照不适合或不可行时,import 可以把受支持的既有对象重新关联到配置地址。除了命令行方式,也有配置驱动的导入流程,并不一定要逐个手工敲命令。导入之后仍需核对资源配置和执行计划,身份绑定完成不意味着下一次 apply 一定没有变化。
共享状态需要访问控制、可恢复的历史,以及具备合适锁定能力的后端。并非所有后端都支持锁;获取锁失败会使操作停止,是否等待、等待多久还取决于锁超时等命令选项。不要为了绕过另一个合法运行而禁用锁,也不要把状态版本历史等同于完整基础设施审计。后端保存了什么记录、能恢复到哪里,都需要独立确认。
漂移与重构是两种决定
已经被状态追踪的资源在外部被修改后,需要决定保留新值还是恢复配置值。保留通常意味着更新配置,普通属性漂移不需要重新 import。refresh-only apply 会更新 Terraform 的记录,而不按照配置去改远端对象;它不会替你编辑配置,因此下一次普通计划仍可能提议把外部改动撤回。
被忽略的属性和 provider 的资源模式,也会影响哪些差异产生操作。控制台变更可能有自己的审计日志,真正的团队问题往往不是「绝无记录」,而是事故处置记录没有关联到下一次部署。把最终要保留的值写清楚,比单纯让一次 refresh 看起来成功更重要。
如果只改地址,却没有记录新旧地址的关系,就可能得到删除旧对象、创建新对象的提案。moved 块可以显式说明这种关系,也包括受支持的模块内迁移,所以兼容的重构不必重建资源。不过,伴随发生的其他配置变化仍可能要求替换对象。直接删掉资源块通常会提议销毁,除非明确使用了合适的移除管理流程。
坏掉的样子
事故中有人临时调大实例规格,却没同步配置;下一次无关的 apply 随后提议缩小它。应当评审相关操作,并记录长期希望保留的值。计划退出码二表示有非空差异,不专门表示漂移,也不自动代表危险或失败。把所有二都当成故障,容易制造让人忽略的告警噪声。
面对意外的 destroy,先比较旧地址和新地址,再决定是否批准。面对「资源不见了」,先确认选中的后端和 workspace,而不是立即断言状态丢失。恢复期间要停止并发写入;一份看起来合理的空状态,并不构成重新创建全部资产的依据。把账单、对象标识和配置地址对应起来,才有恢复的基础。
快速验证
使用 Terraform 1.4 或更新版本,在全新实验目录和已检查的 CLI 设置下操作;继承的 TF_CLI_ARGS、workspace 与配置可能改变行为。逐条运行,遇到错误就停止,因为下面的 shell 块没有自动失败即停保护。内置 terraform_data 改变本地状态,不创建云基础设施;不要混入已有生产目录。
lab=$(mktemp -d)
cd "$lab" || exit 1
cat > main.tf <<'HCL'
resource "terraform_data" "old" { input = "kept" }
HCL
terraform init -input=false
terraform validate
terraform apply -input=false -auto-approve
terraform state show terraform_data.old
cat > main.tf <<'HCL'
resource "terraform_data" "new" { input = "kept" }
HCL
terraform plan
cat >> main.tf <<'HCL'
moved {
from = terraform_data.old
to = terraform_data.new
}
HCL
terraform validate
terraform plan -out=moved.tfplan
terraform apply -input=false moved.tfplan
terraform state show terraform_data.new
terraform plan -detailed-exitcode
保留的 Terraform 1.13.3 审阅记录报告:未记录关系的改名提议创建一个、删除一个,不应执行这个中间计划。加上 moved 后,资源动作数为零、标识相同、最终退出码为零。本次没有重跑。只有地址变化的详细计划仍可能返回二,不能把资源动作数为零当成状态没有变化。
该夹具用于检查 Terraform 客户端的本地计划和地址迁移,没有验证云 provider 导入、远端漂移检测或后端锁。详细退出码的一般含义是:零表示没有变更,一表示错误,二表示存在变更。应该继续读具体动作,不能因为出现二就认定失败,也不能因为资源操作数为零就忽略状态映射的变动。
实验结束后,先用 cd - 返回原来的目录,再删除 $lab 指向的那一个临时目录。其中只保留本实验生成的配置、计划和本地状态;在明确清理前,这些文件仍会留在磁盘上。
来源
- Terraform:状态,地址绑定与状态的作用,已核验 2026-10-15。
- Terraform:plan 命令,计划模式、保存计划、锁选项与退出码,已核验 2026-10-15。
- Terraform:远程状态,共享存储与后端能力,已核验 2026-10-15。
- Terraform:状态锁,后端支持范围与获取锁失败的行为,已核验 2026-10-15。
- Terraform:重构模块,显式 moved 映射与兼容重构,已核验 2026-10-15。
- Terraform:导入概览,通过配置接管既有资源,已核验 2026-10-15。
- Terraform:命令行导入,另一种命令行导入流程,已核验 2026-10-15。
- Terraform:管理资源漂移,刷新观察结果与协调配置,已核验 2026-10-15。
- Terraform:生命周期,忽略属性与移除配置的后果,已核验 2026-10-15。
- Terraform:terraform_data,实验所用的内置本地生命周期资源,已核验 2026-10-15。
- Terraform:apply 命令,执行保存计划与部分失败的语义,已核验 2026-10-15。
- Terraform CLI 环境变量,继承的 CLI 参数、工作区与配置,已核验 2026-10-18。