DEV Community

Vivesh
Vivesh

Posted on

Terraform Modules

  • Definition: A Terraform module is a container for multiple resources that are used together. Modules help organize, reuse, and manage your Terraform code efficiently.
  • Structure:
    • Root Module: The directory where terraform init is run.
    • Child Module: Any module called by another module (e.g., a reusable VPC or EC2 setup).

Example:

A reusable VPC module might create subnets, route tables, and an Internet Gateway.


Why Use Modules?

  1. Reusability: Share modules across multiple projects.
  2. Maintainability: Separate infrastructure into logical, manageable pieces.
  3. Consistency: Apply standardized configurations across environments (e.g., dev, staging, production).
  4. Simplified Management: Focus on high-level architecture by abstracting complex configurations.

Creating a Terraform Module

Example: VPC Module

  1. Module Directory Structure:


    modules/
    └── vpc/
    ├── main.tf
    ├── variables.tf
    ├── outputs.tf

  2. main.tf (VPC resources):

    `
    resource "aws_vpc" "example" {
    cidr_block = var.cidr_block
    }

resource "aws_subnet" "public" {
count = var.public_subnet_count
cidr_block = element(var.public_subnet_cidrs, count.index)
availability_zone = element(var.availability_zones, count.index)
vpc_id = aws_vpc.example.id
}
`

  1. variables.tf (Input Variables):


    variable "cidr_block" {}
    variable "public_subnet_cidrs" {
    type = list(string)
    }
    variable "public_subnet_count" {}
    variable "availability_zones" {}

  2. outputs.tf (Outputs):

    `
    output "vpc_id" {
    value = aws_vpc.example.id
    }

output "public_subnets" {
value = aws_subnet.public[*].id
}
`

  1. Using the Module: In your root module: module "vpc" { source = "./modules/vpc" cidr_block = "10.0.0.0/16" public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"] public_subnet_count = 2 availability_zones = ["us-east-1a", "us-east-1b"] }

Terraform Best Practices

  1. Organize Code into Modules:

    • Group related resources into modules (e.g., network, database, compute).
  2. Use Remote Backends:

    • Store Terraform state in remote backends like S3 with state locking via DynamoDB to avoid conflicts.
  3. Use Version Control:

    • Pin versions for the Terraform provider and modules: terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } }
  4. Implement Input Validation:

    • Use validation blocks in variables: variable "environment" { type = string validation { condition = var.environment in ["dev", "staging", "prod"] error_message = "Invalid environment. Choose dev, staging, or prod." } }
  5. Minimize Hardcoding:

    • Use variables and outputs to increase flexibility and portability.
  6. Keep State Secure:

    • Encrypt your state file when using remote backends.
  7. Write Meaningful Outputs:

    • Provide critical resource IDs or URLs to simplify downstream usage.
  8. Use Terraform Workspaces:

    • Manage multiple environments (e.g., dev, staging, prod):
     terraform workspace new staging
     terraform workspace select staging
    
  9. Adopt a CI/CD Pipeline:

    • Automate plan and apply actions while enforcing code reviews and approvals.

Happy Learning !!!

Top comments (0)