Terraform AWS 实战¶
一句话概述:Terraform 是 HashiCorp 出品的基础设施即代码(IaC)工具,用 HCL 语言声明式定义云资源,一条命令就能创建/修改/销毁整套 AWS 基础设施。
核心知识点¶
| 概念 | 白话解释 |
|---|---|
| Provider | 提供商 = 告诉 Terraform 要操作哪个云(AWS/Azure/GCP) |
| Resource | 资源 = 一个具体的云资源(如 EC2 实例、S3 桶) |
| State | 状态文件 = Terraform 记录"当前基础设施长什么样"的数据库 |
| Plan | 计划 = 执行前先预览要做哪些改变 |
| Apply | 应用 = 真正创建/修改资源 |
| Module | 模块 = 可复用的资源组合(像乐高积木) |
| Variable | 变量 = 让配置可参数化 |
| Output | 输出 = 资源创建后返回有用信息(如 IP 地址) |
| Data Source | 数据源 = 查询已有资源的信息 |
| Backend | 后端 = 状态文件存储位置(推荐用 S3) |
安装配置¶
# === 安装 Terraform ===
# macOS
brew tap hashicorp/tap # 添加 HashiCorp 仓库
brew install hashicorp/tap/terraform # 安装 Terraform
# Ubuntu/Debian
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg # 导入密钥
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list # 添加源
sudo apt update && sudo apt install terraform # 安装
# 验证安装
terraform version # 查看版本(当前最新 1.14.x)
# === 配置 AWS 凭证 ===
# 方式1:环境变量(推荐用于 CI/CD)
export AWS_ACCESS_KEY_ID="your-key" # AWS 访问密钥
export AWS_SECRET_ACCESS_KEY="your-secret" # AWS 密钥
# 方式2:AWS CLI 配置文件
aws configure # 交互式配置,凭证存在 ~/.aws/credentials
项目初始化¶
# main.tf — 主配置文件
terraform {
required_version = ">= 1.14" # 要求 Terraform 最低版本
required_providers {
aws = {
source = "hashicorp/aws" # AWS 提供商
version = "~> 6.0" # AWS Provider 6.0(最新大版本)
}
}
# 远程状态存储(团队协作必须)
backend "s3" {
bucket = "my-terraform-state" # S3 桶名
key = "prod/terraform.tfstate" # 状态文件路径
region = "us-east-1" # 区域
encrypt = true # 加密存储
}
}
provider "aws" {
region = var.aws_region # 使用变量指定区域
}
# 初始化项目(下载 Provider 插件)
terraform init # 初始化,下载依赖
# 格式化代码
terraform fmt # 自动格式化 .tf 文件
# 验证配置
terraform validate # 检查配置语法
基本使用¶
1. 创建 EC2 实例¶
# variables.tf — 变量定义
variable "aws_region" {
description = "AWS 区域" # 变量描述
type = string # 类型:字符串
default = "us-east-1" # 默认值
}
variable "instance_type" {
description = "EC2 实例类型"
type = string
default = "t3.micro" # 免费套餐可用的实例类型
}
# main.tf — 资源定义
resource "aws_instance" "web" {
ami = "ami-0c55b159cbfafe1f0" # Amazon Linux 2 AMI ID
instance_type = var.instance_type # 使用变量
tags = {
Name = "WebServer" # 实例名称标签
Env = "production" # 环境标签
}
}
# outputs.tf — 输出定义
output "instance_ip" {
description = "EC2 公网 IP"
value = aws_instance.web.public_ip # 输出实例的公网 IP
}
# 执行流程
terraform plan # 预览变更(不会真的创建)
terraform apply # 确认后创建资源
terraform show # 查看当前资源状态
terraform destroy # 销毁所有资源(谨慎!)
2. 创建 VPC + 子网¶
# VPC(虚拟私有云 = 你在 AWS 上的独立网络空间)
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16" # IP 地址范围(65536个地址)
enable_dns_hostnames = true # 启用 DNS 主机名
tags = { Name = "main-vpc" }
}
# 公有子网(放可以直接访问互联网的资源)
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id # 属于哪个 VPC
cidr_block = "10.0.1.0/24" # 子网 IP 范围(256个地址)
availability_zone = "us-east-1a" # 可用区
map_public_ip_on_launch = true # 自动分配公网 IP
tags = { Name = "public-subnet" }
}
# 互联网网关(让 VPC 能连上互联网)
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.main.id # 绑定到 VPC
tags = { Name = "main-igw" }
}
# 路由表(告诉网络流量怎么走)
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0" # 所有外部流量
gateway_id = aws_internet_gateway.gw.id # 走互联网网关
}
}
# 关联路由表到子网
resource "aws_route_table_association" "public" {
subnet_id = aws_subnet.public.id
route_table_id = aws_route_table.public.id
}
3. S3 存储桶¶
resource "aws_s3_bucket" "data" {
bucket = "my-bioinfo-data-bucket" # 桶名(全球唯一)
tags = { Name = "bioinfo-data" }
}
# 桶的版本控制
resource "aws_s3_bucket_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration {
status = "Enabled" # 启用版本控制
}
}
# 桶的加密
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256" # 默认 AES256 加密
}
}
}
高级用法¶
1. 模块化¶
# modules/ec2/main.tf — 自定义模块
variable "name" { type = string }
variable "instance_type" { type = string; default = "t3.micro" }
resource "aws_instance" "this" {
ami = data.aws_ami.latest.id
instance_type = var.instance_type
tags = { Name = var.name }
}
output "id" { value = aws_instance.this.id }
# 主配置中调用模块
module "web_server" {
source = "./modules/ec2" # 模块路径
name = "web-server"
instance_type = "t3.small"
}
2. 条件与循环¶
# 条件创建资源
resource "aws_instance" "monitor" {
count = var.enable_monitoring ? 1 : 0 # 根据变量决定是否创建
ami = "ami-xxx"
instance_type = "t3.micro"
}
# 用 for_each 循环创建多个资源
variable "buckets" {
default = ["logs", "data", "backup"] # 要创建的桶列表
}
resource "aws_s3_bucket" "multi" {
for_each = toset(var.buckets) # 遍历列表
bucket = "myproject-${each.value}" # 每个桶的名字
}
3. 工作区(Workspace)¶
terraform workspace new dev # 创建 dev 工作区
terraform workspace new prod # 创建 prod 工作区
terraform workspace select dev # 切换到 dev
terraform workspace list # 列出所有工作区
常见报错¶
| 报错信息 | 原因 | 解决方法 |
|---|---|---|
Error: No valid credential sources | AWS 凭证未配置 | 设置环境变量或 aws configure |
Error: Error acquiring the state lock | 状态文件被锁 | terraform force-unlock <ID> |
Error: Unsupported Terraform Core version | 版本不匹配 | 升级 Terraform 或调整 required_version |
Error: BucketAlreadyExists | S3 桶名已被占用 | 换一个全球唯一的桶名 |
Error: Invalid provider configuration | Provider 配置错误 | 检查 region 和凭证 |
Error: Resource already exists | 资源已存在但不在 state 中 | terraform import 导入现有资源 |
速查表¶
# === 核心命令 ===
terraform init # 初始化(下载 Provider)
terraform plan # 预览变更
terraform apply # 执行变更
terraform destroy # 销毁资源
terraform fmt # 格式化代码
terraform validate # 验证配置
terraform show # 查看状态
terraform output # 查看输出值
terraform import <addr> <id> # 导入已有资源
terraform state list # 列出状态中的资源
terraform state rm <addr> # 从状态中移除资源
# === HCL 语法 ===
variable "x" {} # 声明变量
var.x # 引用变量
resource "type" "name" # 定义资源
data "type" "name" # 数据源(查询已有资源)
module "name" # 调用模块
output "name" # 定义输出
locals { k = "v" } # 本地值(计算中间变量)
# === 内置函数 ===
length(list) # 列表长度
join(",", list) # 列表连接成字符串
lookup(map, key) # 查找 map 中的值
file("path") # 读取文件内容
templatefile("t", vars) # 模板渲染
cidrsubnet(prefix, n, i) # 计算子网 CIDR
参考:Terraform 文档 | AWS Provider 6.0 | 更新于 2026 年