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 为例:

IaC 标准工作流(Terraform 示例) IaC 标准工作流(Terraform 示例) 1. 编写 HCL 代码 2. terraform init 3. terraform plan 4. terraform apply 状态文件(terraform.tfstate) 记录当前基础设施的真实状态,用于后续的增量更新和漂移检测

4.5 IaC 最佳实践

在平台工程中实施 IaC 时,应遵循以下关键实践:

  1. 代码版本化: 将所有 IaC 代码(包括模块、变量、状态文件配置)纳入 Git 仓库,与应用程序代码采用相同的分支策略和代码审查流程。
  2. 模块化与复用: 将通用基础设施模式(如 VPC 网络、数据库集群、Kubernetes 集群)封装为可复用的模块。Terraform 使用 Module,Pulumi 使用 Component Resource。
  3. 远程状态与锁定: 使用远程 Backend(如 AWS S3 + DynamoDB、Terraform Cloud、Pulumi Cloud)存储状态文件,并启用状态锁定,防止多人同时执行导致状态冲突。
  4. 环境隔离: 使用 Workspace(Terraform)或 Stack(Pulumi)隔离开发、测试、生产环境。每个环境拥有独立的状态文件和变量配置。
  5. 持续验证与自动化: 在 CI/CD 流水线中集成 terraform plan 或 pulumi preview,在合并请求中自动生成基础设施变更预览,人工确认后再执行 apply。
  6. 安全与合规: 使用策略即代码工具(如 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 代码定义的状态保持一致。