kb.erickguedes.com
Terraform: Infraestrutura como Código

Modules — Reutilização

Aula 3 de 7

Estrutura de Módulos

Módulos são a unidade de reutilização do Terraform. Um módulo pode ser local, do registry, ou de git.

modules/
├── vpc/
│   ├── main.tf
│   ├── variables.tf
│   └── outputs.tf
├── ec2/
│   ├── main.tf
│   ├── variables.tf
│   └── outputs.tf
└── rds/
    ├── main.tf
    ├── variables.tf
    └── outputs.tf

Módulo VPC

# modules/vpc/main.tf
variable "vpc_cidr" {
  type = string
}

variable "environment" {
  type = string
}

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_support   = true
  enable_dns_hostnames = true

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

resource "aws_subnet" "public" {
  count             = length(var.public_subnet_cidrs)
  vpc_id            = aws_vpc.main.id
  cidr_block        = var.public_subnet_cidrs[count.index]
  availability_zone = var.azs[count.index]

  map_public_ip_on_launch = true

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

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

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

Consumindo Módulos

# infra/main.tf
module "vpc" {
  source = "../modules/vpc"

  vpc_cidr           = "10.0.0.0/16"
  environment        = "prod"
  public_subnet_cidrs = ["10.0.1.0/24", "10.0.2.0/24"]
  azs                = ["us-east-1a", "us-east-1b"]
}

module "web_app" {
  source = "../modules/ec2"

  environment     = module.vpc.environment
  subnet_id       = module.vpc.public_subnet_ids[0]
  vpc_id          = module.vpc.vpc_id
  instance_type   = "t3.micro"
  ami_id          = data.aws_ami.ubuntu.id
}

Registry e Fontes de Módulos

# Terraform Registry (oficial)
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"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
  public_subnets  = ["10.0.3.0/24", "10.0.4.0/24"]

  enable_nat_gateway = true
  enable_vpn_gateway = false
}

# Git (privado)
module "seguranca" {
  source = "git::https://github.com/minha-org/terraform-modules//security-baseline?ref=v1.2.0"
}

# Path local
module "local" {
  source = "./modules/database"
}

Input/Output Contracts

# modules/ec2/variables.tf
variable "instance_type" {
  type        = string
  description = "Tipo da instância EC2"
  nullable    = false

  validation {
    condition     = can(regex("^[tcmr][0-9]g?\\.", var.instance_type))
    error_message = "Use tipo de instância válido (ex: t3.micro)."
  }
}

variable "user_data_path" {
  type        = string
  default     = null
  description = "Caminho para script user_data"
}

# modules/ec2/outputs.tf
output "instance_id" {
  value       = aws_instance.this.id
  description = "ID da instância EC2"
}

output "private_ip" {
  value       = aws_instance.this.private_ip
  description = "IP privado da instância"
  sensitive   = false
}

Versionamento de Módulos

# modules/ec2-versions/
# ├── v1.0.0/
# ├── v1.1.0/
# └── v2.0.0/

# CHANGELOG.md
## [2.0.0] - Breaking
- Removida variável 'old_param'
- Novo output 'instance_arn'
- Mínimo Terraform 1.3
# Versionamento semântico (semver) para módulos
git tag v1.0.0
git tag v1.1.0  # retrocompatível
git tag v2.0.0  # breaking change

Módulos são o equivalente a funções em programação — encapsulam lógica e expõem interface. Prefira módulos do registry validados pela comunidade. Sempre fixe a versão do módulo.