Mastering Terraform Custom Modules: A Comprehensive Guide

A Terraform module is a reusable, self-contained collection of Terraform configuration files that manage a set of related resources. Modules are the building blocks of Terraform, enabling you to organize and encapsulate configurations for easier reuse and maintenance.

Key Components of a Terraform Module:

  • Main Configuration: Typically named main.tf, this file contains the primary resource definitions.
  • Variables: Defined in variables.tf, this file contains the input variables for the module.
  • Outputs: Defined in outputs.tf, this file specifies the output values that can be used by other modules or the root module.
  • Optional Files: Additional configuration files like providers.tf, data.tf, and README.md for documentation.

When to Use a Terraform Module?

Modules are used when you need to:

  1. Encapsulate Configuration: Organize and encapsulate a set of related resources for reuse.
  2. Promote Reusability: Share and reuse configurations across different environments and projects.
  3. Improve Maintainability: Simplify management by breaking down complex configurations into smaller, manageable pieces.
  4. Standardize Practices: Enforce best practices and standards across multiple configurations.

Real-Time Example: Using Terraform Module with AWS

Let’s create a Terraform module to set up an AWS VPC along with a couple of subnets and a security group.

Step-by-Step Implementation

  1. Create the Module Directory Structure:
.
├── modules/
│   └── vpc/
│       ├── main.tf
│       ├── variables.tf
│       ├── outputs.tf
│       └── README.md
├── main.tf
└── terraform.tfvars

2.Define the Module Configuration:

main.tf (inside modules/vpc directory):

provider "aws" {
  region = var.region
}

resource "aws_vpc" "this" {
  cidr_block = var.vpc_cidr
  tags = {
    Name = var.vpc_name
  }
}

resource "aws_subnet" "public" {
  count             = length(var.public_subnets)
  vpc_id            = aws_vpc.this.id
  cidr_block        = var.public_subnets[count.index]
  availability_zone = element(var.azs, count.index)
  tags = {
    Name = "${var.vpc_name}-public-${count.index}"
  }
}

resource "aws_security_group" "this" {
  vpc_id = aws_vpc.this.id
  name   = "${var.vpc_name}-sg"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "${var.vpc_name}-sg"
  }
}

variables.tf:

variable "region" {
  description = "The AWS region to deploy resources"
  type        = string
}

variable "vpc_cidr" {
  description = "The CIDR block for the VPC"
  type        = string
  default     = "10.0.0.0/16"
}

variable "vpc_name" {
  description = "The name of the VPC"
  type        = string
}

variable "public_subnets" {
  description = "List of CIDR blocks for public subnets"
  type        = list(string)
}

variable "azs" {
  description = "List of availability zones"
  type        = list(string)
}

Output.tf

output "vpc_id" {
  description = "The ID of the VPC"
  value       = aws_vpc.this.id
}

output "public_subnet_ids" {
  description = "The IDs of the public subnets"
  value       = aws_subnet.public[*].id
}

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

3.Use the Module in the Root Configuration:

main.tf (root module):

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

module "vpc" {
  source        = "./modules/vpc"
  region        = var.region
  vpc_cidr      = var.vpc_cidr
  vpc_name      = var.vpc_name
  public_subnets = var.public_subnets
  azs           = var.azs
}

output "vpc_id" {
  value = module.vpc.vpc_id
}

output "public_subnet_ids" {
  value = module.vpc.public_subnet_ids
}

output "security_group_id" {
  value = module.vpc.security_group_id
}

4.Define Variables in terraform.tfvars:

terraform.tfvars:

region = "us-west-1"
vpc_cidr = "10.0.0.0/16"
vpc_name = "my-vpc"
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
azs = ["us-west-1a", "us-west-1b"]

5.Initialize and Apply the Configuration:

terraform init
terraform apply

Please find the source code: Click Here

https://gitlab.com/Jaganrajagopal/terraformmoduledemo.git

Explanation

  • The module encapsulates the creation of a VPC, subnets, and a security group.
  • It is parameterized using variables for region, VPC CIDR, subnet CIDRs, availability zones, and VPC name.
  • Outputs are defined to expose the created resources’ IDs.
  • The root module calls the VPC module, providing necessary variable values.

This approach allows for reuse and easier management of the infrastructure components, making your Terraform configurations modular, maintainable, and scalable.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *