Day42-Terraform Modules

Terraform Modules

Terraform Modules are a way to organize, encapsulate, and reuse Terraform configurations. They provide a way to define and package infrastructure components or resources in a modular and reusable format. Here's an explanation of Terraform Modules and why they are used:

1. Encapsulation: Modules allow you to encapsulate a set of related resources and configurations into a single directory. This encapsulation promotes a clear separation of concerns and makes it easier to manage and maintain your infrastructure as code.

2. Reusability: Modules can be reused across different Terraform projects or environments. Once you've defined a module, you can use it in multiple Terraform configurations. This promotes consistency and reduces duplication of code.

3. Abstraction: Modules can abstract complex configurations into simpler, more understandable constructs. For example, you can create a module for a web server that includes all the necessary components like an EC2 instance, security group, and IAM role. Users of the module don't need to understand the details; they can simply use the module to provision a web server.

4. Versioning: Modules can be versioned, allowing you to specify which version of a module you want to use. This ensures that infrastructure components remain consistent across different environments and over time.

5. Collaboration: Modules facilitate collaboration among team members. One team member can create a module, and others can use it without needing to understand all the intricacies of the underlying infrastructure.

6. Testing and Validation: Modules can be individually tested and validated, ensuring that they work as expected before being used in multiple environments.

7. Parameterization: Modules can accept input variables, allowing you to customize the behavior of a module when you use it. This parameterization makes modules flexible and adaptable to different use cases.

Here's an example of how you might use a Terraform module:

Suppose you have a common infrastructure pattern for deploying web applications that includes a load balancer, auto-scaling group, security group, and IAM roles. You can create a module that encapsulates this pattern with input variables for customization. Then, in multiple Terraform configurations for different web applications, you can reuse this module, passing in the necessary parameters to adapt it to each application's specific requirements.

Create An EC2-Instance Module

Step 1: Create a Module Directory

  1. Start by creating a module directory. Let's name it ec2-instance-module.

     mkdir -R Terraform/modules/ec2-instance
    
  2. Inside this directory, create main.tf and variables.tf files for defining the EC2 instance module.

     touch Terraform/modules/ec2-instance/main.tf
     touch Terraform/modules/ec2-instance/variables.tf
    

Step 2: Define EC2 Instance Module

In the ec2-instance-module directory, define your EC2 instance module. Here's an example main.tf for the module:

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
      version = "5.20.0"
    }
  }
}

provider "aws" {
  region = "ap-south-1"
  access_key = ""
  secret_key = ""
}

resource "aws_vpc" "my_vpc" {
  cidr_block = var.vpc-range
  tags = {
    Name = "my-vpc"
  }
}

resource "aws_internet_gateway" "my_igw" {
  vpc_id = aws_vpc.my_vpc.id
  tags = {
    Name = "my-gateway"
  }
}

resource "aws_subnet" "my_subnet" {
  vpc_id                  = aws_vpc.my_vpc.id
  cidr_block              = var.subnet-range
  availability_zone       = var.availability-zone
  map_public_ip_on_launch = true
  tags = {
    Name = "puclic-subnet"
  }
}

resource "aws_security_group" "my_security_group" {
  name        = "terraform-security-group"
  description = "terraform security group to allow SSH, HTTP, and HTTPS traffic"

  vpc_id = aws_vpc.my_vpc.id

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

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

  ingress {
    from_port   = 443
    to_port     = 443
    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 = "trfm-sct-grp"
  }
}

resource "aws_route_table" "my_route_table" {
  vpc_id = aws_vpc.my_vpc.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.my_igw.id
  }
  tags = {
    Name = "public-route"
  }
}

resource "aws_route_table_association" "subnet_association" {
  subnet_id      = aws_subnet.my_subnet.id
  route_table_id = aws_route_table.my_route_table.id
}


resource "aws_key_pair" "my_key_pair" {
  key_name   = var.key_name
  public_key = file("~/.ssh/id_rsa.pub")
}

resource "aws_instance" "my_instance" {
  ami                    = var.ami-id
  instance_type          = var.instance-type
  subnet_id              = aws_subnet.my_subnet.id
  key_name               = aws_key_pair.my_key_pair.key_name
  vpc_security_group_ids = [aws_security_group.my_security_group.id]

  tags = {
    Name = "var.instance_name"
  }
}

And in variables.tf, define the input variables for the module:

variable "ami_id" {
  description = "this is a ami-variable"
}

variable "instance_type" {
  description = "this is a instance-variable"
}

variable "vpc_range" {
  description = "this is a vpc range variable"
}

variable "subnet_range" {
  description = "this is a subnet range variable"
}

variable "availability_zone" {
  description = "this is a subnet avalaiblity zone variable"
}

variable "instance_name" {
  description = "The name to tag the EC2 instance with."
}

variable "key_name" {
  description = "The name of the SSH key pair to use for the EC2 instance."
}

Step 3: Use the Module

  1. In the Terraform directory, create a main.tf file where you'll use the EC2 instance module:

     touch main.tf
    
  2. In main.tf, reference the EC2 instance module and provide values for the required input variables:

     provider "aws" {
       region = "ap-south-1"
     }
    
     module "my_ec2_instance" {
       source = "./modules/ec2-instance-module"
       ami_id         = "ami-0f5ee92e2d63afc18"
       instance_type  = "t2.micro"
       vpc-range      = "192.168.0.0/16"
       subnet-range   = "192.168.0.0/24"
       availability-zone  = "ap-south-1a"
       instance_name  = "my-ec2-instance"
       key_name       = "id_rsa"
     }
    

Step 4: Usage

In your terminal, navigate to the directory containing these files and run:

terraform init
terraform plan
terraform apply