Terraform 模块基础 #

什么是模块? #

模块是 Terraform 配置的容器,用于组织、封装和复用相关资源。每个 Terraform 配置至少包含一个模块(根模块),也可以包含多个子模块。

text
┌─────────────────────────────────────────────────────────────┐
│                    模块的作用                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────┐     ┌─────────────┐     ┌─────────────┐   │
│  │ 代码复用     │     │ 封装抽象     │     │ 组织管理    │   │
│  └─────────────┘     └─────────────┘     └─────────────┘   │
│                                                             │
│  - 相同配置多次使用                                        │
│  - 隐藏实现细节                                            │
│  - 简化配置                                                │
│  - 标准化基础设施                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

模块结构 #

基本结构 #

text
modules/
└── vpc/
    ├── main.tf       主要资源配置
    ├── variables.tf  输入变量
    ├── outputs.tf    输出值
    └── README.md     模块文档

完整结构 #

text
modules/
└── vpc/
    ├── main.tf          主要资源配置
    ├── variables.tf     输入变量定义
    ├── outputs.tf       输出值定义
    ├── versions.tf      版本约束
    ├── providers.tf     Provider 配置
    ├── locals.tf        本地值
    ├── data.tf          数据源
    ├── README.md        模块文档
    └── examples/
        └── complete/
            ├── main.tf
            └── outputs.tf

使用模块 #

模块源 #

hcl
module "vpc" {
  source = "./modules/vpc"
  
  vpc_cidr = "10.0.0.0/16"
}

模块源类型 #

text
┌─────────────────────────────────────────────────────────────┐
│                    模块源类型                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  本地路径:                                                 │
│  source = "./modules/vpc"                                  │
│                                                             │
│  Terraform Registry:                                       │
│  source = "hashicorp/consul/aws"                           │
│                                                             │
│  GitHub:                                                   │
│  source = "github.com/hashicorp/terraform-aws-consul"      │
│                                                             │
│  Git:                                                      │
│  source = "git::https://example.com/vpc.git"               │
│                                                             │
│  S3:                                                       │
│  source = "s3::https://s3.amazonaws.com/bucket/module.zip" │
│                                                             │
│  GCS:                                                      │
│  source = "gcs::https://www.googleapis.com/storage/v1/..." │
│                                                             │
└─────────────────────────────────────────────────────────────┘

本地模块 #

hcl
module "vpc" {
  source = "./modules/vpc"
  
  vpc_cidr     = "10.0.0.0/16"
  environment  = "production"
  project_name = "my-project"
}

Registry 模块 #

hcl
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"
  
  name = "my-vpc"
  cidr = "10.0.0.0/16"
  
  azs             = ["us-east-1a", "us-east-1b", "us-east-1c"]
  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"]
}

GitHub 模块 #

hcl
module "consul" {
  source = "github.com/hashicorp/terraform-aws-consul"
  
  cluster_name = "my-consul"
}

Git 模块 #

hcl
module "vpc" {
  source = "git::https://example.com/terraform-modules/vpc.git"
  
  vpc_cidr = "10.0.0.0/16"
}

module "vpc" {
  source = "git::https://example.com/terraform-modules.git//vpc"
  
  vpc_cidr = "10.0.0.0/16"
}

module "vpc" {
  source = "git::https://example.com/terraform-modules.git//vpc?ref=v1.0.0"
  
  vpc_cidr = "10.0.0.0/16"
}

S3 模块 #

hcl
module "vpc" {
  source = "s3::https://s3.amazonaws.com/my-modules/vpc.zip"
  
  vpc_cidr = "10.0.0.0/16"
}

模块版本 #

版本约束 #

hcl
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"
}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = ">= 5.0.0, < 6.0.0"
}

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"
}

版本约束语法 #

text
┌─────────────────────────────────────────────────────────────┐
│                    版本约束语法                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  "1.0.0"        精确版本                                    │
│  "!= 1.0.0"     排除特定版本                                │
│  "> 1.0.0"      大于                                        │
│  "< 1.0.0"      小于                                        │
│  ">= 1.0.0"     大于等于                                    │
│  "<= 1.0.0"     小于等于                                    │
│  "~> 1.0"       1.x.x                                       │
│  "~> 1.0.0"     1.0.x                                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

创建模块 #

模块文件 #

variables.tf #

hcl
variable "vpc_cidr" {
  description = "CIDR block for VPC"
  type        = string
  default     = "10.0.0.0/16"
}

variable "availability_zones" {
  description = "List of availability zones"
  type        = list(string)
}

variable "public_subnet_cidrs" {
  description = "CIDR blocks for public subnets"
  type        = list(string)
}

variable "private_subnet_cidrs" {
  description = "CIDR blocks for private subnets"
  type        = list(string)
  default     = []
}

variable "environment" {
  description = "Environment name"
  type        = string
  default     = "dev"
}

variable "tags" {
  description = "Tags to apply to all resources"
  type        = map(string)
  default     = {}
}

main.tf #

hcl
locals {
  name_prefix = "${var.environment}-vpc"
  common_tags = merge(var.tags, {
    Environment = var.environment
    ManagedBy   = "terraform"
  })
}

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true
  
  tags = merge(local.common_tags, {
    Name = local.name_prefix
  })
}

resource "aws_subnet" "public" {
  count                   = length(var.public_subnet_cidrs)
  vpc_id                  = aws_vpc.main.id
  cidr_block              = var.public_subnet_cidrs[count.index]
  availability_zone       = var.availability_zones[count.index]
  map_public_ip_on_launch = true
  
  tags = merge(local.common_tags, {
    Name = "${local.name_prefix}-public-${count.index + 1}"
    Tier = "public"
  })
}

resource "aws_subnet" "private" {
  count             = length(var.private_subnet_cidrs)
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.private_subnet_cidrs[count.index]
  availability_zone = var.availability_zones[count.index]
  
  tags = merge(local.common_tags, {
    Name = "${local.name_prefix}-private-${count.index + 1}"
    Tier = "private"
  })
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
  
  tags = merge(local.common_tags, {
    Name = "${local.name_prefix}-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.main.id
  }
  
  tags = merge(local.common_tags, {
    Name = "${local.name_prefix}-public-rt"
  })
}

resource "aws_route_table_association" "public" {
  count          = length(aws_subnet.public)
  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public.id
}

outputs.tf #

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 "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
}

output "internet_gateway_id" {
  description = "The ID of the Internet Gateway"
  value       = aws_internet_gateway.main.id
}

模块输入 #

传递输入变量 #

hcl
module "vpc" {
  source = "./modules/vpc"
  
  vpc_cidr              = "10.0.0.0/16"
  availability_zones    = ["us-east-1a", "us-east-1b", "us-east-1c"]
  public_subnet_cidrs   = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  private_subnet_cidrs  = ["10.0.11.0/24", "10.0.12.0/24", "10.0.13.0/24"]
  environment           = "production"
  tags = {
    Project = "my-project"
  }
}

使用变量传递 #

hcl
variable "vpc_config" {
  type = object({
    vpc_cidr             = string
    availability_zones   = list(string)
    public_subnet_cidrs  = list(string)
    private_subnet_cidrs = list(string)
  })
}

module "vpc" {
  source = "./modules/vpc"
  
  vpc_cidr             = var.vpc_config.vpc_cidr
  availability_zones   = var.vpc_config.availability_zones
  public_subnet_cidrs  = var.vpc_config.public_subnet_cidrs
  private_subnet_cidrs = var.vpc_config.private_subnet_cidrs
}

模块输出 #

访问模块输出 #

hcl
module "vpc" {
  source = "./modules/vpc"
  
  vpc_cidr = "10.0.0.0/16"
}

resource "aws_instance" "web" {
  subnet_id = module.vpc.public_subnet_ids[0]
  
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

output "network_info" {
  value = {
    vpc_id     = module.vpc.vpc_id
    subnet_ids = module.vpc.public_subnet_ids
  }
}

模块初始化 #

初始化模块 #

bash
terraform init

更新模块 #

bash
terraform init -upgrade

获取模块 #

bash
terraform get
terraform get -update

模块最佳实践 #

1. 标准文件结构 #

text
modules/
└── vpc/
    ├── main.tf
    ├── variables.tf
    ├── outputs.tf
    ├── README.md
    └── examples/
        └── complete/
            └── main.tf

2. 添加描述 #

hcl
variable "vpc_cidr" {
  description = "CIDR block for the VPC. Must be a valid IPv4 CIDR."
  type        = string
  
  validation {
    condition     = can(cidrhost(var.vpc_cidr, 0))
    error_message = "Must be a valid IPv4 CIDR block."
  }
}

3. 提供默认值 #

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     = {}
}

4. 使用版本约束 #

hcl
terraform {
  required_version = ">= 1.0.0"
  
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.0.0"
    }
  }
}

5. 编写文档 #

markdown
# VPC Module

## Description

This module creates a VPC with public and private subnets.

## Usage

```hcl
module "vpc" {
  source = "./modules/vpc"
  
  vpc_cidr = "10.0.0.0/16"
}

Inputs #

Name Description Type Default
vpc_cidr CIDR block for VPC string “10.0.0.0/16”

Outputs #

Name Description
vpc_id The ID of the VPC
text

## 下一步

掌握了模块基础后,接下来学习 [模块组合](/docs/terraform/modules/module-composition),了解如何组合多个模块构建复杂架构!
最后更新:2026-03-29