跳到主要内容

生产协作

本章目标:把前 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 中移除。所以「密钥」要分层处理:

  1. 不写死在 .tf:用 variable + sensitive = true 经 TF_VAR_* 或 CI 密钥注入;这能避免泄露到代码和日志,但传给 provider 的秘密仍可能进入 state。
  2. 让工作负载在运行时读取密钥: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
    # 再在运行时通过自身角色读取实际密钥
  3. backend 加密 + 最小权限:state 桶 SSE-KMS,IAM 按角色细分谁能读。
  4. 轮换优先:能轮就轮,凭据泄露后第一时间轮换而非仅靠权限收紧。

3. 破坏性变更护栏​

apply 一旦执行就是真金白银的变更。层层设防:

3.1 prevent_destroy​

对不可重建的资源(数据库、有数据的存储桶、生产 LB)加护栏,任何会触发其销毁的 plan 都会直接报错拦截:

resource "aws_db_instance" "main" {
# ...
lifecycle {
prevent_destroy = true
}
}
prevent_destroy 的边界

它防的是「被 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 作为模块公共输入,缺省不给默认值,强制调用方填。
  • 用 aws provider 的 default_tags 给账号下所有资源统一打底(provider 级兜底)。
  • 定期用 resourcegroupstaggingapi / 云账单按标签出成本报表。

5. 策略即代码(Policy as Code)​

光靠人审 plan 不够稳,用代码强制规则。把 plan 转 JSON 交给策略引擎:

引擎场景
SentinelTerraform 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

  1. 给一个 aws_db_instance 加 prevent_destroy = true,故意改会触发重建的字段,plan 应被拦截
  2. 移除护栏后再 plan,确认拦截解除

练习 B(综合)

  1. 在 CI 配置里加一步:terraform show -json planfile 后用 conftest/简单脚本检查「是否存在 0.0.0.0/0 入站」
  2. 写一份本团队的「Terraform 协作基线」文档,把上面第 7 节清单改成你们的版本

验收清单

  • 执行身份走最小权限 + 临时凭据,无长期密钥
  • 密钥管理分层(变量注入 / 密钥库 / state 加密)
  • 关键资源有 prevent_destroy,生产变更走评审流水线
  • tagging 强制且可归因,策略即代码兜底
  • state 有备份、版本控制与回滚演练

至此,Terraform 系列 9 篇(含导读)完结。回顾路线:装好环境 → 学 HCL → 配 Provider 与多环境 → 管 state → 抽模块 → 规范变更流程 → 纳管存量与漂移 → 收口生产协作。把它和 Ansible 配置编排、Python 运维自动化 组合,就能覆盖「起基础设施 → 初始化与持续配置 → 巡检与平台对接」的完整运维链路。