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 资源)且版本化——模块是库,用同样评审纪律对待。