Objetivos desta aula
- Escrever módulo com interface clara
- Reutilizar entre ambientes
- Detectar drift automaticamente
Módulo é a unidade de reuso: entradas (variables), lógica (resources) e saídas (outputs). Um bom módulo tem interface pequena, valores padrão sensatos e nenhuma suposição escondida sobre o ambiente. Módulo de rede, de aplicação e de banco cobrem a maior parte das necessidades de um projeto do porte do CloudShop.
Drift é a divergência entre o código e a realidade, geralmente causada por alteração manual no console durante uma emergência. O problema não é apenas estético: o próximo apply pode desfazer uma correção urgente ou destruir algo que passou a ser necessário.
A defesa é processo: plan agendado em CI que falha quando há diferença, notificação para o time e regra clara de que alteração manual precisa ser refletida no código no mesmo dia. Quando o recurso já existe fora do Terraform, use import (ou blocos import) para trazê-lo ao controle.
1. O que é um módulo
Qualquer diretório com arquivos .tf. Um bom módulo tem interface pequena (variáveis com tipos e validação), outputs claros e um propósito só, como 'rede do CloudShop'.
2. Versionar módulos
Referencie por tag Git (?ref=v1.2.0) ou registry. Assim prod pode ficar em v1.2 enquanto dev testa v1.3.
3. count e for_each
for_each sobre um map gera recursos com chaves estáveis; count usa índices, e remover um item do meio recria os seguintes. Prefira for_each.
4. Drift
Drift é quando alguém altera a nuvem pelo console. terraform plan -refresh-only revela; a correção é trazer a mudança para o código ou reaplicar. Rode um plan agendado no CI que alerta quando há diferença.
5. Importar e mover
Blocos import trazem recursos existentes para o código; blocos moved renomeiam sem destruir.
6. Checagem final
Você deve criar um módulo de rede reutilizado por dev e prod e detectar uma mudança manual feita no console.
Na prática
Módulo de rede e consumo por ambiente
hcl
# modules/network/variables.tf
variable "env" { type = string }
variable "cidr" { type = string }
variable "azs" { type = list(string), default = ["us-east-1a", "us-east-1b"] }
# modules/network/main.tf
resource "aws_vpc" "this" {
cidr_block = var.cidr
tags = { Name = "cloudshop-${var.env}" }
}
resource "aws_subnet" "private" {
for_each = { for i, az in var.azs : az => i }
vpc_id = aws_vpc.this.id
availability_zone = each.key
cidr_block = cidrsubnet(var.cidr, 8, each.value + 10)
tags = { Name = "cloudshop-${var.env}-priv-${each.key}" }
}
output "vpc_id" { value = aws_vpc.this.id }
output "private_ids" { value = [for s in aws_subnet.private : s.id] }
# envs/staging/main.tf
module "network" {
source = "../../modules/network"
env = "staging"
cidr = "10.30.0.0/16"
}Detecção de drift em CI
yaml
name: drift-check
on:
schedule: [{ cron: "0 7 * * 1-5" }]
workflow_dispatch:
permissions:
contents: read
id-token: write
jobs:
plan:
runs-on: ubuntu-latest
strategy:
matrix:
env: [dev, staging]
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/cloudshop-plan
aws-region: us-east-1
- uses: hashicorp/setup-terraform@v3
- run: terraform -chdir=infra/envs/${{ matrix.env }} init
- name: Plan detecta drift
run: terraform -chdir=infra/envs/${{ matrix.env }} plan -detailed-exitcode -no-color
# exit 2 = ha mudancas pendentes (drift)Nota de segurança: A role de plan deve ter permissão somente de leitura; apply usa role separada com aprovação.
for_each com chaves estáveis
hcl
variable "subnets" {
type = map(object({ cidr = string, az = string }))
}
resource "aws_subnet" "this" {
for_each = var.subnets # chave = nome da subnet
vpc_id = aws_vpc.this.id
cidr_block = each.value.cidr
availability_zone = each.value.az
tags = { Name = each.key }
}Detectar drift e renomear sem destruir
hcl
# terraform plan -refresh-only -detailed-exitcode (exit 2 = ha drift)
moved {
from = aws_s3_bucket.imgs
to = aws_s3_bucket.images
}
import {
to = aws_s3_bucket.logs
id = "cloudshop-dev-logs"
}Por que isso importa
Drift é o boss deste território e uma dor real de todo time que opera nuvem em escala.
Erro comum
Criar módulo gigante com dezenas de variáveis que ninguém entende nem reutiliza.
Dica de produção
Fixe versão do módulo (tag Git) ao consumi-lo: atualização de módulo deve ser decisão explícita.
Pergunta de entrevista
Como você detecta e corrige drift em uma infraestrutura de produção?
Glossário
- drift
- Divergência entre o estado descrito no código e o estado real da infraestrutura.
- import
- Trazer um recurso existente para o controle do Terraform.
- drift
- Diferença entre o código/state e o que existe de fato na nuvem.
- for_each
- Meta-argumento que cria uma instância por item de um map ou set.
- moved block
- Declaração que renomeia um recurso no state sem recriá-lo.
Conexão com o CloudShop
Extrair o módulo de rede do CloudShop e usá-lo em dev e staging.
Quiz da aula
1. O que o exit code 2 de terraform plan -detailed-exitcode indica?
2. Por que preferir for_each a count em listas que mudam?
3. Como detectar drift sem alterar nada?
Minhas anotações
Salvo automaticamente neste navegador.