terraform
1 · terraform#
S - 什么场景:要创建和维护云基础设施,例如 VPC、子网、安全组、ECS/EC2、RDS、Kubernetes 集群、DNS 记录
C - 什么冲突:手工点控制台效率低、不可审计、难以复现;Shell 脚本虽然能自动化,但资源依赖关系、变更对比、状态追踪都很难管
Q - 什么问题:如何用一种可版本化、可复现、可审查的方式去管理基础设施?
A - 回答问题:Terraform — 最主流的 IaC(Infrastructure as Code)工具之一。你用声明式配置描述“想要什么基础设施”,Terraform 负责计算差异并调用云厂商 API 把现实状态收敛到期望状态
1.1 · 0. 为什么需要 Terraform#
S: 一开始资源少,直接在云控制台点一点击就能用 C: 环境一多(dev/staging/prod)、资源一多(网络/机器/数据库/权限),手工操作就会出现遗漏、漂移、无法复现 Q: 怎么把“搭基础设施”这件事工程化? A: 把基础设施写成代码,纳入 Git、Code Review、CI/CD,这就是 IaC;Terraform 是最典型的实现
Terraform 带来的核心价值:
- 可复现:同一份配置可以反复创建相同环境
- 可审查:变更先看
plan,再决定要不要执行 - 可追踪:基础设施变更进入 Git 历史
- 可组合:把常见基础设施封装成 module 重复复用
1.2 · 1. 核心范式:声明式 IaC#
S: 你想创建一套云资源 C: 命令式脚本要自己安排顺序、处理幂等、判断资源是否已存在,脚本很快变脆 Q: 能不能只描述“目标”,不手写“每一步怎么做”? A: 声明式 — 你描述期望状态,Terraform 计算当前状态与目标状态的差异,然后执行变更
你写 .tf 配置(期望状态)
↓
terraform 读取 state(当前已知状态)
↓
对比真实资源与配置
↓
生成执行计划(plan)
↓
调用 provider API 执行
↓
更新 state
这和 Kubernetes 的“声明式 + 控制循环”有相似之处,但 Terraform 更偏:
- 一次性执行式收敛:你运行一次
apply,它做完退出 - 不是常驻控制器:不会持续 watch 并自动修复漂移
1.3 · 2. 核心对象#
1.4 · Provider — 连接具体平台#
Terraform 本身不懂阿里云、AWS、GCP、Kubernetes,它通过 Provider 插件 和外部系统交互。
例如:
hashicorp/aws:管理 AWS 资源aliyun/alicloud:管理阿里云资源hashicorp/kubernetes:管理 Kubernetes 资源hashicorp/helm:管理 Helm Release
你可以把 Provider 理解成“某个平台的 API 适配器”。
1.5 · Resource — Terraform 管理的资源#
Terraform 最核心的对象就是 resource。
resource "aws_instance" "web" {
ami = "ami-123456"
instance_type = "t3.micro"
}
含义:
aws_instance:资源类型web:本地名字- 块里的字段:这个资源的期望属性
Terraform 会把每个 resource 看成状态图中的一个节点,并根据引用关系推导依赖顺序。
1.6 · Data Source — 读,不创建#
有些信息不是你创建的,而是“查出来再复用”,这时用 data:
data "aws_vpc" "default" {
default = true
}
区别:
resource:创建或管理对象data:查询已有对象
1.7 · Variable / Output — 输入与输出#
variable:给配置传参output:把关键结果导出给人看,或给其他模块使用
variable "region" {
type = string
default = "us-east-1"
}
output "instance_ip" {
value = aws_instance.web.public_ip
}
1.8 · Module — 可复用配置单元#
当一组资源经常一起出现,例如“VPC + 子网 + 路由表 + NAT”,就应该抽成 module。
你可以把 module 理解成“基础设施函数”:
- 输入:variables
- 内部:多个 resources
- 输出:outputs
Terraform 的工程化能力,很大程度上就建立在 module 复用上。
1.9 · 3. 工作流:init → plan → apply → destroy#
这是 Terraform 入门必须记住的主线。
1.10 · terraform init#
初始化当前工作目录:
- 下载 provider 插件
- 初始化 backend
- 准备 module 依赖
第一次进入一个 Terraform 项目,通常先跑它。
1.11 · terraform plan#
根据配置 + state 生成执行计划,但不真正修改资源。
它会告诉你:
- 哪些资源会被创建(
+) - 哪些会被修改(
~) - 哪些会被销毁(
-)
这是 Terraform 最重要的安全机制之一:先看 diff,再决定 apply。
1.12 · terraform apply#
真正执行变更,把基础设施推进到目标状态。
通常流程是:
terraform plan
terraform apply
也可以直接 terraform apply,它会先展示计划再询问确认。
1.13 · terraform destroy#
销毁当前配置管理的所有资源。适合临时环境,但生产环境必须慎用。
1.14 · 4. State:Terraform 为什么需要状态文件?#
S: Terraform 不是已经有 .tf 配置了吗?
C: 配置只描述“我想要什么”,但不知道“现在已经有什么”、资源 ID 是多少、哪些对象归我管理
Q: Terraform 靠什么追踪资源?
A: state 文件,默认是 terraform.tfstate
state 的作用:
- 记录 Terraform 管理过的资源及其属性
- 记录资源真实 ID(例如实例 ID、VPC ID)
- 作为 plan 的比较基准
- 帮助 Terraform 建立依赖图和变更路径
如果没有 state,Terraform 很难判断:
- 一个资源是“已经存在,应修改”
- 还是“根本不存在,应新建”
1.14.1 · 本地 state 与远端 state#
入门时常见是本地 terraform.tfstate,但团队协作通常要放到远端 backend,例如:
- S3 + DynamoDB Lock
- 阿里云 OSS
- Terraform Cloud
远端 state 的价值:
- 团队共享
- 避免多人各自持有不同状态
- 提供锁,防止并发 apply
1.15 · 5. 一个最小例子#
下面是一个极简的 Terraform 配置骨架:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "web" {
ami = "ami-123456"
instance_type = "t3.micro"
tags = {
Name = "demo-web"
}
}
output "public_ip" {
value = aws_instance.web.public_ip
}
执行流程:
terraform init
terraform plan
terraform apply
背后的含义是:
- 安装 AWS Provider
- 读取当前 state
- 发现
aws_instance.web不存在 - 调用 AWS API 创建实例
- 把实例 ID 和属性写入 state
- 输出实例公网 IP
1.16 · 6. HCL:Terraform 的配置语言#
Terraform 使用 HCL(HashiCorp Configuration Language),特点是:
- 比 JSON 更适合人写
- 结构清晰,适合表达层级配置
- 支持引用、表达式、条件、循环
常见写法:
name = "web"
count = 2
instance_type = var.instance_type
subnet_id = aws_subnet.app.id
几个入门期最常见的引用规则:
var.xxx:引用变量aws_instance.web.id:引用资源属性module.vpc.vpc_id:引用模块输出
1.17 · 7. Terraform 的依赖关系是怎么推出来的?#
Terraform 默认根据引用关系自动推导依赖。
例如:
resource "aws_subnet" "app" {
vpc_id = aws_vpc.main.id
}
因为 aws_subnet.app 引用了 aws_vpc.main.id,所以 Terraform 知道:
- 先创建
aws_vpc.main - 再创建
aws_subnet.app
必要时也可以显式写 depends_on,但入门阶段记住一句话就够:
能靠引用表达依赖,就不要手写 depends_on。
1.18 · 8. 适合 Terraform 做什么,不适合做什么?#
1.19 · 适合
- 云资源编排:VPC、ECS/EC2、LB、RDS、DNS、IAM
- Kubernetes 基础对象管理
- 多环境基础设施模板化
- 把基础设施纳入 GitOps / CI/CD
1.20 · 不太适合
- 细粒度服务器内配置(更偏 Ansible)
- 高频变更、秒级控制循环(更偏 Kubernetes Controller)
- 复杂业务发布编排
一个常见分工是:
- Terraform:创建机器、网络、托管服务、集群
- Ansible / 脚本:进入机器做配置
- Kubernetes / Helm:部署容器应用
1.21 · 9. 常用命令#
terraform fmt # 格式化 .tf 文件
terraform validate # 校验配置语法和结构
terraform init # 初始化工作目录
terraform plan # 查看执行计划
terraform apply # 执行变更
terraform destroy # 销毁资源
terraform show # 查看 state 或 plan 内容
terraform output # 查看输出值
terraform state list # 列出 state 中的资源
1.22 · 10. 入门阶段最容易踩的坑#
- 没理解 state:删了 state 不等于删了云资源,反而会让 Terraform“失忆”
- 直接 apply 不看 plan:容易误删或误改资源
- 把敏感信息写进代码或 state:密码、密钥要谨慎处理
- 滥用 depends_on:很多依赖本来可以通过引用自然表达
- 一个目录塞太多环境:dev/prod 通常要拆开管理
1.23 · 11. 一句话总结#
Terraform 的本质不是“写几个 .tf 文件去调云 API”,而是:
用声明式配置 + 状态管理 + 差异计算,把基础设施变更变成一件可复现、可审查、可协作的工程活动。