Day 70 : Terraform Modules

Day 70 : Terraform Modules

In this Article, we will dive into terraform modules and you will learn how to write and customize a terraform module and To create a project to launch an EC2 instance using terraform modules.

Infrastructure as Code is first and foremost code, and a chief principle of writing good software is leveraging abstractions to make your code reusable, scalable, and consistent. Terraform modules are the abstraction provided by HashiCorp to take logical groupings of resources and package them together in a reusable object.

What are terraform modules?

A Terraform module is a collection of standard configuration files in a distinct directory. Modules can be used to define things like virtual machines, databases, or load balancers. They can also be used to define more complex infrastructure, such as a complete web application stack.

Modules can be used to create lightweight abstractions, so that you can describe your infrastructure in terms of its architecture, rather than directly in terms of physical objects. Modules are used to create reusable components, improve organization, and treat pieces of infrastructure.

The most important file in a module is the main.tf file. This file defines the entry point for the module and is where you will typically define the module's inputs and outputs.

A typical module can look like this:

.
├── main.tf
├── outputs.tf
├── README.md
└── variables.tf

Other common files in a module include:

  • variables.tf: This file defines the module's variables. Variables are inputs that can be passed to the module when it is used.

  • providers.tf: This file defines the providers that the module will use. Providers are the tools that Terraform uses to interact with the underlying infrastructure.

  • README.md: A markdown file providing documentation for the module. It typically includes information on how to use the module, input variables, outputs, any prerequisites, and any other relevant details.

  • Examples: This directory may contain examples of usage of the module. These examples demonstrate how to use the module in different scenarios or configurations.

  • tests/: Optionally, a directory containing automated tests for the module. Tests can help ensure that the module behaves as expected and doesn't introduce regressions when changes are made.

    Benefits of Terraform modules:

    1. Abstraction: Modules abstract infrastructure components into logical units. For example, you might have a module for provisioning a virtual machine in a cloud provider, another for configuring a database, and so on.

    2. Reusability: Once created, modules can be reused across different projects and environments. This promotes consistency and reduces duplication of code.

    3. Encapsulation: Modules encapsulate configuration details, hiding complexity and making it easier to understand and maintain infrastructure code.

    4. Parameterization: Modules can be parameterized, allowing you to customize their behavior by passing input variables. This enables you to create flexible and adaptable infrastructure configurations.

    5. Composition: Modules can be composed together to create more complex infrastructure setups. For instance, you might combine a compute module with a networking module to create a complete application environment.

How do I write a module?

💡A Terraform module definition is a single or many.tf files stacked together in their own directory. To write a Terraform module, you first need to create a directory for the module. Inside the directory, you will need to create one or more Terraform configuration files. These files will define the resources that the module creates.

💡The resource definitions are normally contained in main.tf, input variables are defined in variables.tf, and outputs of the module are configured in outputs.tf. To set variable values, we can also use other files, like variables.tfvars. Once you have written your module, you can use it in other Terraform configurations by calling the module block.

Syntax of the Terraform Modules Block:

Within your primary Terraform setup, you can call and instantiate modules using the modules block. The syntax is:

    module "module_name" {
      source = "path_of_module"
      [other_arguments]
    }
  • module_name: The user-defined name for the module instance is module_name.

  • source: This identifies the module’s location. A remote module registry (like GitHub or Terraform Registry) or a local file path could both be used.

  • other_arguments: Optional arguments which module can accept as optional arguments.

    🛠Create the Module Structure:
    Create a directory for your module and define the required files. In this example, we'll name the module directory "vm" and assume it will be used to create AWS EC2 instances.

    🛠Define Input Variables:

    In the variables.tf file, define the input variables that users of your module can customize.

      variable "instance_type" {
        description = "The instance type for the VM"
        type        = string
        default     = "t2.micro"
      }
    
      variable "ami" {
        description = "The AMI ID for the VM"
        type        = string
      }
    
      variable "subnet_id" {
        description = "The subnet ID for the VM"
        type        = string
      }
    

    🛠Implement the Main Configuration:

    In the main.tf file, write the main Terraform configuration code that deploys the VM based on the input variables.

      resource "aws_instance" "vm_instance" {
        ami           = var.ami
        instance_type = var.instance_type
        subnet_id     = var.subnet_id
    
        # Add other configuration options as needed
      }
    

    🛠Define Output Values:

    In the outputs.tf file, specify the output values that users can retrieve after deploying the module. These outputs can be used by other Terraform code or scripts.

      output "instance_id" {
        description = "The ID of the deployed VM instance"
        value       = aws_instance.vm_instance.id
      }
    
      output "public_ip" {
        description = "The public IP address of the deployed VM instance"
        value       = aws_instance.vm_instance.public_ip
      }
    

    🛠Usage Example:
    Now, let's see how you can use the module in a Terraform configuration. Create a new .tf file (e.g., main.tf) and use the module block to instantiate the module:

      module "my_vm" {
        source     = "./vm"  # Path to the module directory
    
        instance_type = "t2.micro"
        ami           = "ami-12345678"
        subnet_id     = "subnet-12345678"
      }
    

    In this example, we're using the module located in the current directory ("./vm") and providing values for the input variables instance_type, ami, and subnet_id.

    Run Terraform Commands:
    After creating the Terraform configuration file, run the following commands to initialize and apply the configuration:

      terraform init  # Initialize the working directory
      terraform plan  # To download the necessary provider plugins
      terraform apply # Deploy the VM based on the module
    

    Terraform will initialize the working directory and download the necessary provider plugins. Then, it will deploy the VM using the module, creating the specified AWS EC2 instance.

    🛠Later, we can terminate the entire infrastructure using single command .This is absolutely best thing about Terraform (in my opinion!) is that you can destroy ALL of the resources you created using ,

      terraform destroy
    
  • That's it! You've created a Terraform module for deploying a VM in AWS. Users can utilize the module by providing their desired input values for the instance_type, ami, and subnet_id variables.

Different types of terraform modules :

There are several types of Terraform modules, each serving different purposes and providing various levels of abstraction. Here are some common types, along with examples:

  1. Provider Modules: These modules abstract the configuration of specific cloud providers or services. They typically encapsulate resources and settings related to a particular cloud platform.

    (e.g., AWS, Azure).

  2. Resource Modules: These modules encapsulate configurations for specific types of resources within a cloud provider. They provide a reusable way to define and manage resources.

    • Example: A Terraform module for managing AWS S3 buckets, including settings such as bucket name, access control policies, and versioning.
  3. Composite Modules: These modules combine multiple lower-level modules to create more complex infrastructure setups. They promote modular design by abstracting away complex configurations.

    • Example: A Terraform module for deploying a web application on AWS, which includes sub-modules for provisioning EC2 instances, setting up a load balancer, configuring databases, etc.
  4. Module Composition Modules: These modules facilitate the composition of other modules by providing a higher-level interface or configuration options.

    • Example: A Terraform module that combines various lower-level modules to provision a multi-tier architecture, allowing users to specify parameters such as instance types, database engines, and scaling policies.

Differences between the root module and the child module:

Terraform lets you utilize prebuilt modules available through the Terraform registry or create custom modules to suit their needs. There are thousands of free modules in the Terraform registry that cater to different providers and use cases. But there are three primary types of modules in Terraform that you are likely to encounter:

module types

  1. Root Module:

    • The root module is the main entry point for your Terraform configuration.

    • It typically consists of one or more .tf files in a directory where you run the terraform command.

    • The root module can contain configurations for the entire infrastructure or a subset of it.

    • It often orchestrates the deployment of multiple child modules and may define variables, providers, and backend configurations.

    • Every Terraform configuration consists of the root module as the main directory that works with the .tf files. You can call any number of child modules or published modules from the root module.

Child Module:

  • A child module is a self-contained package of Terraform configurations that is designed to be used within another Terraform configuration.

  • It encapsulates a specific set of resources or functionality, promoting modularity and reusability.

  • Child modules can be created to manage different parts of the infrastructure, such as networking, compute resources, databases, etc.

  • Child modules can be invoked multiple times with different input variables, allowing you to create multiple instances of the same infrastructure component.

  • They typically reside in separate directories and are reusable across different projects and environments.

  • Child modules can be composed together within the root module or other parent modules to create complex infrastructure configurations.

Are modules and Namespaces are same? Justify your answer for both Yes/No

Modules and namespaces are not the same, although they both relate to organizing and structuring resources in a system.

Yes, they are the same:

  1. Organizational Units: Both modules and namespaces provide a way to organize and structure code into logical units. They help manage complexity and maintainability by grouping related components together.

  2. Encapsulation: Both concepts encapsulate functionality, but at different levels. Modules encapsulate Terraform configurations, while namespaces encapsulate code elements such as classes, functions, or variables.

  3. Reuse and Modularity: Both modules and namespaces promote reuse and modularity. Modules can be reused across different projects, while namespaces facilitate the reuse of code elements within a project or codebase.

No, they are not the same :

  1. Scope: Modules in Terraform define reusable infrastructure configurations, while namespaces in programming languages define the scope and visibility of code elements.

  2. Granularity: Modules typically encapsulate a set of related resources or configurations, while namespaces can be more granular, encompassing individual code elements within a larger codebase.

  3. Purpose: Modules in Terraform are primarily used for infrastructure as code (IaC) to manage and provision resources, while namespaces in programming languages are used for organizing code and preventing naming conflicts.

While both modules and namespaces serve organizational purposes, they operate at different levels and serve different roles within their respective contexts. Modules are specific to Terraform and focus on infrastructure configuration management, while namespaces are a broader concept used in programming languages for organizing code.

Create a project to launch an EC2 instance using terraform modules:

In this task, we will launch an EC2 instance using the idea of a Terraform module.

Step1: Let us make a folder called "module" in which we will store our module files like ec2.tf, variable.tf, etc. We will generate provider.tf and main.tf outside of the module folder.

We will install aws provider using the "provider.tf" file, using the following code:.

terraform {
  required_providers {
    # Declare the AWS provider with its source and version constraints.
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0" # Use version 5.x of the AWS provider.
    }
  }
}

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

Step 2: Next, create a file named ec2.tf in which we will create our aws_instance resource inside the module (modules/ec2).

resource "aws_instance" "web_server" {
    ami = var.ami
    instance_type = var.instance_type
    tags = {
        Name = "${var.my_env}-web-server"
    }
}

Step 3: After that, we will create a file named variable.tf in which we will create our input variables for our module (modules/ec2).

variable "my_env" {
    description = "The environment for the app"
    type = string
}

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

variable "ami" {
    description = "value of the ami"
    type = string
}

Step 4: We will create a main.tf file outside the module (module) in which we will call our module (modules). This will be used to launch an EC2 instance for the "dev" environment using the "Ubuntu AMI."

# dev 

module "ec2_module" {
    source = "./ec2_modules"
    my_env = "dev"
    instance_type = "t2.micro"
    ami = "ami-0ddda618e961f2270" 
}

Step 5: Let's use the command below to initialize the Terraform project:

terraform init

Step 6: Once all the prerequisite plugins are satisfied, execute the terraform plan commands to check that our infrastructure met the conditions that we have provided.

Step 7: If everything is fine, execute the command terraform apply to create our complete infrastructure.

Step 8: Now, we will check the terraform state:

Step 9: We can verify it in the AWS console:

Step 10: To view the state of a particular module, use the below command:

terraform state show <module-name>

Step 11: To destroy the particular state of a particular module, we can use

terraform destroy -target <mod>

Step 12: Once you are done with the newly created instance we can use terraform destroy command that will delete the entire infrastructure.

Thank you for 📖reading my blog. 👍 Like it and share it 🔄 with your friends . Hope you find it helpful🤞

Happy learning😊😊