Terraform Operations 是一份面向 Terraform / OpenTofu 基础设施即代码的运维参考技能,涵盖布局、状态、模块、安全、CI/CD 与密钥管理。版本背景为 2026-06 核验:Terraform 1.15.x(自 1.6 起采用 BUSL-1.1 许可)、OpenTofu 1.12.x(MPL-2.0,Terraform 1.5.x 的 fork)。除特别标注外,下列命令通用(terraform ↔ tofu)。
【项目布局】 技能提供布局决策树:单一环境单团队使用单根模块 + tfvars;多环境(dev/staging/prod)若各环境需要不同后端/账户/区域(生产隔离通常需要),推荐按环境划分目录(environments/{dev,staging,prod} 各自作为薄根模块调用共享模块);仅少量变量不同且后端账户相同时,workspaces 可接受但有注意事项。多团队/多状态文件/平台工程场景采用按环境目录 + 按组件拆分状态(network/data/app),可考虑 Terragrunt、Terraform Stacks(HCP)或 OpenTofu + CI 编排。规范多环境布局中,modules/ 存放可复用子模块(不含 provider/backend 块,versions.tf 仅声明 required_providers),environments/ 存放根模块(每个一个状态文件,含 main.tf、backend.tf、providers.tf、terraform.tfvars、versions.tf,provider 配置只出现在根)。技能解释目录通常优于 workspaces 的原因,涉及隔离后端/账户、误操作爆炸半径、环境特定配置分歧、生产 IAM 隔离、代码审查可见性等。workspaces 适合短期临时副本(如 PR 预览环境),不适合 dev/prod 边界。tfvars 约定包含自动加载的 terraform.tfvars、*.auto.tfvars,显式指定 -var-file=prod.tfvars,以及通过 TF_VAR_ 注入密钥。
【状态管理】 以速查表形式给出常用任务:AWS 远程后端(backend "s3",use_lockfile = true,S3 原生锁定,TF ≥1.10 后不再需要 DynamoDB 表)、用 moved 块重命名资源、用 import 块 + plan -generate-config-out 采纳既有基础设施(配置驱动导入优于 CLI)、用 removed 块删除而不销毁(TF ≥1.7)、漂移检测(terraform plan -detailed-exitcode,退出码 0 干净 / 1 错误 / 2 漂移,可定时执行)、只读查看状态(state list / state show)、状态迁移(state mv,最后手段)、紧急 pull/push。技能强调:能用 moved/removed/import 块表达的,就用块,state mv/rm 立即生效、无审查、无版本记录,笔误可导致真实基础设施孤立;任何状态手术前先 state pull 备份。
【模块】 给出模块调用示例(source、version 版本约束,registry 模块建议 ~> 6.0,生产根模块精确固定)。规则包括:组合优于继承(根模块组合扁平模块,避免层层包裹);子模块不含 provider 块;变量上用 validation 块在 plan 阶段失败;对象属性用 optional(type, default),nullable = false 拒绝显式 null;输出即契约;反对仅重命名变量的薄包装模块。
【应用前安全清单与常见陷阱】 清单包含:认真阅读 plan 输出而非略读、确认 destroy/replace 数量是否意外、检查替换行的 forces replacement 属性、apply 同一份已审查的保存计划(plan -out=tfplan → apply tfplan)、对有状态资源加 prevent_destroy、云端删除保护、除非声明为紧急否则不用 -target、可重排集合用 for_each 而非 count。常见陷阱表涵盖 count 索引位移、-target 习惯、prevent_destroy 的虚假安心、滥用 dynamic 块、未固定 provider 版本、apply 与已审查 plan 不一致,并给出修复建议。
【CI/CD】 流程:PR 打开 → fmt -check → validate → tflint → trivy/checkov → plan → plan 作为 PR 评论发布;PR 合并 → 全新 plan → apply,通过 OIDC 认证,不用长期云密钥;每夜 → plan -detailed-exitcode,退出码 2 触发漂移告警。推荐全面使用 OIDC(aws-actions/configure-aws-credentials 的 role-to-assume),工作流中固定 action SHA 而非浮动 tag。策略门禁包括 tflint、trivy config / checkov、OPA/conftest。编排器对比涵盖纯 GitHub Actions、Atlantis、HCP Terraform / Terraform Cloud(免费 ≤500 资源)、Spacelift/env0/Digger/Scalr。技能提供脚本 scripts/check-action-refs.sh 校验 uses: 引用:--offline 做结构校验(CI 安全门禁),--live 通过 GitHub API 解析(404 表示 DRIFT,退出码 10;API 不可达/限流退出码 7,仅建议性,不阻断构建);建议 --live 定期运行而非作为阻断 PR 门禁,离线检查放入 PR CI;设置 GITHUB_TOKEN 避免未认证限流。
【测试】 介绍原生测试框架(TF ≥1.6 / OpenTofu ≥1.6)的 .tftest.hcl 写法:variables、run 块、command = plan(快速类单元测试)或 apply(真实集成,需沙箱账户)、assert、expect_failures。terraform test 运行 tests/ 下所有 *.tftest.hcl。mock_provider 块(TF ≥1.7)可无凭据模拟 apply。Terratest 是多工具/Go 级编排的重量级替代方案。
【密钥】 速查表:sensitive = true(所有版本,仅从 CLI 输出脱敏,状态中仍明文);临时资源(TF ≥1.10 / OpenTofu ≥1.11,运行时获取,不落状态或 plan);write-only 参数(password_wo,TF ≥1.11 / OpenTofu ≥1.11,发送给 provider 但不存状态,通过 _wo_version 轮换);SOPS 加密 tfvars;Vault / 云密钥管理器;OpenTofu 状态加密(≥1.7,客户端 AES-GCM,Terraform 无对应功能)。规则零:始终视状态为密钥,加密后端、限制 IAM、不提交 *.tfstate。
【Terraform vs OpenTofu】 对比许可(BUSL-1.1 vs MPL-2.0)、当前版本(1.15.x vs 1.12.x)、各自独占功能(Terraform:Stacks、Terraform Cloud agents、terraform query;OpenTofu:状态/plan 加密、provider for_each、-exclude 标志、backend/module 块早期变量求值、OCI registry 分发、.tofu 扩展名)、注册表(registry.terraform.io vs registry.opentofu.org)、兼容性(在 1.5.x 分叉)。决策建议:商业再分发 IaC 工具的供应商用 OpenTofu;使用 HCP Terraform/Sentinel 的团队用 Terraform;其他人两者皆可,OpenTofu 的状态加密是最大技术差异点。
【命令速查】 列出常用命令:init -upgrade、fmt -recursive -check、validate、plan -out=tfplan、show -json tfplan | jq、apply tfplan、plan -detailed-exitcode、plan -refresh-only、apply -replace=、state pull > backup.json、output -json、graph | dot,以及 tofu init(命令动词一致)。