跳转至

Terraform 与 OpenTofu

Terraform 和 OpenTofu 都使用声明式配置:代码描述最终应该存在什么,工具通过 Provider 查询真实资源,对比 State 与配置后生成 Plan,再调用远端 API 执行变更。

Terraform 使用 terraform 命令,OpenTofu 使用 tofu 命令。两者核心工作流相近,但团队应为每个环境确定一个主工具,并分别验证 Provider、Module、State Backend 与版本兼容性,不能在同一个 State 上随意交替执行。

核心概念

概念 作用 需要注意
Provider 连接云平台、虚拟化平台或其他 API 固定来源和版本,升级会影响行为
Resource 要创建和管理的真实对象 删除 Resource 代码可能导致真实资源被销毁
Data Source 查询已经存在的外部对象 读取不等于纳入 State 管理
Variable 表达环境差异 密码不能直接写入 Git
Output 输出 IP、ID、域名等结果 敏感输出仍可能进入 State
Module 封装可复用的资源组合 应有明确输入、输出与版本
State 记录代码地址与真实资源 ID 的对应关系 可能包含敏感信息,是核心数据
Backend 保存 State 并支持团队协作 生产环境不应使用个人本地 State

配置结构示例

terraform {
  required_providers {
    example = {
      source  = "company/example"
      version = "~> 1.4"
    }
  }
}

provider "example" {
  endpoint = var.api_endpoint
  token    = var.api_token
}

resource "example_virtual_machine" "app" {
  name   = "app-${var.environment}-01"
  cpu    = 4
  memory = 8192
}

output "app_ip" {
  value = example_virtual_machine.app.ip_address
}

这只是结构示例,Resource 名称和字段由具体 Provider 决定。令牌应通过受保护的 CI 变量、环境变量或密钥系统注入。

标准工作流

Terraform:

terraform init
terraform fmt -check
terraform validate
terraform plan -out=tfplan
terraform apply tfplan

OpenTofu:

tofu init
tofu fmt -check
tofu validate
tofu plan -out=tfplan
tofu apply tfplan
步骤 作用 是否改变基础设施
init 初始化 Backend,下载 Provider 和 Module
fmt 统一配置格式 只修改代码格式
validate 检查配置结构和引用
plan 对比配置、State 和真实资源 通常不改变资源
apply 执行计划中的创建、修改与删除

自动化流水线应保存 Plan,并 Apply 同一个计划文件。Plan 仍可能出现地址、资源名称或敏感字段,不应作为公开制品。

怎样审核 Plan

+   create   新建资源
~   update   原地修改
-  replace  替换资源,可能中断业务
-  destroy  删除真实资源

审核时重点检查:

  • 是否替换磁盘、数据库、IP 或实例。
  • 当前环境和账户是否正确,是否误指向生产。
  • 网络规则是否意外扩大到 0.0.0.0/0
  • Provider 或 Module 升级是否引入额外变化。
  • Apply 前是否需要备份、迁移流量或维护窗口。

State 与 Backend

State 保存资源映射,也可能包含密码、连接字符串和敏感输出。团队环境应使用受访问控制的远端 Backend,并具备锁、版本历史、加密与备份。

下面内容不应提交:

*.tfstate
*.tfstate.*
.terraform/
tfplan
*.tfvars

Provider 锁文件通常应提交:

.terraform.lock.hcl

不要手工编辑 State JSON。导入现有资源、移动资源地址或解除锁时,要先备份并确认精确环境。

Module 与环境目录

tofu/
├── environments/
│   ├── dev/
│   └── prod/
└── modules/
    ├── network/
    └── virtual-machine/

Module 保存公共结构,环境目录只传规格、数量、网段等差异。不要为每个环境复制整套资源代码;也不要让一个 State 无限扩大,应根据权限、生命周期和故障域拆分。

交给 Ansible

Terraform/OpenTofu Output:IP、主机名、角色
  → 静态或动态 Ansible Inventory
  → Ansible 配置用户、软件包、systemd 和应用

Terraform/OpenTofu 管理平台资源,Ansible 管理操作系统内部状态。明确边界后,Plan 才不会长期出现由另一个工具造成的漂移。

常见问题

现象 优先检查
每次 Plan 都出现同样变化 控制台手工修改、Provider 默认值变化或两个工具同时管理
State 被锁 是否有 Apply 正在运行;确认后再按 Backend 流程处理
改名后计划销毁并重建 Resource 地址变化,是否应该移动 State
已有资源却计划重新创建 是否需要 import;是否使用了错误 State 或环境
Provider 初始化失败 网络、版本约束、镜像源和锁文件

官方资料