Terraform Modules
Chapter objectives
- Understand modules
- Create reusable modules
- Use the Terraform Registry
- Organize a project with modules
1 - What is a module?
Definition
A module is a container for several resources used together.
Advantages
| Without modules | With modules |
|---|---|
| Duplicated code | Reusable code |
| Huge files | Isolated components |
| Hard to maintain | Easy to test |
| No versioning | Versionable |
2 - Structure of a module
Standard tree
modules/
└── vpc/
├── main.tf # Ressources principales
├── variables.tf # Variables d'entrée
├── outputs.tf # Valeurs de sortie
├── versions.tf # Versions requises
└── README.md # Documentation
Example VPC module
# modules/vpc/variables.tf
variable "vpc_cidr" {
description = "CIDR block for VPC"
type = string
}
variable "environment" {
description = "Environment name"
type = string
}
variable "availability_zones" {
description = "List of availability zones"
type = list(string)
}
# modules/vpc/main.tf
resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true
tags = {
Name = "${var.environment}-vpc"
Environment = var.environment
}
}
resource "aws_subnet" "public" {
count = length(var.availability_zones)
vpc_id = aws_vpc.main.id
cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index)
availability_zone = var.availability_zones[count.index]
map_public_ip_on_launch = true
tags = {
Name = "${var.environment}-public-${count.index + 1}"
}
}
resource "aws_internet_gateway" "main" {
vpc_id = aws_vpc.main.id
tags = {
Name = "${var.environment}-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 = {
Name = "${var.environment}-public-rt"
}
}
resource "aws_route_table_association" "public" {
count = length(var.availability_zones)
subnet_id = aws_subnet.public[count.index].id
route_table_id = aws_route_table.public.id
}
# modules/vpc/outputs.tf
output "vpc_id" {
description = "ID of the VPC"
value = aws_vpc.main.id
}
output "public_subnet_ids" {
description = "IDs of public subnets"
value = aws_subnet.public[*].id
}
output "vpc_cidr" {
description = "CIDR block of the VPC"
value = aws_vpc.main.cidr_block
}
3 - Use a module
Local module
# main.tf
module "vpc" {
source = "./modules/vpc"
vpc_cidr = "10.0.0.0/16"
environment = "production"
availability_zones = ["eu-west-1a", "eu-west-1b", "eu-west-1c"]
}
# Utiliser les outputs du module
resource "aws_instance" "web" {
subnet_id = module.vpc.public_subnet_ids[0]
# ...
}
# Re-exporter les outputs
output "vpc_id" {
value = module.vpc.vpc_id
}