2. Terraform状态与变更机制
要治理Terraform变更,先要理解Terraform究竟“记住”了什么、在什么时候“决定”要改什么。Terraform本身并不直接管理云上资源,它管理的是期望状态与实际状态之间的差异,而承载这一对照关系的核心对象就是state文件。state是Terraform对已创建资源的“账本”,记录了资源地址、属性值、依赖关系以及元数据(如序列号、Terraform版本)。没有state,Terraform无法知道某个资源是否已经存在,也就无法安全地做增量变更。
state文件默认以JSON结构存储,关键字段包括:version(state格式版本)、terraform_version(生成该state的Terraform版本)、serial(每次写入递增的序列号)、lineage(state血缘标识,用于防止误用其他环境的state)、resources(资源数组,每个资源含type、name、instances、provider、dependencies等)。其中serial与lineage是变更治理的重要抓手:serial用于判断state是否被并发修改,lineage用于识别state是否被错误替换。
state的存储位置决定了协作与治理方式。本地state(terraform.tfstate)只适合个人实验;团队环境必须使用远程后端(如S3+DynamoDB、Terraform Cloud、Azure Storage、GCS),以获得状态锁、版本历史与访问控制。远程后端通过锁机制防止两个apply同时写入同一state,这是变更治理的第一道防线。
plan/apply流程:从差异计算到落地执行
Terraform的核心工作流是init → plan → apply。其中plan是治理价值最高的环节,因为它把“将要发生什么”提前暴露出来。plan的执行过程可以拆解为:读取配置与变量 → 读取state → 刷新(refresh)实际资源属性 → 构建资源依赖图 → 计算差异 → 生成执行计划。执行计划中的每个动作都有明确符号:+创建、-销毁、~原地更新、-/+先销毁再创建(替换)、+/-先创建再销毁。其中-/+与-是高风险动作,往往意味着服务中断或数据丢失。
apply阶段则按依赖图顺序执行计划。Terraform会尽可能并行执行无依赖关系的资源,但对有依赖关系的资源严格串行。执行过程中,state会被逐步更新,最终写入后端。若apply中途失败,state可能处于“部分更新”状态,此时需要人工介入,通过terraform state命令或重新plan来修复。
资源依赖图:变更顺序与影响面的来源
Terraform在plan阶段会构建一张有向无环图(DAG),节点是资源与数据源,边是依赖关系。依赖分为两类:显式依赖(通过depends_on声明)和隐式依赖(通过引用其他资源的属性自动建立)。例如,子网引用VPC的ID,就自动形成“VPC → 子网”的依赖边。依赖图决定了创建顺序(被依赖者先建)和销毁顺序(依赖者先删)。
依赖图也是变更影响面分析的依据。当某个基础资源(如VPC、IAM角色、KMS密钥)发生替换时,依赖它的所有资源都可能被级联替换或更新。治理的关键切入点之一,就是在plan输出中识别这类“根节点变更”,并评估其传播范围。
从机制到治理:四个关键切入点
基于上述机制,可以提炼出四个治理切入点。第一,state可信:确保state存储在后端、启用锁、保留版本历史,并定期校验lineage与serial,防止误操作或并发写入。第二,plan可审:把plan输出纳入变更评审,重点关注-/+替换、-销毁以及涉及数据资源(如数据库、存储桶)的动作。第三,依赖可查:在plan中识别根节点变更,评估级联影响,必要时通过terraform graph或可视化工具查看依赖图。第四,apply可控:对高风险变更采用分阶段apply、-target定向执行或人工审批,避免一次性大规模变更。
一个常见的实践是:在CI流水线中执行terraform plan -out=tfplan,将计划文件保存为制品,再由人工审批后执行terraform apply tfplan。这样既保证了plan与apply的一致性,也留下了审计痕迹。同时,结合terraform show -json tfplan可以提取结构化计划,用于自动化策略检查(如禁止删除生产数据库、禁止公开S3桶)。
terraform state mv/rm/import等命令,并在操作前备份state。理解state、plan/apply与依赖图,是后续策略合规与变更治理的基础。只有把“Terraform看到了什么、准备做什么、按什么顺序做”这三件事看清楚,才能在变更发生前做出正确判断,而不是在故障发生后被动补救。