2. Terraform核心工作流与网络资源生命周期

Terraform 的价值不在于“写一段配置”,而在于把网络资源的整个生命周期纳入一条可重复、可审计的工作流。理解 init → plan → apply → destroy 这条主线,以及状态文件在其中的枢纽作用,是后续所有企业网络自动化实践的基础。本节以“创建一台 VPC 及其子网、安全组”为例,把这条工作流拆开讲清楚:每一步到底发生了什么、输入输出是什么、状态文件如何变化、结果如何判断。

一、四个命令各自解决什么问题

terraform init 是工作流的起点,它做三件事:初始化后端(backend)、下载并安装 provider 插件、初始化模块。以 AWS 为例,配置中声明 provider "aws" 后,init 会从注册表拉取对应版本的插件到 .terraform/ 目录,并生成或校验 .terraform.lock.hcl 锁定文件。如果后端配置为远程存储(如 S3 + DynamoDB 锁),init 还会连接后端并准备状态读写通道。init 是幂等的,可以反复执行,但一旦后端配置变更,需要 terraform init -reconfigure 或 -migrate-state 明确迁移。

terraform plan 是“预演”。它读取当前状态文件、读取真实基础设施(通过 provider 的 Read 接口刷新)、再与配置比对,生成一份执行计划。计划中用符号表达动作:+ 表示创建,~ 表示原地更新,-/+ 表示先销毁再重建(即替换),- 表示销毁。plan 不修改任何真实资源,是评审和变更审批的关键环节。企业实践中通常把 plan 输出保存为文件:terraform plan -out=tfplan,再让 apply 严格按这份计划执行,避免“评审的和执行的不是同一份”。

terraform apply 是“落地”。它默认会再跑一次 plan 并请求确认,若指定了 tfplan 文件则直接执行该计划。apply 按依赖关系图(DAG)并发地调用 provider API 创建/修改资源,每完成一个资源就把结果写回状态文件。因此 apply 是“真实资源”和“状态文件”同时被更新的过程,二者必须保持一致。

terraform destroy 是“回收”。它按依赖关系的逆序销毁配置中管理的所有资源,并同步清理状态文件。企业环境中 destroy 往往受保护:可通过 prevent_destroy = true 的生命周期参数阻止关键资源(如生产 VPC)被误删,也可用 terraform destroy -target 精确销毁某个对象。

Terraform 核心工作流与状态文件枢纽 配置源 .tf provider / resource variable / output terraform init 装插件 / 连后端 生成 lock 文件 terraform plan 刷新 + 比对 输出执行计划 terraform apply 调 API 建资源 写回状态 状态文件 terraform.tfstate 资源 ID · 属性 · 依赖关系 · 版本 远程后端:S3 + DynamoDB 锁 唯一事实来源(Source of Truth) 读取/刷新 写入/更新 真实云上网络资源 VPC · Subnet · Security Group · Route Table 由 provider API 实际创建与销毁 创建/变更 映射 terraform destroy 逆序销毁资源 清理状态条目 同步清理 生命周期保护 prevent_destroy = true create_before_destroy

二、状态文件:工作流的“唯一事实来源”

状态文件(terraform.tfstate)记录了 Terraform 所管理的每个资源的真实 ID、属性值和依赖关系。它之所以关键,是因为 Terraform 并不“记住”自己创建过什么,而是每次通过状态文件把配置中的逻辑名称映射到云上的真实对象。没有状态文件,plan 就无法判断某个资源是“已存在需更新”还是“不存在需创建”。

本地状态只适合个人实验。企业环境必须使用远程后端,原因有三:一是团队协作时多人共享同一份状态,避免各自本地状态分叉;二是远程后端配合锁机制(如 DynamoDB 表)防止并发 apply 造成状态损坏;三是状态文件包含敏感信息(如数据库密码、密钥),远程存储可配合加密与访问控制。一个典型的 S3 后端配置如下:

terraform {
  backend "s3" {
    bucket         = "corp-tfstate-prod"
    key            = "network/vpc/terraform.tfstate"
    region         = "cn-north-1"
    dynamodb_table = "corp-tfstate-lock"
    encrypt        = true
  }
}

需要特别强调的是:状态文件不是“可以随手改的配置文件”。如果资源在云上被手工删除或修改,状态就会与真实情况不一致,此时应使用 terraform refresh(新版已并入 plan 的自动刷新)或 terraform state rm、terraform import 等命令谨慎修复,而不是直接编辑 JSON。

三、网络资源的创建、变更与销毁过程

下面以创建 VPC 与子网为例,观察一次完整的生命周期。配置如下:

resource "aws_vpc" "main" {
  cidr_block = "10.20.0.0/16"
  tags = { Name = "corp-vpc" }
}

resource "aws_subnet" "app" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.20.1.0/24"
  tags = { Name = "corp-app-subnet" }
}

首次执行 terraform plan 时,状态为空,计划会显示两个 + 创建动作,并给出将要设置的属性。执行 terraform apply 后,Terraform 先创建 VPC,拿到返回的 vpc-xxxx ID,再把它作为 vpc_id 传给子网创建请求——这就是依赖关系图驱动的顺序。apply 完成后,状态文件中会出现两条资源记录,各自带有真实 ID 和属性。

变更场景更能体现工作流的价值。假设把子网 CIDR 从 10.20.1.0/24 改为 10.20.2.0/24。由于子网 CIDR 在 AWS 中不可原地修改,plan 会显示 -/+ 替换动作:先销毁旧子网,再创建新子网。如果该子网上还挂着其他资源,替换可能引发中断,此时可用 create_before_destroy = true 让 Terraform 先建新再删旧。反之,若只是修改 tags,plan 会显示 ~ 原地更新,不会重建资源。判断“改一个字段会不会导致重建”,正是 plan 阶段最需要人工评审的地方。

销毁阶段,terraform destroy 会按依赖逆序执行:先删子网,再删 VPC,因为 VPC 被引用。销毁完成后,状态文件中对应条目被移除。对于生产网络,建议在关键资源上设置 prevent_destroy = true,让 destroy 直接报错而非静默删除。

实践建议:把 terraform plan -out=tfplan 与 terraform apply tfplan 配对使用,并在 CI 中把 plan 输出作为变更评审材料。这样“评审的计划”和“执行的计划”是同一份,能有效避免人工确认时被绕过。

四、把工作流串成可复用的操作闭环

综合来看,一次标准的网络资源变更应遵循:先 init 确保插件与后端就绪;再 plan 生成并保存计划,重点检查 +、~、-/+、- 四类动作是否符合预期;确认后 apply 执行;变更完成后通过 terraform output 或云控制台核对资源 ID、CIDR、路由等关键属性是否与计划一致。若需要回收,用 destroy 并配合生命周期保护。整个过程中,状态文件始终是配置与真实资源之间的桥梁,任何绕过它的手工操作都会破坏一致性,这也是企业网络自动化必须坚持“一切变更走 Terraform”的根本原因。