Terraform 模块最佳实践 #
模块设计原则 #
1. 单一职责原则 #
每个模块应该只负责一种类型的基础设施资源。
text
┌─────────────────────────────────────────────────────────────┐
│ 单一职责示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 好的设计: │
│ modules/ │
│ ├── vpc/ 只负责 VPC │
│ ├── subnet/ 只负责子网 │
│ ├── security-group/ 只负责安全组 │
│ └── ec2-instance/ 只负责 EC2 实例 │
│ │
│ 不好的设计: │
│ modules/ │
│ └── infrastructure/ 包含所有资源 │
│ │
└─────────────────────────────────────────────────────────────┘
2. 可组合性 #
模块应该设计为可以轻松组合使用。
hcl
module "vpc" {
source = "./modules/vpc"
}
module "subnet" {
source = "./modules/subnet"
vpc_id = module.vpc.id
}
module "security_group" {
source = "./modules/security-group"
vpc_id = module.vpc.id
}
module "ec2" {
source = "./modules/ec2"
subnet_id = module.subnet.id
security_group_id = module.security_group.id
}
3. 可重用性 #
模块应该设计为可以在不同项目中重用。
hcl
module "vpc_dev" {
source = "./modules/vpc"
environment = "dev"
cidr_block = "10.0.0.0/16"
}
module "vpc_prod" {
source = "./modules/vpc"
environment = "prod"
cidr_block = "10.1.0.0/16"
}
4. 可测试性 #
模块应该易于测试。
hcl
variable "create_resources" {
description = "Whether to create resources"
type = bool
default = true
}
resource "aws_vpc" "main" {
count = var.create_resources ? 1 : 0
cidr_block = var.cidr_block
}
模块结构 #
标准结构 #
text
modules/
└── vpc/
├── main.tf 主要资源配置
├── variables.tf 输入变量定义
├── outputs.tf 输出值定义
├── versions.tf 版本约束
├── providers.tf Provider 配置(可选)
├── locals.tf 本地值(可选)
├── data.tf 数据源(可选)
├── README.md 模块文档
├── LICENSE 许可证
└── examples/ 示例
├── basic/
│ ├── main.tf
│ └── outputs.tf
└── complete/
├── main.tf
└── outputs.tf
文件组织 #
text
┌─────────────────────────────────────────────────────────────┐
│ 文件组织原则 │
├─────────────────────────────────────────────────────────────┤
│ │
│ main.tf 主要资源配置 │
│ variables.tf 所有输入变量 │
│ outputs.tf 所有输出值 │
│ versions.tf Terraform 和 Provider 版本约束 │
│ providers.tf Provider 配置(如果需要) │
│ locals.tf 本地值(如果较多) │
│ data.tf 数据源(如果较多) │
│ README.md 模块文档 │
│ │
└─────────────────────────────────────────────────────────────┘
命名规范 #
模块命名 #
text
┌─────────────────────────────────────────────────────────────┐
│ 模块命名规范 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 使用小写字母和连字符: │
│ ✅ vpc │
│ ✅ security-group │
│ ✅ ec2-instance │
│ ✅ rds-mysql │
│ │
│ 避免使用: │
│ ❌ vpcModule │
│ ❌ SecurityGroup │
│ ❌ ec2_instance │
│ │
└─────────────────────────────────────────────────────────────┘
变量命名 #
hcl
variable "vpc_cidr" {
description = "CIDR block for the VPC"
type = string
}
variable "availability_zones" {
description = "List of availability zones"
type = list(string)
}
variable "enable_dns_hostnames" {
description = "Enable DNS hostnames in the VPC"
type = bool
default = true
}
variable "tags" {
description = "Tags to apply to all resources"
type = map(string)
default = {}
}
输出命名 #
hcl
output "vpc_id" {
description = "The ID of the VPC"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "List of public subnet IDs"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "List of private subnet IDs"
value = aws_subnet.private[*].id
}
输入变量设计 #
必需变量 #
hcl
variable "vpc_cidr" {
description = "CIDR block for the VPC"
type = string
validation {
condition = can(cidrhost(var.vpc_cidr, 0))
error_message = "Must be a valid CIDR block."
}
}
可选变量 #
hcl
variable "enable_dns_hostnames" {
description = "Enable DNS hostnames in the VPC"
type = bool
default = true
}
variable "tags" {
description = "Tags to apply to all resources"
type = map(string)
default = {}
}
复杂类型变量 #
hcl
variable "subnets" {
description = "Map of subnet configurations"
type = map(object({
cidr_block = string
availability_zone = string
map_public_ip_on_launch = optional(bool, false)
}))
default = {}
}
variable "vpc_config" {
description = "VPC configuration"
type = object({
cidr_block = string
enable_dns_hostnames = optional(bool, true)
enable_dns_support = optional(bool, true)
instance_tenancy = optional(string, "default")
})
}
变量验证 #
hcl
variable "environment" {
description = "Environment name"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be dev, staging, or prod."
}
}
variable "instance_type" {
description = "EC2 instance type"
type = string
validation {
condition = can(regex("^t[23]\\.(micro|small|medium|large)$", var.instance_type))
error_message = "Instance type must be t2 or t3 family (micro, small, medium, or large)."
}
}
输出值设计 #
输出所有重要属性 #
hcl
output "vpc_id" {
description = "The ID of the VPC"
value = aws_vpc.main.id
}
output "vpc_cidr_block" {
description = "The CIDR block of the VPC"
value = aws_vpc.main.cidr_block
}
output "vpc_arn" {
description = "The ARN of the VPC"
value = aws_vpc.main.arn
}
output "public_subnet_ids" {
description = "List of public subnet IDs"
value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
description = "List of private subnet IDs"
value = aws_subnet.private[*].id
}
使用对象输出 #
hcl
output "vpc" {
description = "VPC information"
value = {
id = aws_vpc.main.id
cidr_block = aws_vpc.main.cidr_block
arn = aws_vpc.main.arn
}
}
output "subnets" {
description = "Subnet information"
value = {
public = aws_subnet.public[*].id
private = aws_subnet.private[*].id
}
}
版本管理 #
语义化版本 #
text
┌─────────────────────────────────────────────────────────────┐
│ 语义化版本 │
├─────────────────────────────────────────────────────────────┤
│ │
│ MAJOR.MINOR.PATCH │
│ │
│ MAJOR - 不兼容的 API 变更 │
│ MINOR - 向后兼容的功能新增 │
│ PATCH - 向后兼容的问题修复 │
│ │
│ 示例: │
│ 1.0.0 - 初始版本 │
│ 1.1.0 - 新增功能 │
│ 1.1.1 - Bug 修复 │
│ 2.0.0 - 破坏性变更 │
│ │
└─────────────────────────────────────────────────────────────┘
版本约束 #
hcl
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.0.0, < 6.0.0"
}
}
}
Git 标签 #
bash
git tag v1.0.0
git push origin v1.0.0
hcl
module "vpc" {
source = "github.com/myorg/terraform-modules//vpc?ref=v1.0.0"
}
文档 #
README.md #
markdown
# VPC Module
## Description
This module creates a VPC with public and private subnets, NAT gateways, and related networking resources.
## Usage
### Basic Example
```hcl
module "vpc" {
source = "./modules/vpc"
vpc_cidr = "10.0.0.0/16"
}
Complete Example #
hcl
module "vpc" {
source = "./modules/vpc"
vpc_cidr = "10.0.0.0/16"
availability_zones = ["us-east-1a", "us-east-1b"]
public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"]
private_subnet_cidrs = ["10.0.11.0/24", "10.0.12.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
tags = {
Environment = "production"
}
}
Requirements #
| Name | Version |
|---|---|
| terraform | >= 1.0.0 |
| aws | >= 4.0.0 |
Providers #
| Name | Version |
|---|---|
| aws | >= 4.0.0 |
Inputs #
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| vpc_cidr | CIDR block for the VPC | string | n/a | yes |
| availability_zones | List of availability zones | list(string) | n/a | yes |
| tags | Tags to apply to all resources | map(string) | {} | no |
Outputs #
| Name | Description |
|---|---|
| vpc_id | The ID of the VPC |
| public_subnet_ids | List of public subnet IDs |
| private_subnet_ids | List of private subnet IDs |
text
## 测试
### 基本验证
```bash
terraform init
terraform validate
terraform fmt -check
terraform plan
Terratest #
go
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
func TestVPCModule(t *testing.T) {
t.Parallel()
terraformOptions := &terraform.Options{
TerraformDir: "../examples/basic",
Vars: map[string]interface{}{
"vpc_cidr": "10.0.0.0/16",
},
}
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
vpcId := terraform.Output(t, terraformOptions, "vpc_id")
assert.NotEmpty(t, vpcId)
}
最佳实践清单 #
text
┌─────────────────────────────────────────────────────────────┐
│ 最佳实践清单 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 设计: │
│ □ 单一职责原则 │
│ □ 可组合性 │
│ □ 可重用性 │
│ □ 可测试性 │
│ │
│ 结构: │
│ □ 标准文件结构 │
│ □ 清晰的文件组织 │
│ □ 完整的示例 │
│ │
│ 命名: │
│ □ 一致的命名规范 │
│ □ 描述性的名称 │
│ □ 避免缩写 │
│ │
│ 变量: │
│ □ 必需变量无默认值 │
│ □ 可选变量有默认值 │
│ □ 变量验证 │
│ □ 描述文档 │
│ │
│ 输出: │
│ □ 输出所有重要属性 │
│ □ 添加描述 │
│ □ 敏感输出标记 │
│ │
│ 文档: │
│ □ README.md │
│ □ 使用示例 │
│ □ 输入输出说明 │
│ │
│ 版本: │
│ □ 语义化版本 │
│ □ 版本约束 │
│ □ CHANGELOG │
│ │
│ 测试: │
│ □ terraform validate │
│ □ terraform plan │
│ □ 自动化测试 │
│ │
└─────────────────────────────────────────────────────────────┘
下一步 #
掌握了模块最佳实践后,接下来学习 内置函数,了解 Terraform 提供的强大函数库!
最后更新:2026-03-29