Terraform 核心概念与架构
为什么需要 IaC
给一两台云服务器开资源,点点控制台确实快:选机型、选镜像、绑个安全组,几分钟完事。但环境一旦多起来,手工操作就开始变味:
- 重复劳动:测试、预发、生产各点一遍,同样的配置填三次,填到第三遍难免选错一个下拉框。
- 环境漂移:今天临时加条安全组规则救急,明天改了忘了记,几周后没人说得清「这套环境现在到底长什么样」。
- 无法审计:谁、什么时候、改了什么,控制台的操作日志零散难查,想回答「这条规则是谁开的」得靠回忆。
- 无法回滚:改错了想恢复原样?前提是有人记得原样是什么。
IaC(Infrastructure as Code,基础设施即代码)的思路是:把基础设施的期望状态写成代码文件,交给工具去和现实对齐。代码进 git,变更走 review,历史可追溯,改错了回滚一个提交就行——把管应用代码的那套方法搬到基础设施上。
Terraform 是一个「对照清单」工具:你用代码描述想要的基础设施(期望状态),它对比现实环境里已有的(实际状态),算出差异并执行,最终让现实变成你描述的样子。
Terraform 是什么
Terraform 是 HashiCorp 出品的资源编排(Provisioning)工具,定位在「把资源从无到有开出来」这一层:云主机、VPC、数据库、K8s 集群、DNS 记录、对象存储桶……凡是「能通过 API 创建和销毁的东西」,Terraform 基本都能管。
它经常和 Ansible 放在一起比较,但两者管的不是同一层:
| 维度 | Terraform | Ansible |
|---|---|---|
| 定位 | 资源编排:创建、销毁基础设施 | 配置管理:在已有的机器里装软件、改配置 |
| 典型对象 | 云主机、VPC、数据库、K8s 集群、DNS | 操作系统、软件包、配置文件、服务状态 |
| 工作方式 | 调各平台的 API,对比 state 算差异 | 通过 SSH 推模块执行,逐台收敛 |
| 状态记录 | 有,terraform.tfstate 记录资源映射 | 无状态,每次执行时实时检查 |
| 配置语言 | HCL,声明式 | YAML,声明式 |
| 生命周期 | 管资源「从生到死」,destroy 一键回收 | 不管机器的存在与否 |
实际项目里两者是互补关系:Terraform 把机器和网络开出来,Ansible 进去装软件、调配置。一个管「有没有这台机器」,一个管「机器里长什么样」。Ansible 侧的详细介绍见 Ansible 核心概念与架构。
Pulumi 与 Terraform 同赛道,区别在于用通用编程语言(TypeScript、Python、Go)写基础设施代码,而不是专用 DSL。灵活度更高,但平台覆盖度和社区生态不如 Terraform,运维团队里 Terraform 仍是主流选择。
声明式是理解 Terraform 的关键词:你写的是「我要一台 2C4G 的机器」(目标状态),而不是「先调 CreateInstance 接口,再轮询状态直到 running」(操作步骤)。怎么达到目标状态是 Terraform 的事,你只描述结果。
工作方式
Terraform 的工作流可以浓缩成一张图:

日常操作围绕四个命令转:
| 命令 | 干什么 |
|---|---|
terraform init | 初始化工作目录:下载 provider 插件、配置 backend、拉取模块。换目录、改 provider 版本后都要重跑 |
terraform plan | 预演:对比配置(期望)与 state/现实(实际),列出将要发生的增删改,不动任何真实资源 |
terraform apply | 执行 plan,真正调 API 创建/修改/删除资源,成功后更新 state |
terraform destroy | 销毁当前配置管理的全部资源,常用于回收测试环境 |
这张图背后有三个角色在协作:
- Core(核心引擎):解析 HCL 配置,根据资源间的引用关系构建依赖图(DAG),决定创建顺序和可并行的部分;plan 阶段由它算出差异。
- Provider(插件):每个平台一个插件(aws、alicloud、docker、kubernetes……),负责把 Core 的指令翻译成对应平台的 API 调用。Terraform 本体不内置任何云平台逻辑,全靠 provider。
- State(状态文件):
terraform.tfstate,记录「配置里的资源」和「现实里的对象」之间的映射,外加最近一次 apply 后的属性快照。
plan 的逻辑是「只补差异」:配置里有、现实里没有 → 创建;现实和配置不一致 → 修改或重建;配置里删掉了 → 销毁;一模一样就什么都不做。所以对一个没改过的配置执行 apply,输出会是 No changes. Your infrastructure matches the configuration.——这就是 IaC 幂等性的直观体现。
核心概念地图
后面会反复出现的名词先过一遍,有个印象,用到再回来查:
| 概念 | 一句话说明 |
|---|---|
| HCL | HashiCorp 配置语言,Terraform 配置的写法,声明式、可读性好 |
| Provider | 平台插件,负责调某家云或某类服务的 API,registry 上已有数千个 |
| Resource | 资源块,声明一个要管理的对象(机器、网络、文件……),是配置的主体 |
| Data Source | 数据源,只读查询现存资源(比如查一个已有的 AMI ID),不创建不修改 |
| Variable / Output | 输入变量 / 输出值,让配置可参数化,把结果传给别的模块或展示给人看 |
| Module | 模块,把一组 resource 打包成可复用的单元,类似函数库 |
| State | 状态文件,记录配置与现实的映射,是 Terraform 判断「要不要动」的依据 |
| Backend | state 的存储位置配置,默认本地文件,团队协作换成 S3/OSS 等远端存储 |
resource 与 data source 的区别值得多说一句:resource 是「我声明、我负责生死」,data source 是「我只查不管」。比如要引用一个别人手工创建的已有 VPC,用 data source 读它的 ID,之后 Terraform 销毁时绝不会去动它。
声明式与依赖图
资源之间用引用串起来,Terraform 会自动推导出创建顺序,不用手写「先 A 后 B」:
resource "docker_network" "app_net" {
name = "app_net"
}
resource "docker_image" "nginx" {
name = "nginx:alpine"
}
resource "docker_container" "web" {
name = "web"
image = docker_image.nginx.image_id
networks_advanced {
name = docker_network.app_net.name
}
}
这段配置里:
docker_container.web引用了docker_image.nginx.image_id和docker_network.app_net.name,Terraform 据此知道:镜像和网络必须先于容器就绪。docker_network与docker_image互不引用,可以并行创建。- apply 时的输出顺序会印证这一点:镜像拉取和网络创建同时进行,容器最后才创建。
这种「引用即依赖」的推导叫隐式依赖。少数场景下资源间没有属性引用、但仍有先后要求(比如「等数据库初始化脚本跑完再起应用」),可以用 depends_on 声明显式依赖:
resource "null_resource" "app" {
depends_on = [null_resource.db_init]
# ...
}
depends_on 是兜底手段,能靠属性引用就别用它。显式依赖会让依赖图变「钝」——上游任何变化都会级联触发下游重建,plan 里容易出现莫名其妙的 replace。
版本与许可
两件和使用相关的事:
- 版本现状:Terraform 处于 1.x 时代,1.9 之后的版本在稳定性、内置函数和 HCL 表达能力上都已成熟,生产环境跟住 1.x 最新稳定版即可。1.x 系列内承诺向后兼容,跨小版本升级一般无感。
- 许可变更:2023 年 8 月,HashiCorp 把 Terraform 的许可证从 MPL 2.0 换成了 BUSL 1.1(源码可用,但限制拿它做竞争性商业服务)。随后社区基于最后一版 MPL 代码 fork 出了 OpenTofu,交由 Linux 基金会托管,命令是
tofu,用法和配置文件与 Terraform 几乎完全兼容。个人学习和公司内部使用 Terraform 不受 BUSL 影响,不用慌;选型时留意一下团队的许可要求即可。
小结
- IaC 解决手工点控制台的四大痛点:重复劳动、环境漂移、无法审计、无法回滚。
- Terraform 是资源编排工具,与 Ansible 的配置管理互补:一个开机器,一个管机器。
- 工作流四个命令:init → plan → apply → destroy;Core 建依赖图、Provider 调 API、State 记映射,plan 只补差异所以可以放心预演。
- 核心概念八件套:HCL、Provider、Resource、Data Source、Variable/Output、Module、State、Backend。
- 资源用引用串联,Terraform 自动推导创建顺序;
depends_on只作兜底。 - 1.x 是当今主流;BUSL 许可和 OpenTofu 分支了解一下即可,学习与内部使用不受影响。
概念就位,下一篇《安装与快速上手》把 Terraform 装到本机,用一个不依赖任何云账号的 local_file 练习跑通完整的 init/plan/apply/destroy 流程。