基础设施即代码(IaC)基础:定义、原则与工具对比

基础设施即代码(Infrastructure as Code, IaC)是平台工程与 SRE 实践的基石。它通过机器可读的定义文件(而非手动配置)来管理和配置基础设施,将传统运维的“手工操作”转变为“代码驱动”。本章将深入剖析 IaC 的核心定义、声明式与命令式的根本差异、主流工具 Terraform 与 Pulumi 的对比,以及 IaC 在云原生环境中的关键角色。

1. IaC 的定义与核心原则

IaC 是一种通过代码(而非手动流程)来定义、部署和管理基础设施的实践。其核心目标是实现基础设施的版本控制、自动化、可重复性和一致性。

核心原则:
  • 幂等性(Idempotency): 无论执行多少次,最终状态始终与定义一致。
  • 版本控制(Version Control): 所有基础设施定义文件(如 Terraform 的 .tf 文件)都应存储在 Git 中,支持回滚、审计与协作。
  • 自动化(Automation): 通过 CI/CD 管道自动执行基础设施的创建、更新与销毁,消除人为错误。
  • 自文档化(Self-Documenting): 代码本身就是基础设施的精确文档,无需额外维护独立的文档。
  • 可测试性(Testability): 基础设施代码可以像应用代码一样进行单元测试、集成测试和合规性检查。

2. 声明式 vs 命令式:两种范式的根本差异

IaC 工具主要分为声明式(Declarative)和命令式(Imperative)两种范式。理解其差异是选择工具和设计架构的前提。

维度 声明式(Declarative) 命令式(Imperative)
核心思想 描述“最终状态是什么” 描述“如何一步步达到状态”
操作方式 用户定义目标状态,工具自动计算并执行变更 用户编写具体步骤(创建、删除、更新)
幂等性 天然幂等,重复执行结果一致 需手动保证幂等,容易因状态不一致而出错
可读性 高,代码直接反映最终架构 低,代码反映的是操作流程,而非最终架构
典型工具 Terraform, Pulumi (YAML/JSON), AWS CloudFormation Ansible (Playbook), Chef (Recipe), Shell 脚本
适用场景 云资源编排、长期运行的基础设施 配置管理、一次性任务、复杂逻辑控制
平台工程建议: 在编排弹性伸缩任务时,优先采用声明式范式。例如,使用 Terraform 定义“集群期望节点数为 10”,而非编写脚本“如果节点数小于 10,则创建节点”。声明式能更好地应对云环境的动态变化,避免“配置漂移”。
声明式 vs 命令式工作流对比 声明式(Declarative) 1. 用户定义目标状态(.tf 文件) 2. Terraform 读取当前状态 3. 自动计算差异(Diff) 4. 执行变更计划(Plan) 5. 应用变更(Apply) 最终状态 = 目标状态 ✅ 命令式(Imperative) 1. 用户编写步骤(Shell 脚本) 2. 检查当前状态(if 条件) 3. 执行创建/更新命令 4. 再次检查状态 5. 处理错误与重试 最终状态依赖步骤正确性 ⚠️

3. Terraform 与 Pulumi 对比

Terraform 和 Pulumi 是目前最主流的声明式 IaC 工具。Terraform 使用 HCL(HashiCorp Configuration Language),而 Pulumi 允许使用通用编程语言(TypeScript, Python, Go, C# 等)。

对比维度 Terraform Pulumi
语言 HCL(领域特定语言) 通用语言(TS, Python, Go, C#)
状态管理 后端存储(S3, Consul, Terraform Cloud) 后端存储(S3, GCS, Pulumi Cloud)
模块化 Registry 模块,版本化 包管理器(npm, pip, go mod)
循环/条件 count, for_each, 条件表达式 原生语言循环(for, while)
调试体验 Plan/Apply 流程,日志级别 IDE 调试器,断点,堆栈跟踪
生态成熟度 极高,Provider 丰富,社区庞大 高,增长迅速,云原生支持好
学习曲线 中等(需学习 HCL) 低(复用已有编程技能)
选型注意: 如果团队以运维/SRE 为主,且对 HCL 接受度高,Terraform 是更稳妥的选择。如果团队以开发工程师为主,且希望利用 IDE 的代码补全、类型检查和调试能力,Pulumi 能显著提升效率。在弹性伸缩场景中,Pulumi 的循环和条件逻辑更适合编写复杂的伸缩策略。

4. IaC 在云原生环境中的角色

在云原生环境中,IaC 不仅是资源管理工具,更是整个平台工程体系的“粘合剂”。它连接了应用部署、网络策略、安全合规和成本管理。

  • Kubernetes 集群管理: 使用 Terraform 或 Pulumi 创建 EKS/GKE/AKS 集群,并配置 Node Group、VPC、IAM 角色。
  • 弹性伸缩策略定义: 通过 IaC 定义 HPA(Horizontal Pod Autoscaler)、Cluster Autoscaler 和 KEDA 触发器,实现“伸缩即代码”。
  • GitOps 集成: IaC 代码存储在 Git 仓库中,通过 ArgoCD 或 Flux 自动同步到目标环境,实现“声明式 GitOps”。
  • 合规与安全: 在 IaC 代码中嵌入安全策略(如禁止公开 S3 桶),通过 Policy as Code(如 OPA/Sentinel)在部署前自动拦截违规配置。
  • 多环境一致性: 通过 IaC 模块化,确保开发、测试、生产环境的基础设施配置完全一致,消除“环境差异”问题。
IaC 在云原生环境中的角色 IaC 核心层 Terraform / Pulumi GitOps 管道 ArgoCD / Flux K8s 集群 EKS / GKE / AKS 弹性伸缩 HPA / KEDA 安全合规 OPA / Sentinel 成本管理 Infracost IaC 作为平台工程的核心编排层,向下管理基础设施,向上对接 GitOps 与策略引擎

5. 实践案例:使用 Terraform 定义弹性伸缩策略

以下是一个使用 Terraform 定义 AWS EKS 集群的 Cluster Autoscaler 和 HPA 的简化示例,展示 IaC 如何将伸缩策略代码化。

# 定义 EKS 集群的 Node Group 自动伸缩
resource "aws_eks_node_group" "example" {
  cluster_name    = aws_eks_cluster.example.name
  node_group_name = "example-node-group"
  node_role_arn   = aws_iam_role.example.arn
  subnet_ids      = aws_subnet.example[*].id

  scaling_config {
    desired_size = 2
    max_size     = 10
    min_size     = 1
  }

  # 实例类型
  instance_types = ["t3.medium"]
}

# 定义 HPA(通过 Kubernetes Provider)
resource "kubernetes_horizontal_pod_autoscaler_v2" "example" {
  metadata {
    name = "example-hpa"
  }

  spec {
    max_replicas = 20
    min_replicas = 2

    scale_target_ref {
      api_version = "apps/v1"
      kind        = "Deployment"
      name        = "example-app"
    }

    metric {
      type = "Resource"
      resource {
        name = "cpu"
        target {
          type                = "Utilization"
          average_utilization = 70
        }
      }
    }
  }
}
关键点: 通过 IaC 定义伸缩策略后,任何对伸缩参数的修改(如调整 max_size 或 CPU 阈值)都需经过代码审查(Code Review)和 CI/CD 管道,确保变更可追溯、可回滚。这避免了运维人员直接在生产环境手动修改伸缩组带来的风险。