跳转至

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 sourcesAWS 凭证未配置设置环境变量或 aws configure
Error: Error acquiring the state lock状态文件被锁terraform force-unlock <ID>
Error: Unsupported Terraform Core version版本不匹配升级 Terraform 或调整 required_version
Error: BucketAlreadyExistsS3 桶名已被占用换一个全球唯一的桶名
Error: Invalid provider configurationProvider 配置错误检查 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 年