4. 基础设施即代码(IaC)基础
4.1 为什么平台工程需要 IaC?
在平台工程中,环境一致性是核心目标。手动配置基础设施会导致“配置漂移”、环境差异和不可复现的部署。基础设施即代码(IaC)将服务器、网络、数据库等资源的管理从手动操作转变为代码化、版本化、可审计的流程。它是实现“环境一致性基线核验”的基石。
核心价值: 通过 IaC,平台团队可以将环境配置视为软件制品,与应用程序代码一同进行版本控制、代码审查和自动化测试,从而消除环境差异。
4.2 三大主流 IaC 工具核心概念
当前市场主流工具包括 Terraform、Pulumi 和 AWS CloudFormation。下表对比了它们的核心概念与适用场景:
| 维度 | Terraform | Pulumi | AWS CloudFormation |
|---|---|---|---|
| 语言 | HCL(HashiCorp 配置语言) | 通用编程语言(TypeScript, Python, Go, C#, Java 等) | JSON / YAML 模板 |
| 状态管理 | 外部状态文件(本地或远程 Backend) | 外部状态(默认使用 Pulumi Cloud 或自托管) | AWS 服务端管理(无状态文件) |
| 云提供商 | 多云(AWS, Azure, GCP, 阿里云等 200+ Provider) | 多云(AWS, Azure, GCP, Kubernetes 等) | 仅 AWS |
| 资源模型 | Provider + Resource + Data Source | Provider + Resource + Component | Resource + Stack + Change Set |
| 执行引擎 | Plan → Apply 两步验证 | Preview → Up 两步验证 | Change Set → Execute 两步验证 |
| 适用场景 | 多云策略、混合云、平台抽象层 | 需要编程逻辑、复杂循环、条件判断的团队 | 纯 AWS 环境、深度集成 AWS 服务 |
4.3 声明式 vs 命令式:核心范式对比
IaC 的核心在于“声明式”范式。理解声明式与命令式的区别,是掌握 IaC 的关键。
- 声明式(Declarative): 你定义“最终状态”,工具负责如何达到该状态。例如:“我需要一个 EC2 实例,类型为 t3.medium,安全组开放 80 端口。” 工具会自动创建、更新或删除资源以匹配该状态。
- 命令式(Imperative): 你定义“具体步骤”,工具按步骤执行。例如:“先创建一个 VPC,然后创建一个子网,再创建一个安全组,最后启动一个 EC2 实例。” 每一步都需要明确写出。
平台工程建议: 始终优先选择声明式 IaC。声明式代码更易读、更易审计,且能自动处理资源依赖和状态收敛,极大降低环境漂移风险。
下表详细对比了两种范式的差异:
| 对比维度 | 声明式(Declarative) | 命令式(Imperative) |
|---|---|---|
| 关注点 | What(最终状态是什么) | How(如何一步步达到状态) |
| 代码可读性 | 高,直接反映基础设施拓扑 | 低,需要理解执行流程 |
| 状态管理 | 自动跟踪状态,支持漂移检测 | 无状态管理,需手动记录 |
| 幂等性 | 天然幂等,多次执行结果一致 | 需手动编写幂等逻辑 |
| 错误恢复 | 自动回滚或重试至目标状态 | 需编写复杂的错误处理代码 |
| 典型工具 | Terraform, Pulumi, CloudFormation | Ansible, Chef, Shell 脚本 |
4.4 IaC 工作流与状态管理
下图展示了 IaC 的标准工作流,以 Terraform 为例:
4.5 IaC 最佳实践
在平台工程中实施 IaC 时,应遵循以下关键实践:
- 代码版本化: 将所有 IaC 代码(包括模块、变量、状态文件配置)纳入 Git 仓库,与应用程序代码采用相同的分支策略和代码审查流程。
- 模块化与复用: 将通用基础设施模式(如 VPC 网络、数据库集群、Kubernetes 集群)封装为可复用的模块。Terraform 使用 Module,Pulumi 使用 Component Resource。
- 远程状态与锁定: 使用远程 Backend(如 AWS S3 + DynamoDB、Terraform Cloud、Pulumi Cloud)存储状态文件,并启用状态锁定,防止多人同时执行导致状态冲突。
- 环境隔离: 使用 Workspace(Terraform)或 Stack(Pulumi)隔离开发、测试、生产环境。每个环境拥有独立的状态文件和变量配置。
- 持续验证与自动化: 在 CI/CD 流水线中集成
terraform plan或pulumi preview,在合并请求中自动生成基础设施变更预览,人工确认后再执行apply。 - 安全与合规: 使用策略即代码工具(如 Sentinel、OPA、CrossGuard)在 IaC 代码中嵌入安全策略,禁止创建不符合规范(如公开 S3 桶、未加密的 RDS 实例)的资源。
常见陷阱: 避免在 IaC 代码中硬编码敏感信息(如数据库密码、)。应使用变量注入、Secret Store(如 AWS Secrets Manager、HashiCorp Vault)或环境变量来管理机密。
4.6 代码示例对比
以下展示使用 Terraform 和 Pulumi 创建同一组 AWS 资源的代码对比,帮助理解声明式语法的差异:
Terraform (HCL) 示例:
# 创建 S3 存储桶
resource "aws_s3_bucket" "platform_bucket" {
bucket = "platform-env-baseline-001"
acl = "private"
tags = {
Name = "Platform Baseline Bucket"
Environment = "production"
}
}
# 创建 DynamoDB 表用于状态锁定
resource "aws_dynamodb_table" "terraform_lock" {
name = "terraform-state-lock"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
Pulumi (TypeScript) 示例:
import * as aws from "@pulumi/aws";
// 创建 S3 存储桶
const platformBucket = new aws.s3.Bucket("platformBucket", {
bucket: "platform-env-baseline-001",
acl: "private",
tags: {
Name: "Platform Baseline Bucket",
Environment: "production",
},
});
// 创建 DynamoDB 表用于状态锁定
const lockTable = new aws.dynamodb.Table("terraformLock", {
name: "terraform-state-lock",
billingMode: "PAY_PER_REQUEST",
hashKey: "LockID",
attributes: [{
name: "LockID",
type: "S",
}],
});
4.7 环境一致性基线核验中的 IaC 角色
在平台工程中,IaC 是“环境一致性基线核验”的核心执行者。通过以下机制确保基线一致:
- 基线定义: 将环境基线(如安全组规则、IAM 角色、网络 CIDR、Kubernetes 版本)编写为 IaC 模块。
- 自动核验: 在 CI/CD 中运行
terraform plan或pulumi preview,自动检测当前环境与基线代码的差异。 - 漂移修复: 当检测到漂移时,通过
terraform apply自动将环境恢复至基线状态,或生成告警通知平台工程师。 - 移植适配: 通过 IaC 模块的参数化设计,将同一套基线代码适配到不同云区域、不同账户或不同云提供商,实现“一次编写,多处部署”。
关键指标: 平台团队应追踪“环境漂移率”(Drift Rate)和“基线合规率”(Baseline Compliance Rate),确保所有环境始终与 IaC 代码定义的状态保持一致。