TerraWeek day 5:

Passionate AWS Developer | DevOps Engineer with a strong background in cloud architecture and solutions engineering. Leveraging the power of Amazon Web Services (AWS), knowledge of the AWS global infrastructure, design and implement robust cloud-based solutions that align with clients' specific needs.
Task 01:
What are modules in Terraform and why do we need modules in Terraform?
In simple terms, we can say that A module is a simple directory that contains other .tf files. By using modules we can make the code reusable. We need modules for various reasons.
Firstly, modules promote code reuse. Instead of writing the same configuration code over and over again, we can create a module for a specific infrastructure component and reuse it across multiple projects. This saves time and effort and ensures consistency in our infrastructure deployments.
In Terraform, modules are a way to organize and encapsulate your infrastructure code into reusable, self-contained units. They allow you to break down your infrastructure configuration into smaller, manageable components, which can be composed and shared across different Terraform configurations.
What are the benefits of using modules?
Using modules in Terraform offers a range of benefits that enhance the efficiency, reusability, and maintainability of your infrastructure code. Here are the key benefits of using modules in Terraform:
Code Reusability: Modules allow you to define infrastructure components once and reuse them across multiple Terraform configurations. This saves time and reduces redundancy by preventing you from rewriting the same resource configurations.
Abstraction: Modules enable you to abstract the complexity of infrastructure resources. You can encapsulate the details of a resource, making your code more concise and easier to read and understand.
Organization: Modules provide a structured way to organize your infrastructure code. By grouping related resources and configurations into modules, you create a clear separation of concerns and make it easier to navigate and maintain your codebase.
Testing and Isolation: You can develop and test modules independently. This modularity allows you to verify that a module works correctly before using it in multiple configurations, improving the reliability of your infrastructure.
Collaboration: Modules promote collaboration in team environments. Different team members can work on separate modules, and these modules can be shared and reused across the organization. This collaborative approach enhances productivity and consistency.
Parameterization: Modules can be parameterized, allowing you to customize the behavior and configuration of the module instances. This flexibility makes modules adaptable to different use cases and environments without the need to create multiple copies of the same code.
Versioning: Modules can be versioned, enabling you to manage changes to infrastructure components over time while ensuring backward compatibility with existing configurations. This versioning mechanism enhances stability and predictability in your infrastructure.
Simplification of Root Configuration: Using modules reduces the complexity of your root configuration files, making them more readable and focused on the high-level architecture of your infrastructure. This separation of concerns makes it easier to manage the main configuration files.
Best Practices: Modules encourage the adoption of best practices in infrastructure as code (IAC). They promote code reusability and a structured approach to configuration management, which leads to more maintainable, reliable, and scalable infrastructure.
Community Contributions: The Terraform community has created and shared a wide range of modules for common infrastructure components. You can leverage these community modules to jumpstart your infrastructure projects, saving you significant development time.
Scalability: Modules support the growth and evolution of your infrastructure. As your needs change, you can create new module instances, modify existing ones, or develop additional modules, allowing your infrastructure to scale with ease.
Documentation: Modules can include documentation and comments, making it easier for you and your team to understand how to use them effectively and ensuring consistency in configuration.
Task 02:
Create/Define a module in Terraform to encapsulate reusable infrastructure configuration in a modular and scalable manner. For e.g. EC2 instance in AWS, Resource Group in Azure, Cloud Storage bucket in GCP.
In Terraform, you can create a reusable module to encapsulate infrastructure configuration by defining a set of resources, input variables, and output values. Here's an example of how you can create a module named demo-app to provision a Dev/Qa/Prod env in AWS:
Create a directory named Modules/demo-app in the terraform-project directory.
create a ec2.tf file and define a resource block for the instance.
resource "aws_instance" "my-demo-instance" {
count = 2
ami = var.ami_id
instance_type = var.instance_type
tags = {
name = "${var.env_name}_${var.instance_name}" #dev-batch-4-demo-instance
}
}
~
create a s3.tf file to define a bucket.
resource "aws_s3_bucket" "my-demo-bucket" {
bucket = "${var.env_name}_${var.bucket_name}"
}
create a dynamodb.tf to define a dynamodb table for the env.
resource "aws_dynamodb_table" "my-table" {
name = "${var.env_name}-${var.table_name}"
billing_mode = "PAY_PER_REQUEST"
hash_key = "emailID"
attribute {
name = "emailID"
type = "S"
}
}
create a variables.tf to define all the variables.
variable "ami_id" {
description = "This is ami id based on modules"
type = string
}
variable "instance_type" {
description = "This is instance_type based on environment"
type = string
}
variable "instance_name" {
type = string
}
variable "bucket_name" {
type = string
}
variable "table_name" {
type = string
}
variable "env_name" {
type = string
}
create the main.tf file with the following configuration for different environment
#dev nfra
module "dev-demo-app" {
source = "./modules/demo-app"
env_name = "dev"
instance_type = "t2.micro"
ami_id = "ami-053b0d53c279acc90"
instance_name = "batch-4-demo-instance"
bucket_name = "batch-4-demo-bucket9"
table_name = "batch-4-demo-table"
}
#QA nfra
module "qa-demo-app" {
source = "./modules/demo-app"
env_name = "qa"
instance_type = "t2.small"
ami_id = "ami-03a6eaae9938c858c"
instance_name = "batch-4-demo-instance"
bucket_name = "batch-4-demo-bucket9"
table_name = "batch-4-demo-table"
}
#prod infra
module "prod-demo-app" {
source = "./modules/demo-app"
env_name = "prod"
instance_type = "t2.medium"
ami_id = "ami-026ebd4cfe2c043b2"
instance_name = "batch-4-demo-instance"
bucket_name = "batch-4-demo-bucket9"
table_name = "batch-4-demo-table"
}
-- INSERT --
providers.tf file for adding plugin
provider "aws" {
region = "us-east-1"
}
terraform.tf for providers
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.16.1"
}
}
}
Initialize the repository by executing the command terraform init.
Run terraform plan to view the execution plan and once the plan is ready, apply the plan through command terraform apply. This will create a module for a particular demo-app.
Task 03:
Dig into modular composition and module versioning.
Modular composition in Terraform refers to the practice of creating complex infrastructure configurations by combining and reusing smaller, self-contained modules. It allows you to build more intricate infrastructure setups from smaller, manageable pieces, enhancing the maintainability and scalability of your Terraform code.
Here's how modular composition works:
Define Reusable Modules: You create individual modules for different infrastructure components. These modules encapsulate the configuration for specific resources or services (e.g., a database module, a load balancer module, an EC2 instance module).
Configure Input Variables: Within each module, you define input variables, which allow users of the module to customize the behavior and configuration of the resource. These variables can be set as arguments when you use the module.
Use Modules in Root Configuration: In your root configuration (main Terraform file), you reference and use these modules. You specify the input variables' values when using the module instances. This allows you to customize each resource's configuration according to your specific needs.
Compose Complex Infrastructure: By combining multiple module instances in your root configuration, you can create complex infrastructure setups. This approach keeps your root configuration files concise and focused on high-level architecture, while the module configurations handle the resource-specific details.
Benefits of Modular Composition:
Reusability: Modules are reusable across different configurations. You can use the same module to create similar resources in multiple projects.
Maintainability: Modules are self-contained, making it easier to manage, update, and test individual resources or services.
Scalability: As your infrastructure grows, you can add more module instances or create new modules to accommodate additional resources.
Collaboration: Teams can work on separate modules, promoting collaboration and parallel development on different parts of the infrastructure.
Versioning: Modules can be versioned, allowing you to make changes and improvements while maintaining backward compatibility with existing configurations.
Module Versioning:
Module versioning is the practice of assigning versions to your Terraform modules. It's essential for managing changes to modules and ensuring that existing configurations remain stable.
Key aspects of module versioning:
Version Constraints: In your root configuration, you can specify the allowed module versions using version constraints. For example, you can require a module to be at least version 1.0 but less than 2.0.
Module Sources: Modules can be sourced from different locations, including local paths, Git repositories, and the Terraform Module Registry. When you specify a source, you can include the desired version.
Semantic Versioning: Terraform follows semantic versioning (SemVer), with versions structured as
MAJOR.MINOR.PATCH. Increment the MAJOR version for backward-incompatible changes, MINOR for backward-compatible additions, and PATCH for backward-compatible fixes.Module Updates: When you need to update a module in your root configuration, you can increment the version constraint to the desired version. Terraform will use the latest compatible version within the specified constraint.
Benefits of Module Versioning:
Predictable Updates: Version constraints allow you to control when and how module updates are applied, preventing unexpected changes to your infrastructure.
Backward Compatibility: By adhering to SemVer, you ensure that existing configurations using a specific module version remain stable, even as the module evolves.
Change Control: Module versioning provides a clear mechanism for tracking and documenting changes, making it easier to manage infrastructure updates and modifications.
Task 04:
What are the ways to lock Terraform module versions? Explain with code snippets.
Locking Terraform module versions is important to maintain control over the modules used in your infrastructure configurations. It ensures that your infrastructure remains stable and predictable, even as you update or modify your code. Here are the ways to lock Terraform module versions and code snippets to illustrate each approach:
Lock Module Versions with Fixed Version Constraints:
You can lock module versions by specifying fixed version constraints in your root configuration. This is the most straightforward way to ensure that a specific version of a module is always used.
Example in your root configuration (e.g., main.tf):
module "my_module" {
source = "examplecorp/my-module/aws"
version = "1.2.3"
}
In this example, the module is locked to version "1.2.3." Terraform will always use this version unless you explicitly change it.
Lock Module Versions with Range-Based Version Constraints:
You can specify a range of versions for a module to allow for updates that are within a defined range. This provides more flexibility while still ensuring some level of version stability.
Example in your root configuration:
module "my_module" {
source = "examplecorp/my-module/aws"
version = ">= 1.0.0, < 2.0.0"
}
In this example, the module can be any version that is at least 1.0.0 but less than 2.0.0. This allows for updates that include new features or bug fixes but avoids backward-incompatible changes
Lock Module Versions with Git References:
If your modules are stored in a Git repository, you can lock module versions by referencing a specific Git commit, branch, or tag.
Example in your root configuration:
module "my_module" {
source = "git::https://github.com/examplecorp/my-module.git//modules/aws?ref=v1.2.3"
}
In this example, the module is locked to the specific tag "v1.2.3" in the Git repository. This ensures that Terraform always uses that specific commit.
Lock Module Versions with Terraform Registry:
If you're using modules from the Terraform Module Registry, you can lock module versions by specifying the version number. Terraform will download the module from the registry based on the version you've defined.
Example in your root configuration:
module "my_module" {
source = "hashicorp/vpc/aws"
version = "2.0.0"
}
In this example, the module is locked to version "2.0.0" from the Terraform Module Registry.




