2. Terraform核心工作流与基础语法
在上一节中我们已经理解了基础设施即代码(IaC)的基本理念,本节要把理念落到可执行的层面:Terraform 用一套声明式配置描述目标状态,再通过标准命令把这份描述变成云上的真实资源。要真正用起来,需要同时掌握两件事——HCL 语法如何组织配置,以及 init、plan、apply、destroy 四个命令如何驱动状态变化。这两者是一体的:语法决定“写什么”,工作流决定“怎么让云平台变成那样”。
一、HCL:Terraform 的配置语言
HCL(HashiCorp Configuration Language)是 Terraform 的声明式配置语言,文件以 .tf 结尾。它的核心结构是块(block),语法形式为:
块类型 "标签1" "标签2" {
参数名 = 参数值
}
块类型决定这段配置在做什么,标签用于标识具体对象,花括号内是参数。Terraform 中常见的块类型包括:terraform(版本与后端约束)、provider(云平台连接配置)、resource(要创建的资源)、variable(输入变量)、output(输出值)、data(只读查询已有资源)、locals(局部值)。参数值支持字符串、数字、布尔、列表、映射等类型,也支持引用其他对象,例如 var.region、aws_vpc.main.id。
二、provider:连接云平台的入口
provider 是 Terraform 与具体云平台(AWS、Azure、阿里云等)之间的适配层。没有 provider,Terraform 不知道如何调用云 API。一个典型的 AWS provider 配置如下:
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
这里 required_providers 锁定了 provider 的来源和版本范围,provider "aws" 块则声明了使用哪个区域。provider 的认证信息(如 access key)通常不写进代码,而是通过环境变量、共享凭证文件或 IAM 角色注入,避免密钥泄露。
三、resource:声明要创建的资源
resource 块是 Terraform 的主体,每个块对应一个云资源。格式为 resource "资源类型" "本地名称" { ... }。例如创建一个 VPC 和一台 EC2 实例:
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "tf-demo-vpc"
}
}
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = var.instance_type
subnet_id = aws_subnet.public.id
tags = {
Name = "tf-demo-web"
}
}
注意 aws_subnet.public.id 这种引用:Terraform 会自动解析依赖关系,先创建 subnet,再创建 instance。这种隐式依赖是 Terraform 的核心能力之一,不需要手工指定顺序。如果两个资源没有引用关系但存在先后要求,可以用 depends_on 显式声明。
四、variable 与 output:让配置可复用、可观察
把易变的值抽成变量,是配置复用的第一步。变量定义与使用如下:
variable "region" {
type = string
default = "us-east-1"
description = "部署区域"
}
variable "instance_type" {
type = string
default = "t3.micro"
}
output "instance_public_ip" {
value = aws_instance.web.public_ip
description = "Web 实例公网 IP"
}
变量可以通过命令行 -var、.tfvars 文件或环境变量 TF_VAR_ 传入,优先级依次为命令行 > tfvars 文件 > 环境变量 > 默认值。output 则把资源属性暴露出来,apply 结束后会打印,也可以被其他模块或远程状态引用。变量让同一份代码适配不同环境,output 让结果可被观察和传递。
五、标准工作流:init → plan → apply → destroy
配置写好后,Terraform 通过四个命令完成生命周期管理。下图展示了这四个阶段与状态文件之间的数据流关系:
terraform init 是第一步,它读取配置中的 provider 声明,下载对应插件到 .terraform 目录,并初始化后端(本地或远程)。如果配置了远程后端(如 S3 + DynamoDB),init 还会连接后端并校验状态锁。没有 init,后续命令无法运行。
terraform plan 是“预演”。它读取当前状态文件,与配置中的期望状态做对比,输出一份执行计划,用 + 表示新增、~ 表示修改、- 表示删除。plan 本身不改变任何云资源,是安全审查的关键环节。例如新增一台实例时,plan 会显示 Plan: 1 to add, 0 to change, 0 to destroy。
terraform apply 执行计划。它会再次生成计划并请求确认(可用 -auto-approve 跳过),然后按依赖顺序调用云 API 创建、修改或删除资源,最后把真实资源 ID 写回状态文件。apply 成功后,output 中定义的输出值会打印出来,例如实例公网 IP。
terraform destroy 是反向操作,按依赖逆序销毁所有由当前配置管理的资源,并清空状态。它同样会先给出计划再确认。destroy 常用于实验环境清理,生产环境应谨慎使用,通常配合 -target 或工作空间隔离来控制范围。
terraform.tfstate 是 Terraform 的“记忆”,它记录了配置中的逻辑名称与云上真实资源 ID 的映射。团队协作时应使用远程后端(如 S3 + DynamoDB 锁),避免多人同时 apply 导致状态冲突。六、一个可运行的最小示例
把上述内容串起来,一个最小可运行项目包含三个文件:main.tf(provider + resource)、variables.tf(变量定义)、outputs.tf(输出)。执行顺序为:
terraform init
terraform plan -var="region=us-east-1"
terraform apply -var="region=us-east-1"
# 验证 output 中的公网 IP 可访问
terraform destroy -var="region=us-east-1"