一、Terraform 到底管什么
Terraform 是 HashiCorp 出品的 IaC(基础设施即代码)工具。核心就是一句话:把云资源写成代码,用 git 管起来,一条命令部署。
它和 Ansible 经常放在一起提,但职责完全不同:
| Terraform | Ansible | |
|---|---|---|
| 管什么 | 云资源本身(VPC、ECS、RDS) | 机器内部状态(装软件、改配置) |
| 怎么管 | 声明式,写清楚「要什么」 | 命令式,写清楚「怎么做」 |
| 状态 | 有 state 文件追踪 | 无状态 |
| 幂等 | 天然幂等 | 需要自己保证模块幂等 |
简单记:Terraform 管房子造不造得起来,Ansible 管房子里面怎么装修。实际项目里两者经常搭配用——Terraform 先把机器开出来,Ansible 上去装 Docker、配内核参数。
另外,Terraform 不只管云资源。它还可以管理:
K8s 集群对象(Deployment、Service、ConfigMap)
DNS 记录
Datadog / Prometheus 监控
GitHub 仓库与权限
本地文件(local_file)
随机密码(random_password)
TLS 证书(tls_private_key)
只要有对应的 provider,什么都能管。这是 Terraform 和 CloudFormation、ROS 这类云厂商专属工具最大的区别——一套语法,管所有平台。
二、核心概念
Provider
Provider 是 Terraform 和外部平台的"翻译官"。阿里云用 aliyun/alicloud,AWS 用 hashicorp/aws,Kubernetes 用 hashicorp/kubernetes。
terraform {
required_providers {
alicloud = {
source = "aliyun/alicloud"
version = "1.280.0"
}
}
}
provider "alicloud" {
region = "cn-shanghai"
access_key = var.access_key
secret_key = var.secret_key
}
terraform {} 块声明 provider 来源和版本;provider {} 块配置认证。同一个 provider 可以声明多个 alias,对应不同的账号或 region——做多账号管理很实用。
Resource
Resource 是 Terraform 管理的最小单元,一个云资源对应一个 resource 块:
resource "alicloud_vpc" "my_vpc" {
vpc_name = "prod-vpc"
cidr_block = "10.0.0.0/16"
}
resource "alicloud_vswitch" "my_vswitch" {
vpc_id = alicloud_vpc.my_vpc.id
cidr_block = "10.0.1.0/24"
zone_id = "cn-shanghai-b"
}
注意:上面的 alicloud_vswitch.my_vpc.id 是 Terraform 的隐式依赖引用,Terraform 会自动推导创建顺序,不需要你手动声明依赖关系。
Data Source
Data Source 是只读查询,从云平台获取已有资源的信息,不创建任何东西:
data "alicloud_zones" "default" {
available_resource_creation = "VSwitch"
}
data "alicloud_images" "centos" {
name_regex = "^centos_7"
}
典型场景:查可用区列表、查已经存在的 VPC ID、获取最新的镜像 ID。
Variable 与 Output
Variable 让配置参数化,避免硬编码:
variable "region" {
type = string
default = "cn-shanghai"
}
variable "password" {
type = string
sensitive = true
}
加了 sensitive = true 的变量,tf plan 和日志里都不会打印,防止泄密。
Output 把模块的关键信息暴露出来:
output "vpc_id" {
value = alicloud_vpc.my_vpc.id
}
模块之间通过 output 传递信息,调用方用 module.xxx.vpc_id 引用。
Module
Module 是 Terraform 的复用机制。一个大项目写成几十个 module 比堆在一个文件里强太多:
├── main.tf
├── modules/
│ ├── network/ # VPC、子网、NAT、路由
│ ├── k8s/ # 集群、节点池
│ ├── rds/ # 数据库
│ └── ram/ # 用户与权限
调用方式:
module "network" {
source = "./modules/network"
vpc_name = "prod-vpc"
cidr_block = "10.0.0.0/16"
}
source 可以是本地路径、git 仓库、Terraform Registry。不同环境(dev / prod)各自一个目录调用同一套 module,保证一致性的同时能做到差异化管理。
State 与 Backend
State 文件是 Terraform 的"账本",记录它管过哪些资源以及资源当前的状态:
-
tf plan时,Terraform 对比 .tf 文件(期望状态)和 state 文件(实际状态),算出差异 -
tf apply后,state 更新为最新状态
默认 state 存本地,但多人协作用远程后端。阿里云上用的是 OSS:
terraform {
backend "oss" {
bucket = "my-terraform-states"
key = "terraform.tfstate"
region = "cn-shanghai"
}
}
远程后端还能自动加锁——你 apply 的时候别人不能同时 apply,防止状态冲突。
三、一个文件里有哪些关键字
拿一个典型的 main.tf 作为参考:
# 1. 版本与 provider 声明
terraform {
required_version = ">= 1.5"
required_providers {
alicloud = { source = "aliyun/alicloud", version = "~> 1.280" }
}
backend "oss" { ... }
}
# 2. Provider 配置
provider "alicloud" {
alias = "prod"
region = var.region
access_key = var.ak
secret_key = var.sk
}
# 3. 本地变量
locals {
common_tags = {
managed_by = "terraform"
env = var.env
}
}
# 4. Data Source(只读查询)
data "alicloud_zones" "default" {
available_resource_creation = "VSwitch"
}
# 5. Resource
resource "alicloud_vpc" "main" { ... }
# 6. Module
module "k8s" {
source = "./modules/k8s"
vpc_id = alicloud_vpc.main.id
vswitch_ids = alicloud_vswitch.main[*].id
}
# 7. Output
output "vpc_id" {
value = alicloud_vpc.main.id
}
Terraform 的执行顺序不按文件里的书写顺序,而是靠 依赖图 自动推导——你引用了 alicloud_vpc.main.id,Terraform 就知道 VPC 必须先于 K8s 创建。
四、基本工作流
日常开发就 3 个命令来回转:
tf init # 初始化:下载 provider、配置 backend
tf plan # 干跑:看将要创建/修改/删除什么
tf apply # 执行:真正动手
我习惯把 terraform 别名成 tf,每天敲得最多就是这三个。
init 改完 provider 或 backend 的时候跑一次就行。plan 是每次 apply 前必跑的,生产环境尤其——输出里会告诉你 Plan: X to add, Y to change, Z to destroy,看到 destroy 先停下来审查一遍。
还有一个常用组合:
tf fmt -recursive # 格式化所有 .tf 文件
tf validate # 语法检查
提交 git 之前跑一下,团队协作风格统一。
作者:舞鹤Roc
链接:https://www.jianshu.com/p/bab97b6b2c15
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。