TL;DR
Learn how to create, use, and manage reusable Terraform modules effectively
Terraform Modules Demystified
Learn how to write reusable and maintainable infrastructure code using Terraform modules. This guide covers module creation, best practices, and real-world examples.
$1
Modules are containers for multiple resources that are used together. They help you organize and reuse your Terraform code effectively.
$1
A typical Terraform module structure:
`` module-name/
├── main.tf # Main resource definitions
├── variables.tf # Input variables
├── outputs.tf # Output values
└── README.md # Documentation
`
$1
Here's an example of a simple AWS VPC module:
` resource "aws_vpc" "main" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
enable_dns_support = true tags = merge(
var.tags,
{
Name = var.vpc_name
}
)
} 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.availability_zones[count.index] tags = merge(
var.tags,
{
Name = "${var.vpc_name}-private-${count.index + 1}"
}
)
} variable "vpc_cidr" {
type = string
description = "CIDR block for VPC"
} variable "vpc_name" {
type = string
description = "Name of the VPC"
} variable "private_subnets" {
type = list(string)
description = "List of private subnet CIDR blocks"
} variable "availability_zones" {
type = list(string)
description = "List of availability zones"
} variable "tags" {
type = map(string)
description = "Tags to apply to all resources"
default = {}
} output "vpc_id" {
value = aws_vpc.main.id
description = "ID of the created VPC"
} output "private_subnet_ids" {
value = aws_subnet.private[*].id
description = "IDs of private subnets"
}
hcl
`main.tf
variables.tf
outputs.tf
$1
$1
` module "vpc" {
source = "./modules/vpc" vpc_cidr = "10.0.0.0/16"
vpc_name = "my-application"
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
availability_zones = ["us-west-2a", "us-west-2b"]
tags = {
Environment = "production"
Terraform = "true"
}
}
hcl
`
$1
` module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 3.0" name = "my-vpc"
cidr = "10.0.0.0/16"
# ... other configuration
}
hcl
`
$1
Always specify module versions for consistency:
` module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "3.7.0"
# ... configuration
}
hcl
`
$1
Modules can be composed together to create larger infrastructure components:
` module "vpc" {
source = "./modules/vpc"
# ... vpc configuration
} module "ecs" {
source = "./modules/ecs"
vpc_id = module.vpc.vpc_id
# ... ecs configuration
} module "rds" {
source = "./modules/rds"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnet_ids
# ... rds configuration
}
hcl
`
$1
1. Keep Modules Focused
- One responsibility per module
- Clear interface with well-defined inputs and outputs
2. Version Control
- Store modules in version control
- Tag releases for production use
3. Documentation
- Maintain comprehensive README files
- Document all variables and outputs
- Include usage examples
4. Testing
` provider "aws" {
region = "us-west-2"
} module "test" {
source = "../"
# test configuration
}
hcl
`
$1
$1
` variable "create_resource" {
type = bool
default = true
} resource "aws_instance" "example" {
count = var.create_resource ? 1 : 0
# ... configuration
}
hcl
`
$1
` resource "aws_security_group" "example" {
name = "example" dynamic "ingress" {
for_each = var.ingress_rules
content {
from_port = ingress.value.from_port
to_port = ingress.value.to_port
protocol = ingress.value.protocol
cidr_blocks = ingress.value.cidr_blocks
}
}
}
hcl
`
$1
Common issues and solutions:
1. Module Not Found
- Check source path
- Verify Git references
- Run terraform init`
2. Variable Errors
- Ensure all required variables are provided
- Check variable types match
3. Version Conflicts
- Use version constraints
- Update terraform init -upgrade
$1
Modules are fundamental to writing maintainable Terraform code. They enable:
Remember to:
1. Keep modules focused and simple
2. Version your modules
3. Document thoroughly
4. Test comprehensively
$1
Here are essential resources for learning more about Terraform modules:
1. [Terraform Modules Documentation](https://www.terraform.io/docs/language/modules/index.html) - Official documentation on Terraform modules
2. [Terraform Registry](https://registry.terraform.io/) - Public registry for finding and sharing modules
3. [Module Creation - Best Practices](https://www.terraform.io/docs/language/modules/develop/index.html) - Guide to creating reusable modules
4. [Module Composition](https://www.terraform.io/docs/language/modules/develop/composition.html) - How to compose modules effectively
5. [Private Registry Protocol](https://www.terraform.io/docs/registry/private.html) - Setting up private module registries
6. [Module Testing](https://www.terraform.io/docs/language/modules/testing-experiment.html) - Testing Terraform modules
7. [HashiCorp Learn - Modules](https://learn.hashicorp.com/collections/terraform/modules) - Interactive tutorials on Terraform modules
8. [Module Development Guidelines](https://www.terraform-best-practices.com/code-structure#modules) - Community best practices for module development
These resources provide comprehensive information about creating and using Terraform modules effectively.
Why This Matters
Understanding the business and technical context helps you make informed decisions rather than blindly following patterns.
Trade-offs to Consider
Every architectural decision involves trade-offs. Consider your specific requirements, team expertise, and scale when evaluating options.
When NOT to Use This
Knowing when a solution doesn't apply is as valuable as knowing when it does. Consider alternatives for your specific situation.
Decision Framework
Use this framework to evaluate whether this approach is right for your use case based on your specific constraints and requirements.