Skip to main content

Command Palette

Search for a command to run...

L3. Mastering Terraform Modules: Clean, Reusable Infrastructure for DevOps Beginners

Updated
4 min read

One of the most powerful yet underused features of Terraform is the concept of modules.

If you’re a beginner, student, or new DevOps engineer, you’ve probably written Terraform code in one big file. But what happens when your infrastructure grows? What if your team wants to reuse the same code across environments or projects?

Welcome to the world of Terraform modules - a structured, maintainable, and reusable way to write your infrastructure as code.

Let’s explore this in-depth.


📦 What is a Terraform Module?

A module in Terraform is simply a folder that contains .tf files - your Terraform configurations - which can be reused across projects.

A module is to Terraform what a function is to programming.

Why Use Modules?

  • Avoid code duplication

  • Increase reusability across teams and environments

  • Enable better testing and debugging

  • Enforce standards across infrastructure

  • Encourage team collaboration with ownership and modular thinking


🔧 Real-World Analogy

Imagine you're working at a company like amazon.com and the app is a monolithic Java codebase with 1 million+ lines of code. When there's a bug, it's hard to know who wrote what, where to fix it, and how to test it without deploying the entire app.

The fix? Microservices - smaller, decoupled, maintainable codebases.

Similarly in Terraform:

Without modules, your .tf file will grow with:

  • EC2 Instances

  • S3 Buckets

  • VPCs

  • Lambda Functions

  • Load Balancers

  • EKS clusters
    ...and more.

It becomes impossible to maintain or collaborate on.

That’s why we adopt a modular approach in Terraform - breaking things into small, logical, reusable units.


🛠 Creating a Basic Terraform Module (Step-by-Step)

Let’s build a reusable EC2 instance module.

📁 Folder Structure

terraform-project/
├── main.tf
├── modules/
│   └── ec2_instance/
│       ├── main.tf
│       ├── variables.tf
│       ├── outputs.tf

🔨 Step 1: Inside modules/ec2_instance/main.tf

resource "aws_instance" "example" {
  ami           = var.ami_value
  instance_type = var.instance_type_value
  subnet_id     = var.subnet_id_value
}

📥 Step 2: Define Variables in modules/ec2_instance/variables.tf

variable "ami_value" {
  description = "AMI ID for the EC2 instance"
}

variable "instance_type_value" {
  description = "EC2 instance type"
}

variable "subnet_id_value" {
  description = "Subnet ID for the instance"
}

📤 Step 3: Output Public IP in modules/ec2_instance/outputs.tf

output "public_ip" {
  value = aws_instance.example.public_ip
}

🧪 Step 4: Consume the Module in Root main.tf

provider "aws" {
  region = "us-east-1"
}

module "ec2_instance" {
  source              = "./modules/ec2_instance"
  ami_value           = "ami-0c55b159cbfafe1f0"
  instance_type_value = "t2.micro"
  subnet_id_value     = "subnet-0123456789abcdef0"
}

📌 How It Works

When you run:

terraform init
terraform apply

Terraform will:

  • Load the ec2_instance module

  • Inject the variables you passed

  • Create the EC2 instance

  • Output the public IP


🔁 Why This Is So Powerful

Imagine this scenario:

You have 3 dev teams, each needing EC2 instances with different configurations.

With modules:

  • You reuse the same module

  • Just pass different ami, instance_type, and subnet_id

  • No duplicated code

Additional Benefits:

  • 🧱 Modularity – Break infrastructure into building blocks

  • 🔄 Reusability – Use the same logic across teams

  • 🧪 Testability – Test modules in isolation

  • 🔐 Security – Keep secrets in terraform.tfvars (not in code)

  • 📚 Documentation & Ownership – Clear inputs and outputs make team collaboration easier


🔐 Optional: Use terraform.tfvars to Supply Values

Create a terraform.tfvars file in your root directory:

ami_value           = "ami-0c55b159cbfafe1f0"
instance_type_value = "t2.micro"
subnet_id_value     = "subnet-0123456789abcdef0"

Then just run:

terraform apply

Terraform will automatically pick up values from this file.


🗃️ Where Should You Store Modules?

  • In the same repo (like above)

  • In a separate GitHub repo (shared across projects)

  • Use Terraform Registry (like DockerHub for modules)

❗ In production, avoid unknown public modules unless you trust the source.
Companies usually create private module registries in GitHub or Terraform Cloud.


🚀 Pro Tip: Modules Scale With Your Org

Let’s say your team writes modules for:

  • ec2_instance

  • s3_bucket

  • eks_cluster

  • vpc

  • alb

Now, internal developers can simply consume those like building blocks - without writing full configurations.

module "s3_bucket" {
  source = "git::https://github.com/org/modules.git//s3"
  bucket_name = "my-app-logs"
}

✅ Summary

Terraform modules are the secret weapon for writing production-grade infrastructure:

BenefitDescription
ModularitySmaller, manageable components
ReusabilityUse same code across environments/teams
SecurityKeep sensitive data out of source control
CollaborationClear ownership and shared modules
ScalabilityCodebase stays clean as infra grows

🔚 Final Thoughts

If you’re serious about mastering Terraform, start thinking in modules today.

Instead of managing huge .tf files, break your infrastructure into clean, reusable, and testable units - just like developers do with microservices.

"Good DevOps is modular. Great DevOps is reusable."

5 views

More from this blog

Iresh's Blog

20 posts