Terraform Modules

๐Ÿ”ฅ Vibe Prompt

"Create a Terraform module for a standard VPC with public/private subnets and NAT Gateway."

# modules/vpc/main.tf
variable "vpc_cidr" {}
variable "environment" {}

resource "aws_vpc" "main" {
  cidr_block = var.vpc_cidr
  tags = { Name = "vpc-${var.environment}" }
}

resource "aws_subnet" "public" {
  count = length(var.public_subnets)
  vpc_id = aws_vpc.main.id
  cidr_block = var.public_subnets[count.index]
  map_public_ip_on_launch = true
}

output "vpc_id" { value = aws_vpc.main.id }

Using the Module

module "vpc" {
  source = "./modules/vpc"
  vpc_cidr    = "10.0.0.0/16"
  environment = "production"
  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
  private_subnets = ["10.0.10.0/24", "10.0.20.0/24"]
}

Benefits

  • โœ… Reusable across environments
  • โœ… Encapsulated complexity
  • โœ… Tested once, used everywhere
  • โœ… Version-controlled

Chapter Summary

  • Understand core concepts and principles
  • Master implementation methods and techniques
  • Familiar with common issues and solutions
  • Able to apply in real projects

Further Reading

  • Official documentation and API references
  • Open source examples on GitHub
  • Technical books and online courses
  • Community discussions and tech blogs

Implementation Example

Basic Example

# This section provides a complete implementation example

Steps

  1. Setup: Configure development environment
  2. Data: Prepare required data
  3. Implementation: Build core functionality
  4. Testing: Verify correctness
  5. Optimization: Improve performance

Common Errors

| Error Type | Cause | Solution | |------------|-------|----------| | Compilation | Syntax | Check code syntax | | Runtime | Environment | Verify dependencies installed | | Logic | Algorithm | Step-by-step debugging | | Performance | Efficiency | Use profilers |

Code Example

import sys

def main():
    print("Hello, World!")

if __name__ == "__main__":
    main()

References

  • Official documentation
  • API reference
  • Open source examples
  • Community discussions

Module Structure

A Terraform module is a directory with one or more .tf files.

Standard Module Layout

modules/
โ”œโ”€โ”€ networking/
โ”‚   โ”œโ”€โ”€ main.tf          # Core resources
โ”‚   โ”œโ”€โ”€ variables.tf     # Input variables
โ”‚   โ”œโ”€โ”€ outputs.tf       # Output values
โ”‚   โ””โ”€โ”€ README.md        # Documentation
โ”œโ”€โ”€ compute/
โ”‚   โ”œโ”€โ”€ main.tf
โ”‚   โ”œโ”€โ”€ variables.tf
โ”‚   โ””โ”€โ”€ outputs.tf
โ””โ”€โ”€ database/
    โ”œโ”€โ”€ main.tf
    โ”œโ”€โ”€ variables.tf
    โ””โ”€โ”€ outputs.tf

Calling a Module

module "vpc" {
  source = "./modules/networking"

  vpc_cidr        = "10.0.0.0/16"
  environment     = var.environment
  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
  private_subnets = ["10.0.10.0/24", "10.0.11.0/24"]
}

module "web_server" {
  source = "./modules/compute"

  instance_type  = "t3.medium"
  subnet_id      = module.vpc.public_subnet_ids[0]
  security_group = module.vpc.web_sg_id
  instance_count = 3
}

Module Example: VPC Module

# modules/networking/main.tf
resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name        = "${var.environment}-vpc"
    Environment = var.environment
  }
}

resource "aws_subnet" "public" {
  count                   = length(var.public_subnets)
  vpc_id                  = aws_vpc.main.id
  cidr_block              = var.public_subnets[count.index]
  availability_zone       = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true

  tags = {
    Name        = "${var.environment}-public-${count.index + 1}"
    Environment = var.environment
  }
}

resource "aws_internet_gateway" "gw" {
  vpc_id = aws_vpc.main.id

  tags = {
    Name        = "${var.environment}-igw"
    Environment = var.environment
  }
}

Module Registry

The Terraform Registry hosts thousands of reusable modules.

# VPC module from registry
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.0.0"

  name = "my-vpc"
  cidr = "10.0.0.0/16"

  azs             = ["us-east-1a", "us-east-1b", "us-east-1c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway = true
  enable_vpn_gateway = true

  tags = {
    Environment = "production"
  }
}

Module Best Practices

| Practice | Why | |----------|-----| | Version all modules | Prevent breaking changes | | Document with README | Other users can understand usage | | Keep modules focused | Single responsibility principle | | Use variables for all configs | Never hardcode in module | | Export useful outputs | Callers need connection info | | Test modules independently | Validate before integration |

Summary

Terraform modules package reusable infrastructure components. They accept variables, return outputs, and can be sourced from local paths or the public registry.

Key takeaways:

  • Module = directory of .tf files with variables and outputs |
  • Call modules with module "name" { source = "..." } |
  • Registry modules: terraform-aws-modules/vpc/aws |
  • Always version registry modules to lock behavior |
  • Input variables make modules configurable |
  • Outputs expose resource attributes to callers |
  • Local modules (./modules/) keep code DRY |
  • Document modules with README for team consumption |

What's Next: Multi-Environment

The next chapter covers managing multiple environments (dev/staging/prod).

Unlock Full Tutorial

This chapter is paid content. Join the project to unlock over 5000 words of deep analysis, including 10+ god-tier Prompts and real Source Code examples!