Day 15: Modules in Terraform – Structuring and Scaling Infrastructure

Pritish AnandPritish Anand
5 min read

Introduction

As Terraform projects grow, maintaining clean, reusable, and organized infrastructure code becomes critical. Terraform Modules are the solution to this problem. By bundling resources and configurations into self-contained modules, you can manage complex infrastructure as smaller, manageable pieces. This not only makes your code reusable but also makes your infrastructure scalable across multiple environments.

In today’s blog, we’ll explore:

  • What modules are in Terraform

  • How to create and use modules

  • The advantages of using modules

  • Best practices for module management

  • Real-world examples and use cases


What Are Terraform Modules?

At its core, a module in Terraform is a container for multiple resources that are used together. Every Terraform configuration file (.tf) is actually a module, even if you don’t explicitly define it as such. However, defining reusable modules allows you to manage pieces of infrastructure across projects and environments.

Why Use Terraform Modules?

✔️ Reusability – Modules let you define resources once and use them across multiple projects. ✔️ Consistency – Ensures consistent infrastructure configurations across your environments (Dev, Test, Production). ✔️ Simplified Management – Modularized code is easier to maintain and troubleshoot. ✔️ Scalability – Simplifies scaling infrastructure by using reusable, scalable modules.


How to Create and Use Terraform Modules

1. Creating a Module

To create a module, you organize your Terraform configurations into a dedicated directory structure. Let’s consider a module for AWS EC2 instances.

Directory Structure:

/terraform-aws-ec2/
  ├── main.tf
  ├── variables.tf
  ├── outputs.tf
  • main.tf – Contains the actual resources and configuration

  • variables.tf – Defines the input variables needed for the module

  • outputs.tf – Specifies the output values of the module

Example: Main.tf – EC2 Module

resource "aws_instance" "ec2_instance" {
  ami           = var.ami_id
  instance_type = var.instance_type
  tags = {
    Name = var.instance_name
  }
}

resource "aws_security_group" "ec2_sg" {
  name_prefix = "ec2_sg_"
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Example: Variables.tf

variable "ami_id" {
  type        = string
  description = "The ID of the Amazon Machine Image (AMI) to use"
}

variable "instance_type" {
  type        = string
  description = "The EC2 instance type"
  default     = "t2.micro"
}

variable "instance_name" {
  type        = string
  description = "The name to apply to the EC2 instance"
}

Example: Outputs.tf

output "instance_id" {
  value       = aws_instance.ec2_instance.id
  description = "The ID of the created EC2 instance"
}

output "security_group_id" {
  value       = aws_security_group.ec2_sg.id
  description = "The ID of the created security group"
}

2. Using a Module

Once you’ve defined the module, you can use it in any Terraform project by referencing the module’s path. This is where reusability comes in.

Example: Using the EC2 Module

module "ec2_instance" {
  source         = "./terraform-aws-ec2"
  ami_id         = "ami-123456"
  instance_type  = "t2.micro"
  instance_name  = "my-ec2-instance"
}

In this example:

  • source – Path to the module directory.

  • ami_id, instance_type, and instance_name are input variables passed to the module.


Real-World Use Cases for Terraform Modules

1. Environment-Specific Modules

You can create environment-specific modules (e.g., Dev, Staging, Production) to provision infrastructure with different configurations per environment.

module "dev_ec2" {
  source        = "./terraform-aws-ec2"
  ami_id        = "ami-dev-id"
  instance_type = "t2.micro"
  instance_name = "dev-ec2-instance"
}

module "prod_ec2" {
  source        = "./terraform-aws-ec2"
  ami_id        = "ami-prod-id"
  instance_type = "t2.large"
  instance_name = "prod-ec2-instance"
}

2. Networking and Security Modules

You can create a reusable module for setting up Virtual Private Cloud (VPC), subnets, route tables, and security groups, and use it across multiple environments or projects.


Best Practices for Terraform Modules

✔️ Keep Modules Simple and Focused – Each module should focus on a single responsibility, such as networking, compute, or security. This ensures modularity and reusability.

✔️ Use Version Control – Keep your modules in a version-controlled repository like GitHub to maintain a history of changes and avoid unintentional updates.

✔️ Leverage Input and Output Variables – Use input variables to make your modules flexible and output variables to expose necessary values for other modules or resources.

✔️ Document Your Modules – Clearly document the purpose of the module, input/output variables, and how to use it. This makes it easier for others to understand and implement your module.

✔️ Avoid Hard-Coding Values – Always parameterize your modules using variables to avoid hardcoding configurations that might change across environments.

✔️ Version Locking – If you're using third-party modules from Terraform Registry or GitHub, ensure you use version locking (version = "x.y.z") to avoid breaking changes.


Using Terraform Registry for Modules

Terraform Registry offers a collection of modules maintained by HashiCorp and the Terraform community. Using Terraform Registry is a great way to accelerate your infrastructure automation.

Example of Using a Module from Terraform Registry:

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

  name = "my-vpc"
  cidr = "10.0.0.0/16"

  azs             = ["us-west-1a", "us-west-1b"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24"]
}

In this example, the AWS VPC module from Terraform Registry is used to create a VPC, private subnets, and public subnets. The module version is locked to 2.77.0 to avoid unintended upgrades.


Conclusion

Terraform modules are essential for managing scalable, maintainable infrastructure across projects and environments. They help you break down complex infrastructure into reusable, manageable components, making your Terraform projects modular and organized.

In this article, we covered:

  • What Terraform modules are and how they work

  • How to create, use, and manage modules

  • Best practices for module management

  • Real-world examples of using modules for EC2, networking, and security

By embracing Terraform modules, you can streamline your infrastructure automation process and ensure consistency across your environments.


What’s Next?

Tomorrow’s topic is Day 16: Best Practices for Terraform Modules (Part 1) where we’ll dive into more advanced concepts and strategies to write efficient modules. Stay tuned!

0
Subscribe to my newsletter

Read articles from Pritish Anand directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Pritish Anand
Pritish Anand