2. Terraform核心机制回顾
在进入平台化交付之前,有必要把 Terraform 的几条核心机制重新梳理一遍。平台化并不是另起一套体系,而是在这些原生机制之上叠加抽象、约束与自动化。理解它们各自的职责边界,才能判断哪些能力可以封装、哪些必须保留给使用者。
Provider:与外部 API 的适配层
Provider 是 Terraform 与真实基础设施之间的翻译器。它把 HCL 中声明的资源类型映射为对云厂商、Kubernetes、DNS、监控系统等 API 的调用。每个 Provider 需要声明来源地址与版本约束,例如:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.40"
}
}
}
provider "aws" {
region = "cn-north-1"
}
平台化场景下,Provider 的版本与认证方式是最需要收敛的部分。版本约束若由各业务团队自由填写,同一平台内会出现多个不兼容的 Provider 版本,导致状态迁移困难。认证信息则不应出现在业务代码里,而应通过环境变量、OIDC 角色或平台注入的凭据链提供。Provider 的 alias 机制可以支持多区域、多账号,但 alias 命名规范应由平台统一约定,否则后续策略校验无法稳定识别目标账号。
Resource 与 Data Source:声明与查询的两类对象
Resource 描述"我要创建或管理什么",Data Source 描述"我要读取什么已存在的信息"。二者在语法上相似,但语义完全不同:Resource 参与状态写入与生命周期管理,Data Source 只在 plan 阶段读取,不写入 state 中的资源实例。
data "aws_vpc" "shared" {
tags = { Name = "platform-shared-vpc" }
}
resource "aws_subnet" "app" {
vpc_id = data.aws_vpc.shared.id
cidr_block = "10.20.1.0/24"
availability_zone = "cn-north-1a"
}
平台化时,Data Source 常被用来引用平台预置的网络、密钥、镜像等共享资产。这里有一个容易忽略的边界:Data Source 的读取结果会进入 plan 的 diff 计算,如果它依赖的远端对象在 apply 前发生变化,plan 结果可能失效。因此平台应尽量把共享资产的关键属性固化为变量或远程 state 输出,而不是让业务模块在每次 plan 时动态查询。
State:唯一的事实来源
State 记录 Terraform 认为已存在的资源及其属性映射。它既是 plan 的输入,也是 apply 的写入目标。平台化最核心的治理动作之一,就是 State 的隔离与访问控制。常见做法是按环境、账号、业务域划分独立的 state 文件,并使用远程后端(如 S3 + DynamoDB 锁、Terraform Cloud、GitLab 后端)保证并发安全。
需要特别注意的是,state 中包含敏感属性(如数据库密码、密钥材料),因此后端必须启用加密与访问审计。平台不应允许业务团队直接下载或手工编辑 state,而应通过受控的 CI 流水线执行 plan/apply。当出现资源漂移时,优先使用 terraform import 或 terraform state mv/rm 修正,而不是手工改 JSON。
Plan/Apply 工作流:从差异到收敛
标准工作流是 init → validate → plan → apply。plan 阶段会刷新 state、读取 Data Source、计算目标配置与当前状态的差异,输出将要执行的动作(create、update、replace、destroy)。apply 则按依赖图顺序执行这些动作并更新 state。
平台化后,这条链路通常被包装为流水线:合并请求触发 plan,人工审批后触发 apply。关键边界在于:plan 与 apply 之间必须使用同一份 plan 文件(terraform plan -out=tfplan 后 terraform apply tfplan),否则中间的状态变化会导致实际执行与审批内容不一致。此外,plan 输出需要被结构化解析,才能实现"禁止 destroy 生产数据库""限制高危资源类型"等策略。
平台化场景下的关键边界
把上述机制放进平台语境,会浮现出几条必须提前划定的边界。
- 版本边界:Provider 与模块版本由平台锁定,业务侧只能选择平台发布的版本组合,避免"同一平台、多套依赖"的碎片化。
- 状态边界:state 按环境与账号隔离,跨 state 的引用通过远程输出或 Data Source 完成,禁止直接读取他人 state 文件。
- 凭据边界:认证信息不进入代码仓库,由 CI 运行时通过 OIDC 或密钥管理服务注入,Provider 配置只声明角色与区域。
- 执行边界:plan 与 apply 必须使用同一份 plan 文件,且 apply 只能由受控流水线触发,人工不得在本地对生产 state 执行 apply。
- 策略边界:plan 输出需被结构化解析,对 destroy、替换、高危资源类型设置拦截规则,把"能不能做"的判断前移到审批之前。
回顾这些机制的目的不是复述语法,而是为后续的平台抽象找到锚点。Provider 决定能力边界,Resource/Data Source 决定表达方式,State 决定事实归属,Plan/Apply 决定变更路径。平台化的每一步设计,本质上都是在这四者之上做约束与封装。