Skip to content
返回构建教程

IaC 入门

用 Terraform/Pulumi 定义云基础设施,让环境可复现且可丢弃。

为什么

点击运维的基础设施不可评审、不可复现、不可丢弃——你无法创建匹配 prod 的 staging 环境,因为没人记得勾了哪些复选框。基础设施即代码让每个云资源成为评审过的版本化产物:新 staging 环境是 'terraform apply -var-file=staging.tfvars',按构造匹配 prod。prod 漂移时你 diff 计划而非截控制台图。盈亏平衡是重建一次环境——如果你曾在周五手工重建 VPC,你已知道没有 IaC 的代价。

何时使用

有 ≥2 个云资源或 ≥2 个环境时。Terraform 基础约 2-3 小时。纯静态部署到 CDN 可跳过。

如何做

1. 选 Terraform(HCL、声明式)或 Pulumi(TS/Python、可编程)
   - Terraform:生态更大,纯云资源更简单
   - Pulumi:团队已写 TS 且要循环/条件时更好

2. 按环境组织:modules/(可复用)+ envs/{staging,prod}/(组合)
   - modules/db/ 定义 Postgres 实例及所有参数
   - envs/staging/main.tf 用 staging 专用变量调该模块

3. 用远程 state 后端(S3+DynamoDB 锁,或 Terraform Cloud)
   - 团队里永不用本地 state——会得到并发 apply 损坏
   - State 含密钥输出值;用加密 + IAM 保护后端

4. 每个资源打标签 {Environment, Project, ManagedBy="terraform"}
   - 标签让你找未托管资源(漂移)并在账单面板成本分摊

5. CI PR 上 plan:每个 PR 跑 terraform plan,合 main 时 apply
   - PR 评论显示 plan diff——评审者在 apply 前看到确切云变更

示例

# modules/db/main.tf
resource "aws_db_instance" "main" {
  identifier         = "${var.env}-db"
  engine             = "postgres"
  instance_class     = var.instance_class
  allocated_storage  = 20
  name               = "appdb"
  username           = var.db_user
  password           = var.db_password  # 来自密钥管理器,非明文
  tags = {
    Environment = var.env
    ManagedBy   = "terraform"
  }
}

# envs/staging/main.tf
module "db" {
  source        = "../../modules/db"
  env           = "staging"
  instance_class = "db.t4g.small"
}

常见问题

  • ⚠本地存 state,两开发者同时 apply 时得 'state lock' 错误。
  • ⚠DB 密码放明文变量而非引用密钥管理器——它们以明文进 state 文件。
  • ⚠在控制台手动修资源,Terraform 现在永远显示漂移且 apply 试图'修'回去。
  • ⚠一个巨型 main.tf 含 500 资源而非模块——每次变更都有破坏无关资源的风险。

最佳实践

  • ✓CI 里 plan 前跑 'terraform fmt -recursive' 和 'terraform validate'——格式漂移是 PR diff 里的噪音。
  • ✓用 'terraform import' 采纳现有手工创建的资源而非销毁重建。
  • ✓持有数据的资源标 lifecycle { prevent_destroy = true },坏 apply 删不掉 prod 数据。
  • ✓模块小(≤20 资源)且版本化——模块是库,用同样评审纪律对待。