4. 基础设施即代码(IaC)
在平台工程中,环境编排的核心挑战在于如何以可重复、可版本控制、可审计的方式管理云基础设施。Terraform 作为业界最广泛使用的声明式 IaC 工具,通过 Provider、Resource、State 三大核心概念,将基础设施的声明、编排与生命周期管理标准化。本章深入剖析其核心机制与最佳实践。
4.1 核心概念:Provider / Resource / State
Terraform 的运作模型围绕三个抽象层展开:Provider 负责与目标 API 通信,Resource 描述期望的基础设施对象,State 则作为真实世界与配置文件的映射桥梁。
| 概念 | 角色 | 关键特征 |
|---|---|---|
| Provider | API 适配器 | 封装云厂商(AWS/Azure/GCP)或服务(Kubernetes/Helm)的 API 调用;通过 required_providers 声明版本约束。 |
| Resource | 基础设施对象 | 使用 resource "type" "name" 块定义;支持参数、元参数(count/for_each)、依赖关系。 |
| State | 映射文件 | JSON 格式存储资源 ID、属性及依赖;用于 plan 对比与 apply 变更;必须安全存储。 |
平台工程视角: Provider 是平台团队封装底层差异的关键接口。通过定制 Provider 或使用
terraform-provider-http,可以将内部系统(如 CMDB、工单系统)暴露为 Terraform 资源,实现统一编排。
4.2 HCL 语法与模块化设计
HCL(HashiCorp Configuration Language)是 Terraform 的声明式语言,强调可读性与层次结构。模块化设计则通过封装可复用的配置单元,降低平台环境的重复代码。
4.2.1 HCL 基础语法
# 变量定义
variable "environment" {
description = "部署环境名称"
type = string
default = "dev"
}
# 本地值
locals {
name_prefix = "${var.environment}-platform"
}
# 数据源:查询现有资源
data "aws_vpc" "selected" {
tags = {
Name = "${var.environment}-vpc"
}
}
# 资源声明
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t3.medium"
subnet_id = data.aws_vpc.selected.main_route_table_id
tags = {
Name = "${local.name_prefix}-web"
Environment = var.environment
}
}
# 输出值
output "instance_ip" {
value = aws_instance.web.public_ip
}
4.2.2 模块化设计原则
- 单一职责: 每个模块只管理一类资源(如网络、计算、数据库)。
- 版本化: 使用 Git 标签或 Terraform Registry 管理模块版本,避免隐式变更。
- 输入输出契约: 明确定义
variable与output,隐藏内部实现细节。 - 组合而非继承: 通过
module块嵌套组合,避免模块内部条件分支过多。
# 调用网络模块
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.0.0"
name = "${var.environment}-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24"]
enable_nat_gateway = true
}
模块设计避坑: 避免在模块内部使用
count 或 for_each 创建大量资源,这会导致 plan 输出难以阅读。优先将循环逻辑放在调用方。
4.3 状态管理后端
State 是 Terraform 的核心敏感资产,包含资源 ID、连接信息及依赖关系。平台工程必须采用远程后端(Remote Backend)实现状态共享、锁定与版本历史。
4.3.1 常用后端对比
| 后端类型 | 锁定机制 | 适用场景 | 注意事项 |
|---|---|---|---|
| S3 + DynamoDB | DynamoDB 表行锁 | AWS 原生环境,团队协作 | 需配置 DynamoDB 表;S3 版本控制必须开启 |
| Azure Storage | Blob 租约锁 | Azure 环境 | 支持公共/私有容器;需 SAS 令牌或 RBAC |
| GCS | 对象版本控制 + 条件更新 | GCP 环境 | 需启用对象版本控制;IAM 权限精细控制 |
| Terraform Cloud | 内置工作区锁 | 全托管,SaaS 模式 | 需考虑数据驻留与网络隔离 |
4.3.2 后端配置示例(S3 + DynamoDB)
terraform {
backend "s3" {
bucket = "my-platform-terraform-state"
key = "prod/network/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-state-lock"
}
}
安全警告: State 文件可能包含明文密码、密钥或连接字符串。务必启用存储后端的加密(如 S3 SSE-S3 或 KMS),并限制 IAM 权限仅允许最小必要操作(
s3:GetObject/s3:PutObject)。
4.4 Terraform 核心工作流与状态流转
下图展示了从代码编写到基础设施变更的完整状态流转,突出 State 在 Plan 与 Apply 阶段的核心作用。
4.5 平台工程中的 IaC 策略
在发布工程自助门户中,Terraform 不仅仅是 CLI 工具,更是平台能力的核心引擎。以下策略可提升 IaC 的可维护性与安全性:
- 策略即代码(Policy as Code): 集成
terraform-plan输出到 OPA(Open Policy Agent)或 Sentinel,在 Apply 前自动检查合规性(如禁止公开 S3 桶、强制加密)。 - 工作区(Workspace)隔离: 每个环境(dev/staging/prod)使用独立 Workspace 或独立 State 文件,避免环境间资源冲突。
- 自动化 CI/CD 集成: 在 GitLab CI / GitHub Actions 中运行
terraform plan,将输出作为 MR 评论;仅允许apply在合并到主分支后触发。 - 状态文件加密与备份: 后端存储必须启用加密(如 AWS KMS),并配置跨区域备份策略,防止单点故障。
平台工程最佳实践: 将 Terraform 模块封装为内部 Registry(如 Terraform Enterprise 或 GitLab Terraform Module Registry),平台团队统一发布版本,应用团队通过
source 引用,无需关心底层实现。