生产协作
本章目标:把前 8 章串成一套可放心用于生产的协作规范——最小权限、密钥管理、破坏性变更护栏、命名策略与审计。技术会过时,但「谁能动、动了什么、怎么回滚」的纪律不会。 你能照着搭出一套团队可用的 Terraform 协作基线。
1. 执行身份:最小权限 + 临时凭据
Terraform 执行的身份(本地或 CI)应只拥有完成本职所需的权限,且尽量用临时凭据而非长期密钥。
| 方式 | 说明 |
|---|---|
| 云厂商 OIDC(推荐 CI) | CI 用工作负载身份联邦换短期令牌,无长期 AK/SK |
| 实例/任务角色 | 跑在云上的 CI runner 用角色,不落盘密钥 |
| 本地开发 | 个人短期凭证,避免把 AK/SK 写进 ~/.aws/credentials 长期留存 |
任何 AKIA... / 私钥一旦进 Git 历史,基本等于泄露(有扫描机器人盯梢)。用 OIDC / 角色,或至少用 aws-vault 等短期凭据代理。泄露立即吊销 + 轮换。
2. 密钥管理:别让 state 变成密码库
回顾第 5 章:state 可能保存 provider 接收到的敏感值,sensitive = true 只影响展示,不能把秘密从 state 中移除。所以「密钥」要分层处理:
- 不写死在
.tf:用variable+sensitive = true经TF_VAR_*或 CI 密钥注入;这能避免泄露到代码和日志,但传给 provider 的秘密仍可能进入 state。 - 让工作负载在运行时读取密钥:Terraform 只管理 Secret 的名称、ARN 或访问策略,由应用通过角色从 Secrets Manager / Vault 获取实际值。直接读取
secret_string等 data source 属性,同样可能把明文写入 state。data "aws_secretsmanager_secret" "db" {name = "prod/db/master"}# 不读取 secret_string;工作负载只接收 data.aws_secretsmanager_secret.db.arn# 再在运行时通过自身角色读取实际密钥 - backend 加密 + 最小权限:state 桶 SSE-KMS,IAM 按角色细分谁能读。
- 轮换优先:能轮就轮,凭据泄露后第一时间轮换而非仅靠权限收紧。
3. 破坏性变更护栏
apply 一旦执行就是真金白银的变更。层层设防:
3.1 prevent_destroy
对不可重建的资源(数据库、有数据的存储桶、生产 LB)加护栏,任何会触发其销毁的 plan 都会直接报错拦截:
resource "aws_db_instance" "main" {
# ...
lifecycle {
prevent_destroy = true
}
}
它防的是「被 Terraform 删」。若有人手动在控制台删了真实资源,state 仍在,apply 会尝试重建——所以护栏要配合权限管控,而非替代。
3.2 评审 + 流水线门禁
- 本地不直接
apply生产:所有生产变更走 PR → CI plan → 评审 → 流水线apply。(流程见第 7 章) - 禁止
-auto-approve上生产:必须有人看过计划。 - 变更窗口:生产变更限制在约定窗口,避开业务高峰。
3.3 供应链:外部模块与 provider 审查
- 外部模块固定受保护 tag 或 commit SHA,绝不跟分支。
- 提交
.terraform.lock.hcl锁定 provider 校验和;模块版本仍由source中的ref负责。 - 定期审视第三方模块/provider 的来源与更新(供应链安全)。
4. 命名与 tagging 策略
统一的标签是成本核算、权限、运维检索的基础(第 4 章提过,这里落到「强制」):
variable "mandatory_tags" {
type = map(string)
default = {
Environment = "prod"
Owner = "platform-team"
Project = "rootwiki"
CostCenter = "cc-1234"
ManagedBy = "terraform"
}
}
落地方式:
- 把
mandatory_tags作为模块公共输入,缺省不给默认值,强制调用方填。 - 用
awsprovider 的default_tags给账号下所有资源统一打底(provider 级兜底)。 - 定期用
resourcegroupstaggingapi/ 云账单按标签出成本报表。
5. 策略即代码(Policy as Code)
光靠人审 plan 不够稳,用代码强制规则。把 plan 转 JSON 交给策略引擎:
| 引擎 | 场景 |
|---|---|
| Sentinel | Terraform Cloud/Enterprise 原生 |
| OPA / Conftest | 自托管,对 terraform show -json planfile 跑 Rego 规则 |
常见规则:禁止公开 S3、强制加密、强制必需标签、限制可创建实例规格、禁止 0.0.0.0/0 入站等。
terraform show -json planfile > plan.json
conftest test plan.json --policy policy/ # 不通过则 CI 失败
6. 审计与灾难恢复
- state 在远程 backend:开启版本控制(误改可回滚)+ 定期备份(导出到独立冷存储)。
- Git 是配置真相源:每次变更有 PR、有 review、有记录。
- 锁表异常恢复:
force-unlock仅在确认无人操作时(见第 5 章)。 - 演练回滚:定期做「从备份 state 恢复 / 用旧 commit 重新 apply」的演练,别等出事才第一次试。
7. 一套可落地的协作基线(清单)
- 执行身份用 OIDC / 角色,无长期密钥落盘
- state backend 加密 + 最小权限 IAM,开启版本控制
- 密钥经变量/密钥库注入,不写死;
sensitive仅打码 - 关键资源
prevent_destroy;生产禁-auto-approve、走 PR + 流水线 - 外部模块用受保护 tag / commit SHA,provider 固定版本并提交 lock 文件
- 强制 tagging,可出成本与责任报表
- 策略即代码拦截高危变更
- 有 state 备份与回滚演练
8. 练习与验收
练习 A
- 给一个
aws_db_instance加prevent_destroy = true,故意改会触发重建的字段,plan应被拦截 - 移除护栏后再
plan,确认拦截解除
练习 B(综合)
- 在 CI 配置里加一步:
terraform show -json planfile后用 conftest/简单脚本检查「是否存在0.0.0.0/0入站」 - 写一份本团队的「Terraform 协作基线」文档,把上面第 7 节清单改成你们的版本
验收清单
- 执行身份走最小权限 + 临时凭据,无长期密钥
- 密钥管理分层(变量注入 / 密钥库 / state 加密)
- 关键资源有
prevent_destroy,生产变更走评审流水线 - tagging 强制且可归因,策略即代码兜底
- state 有备份、版本控制与回滚演练
至此,Terraform 系列 9 篇(含导读)完结。回顾路线:装好环境 → 学 HCL → 配 Provider 与多环境 → 管 state → 抽模块 → 规范变更流程 → 纳管存量与漂移 → 收口生产协作。把它和 Ansible 配置编排、Python 运维自动化 组合,就能覆盖「起基础设施 → 初始化与持续配置 → 巡检与平台对接」的完整运维链路。