TerraWeek Day-05

TerraWeek Day-05

TerraWeek Day 5: Terraform Modules, Composition, and Versioning

Welcome back to TerraWeek Day 5! In today’s post, we will dive into the core concepts of Terraform Modules, Modular Composition, and Module Versioning. We'll also take a look at how to lock Terraform module versions for stable and consistent infrastructure deployments.

Task 1: Understanding Terraform Modules

What are Terraform Modules?

In Terraform, modules are containers for multiple resources that work together. They encapsulate reusable infrastructure code into units that can be managed and deployed independently.

Why Do We Need Terraform Modules?

Modules are essential for the following reasons:

  • Reusability: Write the code once and use it across different projects or environments.

  • Consistency: Standardize infrastructure components, ensuring uniform deployments.

  • Abstraction: Simplify complex configurations by breaking them down into manageable parts.

  • Scalability: Build a modular architecture to scale deployments without rewriting code.

Benefits of Using Modules

  1. Easier Collaboration: Teams can work on individual modules without interfering with others.

  2. Version Control: Track changes to modules and roll back to previous versions.

  3. Reduced Errors: Standardized modules reduce the chances of configuration errors.

  4. Faster Development: Reusing modules speeds up infrastructure deployments.

Task 2: Defining a Module in Terraform

Now, let’s define a Terraform module to encapsulate reusable infrastructure configuration. For this example, we’ll create an EC2 instance in AWS.

Directory Structure

day05
├── main.tf
├── terraform.tf
├── terraform-infra
│   ├── ec2.tf
│   ├── output.tf
│   └── variable.tf

Code for main.tf (Root Module)

module "ec2_instance" {
  source         = "./terraform-infra"
  ami_id         = "ami-0e9085e60087ce171"
  instance_type  = "t2.micro"
  instance_name  = "WebServer1"
}

output "instance_public_ip" {
  value = module.ec2_instance.public_ip
}

Code for terraform-infra/ec2.tf (EC2 Module)

resource "aws_instance" "web_server" {
  ami           = var.ami_id
  instance_type = var.instance_type

  tags = {
    Name = var.instance_name
  }
}

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

Code for terraform-infra/variable.tf

variable "ami_id" {
  description = "The AMI ID to use for the EC2 instance"
  type        = string
}

variable "instance_type" {
  description = "The type of the EC2 instance"
  type        = string
}

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

Steps to Apply Terraform

  1. Initialize Terraform:

     terraform init
    
  2. Review the Terraform Plan:

     terraform plan
    
  3. Apply Changes:

     terraform apply --auto-approve
    
  4. Verify the EC2 Instance: You will see the public IP of the EC2 instance in the output.

Final Output of EC2 Instance

Task 3: Modular Composition and Versioning

Modular Composition

In Terraform, modular composition allows you to nest modules, creating hierarchical structures for better organization. Let’s update our main.tf file to deploy two EC2 instances with shared configurations.

Updated main.tf (with Composition)

module "ec2_instance1" {
    source         = "./terraform-infra"
    ami_id         = "ami-0e9085e60087ce171"
    instance_type  = "t2.micro"
    instance_name  = "WebServer1"
}

module "ec2_instance2" {
    source         = "./terraform-infra"
    ami_id         = module.ec2_instance1.ami_id
    instance_type  = module.ec2_instance1.instance_type
    instance_name  = "WebServer2"
}

output "instance1_public_ip" {
    value = module.ec2_instance1.public_ip
}

output "instance2_public_ip" {
    value = module.ec2_instance2.public_ip
}

This configuration creates two EC2 instances with shared configurations, showcasing the concept of modular composition.

Output of Two EC2 Instances

Module Versioning

When using modules in Terraform, you may want to lock the version of a module to ensure consistent deployments. Here are some ways to lock module versions:

  1. Fixed Version:

     module "example" {
       source  = "terraform-aws-modules/vpc/aws"
       version = "2.78.0"
     }
    
  2. Version Range:

     module "example" {
       source  = "terraform-aws-modules/vpc/aws"
       version = "~> 2.0"
     }
    

    This allows patch updates but not major updates.

  3. Git Repository with Commit Hash:

     module "example" {
       source = "git::https://github.com/example/module.git?ref=abc123"
     }
    
  4. Git Tag or Branch:

     module "example" {
       source = "git::https://github.com/example/module.git?ref=v1.0.0"
     }
    

These methods ensure that the module version remains consistent, preventing unexpected changes when modules are updated.

Task 4: Locking Terraform Module Versions

Why Lock Module Versions?

Locking module versions ensures that the infrastructure deployed by Terraform is predictable and stable, avoiding issues that may arise from updates or breaking changes in a module.

Ways to Lock Terraform Module Versions:

  1. Specify a Fixed Version:

     module "example" {
       source  = "terraform-aws-modules/vpc/aws"
       version = "2.78.0"
     }
    
  2. Version Range:

     module "example" {
       source  = "terraform-aws-modules/vpc/aws"
       version = "~> 2.0"
     }
    
  3. Git Repository with Commit Hash:

     module "example" {
       source = "git::https://github.com/example/module.git?ref=abc123"
     }
    
  4. Git Tag or Branch:

     module "example" {
       source = "git::https://github.com/example/module.git?ref=v1.0.0"
     }
    

By locking module versions, you ensure that your infrastructure is consistently deployed with the same code, reducing the risk of unexpected changes.


Checkout Github repo (if needed) : https://github.com/Amitabh-DevOps/TerraWeek/tree/feat/day05/day05


Conclusion
In today’s lesson, we covered the essential concepts of Terraform modules, modular composition, and module versioning. By using modules, you can build scalable, reusable, and maintainable infrastructure code that promotes consistency and collaboration within your team. Locking module versions is also crucial to ensure that your infrastructure remains stable across different environments.


Feel free to share your thoughts in the comments below or reach out if you have any questions!
Also, don’t forget to check out my LinkedIn profile for more updates on my DevOps journey. Happy Terraforming! 🌍