+55 (11) 3280-8787
Atendimento 24h

Terraform na prática – organizando código de infraestrutura

A bagunça que todo mundo já viveu

Sabe aquele momento quando você abre um projeto Terraform depois de 6 meses e pensa “quem foi o animal que escreveu isso”? E aí percebe que foi você mesmo. Já passei por isso mais vezes do que gostaria de admitir.

Organizar código Terraform não é luxo, é necessidade. Especialmente quando a gente trabalha com múltiplos ambientes, equipes grandes ou projetos que crescem além do que imaginávamos inicialmente.

A estrutura básica que funciona

Depois de anos organizando infraestrutura na AWS, Azure e Google Cloud, descobri que existe uma estrutura que funciona na maioria dos casos:


project-name/
├── environments/
│   ├── dev/
│   ├── staging/
│   └── prod/
├── modules/
│   ├── vpc/
│   ├── eks/
│   └── rds/
├── shared/
└── scripts/

Cada pasta tem seu propósito específico. Os environments guardam as configurações de cada ambiente. Os modules são pedaços reutilizáveis de código. O shared fica com recursos compartilhados entre ambientes.

Módulos: seu melhor amigo

Se você ainda não usa módulos Terraform, está perdendo tempo e dinheiro. Eles são como funções no código: escreveu uma vez, usa em qualquer lugar.

Exemplo prático de um módulo VPC simples:


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

  tags = {
    Name = "${var.project_name}-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.project_name}-public-${count.index + 1}"
  }
}

Agora você pode usar esse módulo em qualquer ambiente:


# environments/prod/vpc.tf
module "vpc" {
  source = "../../modules/vpc"
  
  project_name    = "meu-projeto"
  environment     = "prod"
  cidr_block      = "10.0.0.0/16"
  public_subnets  = ["10.0.1.0/24", "10.0.2.0/24"]
}

Variáveis e outputs organizados

Cada módulo precisa de três arquivos básicos: main.tf, variables.tf e outputs.tf. Parece burocracia, mas salva sua vida depois.


# modules/vpc/variables.tf
variable "project_name" {
  description = "Nome do projeto"
  type        = string
}

variable "environment" {
  description = "Ambiente (dev, staging, prod)"
  type        = string
}

variable "cidr_block" {
  description = "CIDR block da VPC"
  type        = string
}

variable "public_subnets" {
  description = "Lista de CIDR blocks para subnets públicas"
  type        = list(string)
}

E os outputs para referenciar em outros módulos:


# modules/vpc/outputs.tf
output "vpc_id" {
  description = "ID da VPC criada"
  value       = aws_vpc.main.id
}

output "public_subnet_ids" {
  description = "IDs das subnets públicas"
  value       = aws_subnet.public[*].id
}

Separação por ambientes

Cada ambiente deve ter sua própria pasta com state separado. Isso evita que mudanças em dev quebrem produção (já vi isso acontecer, não é bonito).


# environments/prod/main.tf
terraform {
  backend "s3" {
    bucket = "meu-projeto-terraform-state"
    key    = "prod/terraform.tfstate"
    region = "us-east-1"
  }
}

module "vpc" {
  source = "../../modules/vpc"
  # configurações específicas de prod
}

module "eks" {
  source = "../../modules/eks"
  
  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.vpc.public_subnet_ids
  # outras configurações
}

Caso real: refatoração que salvou o projeto

Semana passada ajudamos uma startup que tinha tudo em um arquivo main.tf de 800 linhas. Deploy demorava 40 minutos e qualquer mudança era um risco.

Quebramos em 6 módulos: VPC, EKS, RDS, ElastiCache, ALB e monitoring. Resultado: deploys de 8 minutos e zero downtime nos últimos 30 dias.

O segredo foi criar módulos pequenos e específicos. Cada um com responsabilidade única.

Ferramentas que facilitam a vida

Algumas ferramentas que uso todo dia:

  • terraform-docs: gera documentação automática dos módulos
  • tflint: pega erros antes do apply
  • terragrunt: DRY para configurações Terraform
  • pre-commit hooks: valida código antes do commit

Configuração básica do pre-commit:


# .pre-commit-config.yaml
repos:
  - repo: https://github.com/antonbabenko/pre-commit-terraform
    rev: v1.77.0
    hooks:
      - id: terraform_fmt
      - id: terraform_validate
      - id: terraform_docs
      - id: terraform_tflint

Versionamento de módulos

Quando os módulos começam a ser usados por várias equipes, versionar vira obrigatório. Uso tags Git simples:


module "vpc" {
  source = "git::https://github.com/empresa/terraform-modules.git//vpc?ref=v1.2.0"
  
  # configurações
}

Assim cada ambiente pode usar versões diferentes sem quebrar nada.

Naming conventions que salvam

Padronize nomes desde o início. Uso este padrão:

  • Resources: ${projeto}-${ambiente}-${tipo}
  • Variáveis: snake_case sempre
  • Outputs: descritivos e consistentes
  • Tags: Project, Environment, Owner obrigatórias

Organização não é perfumaria. É economia de tempo, dinheiro e stress. Comece simples, mas comece desde o primeiro dia. Seu eu do futuro vai agradecer.

Equipe Bolsoni Tech

Contato

Vamos conversar sobre o seu projeto?

Primeira conversa sem compromisso. Conte pra gente o que precisa e a gente te mostra como pode ajudar.

+55 (11) 3280-8787 · Atendimento 24x7