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:
| 步骤 | 作用 | 是否改变基础设施 |
|---|---|---|
init |
初始化 Backend,下载 Provider 和 Module | 否 |
fmt |
统一配置格式 | 只修改代码格式 |
validate |
检查配置结构和引用 | 否 |
plan |
对比配置、State 和真实资源 | 通常不改变资源 |
apply |
执行计划中的创建、修改与删除 | 是 |
自动化流水线应保存 Plan,并 Apply 同一个计划文件。Plan 仍可能出现地址、资源名称或敏感字段,不应作为公开制品。
怎样审核 Plan¶
审核时重点检查:
- 是否替换磁盘、数据库、IP 或实例。
- 当前环境和账户是否正确,是否误指向生产。
- 网络规则是否意外扩大到
0.0.0.0/0。 - Provider 或 Module 升级是否引入额外变化。
- Apply 前是否需要备份、迁移流量或维护窗口。
State 与 Backend¶
State 保存资源映射,也可能包含密码、连接字符串和敏感输出。团队环境应使用受访问控制的远端 Backend,并具备锁、版本历史、加密与备份。
下面内容不应提交:
Provider 锁文件通常应提交:
不要手工编辑 State JSON。导入现有资源、移动资源地址或解除锁时,要先备份并确认精确环境。
Module 与环境目录¶
Module 保存公共结构,环境目录只传规格、数量、网段等差异。不要为每个环境复制整套资源代码;也不要让一个 State 无限扩大,应根据权限、生命周期和故障域拆分。
交给 Ansible¶
Terraform/OpenTofu 管理平台资源,Ansible 管理操作系统内部状态。明确边界后,Plan 才不会长期出现由另一个工具造成的漂移。
常见问题¶
| 现象 | 优先检查 |
|---|---|
| 每次 Plan 都出现同样变化 | 控制台手工修改、Provider 默认值变化或两个工具同时管理 |
| State 被锁 | 是否有 Apply 正在运行;确认后再按 Backend 流程处理 |
| 改名后计划销毁并重建 | Resource 地址变化,是否应该移动 State |
| 已有资源却计划重新创建 | 是否需要 import;是否使用了错误 State 或环境 |
| Provider 初始化失败 | 网络、版本约束、镜像源和锁文件 |