terraform-module-writer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTerraform Module Writer
Terraform 模块编写指南
Эксперт по созданию высококачественных, переиспользуемых Terraform модулей с соблюдением industry best practices.
本指南用于创建符合行业最佳实践的高质量、可重用Terraform模块。
Module Structure
模块结构
Standard Directory Layout
标准目录布局
modules/
└── my-module/
├── main.tf # Primary resource definitions
├── variables.tf # Input variable declarations
├── outputs.tf # Output value definitions
├── versions.tf # Provider version constraints
├── locals.tf # Local values and computations
├── data.tf # Data source definitions
├── README.md # Module documentation
├── CHANGELOG.md # Version history
├── examples/
│ ├── basic/
│ │ ├── main.tf
│ │ └── outputs.tf
│ └── advanced/
│ ├── main.tf
│ └── outputs.tf
└── tests/
└── module_test.gomodules/
└── my-module/
├── main.tf # 核心资源定义
├── variables.tf # 输入变量声明
├── outputs.tf # 输出值定义
├── versions.tf # 提供商版本约束
├── locals.tf # 本地值与计算逻辑
├── data.tf # 数据源定义
├── README.md # 模块文档
├── CHANGELOG.md # 版本历史
├── examples/
│ ├── basic/
│ │ ├── main.tf
│ │ └── outputs.tf
│ └── advanced/
│ ├── main.tf
│ └── outputs.tf
└── tests/
└── module_test.goversions.tf Template
versions.tf 模板
hcl
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0.0, < 6.0.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.5.0"
}
}
}hcl
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.0.0, < 6.0.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.5.0"
}
}
}Input Variable Design
输入变量设计
Variable Declaration Best Practices
变量声明最佳实践
hcl
undefinedhcl
undefinedvariables.tf
variables.tf
Required variables (no default)
必填变量(无默认值)
variable "name" {
description = "Name prefix for all resources created by this module"
type = string
validation {
condition = can(regex("^[a-z][a-z0-9-]*$", var.name))
error_message = "Name must start with a letter and contain only lowercase letters, numbers, and hyphens."
}
}
variable "environment" {
description = "Environment name (e.g., dev, staging, prod)"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "Environment must be one of: dev, staging, prod."
}
}
variable "name" {
description = "本模块创建的所有资源的名称前缀"
type = string
validation {
condition = can(regex("^[a-z][a-z0-9-]*$", var.name))
error_message = "名称必须以字母开头,且仅包含小写字母、数字和连字符。"
}
}
variable "environment" {
description = "环境名称(例如:dev、staging、prod)"
type = string
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "环境必须是以下值之一:dev、staging、prod。"
}
}
Optional variables with sensible defaults
可选变量(含合理默认值)
variable "instance_type" {
description = "EC2 instance type for the application servers"
type = string
default = "t3.medium"
validation {
condition = can(regex("^[a-z][0-9][.][a-z]+$", var.instance_type))
error_message = "Instance type must be a valid AWS instance type format."
}
}
variable "enable_monitoring" {
description = "Enable detailed monitoring for resources"
type = bool
default = true
}
variable "min_instances" {
description = "Minimum number of instances in the Auto Scaling Group"
type = number
default = 2
validation {
condition = var.min_instances >= 1 && var.min_instances <= 100
error_message = "Minimum instances must be between 1 and 100."
}
}
variable "max_instances" {
description = "Maximum number of instances in the Auto Scaling Group"
type = number
default = 10
validation {
condition = var.max_instances >= 1 && var.max_instances <= 100
error_message = "Maximum instances must be between 1 and 100."
}
}
undefinedvariable "instance_type" {
description = "应用服务器的EC2实例类型"
type = string
default = "t3.medium"
validation {
condition = can(regex("^[a-z][0-9][.][a-z]+$", var.instance_type))
error_message = "实例类型必须符合AWS实例类型的有效格式。"
}
}
variable "enable_monitoring" {
description = "为资源启用详细监控"
type = bool
default = true
}
variable "min_instances" {
description = "自动扩缩容组中的最小实例数"
type = number
default = 2
validation {
condition = var.min_instances >= 1 && var.min_instances <= 100
error_message = "最小实例数必须在1到100之间。"
}
}
variable "max_instances" {
description = "自动扩缩容组中的最大实例数"
type = number
default = 10
validation {
condition = var.max_instances >= 1 && var.max_instances <= 100
error_message = "最大实例数必须在1到100之间。"
}
}
undefinedComplex Variable Types
复杂变量类型
hcl
undefinedhcl
undefinedObject type with optional attributes
含可选属性的对象类型
variable "vpc_config" {
description = "VPC configuration for the module"
type = object({
vpc_id = string
subnet_ids = list(string)
security_group_ids = optional(list(string), [])
assign_public_ip = optional(bool, false)
})
validation {
condition = length(var.vpc_config.subnet_ids) >= 2
error_message = "At least 2 subnet IDs required for high availability."
}
}
variable "vpc_config" {
description = "模块的VPC配置"
type = object({
vpc_id = string
subnet_ids = list(string)
security_group_ids = optional(list(string), [])
assign_public_ip = optional(bool, false)
})
validation {
condition = length(var.vpc_config.subnet_ids) >= 2
error_message = "为实现高可用性,至少需要2个子网ID。"
}
}
Map with specific value types
特定值类型的映射
variable "tags" {
description = "Additional tags to apply to all resources"
type = map(string)
default = {}
validation {
condition = alltrue([for k, v in var.tags : can(regex("^[a-zA-Z][a-zA-Z0-9:/_-]*$", k))])
error_message = "Tag keys must start with a letter and contain only valid characters."
}
}
variable "tags" {
description = "应用于所有资源的附加标签"
type = map(string)
default = {}
validation {
condition = alltrue([for k, v in var.tags : can(regex("^[a-zA-Z][a-zA-Z0-9:/_-]*$", k))])
error_message = "标签键必须以字母开头,且仅包含有效字符。"
}
}
List of objects
对象列表
variable "ingress_rules" {
description = "List of ingress rules for the security group"
type = list(object({
description = string
from_port = number
to_port = number
protocol = string
cidr_blocks = optional(list(string), [])
security_groups = optional(list(string), [])
}))
default = []
validation {
condition = alltrue([
for rule in var.ingress_rules :
rule.from_port >= 0 && rule.from_port <= 65535 &&
rule.to_port >= 0 && rule.to_port <= 65535
])
error_message = "Port numbers must be between 0 and 65535."
}
}
variable "ingress_rules" {
description = "安全组的入站规则列表"
type = list(object({
description = string
from_port = number
to_port = number
protocol = string
cidr_blocks = optional(list(string), [])
security_groups = optional(list(string), [])
}))
default = []
validation {
condition = alltrue([
for rule in var.ingress_rules :
rule.from_port >= 0 && rule.from_port <= 65535 &&
rule.to_port >= 0 && rule.to_port <= 65535
])
error_message = "端口号必须在0到65535之间。"
}
}
Sensitive variables
敏感变量
variable "database_password" {
description = "Master password for the RDS instance"
type = string
sensitive = true
validation {
condition = length(var.database_password) >= 16
error_message = "Database password must be at least 16 characters."
}
}
---variable "database_password" {
description = "RDS实例的主密码"
type = string
sensitive = true
validation {
condition = length(var.database_password) >= 16
error_message = "数据库密码长度至少为16个字符。"
}
}
---Local Values
本地值
locals.tf Template
locals.tf 模板
hcl
locals {
# Naming convention
name_prefix = "${var.name}-${var.environment}"
# Common tags applied to all resources
common_tags = merge(
var.tags,
{
Name = local.name_prefix
Environment = var.environment
ManagedBy = "terraform"
Module = "my-module"
Project = var.name
}
)
# Computed values
is_production = var.environment == "prod"
enable_encryption = local.is_production
backup_retention = local.is_production ? 30 : 7
instance_count = local.is_production ? var.max_instances : var.min_instances
# Derived configurations
monitoring_config = {
enabled = var.enable_monitoring || local.is_production
detailed = local.is_production
retention_days = local.is_production ? 90 : 30
alarm_threshold = local.is_production ? 80 : 90
}
# Dynamic block helpers
ingress_rules_map = {
for idx, rule in var.ingress_rules :
"${rule.protocol}-${rule.from_port}-${rule.to_port}" => rule
}
# Conditional resource naming
bucket_name = var.bucket_name != null ? var.bucket_name : "${local.name_prefix}-storage-${random_id.bucket.hex}"
}hcl
locals {
# 命名规范
name_prefix = "${var.name}-${var.environment}"
# 应用于所有资源的通用标签
common_tags = merge(
var.tags,
{
Name = local.name_prefix
Environment = var.environment
ManagedBy = "terraform"
Module = "my-module"
Project = var.name
}
)
# 计算值
is_production = var.environment == "prod"
enable_encryption = local.is_production
backup_retention = local.is_production ? 30 : 7
instance_count = local.is_production ? var.max_instances : var.min_instances
# 派生配置
monitoring_config = {
enabled = var.enable_monitoring || local.is_production
detailed = local.is_production
retention_days = local.is_production ? 90 : 30
alarm_threshold = local.is_production ? 80 : 90
}
# 动态块助手
ingress_rules_map = {
for idx, rule in var.ingress_rules :
"${rule.protocol}-${rule.from_port}-${rule.to_port}" => rule
}
# 条件资源命名
bucket_name = var.bucket_name != null ? var.bucket_name : "${local.name_prefix}-storage-${random_id.bucket.hex}"
}Resource Definitions
资源定义
main.tf Template
main.tf 模板
hcl
undefinedhcl
undefinedmain.tf
main.tf
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
Security Group
安全组
#------------------------------------------------------------------------------
resource "aws_security_group" "this" {
name_prefix = "${local.name_prefix}-sg-"
description = "Security group for ${var.name} ${var.environment}"
vpc_id = var.vpc_config.vpc_id
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-sg"
})
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group_rule" "ingress" {
for_each = local.ingress_rules_map
type = "ingress"
security_group_id = aws_security_group.this.id
description = each.value.description
from_port = each.value.from_port
to_port = each.value.to_port
protocol = each.value.protocol
cidr_blocks = length(each.value.cidr_blocks) > 0 ? each.value.cidr_blocks : null
source_security_group_id = length(each.value.security_groups) > 0 ? each.value.security_groups[0] : null
}
resource "aws_security_group_rule" "egress" {
type = "egress"
security_group_id = aws_security_group.this.id
description = "Allow all outbound traffic"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
resource "aws_security_group" "this" {
name_prefix = "${local.name_prefix}-sg-"
description = "${var.name} ${var.environment}环境的安全组"
vpc_id = var.vpc_config.vpc_id
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-sg"
})
lifecycle {
create_before_destroy = true
}
}
resource "aws_security_group_rule" "ingress" {
for_each = local.ingress_rules_map
type = "ingress"
security_group_id = aws_security_group.this.id
description = each.value.description
from_port = each.value.from_port
to_port = each.value.to_port
protocol = each.value.protocol
cidr_blocks = length(each.value.cidr_blocks) > 0 ? each.value.cidr_blocks : null
source_security_group_id = length(each.value.security_groups) > 0 ? each.value.security_groups[0] : null
}
resource "aws_security_group_rule" "egress" {
type = "egress"
security_group_id = aws_security_group.this.id
description = "允许所有出站流量"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
#------------------------------------------------------------------------------
Launch Template
启动模板
#------------------------------------------------------------------------------
resource "aws_launch_template" "this" {
name_prefix = "${local.name_prefix}-lt-"
description = "Launch template for ${var.name} ${var.environment}"
image_id = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
network_interfaces {
associate_public_ip_address = var.vpc_config.assign_public_ip
security_groups = concat([aws_security_group.this.id], var.vpc_config.security_group_ids)
delete_on_termination = true
}
iam_instance_profile {
arn = aws_iam_instance_profile.this.arn
}
monitoring {
enabled = local.monitoring_config.detailed
}
metadata_options {
http_endpoint = "enabled"
http_tokens = "required" # IMDSv2
http_put_response_hop_limit = 1
}
block_device_mappings {
device_name = "/dev/xvda"
ebs {
volume_size = var.root_volume_size
volume_type = "gp3"
encrypted = local.enable_encryption
kms_key_id = local.enable_encryption ? var.kms_key_id : null
delete_on_termination = true
}
}
tag_specifications {
resource_type = "instance"
tags = local.common_tags
}
tag_specifications {
resource_type = "volume"
tags = local.common_tags
}
tags = local.common_tags
lifecycle {
create_before_destroy = true
}
}
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
resource "aws_launch_template" "this" {
name_prefix = "${local.name_prefix}-lt-"
description = "${var.name} ${var.environment}环境的启动模板"
image_id = data.aws_ami.amazon_linux.id
instance_type = var.instance_type
network_interfaces {
associate_public_ip_address = var.vpc_config.assign_public_ip
security_groups = concat([aws_security_group.this.id], var.vpc_config.security_group_ids)
delete_on_termination = true
}
iam_instance_profile {
arn = aws_iam_instance_profile.this.arn
}
monitoring {
enabled = local.monitoring_config.detailed
}
metadata_options {
http_endpoint = "enabled"
http_tokens = "required" # IMDSv2
http_put_response_hop_limit = 1
}
block_device_mappings {
device_name = "/dev/xvda"
ebs {
volume_size = var.root_volume_size
volume_type = "gp3"
encrypted = local.enable_encryption
kms_key_id = local.enable_encryption ? var.kms_key_id : null
delete_on_termination = true
}
}
tag_specifications {
resource_type = "instance"
tags = local.common_tags
}
tag_specifications {
resource_type = "volume"
tags = local.common_tags
}
tags = local.common_tags
lifecycle {
create_before_destroy = true
}
}
#------------------------------------------------------------------------------
Auto Scaling Group
自动扩缩容组
#------------------------------------------------------------------------------
resource "aws_autoscaling_group" "this" {
name_prefix = "${local.name_prefix}-asg-"
desired_capacity = var.desired_instances
min_size = var.min_instances
max_size = var.max_instances
vpc_zone_identifier = var.vpc_config.subnet_ids
health_check_type = "ELB"
health_check_grace_period = 300
launch_template {
id = aws_launch_template.this.id
version = "$Latest"
}
dynamic "tag" {
for_each = local.common_tags
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
lifecycle {
create_before_destroy = true
ignore_changes = [desired_capacity]
}
}
---#------------------------------------------------------------------------------
resource "aws_autoscaling_group" "this" {
name_prefix = "${local.name_prefix}-asg-"
desired_capacity = var.desired_instances
min_size = var.min_instances
max_size = var.max_instances
vpc_zone_identifier = var.vpc_config.subnet_ids
health_check_type = "ELB"
health_check_grace_period = 300
launch_template {
id = aws_launch_template.this.id
version = "$Latest"
}
dynamic "tag" {
for_each = local.common_tags
content {
key = tag.key
value = tag.value
propagate_at_launch = true
}
}
lifecycle {
create_before_destroy = true
ignore_changes = [desired_capacity]
}
}
---Data Sources
数据源
data.tf Template
data.tf 模板
hcl
undefinedhcl
undefineddata.tf
data.tf
Get current AWS account info
获取当前AWS账户信息
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
data "aws_partition" "current" {}
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
data "aws_partition" "current" {}
Get latest Amazon Linux 2023 AMI
获取最新的Amazon Linux 2023 AMI
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
}
data "aws_ami" "amazon_linux" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["al2023-ami-*-x86_64"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "architecture"
values = ["x86_64"]
}
}
Get VPC info if not provided
获取VPC信息(若未提供)
data "aws_vpc" "selected" {
id = var.vpc_config.vpc_id
}
data "aws_vpc" "selected" {
id = var.vpc_config.vpc_id
}
Get subnet info for AZ distribution
获取子网信息用于可用区分布
data "aws_subnet" "selected" {
for_each = toset(var.vpc_config.subnet_ids)
id = each.value
}
data "aws_subnet" "selected" {
for_each = toset(var.vpc_config.subnet_ids)
id = each.value
}
Get available AZs
获取可用可用区
data "aws_availability_zones" "available" {
state = "available"
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
---data "aws_availability_zones" "available" {
state = "available"
filter {
name = "opt-in-status"
values = ["opt-in-not-required"]
}
}
---Output Definitions
输出定义
outputs.tf Template
outputs.tf 模板
hcl
undefinedhcl
undefinedoutputs.tf
outputs.tf
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
Primary Outputs
核心输出
#------------------------------------------------------------------------------
output "id" {
description = "The unique identifier for this module instance"
value = aws_autoscaling_group.this.id
}
output "name" {
description = "The name prefix used for all resources"
value = local.name_prefix
}
output "arn" {
description = "ARN of the Auto Scaling Group"
value = aws_autoscaling_group.this.arn
}
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
output "id" {
description = "本模块实例的唯一标识符"
value = aws_autoscaling_group.this.id
}
output "name" {
description = "用于所有资源的名称前缀"
value = local.name_prefix
}
output "arn" {
description = "自动扩缩容组的ARN"
value = aws_autoscaling_group.this.arn
}
#------------------------------------------------------------------------------
Security Group Outputs
安全组输出
#------------------------------------------------------------------------------
output "security_group_id" {
description = "ID of the security group created for this module"
value = aws_security_group.this.id
}
output "security_group_arn" {
description = "ARN of the security group"
value = aws_security_group.this.arn
}
output "security_group_name" {
description = "Name of the security group"
value = aws_security_group.this.name
}
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
output "security_group_id" {
description = "为本模块创建的安全组ID"
value = aws_security_group.this.id
}
output "security_group_arn" {
description = "安全组的ARN"
value = aws_security_group.this.arn
}
output "security_group_name" {
description = "安全组的名称"
value = aws_security_group.this.name
}
#------------------------------------------------------------------------------
Launch Template Outputs
启动模板输出
#------------------------------------------------------------------------------
output "launch_template_id" {
description = "ID of the launch template"
value = aws_launch_template.this.id
}
output "launch_template_arn" {
description = "ARN of the launch template"
value = aws_launch_template.this.arn
}
output "launch_template_latest_version" {
description = "Latest version of the launch template"
value = aws_launch_template.this.latest_version
}
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
output "launch_template_id" {
description = "启动模板的ID"
value = aws_launch_template.this.id
}
output "launch_template_arn" {
description = "启动模板的ARN"
value = aws_launch_template.this.arn
}
output "launch_template_latest_version" {
description = "启动模板的最新版本"
value = aws_launch_template.this.latest_version
}
#------------------------------------------------------------------------------
Computed/Derived Outputs
计算/派生输出
#------------------------------------------------------------------------------
output "ami_id" {
description = "ID of the AMI used for instances"
value = data.aws_ami.amazon_linux.id
}
output "availability_zones" {
description = "List of availability zones where resources are deployed"
value = distinct([for s in data.aws_subnet.selected : s.availability_zone])
}
output "configuration" {
description = "Summary of the module configuration"
value = {
environment = var.environment
instance_type = var.instance_type
min_instances = var.min_instances
max_instances = var.max_instances
monitoring_enabled = local.monitoring_config.enabled
encryption_enabled = local.enable_encryption
}
}
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
output "ami_id" {
description = "用于实例的AMI ID"
value = data.aws_ami.amazon_linux.id
}
output "availability_zones" {
description = "资源部署的可用区列表"
value = distinct([for s in data.aws_subnet.selected : s.availability_zone])
}
output "configuration" {
description = "模块配置摘要"
value = {
environment = var.environment
instance_type = var.instance_type
min_instances = var.min_instances
max_instances = var.max_instances
monitoring_enabled = local.monitoring_config.enabled
encryption_enabled = local.enable_encryption
}
}
#------------------------------------------------------------------------------
Sensitive Outputs
敏感输出
#------------------------------------------------------------------------------
output "iam_role_arn" {
description = "ARN of the IAM role attached to instances"
value = aws_iam_role.this.arn
sensitive = false
}
---#------------------------------------------------------------------------------
output "iam_role_arn" {
description = "附加到实例的IAM角色ARN"
value = aws_iam_role.this.arn
sensitive = false
}
---Conditional Resource Creation
条件资源创建
Using count vs for_each
使用count vs for_each
hcl
undefinedhcl
undefinedUse count for simple on/off toggles
简单开关使用count
resource "aws_cloudwatch_metric_alarm" "high_cpu" {
count = var.enable_monitoring ? 1 : 0
alarm_name = "${local.name_prefix}-high-cpu"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 300
statistic = "Average"
threshold = local.monitoring_config.alarm_threshold
alarm_description = "CPU utilization exceeded threshold"
alarm_actions = var.alarm_actions
dimensions = {
AutoScalingGroupName = aws_autoscaling_group.this.name
}
tags = local.common_tags
}
resource "aws_cloudwatch_metric_alarm" "high_cpu" {
count = var.enable_monitoring ? 1 : 0
alarm_name = "${local.name_prefix}-high-cpu"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/EC2"
period = 300
statistic = "Average"
threshold = local.monitoring_config.alarm_threshold
alarm_description = "CPU使用率超过阈值"
alarm_actions = var.alarm_actions
dimensions = {
AutoScalingGroupName = aws_autoscaling_group.this.name
}
tags = local.common_tags
}
Use for_each for collections
集合类资源使用for_each
resource "aws_s3_bucket" "logs" {
for_each = var.enable_logging ? toset(["access", "audit", "error"]) : toset([])
bucket = "${local.name_prefix}-${each.key}-logs"
tags = merge(local.common_tags, {
LogType = each.key
})
}
resource "aws_s3_bucket" "logs" {
for_each = var.enable_logging ? toset(["access", "audit", "error"]) : toset([])
bucket = "${local.name_prefix}-${each.key}-logs"
tags = merge(local.common_tags, {
LogType = each.key
})
}
for_each with complex objects
复杂对象使用for_each
resource "aws_route53_record" "this" {
for_each = {
for record in var.dns_records :
"${record.name}-${record.type}" => record
}
zone_id = var.route53_zone_id
name = each.value.name
type = each.value.type
ttl = each.value.ttl
records = each.value.records
}
---resource "aws_route53_record" "this" {
for_each = {
for record in var.dns_records :
"${record.name}-${record.type}" => record
}
zone_id = var.route53_zone_id
name = each.value.name
type = each.value.type
ttl = each.value.ttl
records = each.value.records
}
---Module Composition
模块组合
Root Module Example
根模块示例
hcl
undefinedhcl
undefinedexamples/complete/main.tf
examples/complete/main.tf
terraform {
required_version = ">= 1.5.0"
}
provider "aws" {
region = var.region
}
terraform {
required_version = ">= 1.5.0"
}
provider "aws" {
region = var.region
}
Network module
网络模块
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "${var.name}-vpc"
cidr = "10.0.0.0/16"
azs = ["${var.region}a", "${var.region}b", "${var.region}c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
single_nat_gateway = var.environment != "prod"
tags = var.tags
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "${var.name}-vpc"
cidr = "10.0.0.0/16"
azs = ["${var.region}a", "${var.region}b", "${var.region}c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
single_nat_gateway = var.environment != "prod"
tags = var.tags
}
Application module
应用模块
module "app" {
source = "../../"
name = var.name
environment = var.environment
vpc_config = {
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
}
instance_type = var.instance_type
min_instances = var.min_instances
max_instances = var.max_instances
enable_monitoring = true
ingress_rules = [
{
description = "HTTP from ALB"
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [module.alb.security_group_id]
}
]
tags = var.tags
}
module "app" {
source = "../../"
name = var.name
environment = var.environment
vpc_config = {
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
}
instance_type = var.instance_type
min_instances = var.min_instances
max_instances = var.max_instances
enable_monitoring = true
ingress_rules = [
{
description = "来自ALB的HTTP流量"
from_port = 80
to_port = 80
protocol = "tcp"
security_groups = [module.alb.security_group_id]
}
]
tags = var.tags
}
ALB module
ALB模块
module "alb" {
source = "terraform-aws-modules/alb/aws"
version = "~> 8.0"
name = "${var.name}-alb"
load_balancer_type = "application"
vpc_id = module.vpc.vpc_id
subnets = module.vpc.public_subnets
target_groups = [
{
name = "${var.name}-tg"
backend_protocol = "HTTP"
backend_port = 80
target_type = "instance"
}
]
tags = var.tags
}
module "alb" {
source = "terraform-aws-modules/alb/aws"
version = "~> 8.0"
name = "${var.name}-alb"
load_balancer_type = "application"
vpc_id = module.vpc.vpc_id
subnets = module.vpc.public_subnets
target_groups = [
{
name = "${var.name}-tg"
backend_protocol = "HTTP"
backend_port = 80
target_type = "instance"
}
]
tags = var.tags
}
Outputs
输出
output "vpc_id" {
value = module.vpc.vpc_id
}
output "app_security_group_id" {
value = module.app.security_group_id
}
output "alb_dns_name" {
value = module.alb.lb_dns_name
}
---output "vpc_id" {
value = module.vpc.vpc_id
}
output "app_security_group_id" {
value = module.app.security_group_id
}
output "alb_dns_name" {
value = module.alb.lb_dns_name
}
---Documentation
文档
README.md Template
README.md 模板
markdown
undefinedmarkdown
undefinedModule Name
模块名称
Brief description of what this module creates.
本模块创建资源的简要说明。
Features
特性
- Feature 1
- Feature 2
- Feature 3
- 特性1
- 特性2
- 特性3
Usage
使用方法
Basic
基础用法
hcl
module "example" {
source = "github.com/org/terraform-aws-module?ref=v1.0.0"
name = "my-app"
environment = "prod"
vpc_config = {
vpc_id = "vpc-12345678"
subnet_ids = ["subnet-1", "subnet-2"]
}
}hcl
module "example" {
source = "github.com/org/terraform-aws-module?ref=v1.0.0"
name = "my-app"
environment = "prod"
vpc_config = {
vpc_id = "vpc-12345678"
subnet_ids = ["subnet-1", "subnet-2"]
}
}Advanced
高级用法
hcl
module "example" {
source = "github.com/org/terraform-aws-module?ref=v1.0.0"
name = "my-app"
environment = "prod"
vpc_config = {
vpc_id = "vpc-12345678"
subnet_ids = ["subnet-1", "subnet-2"]
security_group_ids = ["sg-existing"]
assign_public_ip = false
}
instance_type = "t3.large"
min_instances = 3
max_instances = 10
enable_monitoring = true
ingress_rules = [
{
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
]
tags = {
Team = "platform"
CostCenter = "12345"
}
}hcl
module "example" {
source = "github.com/org/terraform-aws-module?ref=v1.0.0"
name = "my-app"
environment = "prod"
vpc_config = {
vpc_id = "vpc-12345678"
subnet_ids = ["subnet-1", "subnet-2"]
security_group_ids = ["sg-existing"]
assign_public_ip = false
}
instance_type = "t3.large"
min_instances = 3
max_instances = 10
enable_monitoring = true
ingress_rules = [
{
description = "HTTPS流量"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/8"]
}
]
tags = {
Team = "platform"
CostCenter = "12345"
}
}Requirements
依赖要求
| Name | Version |
|---|---|
| terraform | >= 1.5.0 |
| aws | >= 5.0.0, < 6.0.0 |
| 名称 | 版本 |
|---|---|
| terraform | >= 1.5.0 |
| aws | >= 5.0.0, < 6.0.0 |
Providers
提供商
| Name | Version |
|---|---|
| aws | >= 5.0.0 |
| 名称 | 版本 |
|---|---|
| aws | >= 5.0.0 |
Inputs
输入参数
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| name | Name prefix for resources | | n/a | yes |
| environment | Environment (dev/staging/prod) | | n/a | yes |
| vpc_config | VPC configuration | | n/a | yes |
| instance_type | EC2 instance type | | | no |
| min_instances | Minimum ASG size | | | no |
| max_instances | Maximum ASG size | | | no |
| 名称 | 说明 | 类型 | 默认值 | 是否必填 |
|---|---|---|---|---|
| name | 资源名称前缀 | | n/a | 是 |
| environment | 环境(dev/staging/prod) | | n/a | 是 |
| vpc_config | VPC配置 | | n/a | 是 |
| instance_type | EC2实例类型 | | | 否 |
| min_instances | ASG最小规模 | | | 否 |
| max_instances | ASG最大规模 | | | 否 |
Outputs
输出参数
| Name | Description |
|---|---|
| id | Auto Scaling Group ID |
| security_group_id | Security Group ID |
| launch_template_id | Launch Template ID |
| 名称 | 说明 |
|---|---|
| id | 自动扩缩容组ID |
| security_group_id | 安全组ID |
| launch_template_id | 启动模板ID |
License
许可证
MIT
---MIT
---Лучшие практики
最佳实践
- Используй версионирование — семантическое версионирование для модулей
- Валидируй входные переменные — используй validation blocks
- Документируй всё — описания для variables и outputs
- Избегай hardcoded значений — всё должно быть configurable
- Используй for_each вместо count — лучше управление state
- Группируй связанные ресурсы — логическая организация main.tf
- Тестируй модули — используй terratest или terraform test
- Следуй naming conventions — консистентное именование ресурсов
- 使用版本控制 — 为模块采用语义化版本控制
- 验证输入变量 — 使用validation块
- 全面文档化 — 为variables和outputs添加描述
- 避免硬编码值 — 所有配置项应支持自定义
- 优先使用for_each而非count — 更优的状态管理
- 分组关联资源 — 按逻辑组织main.tf
- 测试模块 — 使用terratest或terraform test
- 遵循命名规范 — 资源命名保持一致性