第五章:模块化¶
什么是模块?¶
模块是 Terraform 配置的可复用单元,用于组织和管理相关资源。
模块结构¶
modules/
└── vpc/
├── main.tf # 主配置
├── variables.tf # 输入变量
├── outputs.tf # 输出值
├── versions.tf # 版本约束
└── README.md # 文档
创建模块¶
variables.tf¶
# 输入变量
variable "name" {
description = "VPC name"
type = string
}
variable "cidr" {
description = "VPC CIDR block"
type = string
default = "10.0.0.0/16"
}
variable "azs" {
description = "Availability zones"
type = list(string)
}
variable "public_subnets" {
description = "Public subnet CIDR blocks"
type = list(string)
default = []
}
variable "private_subnets" {
description = "Private subnet CIDR blocks"
type = list(string)
default = []
}
variable "enable_nat_gateway" {
description = "Enable NAT Gateway"
type = bool
default = true
}
variable "tags" {
description = "Tags for resources"
type = map(string)
default = {}
}
main.tf¶
# VPC
resource "aws_vpc" "main" {
cidr_block = var.cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = merge(var.tags, {
Name = var.name
})
}
# 公有子网
resource "aws_subnet" "public" {
count = length(var.public_subnets)
vpc_id = aws_vpc.main.id
cidr_block = var.public_subnets[count.index]
availability_zone = var.azs[count.index]
map_public_ip_on_launch = true
tags = merge(var.tags, {
Name = "${var.name}-public-${count.index + 1}"
Type = "public"
})
}
# 私有子网
resource "aws_subnet" "private" {
count = length(var.private_subnets)
vpc_id = aws_vpc.main.id
cidr_block = var.private_subnets[count.index]
availability_zone = var.azs[count.index]
tags = merge(var.tags, {
Name = "${var.name}-private-${count.index + 1}"
Type = "private"
})
}
# Internet Gateway
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = merge(var.tags, {
Name = "${var.name}-igw"
})
}
# NAT Gateway
resource "aws_eip" "nat" {
count = var.enable_nat_gateway ? 1 : 0
domain = "vpc"
tags = merge(var.tags, {
Name = "${var.name}-nat-eip"
})
}
resource "aws_nat_gateway" "main" {
count = var.enable_nat_gateway ? 1 : 0
allocation_id = aws_eip.nat[0].id
subnet_id = aws_subnet.public[0].id
tags = merge(var.tags, {
Name = "${var.name}-nat"
})
depends_on = [aws_internet_gateway.main]
}
# 路由表
resource "aws_route_table" "public" {
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.main.id
}
tags = merge(var.tags, {
Name = "${var.name}-public-rt"
})
}
resource "aws_route_table" "private" {
count = var.enable_nat_gateway ? 1 : 0
vpc_id = aws_vpc.main.id
route {
cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.main[0].id
}
tags = merge(var.tags, {
Name = "${var.name}-private-rt"
})
}
# 路由表关联
resource "aws_route_table_association" "public" {
count = length(var.public_subnets)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
resource "aws_route_table_association" "private" {
count = var.enable_nat_gateway ? length(var.private_subnets) : 0
subnet_id = aws_subnet.private[count.index].id
route_table_id = aws_route_table.private[0].id
}
outputs.tf¶
output "vpc_id" {
description = "VPC ID"
value = aws_vpc.main.id
}
output "vpc_cidr" {
description = "VPC CIDR block"
value = aws_vpc.main.cidr_block
}
output "public_subnet_ids" {
description = "Public subnet IDs"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "Private subnet IDs"
value = aws_subnet.private[*].id
}
output "nat_gateway_id" {
description = "NAT Gateway ID"
value = var.enable_nat_gateway ? aws_nat_gateway.main[0].id : null
}
output "internet_gateway_id" {
description = "Internet Gateway ID"
value = aws_internet_gateway.main.id
}
versions.tf¶
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0"
}
}
}
使用模块¶
本地模块¶
module "vpc" {
source = "./modules/vpc"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
tags = {
Environment = "production"
}
}
# 引用模块输出
resource "aws_instance" "web" {
subnet_id = module.vpc.public_subnet_ids[0]
}
Terraform Registry 模块¶
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
public_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
enable_nat_gateway = true
tags = {
Environment = "production"
}
}
GitHub 模块¶
module "vpc" {
source = "github.com/user/terraform-aws-vpc?ref=v1.0.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
}
模块版本¶
版本约束¶
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0" # 5.x 最新版本
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = ">= 5.0.0, < 6.0.0" # 5.x 范围
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "5.1.0" # 精确版本
}
模块嵌套¶
# 模块调用其他模块
module "network" {
source = "./modules/network"
vpc_id = module.vpc.vpc_id
}
module "compute" {
source = "./modules/compute"
subnet_ids = module.vpc.private_subnet_ids
}
模块最佳实践¶
1. 标准结构¶
modules/
└── my-module/
├── main.tf # 主配置
├── variables.tf # 输入变量
├── outputs.tf # 输出值
├── versions.tf # 版本约束
├── README.md # 文档
└── examples/
└── basic/
├── main.tf
└── outputs.tf
2. 变量验证¶
variable "instance_type" {
description = "EC2 instance type"
type = string
validation {
condition = contains(["t3.micro", "t3.small", "t3.medium"], var.instance_type)
error_message = "Instance type must be t3.micro, t3.small, or t3.medium."
}
}
3. 默认值¶
variable "tags" {
description = "Tags for resources"
type = map(string)
default = {}
}
# 使用时合并
tags = merge(var.tags, {
ManagedBy = "terraform"
})
4. 输出文档¶
5. README 文档¶
# VPC Module
## Description
Creates a VPC with public and private subnets.
## Usage
```hcl
module "vpc" {
source = "./modules/vpc"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b"]
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
}
Inputs¶
| Name | Description | Type | Default |
|---|---|---|---|
| name | VPC name | string | - |
| cidr | VPC CIDR | string | "10.0.0.0/16" |
Outputs¶
| Name | Description |
|---|---|
| vpc_id | VPC ID |
| public_subnet_ids | Public subnet IDs |
| ``` |
小结¶
本章学习了:
- ✅ 模块概念和结构
- ✅ 创建模块
- ✅ 使用模块
- ✅ 模块版本管理
- ✅ 模块最佳实践
下一章¶
第六章:多云部署 - 学习多云架构部署。