Terraform 与 OpenTofu 基础设施即代码生产治理

基础设施即代码(IaC)真正的价值不是“用代码创建虚机”,而是把基础设施的期望状态、评审、审计、复用、漂移检测和恢复流程纳入工程体系。Terraform 与 OpenTofu 具有相似的 HCL 工作流,但生产落地必须处理 State、锁、模块、Provider、密钥、导入、销毁保护、流水线和组织权限。

apply、destroy、state rm、state push、force-unlock 和资源替换都可能直接改变生产。不要在个人电脑上用管理员凭证对生产执行未经评审的计划。

一、IaC 的适用边界

适合:云资源、网络、负载均衡、DNS、IAM、集群基础、可重复的平台组件。谨慎管理:数据库内部数据、一次性迁移、频繁变化的业务配置、没有稳定 API 的设备和需要复杂人工确认的操作。

HCL 配置 + 模块 + Provider 锁文件
        ↓
fmt / validate / lint / security check
        ↓
Plan(可审阅变更)
        ↓ 审批
Apply(使用同一份 Plan)
        ↓
远端 State + 锁 + 审计日志

二、State 是核心资产

State 保存配置资源与真实对象的绑定,也可能包含密码、连接串和私有地址等敏感数据。它不是普通缓存。

生产要求:

  • 使用支持访问控制、加密、版本控制和锁的远端 Backend;
  • 不把 State 提交 Git;
  • 限制下载和读取权限;
  • 备份并验证恢复;
  • 监控锁、版本和异常写入;
  • 不直接手工编辑 JSON。

OpenTofu 支持 State/Plan 静态加密,但密钥丢失会导致 State 无法读取;加密也不防止文件损坏或旧 State 重放。

三、State 锁与并发

支持锁的 Backend 会在写操作前自动加锁,避免多个 Apply 同时修改同一 State。不要用 -lock=false 绕过生产锁。

terraform plan -lock-timeout=10m -out=prod.tfplan
terraform apply prod.tfplan

force-unlock 只能在确认原执行进程已结束、锁确实遗留,并核对 Lock ID 后使用。错误解锁可能造成多个写者和 State 损坏。

四、State 拆分策略

State 太大时,计划慢、影响面大、权限难隔离;拆得太碎又会产生依赖和输出耦合。常按以下边界拆分:

  • 账号/订阅与区域;
  • 网络基础与应用资源;
  • 共享平台与业务团队;
  • 生命周期和变更频率;
  • 权限和故障域。

不要仅用 Workspace 代替所有环境隔离。高风险生产通常需要独立 Backend、凭证和审批边界。

五、模块设计与版本治理

模块应表达稳定能力,而不是把所有参数都暴露。优秀模块包含:

  • 清晰输入、输出和类型约束;
  • 合理默认值与前置条件;
  • 标签、日志、加密等安全基线;
  • 示例和升级说明;
  • 单元/集成测试;
  • 语义化版本和变更日志。
module "app_network" {
  source  = "git::ssh://git.example/iac/network.git?ref=v2.4.1"
  name    = "payment-prod"
  cidr    = "10.42.0.0/16"
  enable_flow_logs = true
}

生产必须固定模块版本。直接引用 main 会让同一配置在不同时间产生不同结果。

六、Provider 与锁文件

Provider 是实际调用基础设施 API 的代码,应固定版本范围并提交 .terraform.lock.hcl。升级时阅读变更说明,在测试环境生成 Plan,确认 Schema 和默认行为变化。

terraform {
  required_version = ">= 1.6, < 2.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 6.0"
    }
  }
}

版本示例需要按组织实际兼容性调整,不能把“最新版本”当作自动安全。

七、变量、敏感值与凭证

sensitive = true 只控制部分界面输出,不保证敏感值不会进入 State。安全做法:

  • 流水线使用短期身份或工作负载身份;
  • 不在 .tfvars 中提交生产密钥;
  • 从 Vault/KMS/CI Secret 注入;
  • 限制 Plan 文件下载,因为 Plan 也可能包含敏感值;
  • 避免通过 Output 暴露秘密;
  • 定期轮换并审计 Provider 凭证。

八、生产流水线

推荐阶段:

  1. fmt -check;
  2. init(只读或受控插件源);
  3. validate;
  4. Lint、安全与策略检查;
  5. 生成二进制 Plan;
  6. 将人类可读摘要附加到 PR;
  7. 生产审批;
  8. 使用同一份已审批 Plan 执行 Apply;
  9. 保存日志、State 版本和变更结果。

Plan 与 Apply 之间若配置、变量、Provider 或 State 已改变,应重新 Plan,而不是继续执行旧结果。

九、Plan 审阅重点

审阅不能只看“3 add, 1 change, 0 destroy”。需要判断:

  • 是否出现 Replace;
  • 数据库、磁盘、IP、DNS、IAM 是否被删除或重建;
  • 安全组是否扩大到公网;
  • 加密、日志、备份是否被关闭;
  • Count/for_each Key 改动是否造成地址整体变化;
  • Provider 默认值是否改变;
  • 资源依赖是否导致级联更新;
  • 未知值是否掩盖关键差异。

十、策略即代码

通过 OPA/Conftest、Sentinel 或组织策略阻止高风险配置,例如:

  • 公网开放管理端口;
  • 未加密磁盘或数据库;
  • 未启用审计日志;
  • 生产资源缺少删除保护;
  • 标签、区域或实例规格不合规;
  • 计划中删除数量超过阈值。

策略应有分级:硬阻断、需审批、仅提示。一次性将所有规则设为阻断,会导致团队绕过治理。

十一、导入存量资源

导入只是把真实对象与资源地址绑定,不会自动生成完美配置。安全流程:

  1. 盘点真实资源和依赖;
  2. 编写最小配置;
  3. 在独立 State 中导入;
  4. 多次 Plan,逐步补齐差异;
  5. 确保最终 Plan 为无变更或仅包含明确变更;
  6. 再纳入正式流水线。
import {
  to = aws_s3_bucket.logs
  id = "company-prod-logs"
}

不要在第一次导入后立即 Apply 大量“默认值修正”。

十二、重构资源地址

模块重命名、count 改 for_each 或目录重构可能让工具误判资源需删除重建。优先使用 moved 块表达地址迁移。

moved {
  from = aws_instance.web
  to   = module.web.aws_instance.this
}

重构与业务参数变更应分开提交,让 Plan 更容易审阅。

十三、漂移检测

手工控制台变更、自动伸缩、外部控制器和紧急处置都会造成漂移。定期执行只读 Plan,并把结果分类:

  • 应回写代码的有效变化;
  • 应由 IaC 恢复的违规变化;
  • 应通过 ignore_changes 精确忽略的外部管理字段;
  • 应重新划分资源所有权的冲突。

不要用大范围 ignore_changes = all 消除噪声。

十四、销毁与替换保护

关键资源可配置生命周期保护,但它不是唯一防线。

lifecycle {
  prevent_destroy = true
}

还应结合云侧删除保护、备份、审批、策略和权限隔离。prevent_destroy 被从配置中删除后不再生效,因此不能替代组织控制。

十五、故障场景

Apply 中断

先检查真实资源与 State,不要立即重跑。Provider 可能已经创建资源但尚未写回 State。重新 Plan,确认是继续、导入还是清理。

State 写回失败

保护本地生成的恢复 State,暂停其他执行,核对 Backend 当前版本后再按官方流程 Push。state push -force 是最后手段。

资源在控制台被删除

Plan 通常会尝试重建。先确认删除是事故还是有意操作,检查数据恢复和依赖后再 Apply。

锁长期存在

确认流水线执行器、进程和后台任务已经结束,核对锁持有者与时间,再决定解锁。

十六、灾难恢复

需要备份:代码仓库、模块仓库、Provider 镜像或缓存策略、Backend State 历史、加密密钥、流水线配置、策略、变量和身份配置。

演练方式是在隔离账号或沙箱中恢复 State,执行 plan -refresh-only 或等价检查,确认能识别真实资源且不会大规模重建。仅保存 HCL 而没有 State,并不能无损接管现有基础设施。

十七、监控与度量

关注:Plan/Apply 成功率、执行时长、等待锁时间、漂移数量、Replace/Destroy 数、策略阻断、人工控制台变更、模块版本分布、失败恢复时间和生产紧急变更次数。

十八、上线检查清单

  • State 使用加密、版本控制、锁和最小权限远端 Backend;
  • 配置、模块和 Provider 版本固定;
  • 生产凭证使用短期身份,不落地个人电脑;
  • Plan 经过机器策略与人工审阅;
  • Apply 使用已审批的同一份 Plan;
  • 高风险资源具备多层删除保护;
  • 定期漂移检测;
  • State、密钥和流水线完成恢复演练。

参考资料

  • Terraform State:https://developer.hashicorp.com/terraform/language/state
  • Terraform State Locking:https://developer.hashicorp.com/terraform/language/state/locking
  • OpenTofu State Backends:https://opentofu.org/docs/language/state/backends/
  • OpenTofu State and Plan Encryption:https://opentofu.org/docs/language/state/encryption/
Copyright © yan-jian.com 2023 - 2026 · Powered by GitBook更新时间: 2026-11-03 16:23:44

results matching ""

    No results matching ""