4. Terraform 入门:环境配置与第一个脚本

Terraform 是 HashiCorp 公司推出的基础设施即代码工具,采用声明式配置语言 HCL(HashiCorp Configuration Language)。它通过“期望状态”模型驱动基础设施的生命周期管理:用户描述目标状态,Terraform 自动计算并执行变更路径。本章将带你完成从安装、初始化到编写第一个脚本的完整闭环。

4.1 Terraform 核心概念

在动手之前,先建立三个关键认知:

概念 说明 类比
Provider 与目标云平台/服务交互的插件,负责 API 翻译与资源生命周期管理 数据库驱动
Resource 基础设施中的具体组件,如虚拟机、VPC、DNS 记录 数据库中的表记录
State 记录当前已管理资源的映射文件,Terraform 据此计算变更 数据库快照
关键原则:Terraform 只管理 State 中记录的资源。手动在控制台创建的资源不会被 Terraform 感知,除非通过 import 导入。

4.2 安装与版本选择

Terraform 以单一二进制文件分发,安装过程极简。推荐使用版本管理器 tfenv 或 tenv 来切换多版本。

4.2.1 安装方式对比

方式 适用场景 命令示例
包管理器(macOS/Linux) 单版本、快速上手 brew install terraform
手动下载 离线环境、指定版本 从 releases.hashicorp.com 下载并放入 PATH
tfenv(推荐) 多项目多版本切换 tfenv install 1.9.8

4.2.2 验证安装

terraform --version
# 输出示例:Terraform v1.9.8 on darwin_arm64
版本兼容性注意:Provider 与 Terraform 核心版本有对应关系。1.5.x 以上版本支持 import 代码生成和 check 块,建议新项目直接使用 1.6+。

4.3 Provider 配置:声明与初始化

Provider 是 Terraform 与目标平台之间的桥梁。每个 Provider 需要声明来源和版本约束。

4.3.1 Provider 声明格式

terraform {
  required_version = ">= 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "3.6.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}
参数 含义 推荐做法
source Provider 的注册地址,格式为 命名空间/类型 始终使用官方命名空间(如 hashicorp)
version 版本约束,支持 >=、~>、!= 等 使用 ~> x.y 锁定次要版本,避免意外升级
region Provider 级别的默认区域 通过变量传入,不硬编码

4.3.2 terraform init 执行流程

terraform init 是每个 Terraform 项目的第一个命令,完成以下工作:

  1. 读取 required_providers 块
  2. 从 Terraform Registry 下载 Provider 插件到 .terraform/ 目录
  3. 创建或更新 .terraform.lock.hcl 锁定文件
  4. 初始化后端(Backend)配置(如远程 State 存储)
  5. 加载模块(Module)
# 执行初始化
terraform init

# 输出关键行示例:
# - Initializing the backend...
# - Initializing provider plugins...
# - Finding hashicorp/aws versions matching "~> 5.0"...
# - Installing hashicorp/aws v5.82.2...
# - Terraform has been successfully initialized!
最佳实践:将 .terraform.lock.hcl 提交到版本控制。它确保团队所有成员使用完全相同的 Provider 版本,避免“在我机器上能跑”的问题。

4.4 第一个 Terraform 脚本:创建 AWS EC2 实例

以下脚本创建一个带有随机名称的 AWS EC2 实例,展示 Terraform 的核心工作流。

4.4.1 完整脚本

# main.tf
terraform {
  required_version = ">= 1.6"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    random = {
      source  = "hashicorp/random"
      version = "3.6.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

resource "random_pet" "server" {
  length = 2
}

resource "aws_instance" "web" {
  ami           = "ami-0e4e4b2f188e9e1e1"  # Amazon Linux 2023 in ap-northeast-1
  instance_type = "t3.micro"

  tags = {
    Name = "web-${random_pet.server.id}"
  }
}

output "instance_id" {
  value = aws_instance.web.id
}

output "public_ip" {
  value = aws_instance.web.public_ip
}

4.4.2 工作流步骤

步骤 命令 说明
1. 初始化 terraform init 下载 Provider,初始化后端
2. 格式化 terraform fmt 自动格式化 HCL 代码,保持风格一致
3. 验证 terraform validate 检查语法和配置错误
4. 预览 terraform plan 显示将要创建/修改/删除的资源清单
5. 应用 terraform apply 执行变更,创建基础设施
6. 销毁 terraform destroy 清理所有被管理的资源

4.4.3 plan 输出解读

terraform plan

# 输出关键部分:
Terraform will perform the following actions:

  # random_pet.server will be created
  + resource "random_pet" "server" {
      + id        = (known after apply)
      + length    = 2
      + separator = "-"
    }

  # aws_instance.web will be created
  + resource "aws_instance" "web" {
      + ami                          = "ami-0e4e4b2f188e9e1e1"
      + instance_type                = "t3.micro"
      + tags                         = {
          + "Name" = "web-${random_pet.server.id}"
        }
      + (其他属性省略...)
    }

Plan: 2 to add, 0 to change, 0 to destroy.
解读技巧:+ 表示创建,~ 表示修改,- 表示删除。(known after apply) 表示该值在 apply 之前无法确定,Terraform 会在执行时计算。

4.5 Terraform 工作流可视化

下图展示了从编写代码到基础设施生效的完整数据流:

Terraform 工作流与数据流 Terraform 工作流与数据流 HCL 配置 main.tf / variables.tf terraform init 下载 Provider terraform plan 预览变更 terraform apply 执行变更 State 文件 terraform.tfstate 云平台 API AWS / Azure / GCP 关键数据流说明 1. HCL 配置 → init:Provider 插件下载到 .terraform/ 目录 2. plan:读取 State + 配置,计算差异,生成执行计划 3. apply:调用云平台 API 创建/更新资源,并将结果写入 State

4.6 常见问题与避坑指南

问题 1:terraform init 报错 Failed to query available provider packages
原因:网络无法访问 registry.terraform.io,或 Provider source 拼写错误。
解决:配置代理或使用 terraform providers mirror 离线缓存。
问题 2:terraform apply 提示 Error: No valid credential sources found
原因:AWS 凭证未配置或 Provider 未正确读取。
解决:检查环境变量 AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY,或使用 aws configure 配置。
调试技巧:设置 TF_LOG=DEBUG 环境变量可输出详细日志,定位 API 调用和 State 操作问题。生产环境慎用,日志量较大。

4.7 本章要点总结

  • Terraform 使用声明式 HCL 语言,通过 Provider 与云平台交互
  • terraform init 是每个项目的第一个命令,负责下载 Provider 和初始化后端
  • Provider 配置需指定 source 和 version,推荐使用 ~> x.y 锁定次要版本
  • 标准工作流:init → fmt → validate → plan → apply
  • State 文件是 Terraform 的核心资产,记录资源映射关系,必须妥善保管
  • 始终在 apply 之前执行 plan,确认变更符合预期