Understanding and Using Terraform Modules
Terraform modules are containers for multiple resources that are used together. They allow you to create reusable components, improve organization, and encapsulate groups of resources in your infrastructure code.
What are Terraform Modules?
A module is a collection of .tf
and/or .tf.json
files kept together in a directory. Modules are the key to writing reusable and maintainable Terraform code. They allow you to:
- Organize configuration
- Encapsulate configuration
- Re-use configuration
- Provide consistency and ensure standards
Module Structure
A typical module structure might look like this:
my_module/
│
├── main.tf
├── variables.tf
├── outputs.tf
├── README.md
└── examples/
└── simple/
├── main.tf
└── outputs.tf
main.tf
: Contains the main set of configuration for your modulevariables.tf
: Contains the variable definitions for your moduleoutputs.tf
: Contains the output definitions for your moduleREADME.md
: Contains documentation describing how to use your module
Creating a Module
Here's an example of a simple module that creates an AWS S3 bucket:
# main.tf
resource "aws_s3_bucket" "this" {
bucket = var.bucket_name
acl = "private"
tags = {
Name = var.bucket_name
Environment = var.environment
}
}
# variables.tf
variable "bucket_name" {
description = "The name of the S3 bucket"
type = string
}
variable "environment" {
description = "The environment this bucket is for"
type = string
}
# outputs.tf
output "bucket_id" {
description = "The ID of the S3 bucket"
value = aws_s3_bucket.this.id
}
Using a Module
To use a module in your Terraform configuration, you can do the following:
module "my_s3_bucket" {
source = "./modules/s3_bucket"
bucket_name = "my-unique-bucket-name"
environment = "production"
}
output "s3_bucket_id" {
value = module.my_s3_bucket.bucket_id
}
Module Sources
Modules can be sourced from various locations:
- Local paths
- Terraform Registry
- GitHub
- BitBucket
- Generic Git, Mercurial repositories
- HTTP URLs
- S3 buckets
- GCS buckets
Example using a module from the Terraform Registry:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "3.14.0"
name = "my-vpc"
cidr = "10.0.0.0/16"
azs = ["us-west-2a", "us-west-2b", "us-west-2c"]
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
enable_vpn_gateway = true
tags = {
Terraform = "true"
Environment = "dev"
}
}
Module Composition
Modules can be nested within other modules, allowing for complex compositions:
module "network" {
source = "./modules/network"
# ...
}
module "application" {
source = "./modules/application"
vpc_id = module.network.vpc_id
# ...
}
Versioning Modules
When using modules from a registry or version control system, it's important to specify the version:
module "s3_bucket" {
source = "terraform-aws-modules/s3-bucket/aws"
version = "3.3.0"
# ...
}
This ensures consistent behavior and prevents unexpected changes when the module is updated.