Skip to content

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 module
  • variables.tf: Contains the variable definitions for your module
  • outputs.tf: Contains the output definitions for your module
  • README.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.