Terraform 基础设施即代码:声明式云资源管理
Terraform 基础设施即代码:声明式云资源管理
在云原生时代,手动在控制台点击创建资源已难以满足规模化、可重复和可审计的要求。基础设施即代码(Infrastructure as Code,IaC)正是解决这一问题的核心理念。Terraform 作为 IaC 领域的标杆工具,以其声明式语法、多云支持和强大的状态管理能力,成为开发者与运维工程师的必备技能。本教程将带你从零掌握 Terraform,从安装、核心概念到实战编写,实现云资源的声明式管理。
1. 什么是基础设施即代码(IaC)?
基础设施即代码是指通过可读、可版本化的代码定义和管理 IT 基础设施,而不是通过物理硬件配置或交互式工具。IaC 带来三大核心价值:
- 可重复性:同一份代码可以在不同环境(开发、测试、生产)中生成完全一致的基础设施。
- 可版本化:使用 Git 等版本控制系统,所有变更拥有完整历史,便于审计与回滚。
- 自动化:从手动操作转变为自动化交付,减少人为错误,提升交付速度。
IaC 工具主要分为两类:命令式与声明式。命令式(如 Ansible)需要编写达到期望状态的步骤;而声明式(如 Terraform)只需描述最终状态,工具自动计算执行路径。
2. Terraform 核心概念
2.1 声明式工作流
Terraform 采用声明式语言 HCL(HashiCorp Configuration Language)编写配置文件。你只需告诉 Terraform “我想要一个具有这些属性的虚拟机”,而不必写创建它的具体 API 调用。Terraform 会对比当前实际基础设施与期望状态,自动生成创建、更新或删除计划。
2.2 Provider(提供者)
Provider 是 Terraform 与云平台、SaaS 服务等交互的插件。每个 Provider 封装了对应平台的 API。例如,aws Provider 管理 AWS 资源,azurerm 管理 Azure,google 管理 GCP。通过声明所需的 Provider,Terraform 即可与对应平台通信。
2.3 Resource(资源)
Resource 是基础设施中的最小可管理单元,如一台云服务器、一个网络接口、一条 DNS 记录。在配置文件中,一个 resource 块代表一个真实世界的资源。
2.4 State(状态)
Terraform 将基础设施的实际状态记录在状态文件(terraform.tfstate)中。这个文件至关重要,它是 Terraform 进行“计划”和“应用”的基准。状态可以本地存储,也可远程存储在 S3、Terraform Cloud 等后端,实现团队协作与安全共享。
2.5 Module(模块)
模块是一组被组织在一起的资源集合,是 Terraform 代码复用与封装的主要方式。根模块(工作目录下的所有 .tf 文件)是最基础的模块,第三方模块(如 VPC 模块)可从 Terraform Registry 引用。
3. 安装 Terraform
Terraform 是单文件二进制程序,安装极其简单。
- macOS:使用 Homebrew
brew install terraform - Windows:下载 exe 文件并添加到 PATH,或使用 Chocolatey
choco install terraform - Linux:下载二进制包,解压后放入
/usr/local/bin
安装完成后,在终端执行 terraform -version 验证,输出类似 Terraform v1.6.0。
4. 第一个 Terraform 配置:在 Docker 中运行 Nginx
为了快速体验 Terraform 的工作流,我们使用 Docker Provider 在本地启动一个 Nginx 容器。无需任何云账号。
4.1 编写配置文件
创建一个新目录 learn-terraform,进入后新建 main.tf 文件:
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0"
}
}
}
provider "docker" {}
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "nginx" {
image = docker_image.nginx.image_id
name = "tutorial-nginx"
ports {
internal = 80
external = 8080
}
}
文件含义:
terraform块声明了所需的 Provider 来源与版本。provider "docker"配置了 Docker Provider(默认连接本地 Docker 守护进程)。docker_image资源拉取 Nginx 镜像。docker_container资源创建一个容器,映射端口 80 到宿主机 8080。
4.2 初始化
在配置文件目录执行:
terraform init
该命令会下载所需的 Docker Provider 插件,初始化工作目录,并生成 .terraform.lock.hcl 锁定版本。
4.3 生成执行计划
terraform plan
Terraform 会读取配置与当前状态,输出将要执行的操作。因为是首次执行,状态为空,计划会显示所有资源将被创建。每个操作用 + 标记,带有详细信息。
4.4 应用更改
terraform apply
再次显示计划并要求确认,输入 yes 后 Terraform 开始创建 Docker 镜像和容器。完成后,访问 http://localhost:8080 即可看到 Nginx 欢迎页。
4.5 查看状态
terraform show
显示当前状态中所有资源及属性。也可以用 terraform state list 列出资源。
4.6 销毁资源
terraform destroy
确认后所有由该配置创建的资源将被彻底删除。这是一种干净的资源回收方式。
5. HCL 语言基础
HCL 是为人类可读和机器友好而设计的结构化配置语言。以下是常见元素:
5.1 变量(Variables)
变量可以让配置更加灵活。定义变量文件 variables.tf:
variable "container_name" {
description = "Name of the container"
type = string
default = "tutorial-nginx"
}
引用时用 var.container_name。变量值可通过 -var 参数、环境变量(TF_VAR_前缀)或 .tfvars 文件传入。
5.2 输出(Outputs)
输出可以提取资源属性,供外部引用或打印。在 outputs.tf 中定义:
output "container_id" {
description = "The ID of the created container"
value = docker_container.nginx.id
}
执行 terraform apply 后会显示输出内容,也可用 terraform output container_id 单独获取。
5.3 局部值(Locals)
局部值用于定义可复用的表达式片段:
locals {
common_tags = {
Project = "Tutorial"
Owner = "DevOps"
}
}
引用为 local.common_tags。
5.4 数据类型与表达式
HCL 支持字符串、数字、布尔、列表、映射等类型,并有丰富的内置函数(如 join、lookup、file)。表达式允许条件判断 condition ? true_val : false_val 和循环(for 表达式)。
6. 管理 Terraform 状态
状态文件是 Terraform 的数据库。本地状态在学习和个人项目中足够,但在团队协作中存在锁定、私密数据暴露等问题。推荐使用远程状态后端。
6.1 配置远程后端
以 AWS S3 为例,需先创建 S3 存储桶和 DynamoDB 表(用于锁定),然后在 terraform 块中配置后端:
terraform {
backend "s3" {
bucket = "my-terraform-state-bucket"
key = "learn/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-lock"
}
}
运行 terraform init 会提示迁移现有状态到远程。此后团队中任何人执行 plan 或 apply 都会自动获取和锁定远程状态,避免并发冲突。
7. 模块化与代码复用
随着基础设施规模扩大,单一目录下的所有 .tf 文件会变得难以维护。模块可以将一系列资源封装成可复用的组件。
7.1 使用模块
假设有一个定义了 Web 服务器的模块,放在 ./modules/web-server。根模块调用它:
module "web" {
source = "./modules/web-server"
server_name = "my-web"
environment = "dev"
instance_type = "t3.micro"
}
source 可以是本地路径、Git 仓库或 Terraform Registry。
7.2 创建模块
模块本质上是一个包含 main.tf, variables.tf, outputs.tf 的目录。模块内部定义的变量需要被暴露出来,输出也需显式声明。第三方模块通常提供灵活的参数和最佳实践封装,例如官方的 AWS VPC 模块。
8. 工作流最佳实践
- 版本控制:将 Terraform 配置与
.terraform.lock.hcl提交到 Git,但.tfstate和.terraform目录必须排除。 - 敏感数据:敏感值使用变量标记为
sensitive = true,或通过环境变量传入,避免硬编码。状态文件中包含明文敏感信息时,必须开启后端加密。 - 环境分离:使用目录结构或工作空间区分环境。推荐目录结构:
envs/dev、envs/prod,各自拥有独立的状态文件和变量。 - 策略即代码:结合 Sentinel 或 OPA 在
apply前实施合规策略,确保资源符合安全与规范。 - 自动化:将
terraform plan和apply集成到 CI/CD 流水线中,实现 GitOps 风格的基础设施交付。
9. 进阶方向
掌握基础后,可继续深入:
- Terraform Cloud / Enterprise:提供远程运行、团队管理、策略引擎和成本预估等协作功能。
- CDK for Terraform (CDKTF):使用 TypeScript、Python 等通用编程语言定义基础设施,享受 IDE 的完整支持。
- 自定义 Provider 开发:为私有平台编写 Provider,扩展 Terraform 的管理边界。
- 性能优化:通过并行度控制、资源依赖精细化、模块缓等技巧加速大型项目。
Terraform 的声明式哲学简化了云资源管理的复杂度,无论是单台服务器还是跨多云架构,都可以用代码描述并自动化交付。现在,打开你的终端,从刚才的 Docker 示例起步,逐步将云上资源纳入声明式管理吧。