MÓDULO 12 · CONCEITO 02 DE 12

Infrastructure as Code — Terraform, Pulumi e CDK

Por que IaC é pré-requisito para operação confiável. Terraform: HCL, providers, state, workspaces, módulos. Pulumi: IaC com linguagem real. CDK: constructs e escape hatches. State remoto com S3 + DynamoDB.

Tempo de leitura ~22 min Pré-requisito 01 · Modelos de Cloud Próximo 03 · Kubernetes em Produção →

Em 2017, a GitLab sofreu um incidente famoso: um engenheiro de banco de dados, tentando remediar replicação quebrada em produção, deletou acidentalmente o diretório de dados do PostgreSQL primário. O restore falhou por quatro razões: o backup automático não estava funcionando há meses, o WAL archiving estava desabilitado, a réplica de staging era do dia anterior, e o processo de restore nunca havia sido testado. Seis horas de downtime e 300 GB de dados perdidos depois, a GitLab publicou o postmortem — e mudou a forma como toda a indústria pensa sobre operação de banco de dados. O que isso tem a ver com IaC? Nenhum dos cinco sistemas de backup era gerenciado como código. Eles eram scripts manuais e configurações feitas à mão por indivíduos. Quando o indivíduo estava dormindo, os scripts não estavam rodando.

Infrastructure as Code é a prática de definir e provisionar infraestrutura através de código versionado, revisado por pares, e executado de forma idempotente — em vez de através de cliques em console ou scripts shell ad hoc. A palavra "código" implica todas as práticas que o código de aplicação já tem: version control (git), code review (pull request), testes, CI/CD, e rollback. Quando você trata infra como código, incidentes como o da GitLab ficam impossíveis por construção: você não pode ter uma configuração que "alguém fez" e que ninguém mais conhece.

Por que IaC é pré-requisito

Sem IaC, os problemas recorrentes de operação são:

IaC resolve todos esses problemas porque o estado desejado da infraestrutura está em um repositório git, com histórico completo, autoria, e revisão.

Terraform — o padrão de mercado

Terraform (HashiCorp, 2014) é a ferramenta de IaC mais adotada. Usa HCL (HashiCorp Configuration Language), uma DSL declarativa orientada a blocos. Você descreve o estado desejado — não como chegar lá — e o Terraform calcula e executa o delta:

# main.tf — VPC simples com subnet pública
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
  backend "s3" {
    bucket         = "minha-empresa-terraform-state"
    key            = "producao/vpc/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-state-lock"
    encrypt        = true
  }
}

provider "aws" {
  region = var.aws_region
}

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true

  tags = {
    Name        = "vpc-producao"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

resource "aws_subnet" "public" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet("10.0.0.0/16", 8, count.index)
  availability_zone = var.availability_zones[count.index]

  tags = {
    Name = "subnet-publica-${var.availability_zones[count.index]}"
  }
}

variable "aws_region"          { default = "us-east-1" }
variable "environment"         { default = "producao" }
variable "availability_zones"  { default = ["us-east-1a", "us-east-1b", "us-east-1c"] }

O fluxo de trabalho Terraform é sempre: terraform initterraform plan → review humano do plan → terraform apply. O plan mostra exatamente o que vai ser criado, modificado, ou destruído — sem executar nada. Isso permite code review de mudanças de infraestrutura antes que aconteçam.

State file — a peça crítica

Terraform mantém um state file que mapeia recursos declarados no HCL para recursos reais no provider. Sem o state, o Terraform não sabe que o aws_vpc.main no seu código corresponde ao vpc-0a1b2c3d4e5f na AWS. O state é o que permite o plano de mudança incremental — e é o que mais costuma causar problemas.

nunca faça isso

Nunca use state local em produção (o padrão quando não se configura backend). O arquivo terraform.tfstate no filesystem de um desenvolvedor individual é um ponto único de falha. Se esse arquivo for perdido, corrompido, ou ficar fora de sincronia, o Terraform não sabe o que já existe na cloud — podendo deletar ou recriar recursos existentes. Use sempre remote state com locking.

State remoto com S3 + DynamoDB é o padrão para AWS:

# Criar o bucket e a tabela DynamoDB para state (bootstrap — feito uma vez, manualmente)
# O estado do estado não pode ser gerenciado pelo próprio Terraform
aws s3api create-bucket \
  --bucket minha-empresa-terraform-state \
  --region us-east-1

aws s3api put-bucket-versioning \
  --bucket minha-empresa-terraform-state \
  --versioning-configuration Status=Enabled

aws dynamodb create-table \
  --table-name terraform-state-lock \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST

O S3 armazena o state com versionamento (rollback possível), e o DynamoDB fornece locking distribuído (impede dois terraform apply concorrentes no mesmo state — condição de corrida que pode corromper infra).

Workspaces e módulos

Workspaces permitem múltiplos states a partir do mesmo código HCL — tipicamente para ambientes (dev, staging, prod). A alternativa mais robusta para equipes maiores é ter diretórios separados por ambiente com módulos compartilhados:

infra/
├── modules/
│   ├── vpc/           # módulo reutilizável
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── eks-cluster/   # outro módulo
│       └── ...
├── environments/
│   ├── dev/
│   │   └── main.tf    # usa os módulos acima
│   ├── staging/
│   │   └── main.tf
│   └── prod/
│       └── main.tf

Módulos são a unidade de reuso em Terraform. Um módulo bem escrito encapsula um conjunto de recursos com uma interface de variáveis e outputs — como uma função em código de aplicação. O Terraform Registry tem módulos oficiais para VPC, EKS, RDS e praticamente qualquer serviço AWS/GCP/Azure.

OpenTofu — o fork open source

Em 2023, a HashiCorp mudou a licença do Terraform de MPL (Mozilla Public License) para BSL (Business Source License) — que proíbe uso comercial de produtos que competem com a HashiCorp. A comunidade criou o OpenTofu (fork do Terraform 1.5.x) sob a Linux Foundation. OpenTofu mantém compatibilidade total com HCL do Terraform e é a escolha para quem quer Terraform sem dependência da HashiCorp. Para uso interno (não competindo com HashiCorp), Terraform BSL é permitido — mas muitas empresas migraram para OpenTofu por princípio.

Pulumi — IaC com linguagem de programação real

O problema fundamental do HCL é que ele não é uma linguagem de programação. Loops (count, for_each), condicionais (dynamic), e abstração (módulos) existem mas são limitados. Para lógica complexa — "criar 3 security groups com regras derivadas de uma lista de serviços" — HCL fica verboso e difícil de testar.

Pulumi resolve isso usando linguagens reais: TypeScript, Python, Go, C#, Java. A infraestrutura é definida em código de verdade, com tipos, funções, loops, e testes unitários reais:

# Python — Pulumi criando cluster EKS
import pulumi
import pulumi_aws as aws
import pulumi_eks as eks

config = pulumi.Config()
env = config.get("environment", "dev")

vpc = aws.ec2.Vpc(
    f"vpc-{env}",
    cidr_block="10.0.0.0/16",
    enable_dns_hostnames=True,
    tags={"Environment": env, "ManagedBy": "pulumi"}
)

cluster = eks.Cluster(
    f"eks-{env}",
    vpc_id=vpc.id,
    subnet_ids=subnets,
    instance_type="t3.medium",
    desired_capacity=3,
    min_size=1,
    max_size=10,
)

pulumi.export("cluster_name", cluster.eks_cluster.name)
pulumi.export("kubeconfig", cluster.kubeconfig)

O workflow Pulumi é análogo ao Terraform: pulumi preview (= terraform plan) → review → pulumi up (= terraform apply). State é armazenado no Pulumi Cloud (gratuito para uso individual) ou em S3/Azure Blob/GCS para uso self-hosted.

A vantagem real do Pulumi aparece em duas situações:

  1. Lógica complexa: derivar configurações de infraestrutura de uma lista de serviços, calcular CIDRs programaticamente, validar configurações antes de aplicar
  2. Times de desenvolvimento: engenheiros que já sabem Python ou TypeScript não precisam aprender HCL — podem usar as ferramentas de teste (pytest, jest) que já conhecem

AWS CDK — constructs com escape hatches

O AWS Cloud Development Kit (CDK) permite definir infraestrutura AWS em TypeScript, Python, Java, ou C# — mas diferente do Pulumi, o CDK compila para CloudFormation. Isso significa que toda infra CDK é infraestrutura CloudFormation por baixo.

O modelo de abstração do CDK é baseado em constructs com três níveis:

O escape hatch permite sair de um nível para outro quando o L2/L3 não oferece o que você precisa:

import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';

const bucket = new s3.Bucket(this, 'MeuBucket', {
  encryption: s3.BucketEncryption.S3_MANAGED,
  versioned: true,
  removalPolicy: cdk.RemovalPolicy.RETAIN,
});

// Escape hatch: acessar o recurso CloudFormation subjacente
// para configurar algo que o L2 não expõe
const cfnBucket = bucket.node.defaultChild as s3.CfnBucket;
cfnBucket.addOverride('Properties.ObjectOwnership', 'BucketOwnerEnforced');

CDK é a escolha natural para equipes profundamente investidas em AWS que querem reusar componentes como bibliotecas npm/PyPI. O custo é o lock-in total em AWS e dependência de CloudFormation (com seus próprios limites de escala e depuração). Para multi-cloud ou portabilidade, Terraform ou Pulumi são mais adequados.

Comparação de ferramentas

Critério Terraform / OpenTofu Pulumi AWS CDK
Linguagem HCL (DSL) TypeScript/Python/Go/C# TypeScript/Python/Java/C#
Multi-cloud Sim (1500+ providers) Sim (usa providers Terraform) Não (só AWS)
Testabilidade Limitada (Terratest em Go) Nativa (qualquer test framework) Nativa (cdk assert)
Ecossistema Maior (Terraform Registry) Usa providers Terraform AWS Constructs Library
Curva de aprendizado HCL simples no início, limitante depois Baixa para quem já programa Baixa para devs AWS
State S3/GCS/Azure Blob/Terraform Cloud Pulumi Cloud / S3 self-hosted CloudFormation (gerenciado)

IaC no CI/CD — plan no PR, apply no merge

IaC sem automação de CI/CD é metade do valor. O padrão completo:

# .github/workflows/terraform.yml
on:
  pull_request:
    paths: ['infra/**']
  push:
    branches: [main]
    paths: ['infra/**']

jobs:
  plan:
    if: github.event_name == 'pull_request'
    runs-on: ubuntu-latest
    permissions:
      id-token: write   # Para OIDC — sem AWS keys no repositório
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/github-actions-plan
          aws-region: us-east-1
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
        working-directory: infra/environments/prod
      - id: plan
        run: terraform plan -no-color -out=tfplan
        working-directory: infra/environments/prod
      - uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              body: '## Terraform Plan\n```\n' + process.env.PLAN + '\n```'
            })

  apply:
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: producao   # Requer aprovação manual configurada no GitHub
    permissions:
      id-token: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/github-actions-apply
          aws-region: us-east-1
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init && terraform apply -auto-approve
        working-directory: infra/environments/prod

O padrão crítico aqui é OIDC para autenticação AWS: o workflow GitHub Actions não tem AWS access keys armazenadas como secrets. Em vez disso, o GitHub emite um token OIDC que a AWS troca por credenciais temporárias via AssumeRoleWithWebIdentity. As credenciais expiram após a execução — eliminando o risco de keys permanentes vazadas no repositório (ver Módulo 11 · Secrets Management).

princípio de IaC

Toda mudança de infraestrutura que vai para produção deve passar por: código em PR → review humano do plan → merge → apply automático. Nunca aplique Terraform direto do laptop em produção — isso remove o histórico, o review, e o rastreamento de quem mudou o quê. "Mas é só uma mudança pequena" é o começo de todos os incidentes de infra.

Decisões de engenharia

Terraform/OpenTofu vs Pulumi vs CDK

Terraform/OpenTofu quando: a equipe não tem forte background de programação, você precisa de multi-cloud com um único tooling, ou o ecossistema de providers do Terraform Registry resolve todos os seus casos de uso — é a ferramenta com maior cobertura de providers e maior base de conhecimento disponível. Pulumi quando: a infraestrutura tem lógica complexa que HCL expressa mal (derivação dinâmica de configuração, validação programática), ou quando o time é de developers que querem testar infra com as mesmas ferramentas que usam para aplicação. CDK quando: a equipe é all-in AWS, quer reusar constructs como bibliotecas publicadas no npm/PyPI, e aceita lock-in em CloudFormation como trade-off pela abstração de L2/L3.

Workspaces vs diretórios separados por ambiente

Workspaces Terraform são simples de configurar mas têm um problema: um único terraform apply no workspace errado pode destruir produção quando você queria mudar staging. Para equipes menores com 1–2 ambientes, workspaces são suficientes. Para equipes maiores, diretórios separados por ambiente com módulos compartilhados é mais seguro: cada ambiente é um diretório independente com seu próprio state, e você precisa navegar explicitamente para o diretório de prod antes de poder aplicar qualquer coisa nele. O padrão com diretórios também torna a configuração por ambiente explícita no código — diferenças entre dev e prod são visíveis no git diff, não escondidas em variáveis de workspace.

Onde armazenar state: S3+DynamoDB vs Terraform Cloud vs GitLab

S3 + DynamoDB é o padrão para AWS — custo mínimo ($<1/mês), sem dependência de serviço externo, versionamento nativo do S3 como rollback. Terraform Cloud (gratuito até 5 usuários) adiciona UI para histórico de runs, estado de locks visível, e integração com Sentinel para policy-as-code — adequado quando o time quer visibilidade centralizada de todas as operações Terraform. GitLab Managed State é a escolha natural para equipes que usam GitLab como plataforma principal — zero configuração adicional, state vinculado ao repositório. Evite state no Terraform Cloud para equipes que não querem dependência de serviço SaaS externo na infra crítica; prefira self-hosted (S3/GCS/Azure Blob) nesses casos.

Estratégia de adoção de IaC em infra existente sem IaC

Duas abordagens: (1) terraform import — importar recursos existentes para o state do Terraform sem recriá-los. Preserva a infra mas requer escrever HCL que corresponde exatamente ao estado atual (senão o plan vai querer modificar o recurso). Adequado quando você quer gerenciar recursos existentes sem downtime de recriação. (2) Greenfield paralelo — criar nova infra com Terraform do zero e migrar workloads gradualmente, descomissionando a infra antiga. Mais limpo mas requer janela de migração. Para a maioria dos casos, comece importando os recursos mais críticos (VPC, banco, EKS) e deixe recursos menos críticos para serem recriados posteriormente. Nunca tente importar toda a infra de uma vez — é muito trabalho de validação simultâneo.

Perguntas de entrevista

O que é state drift no Terraform e como lidar com recursos criados fora do IaC?

State drift ocorre quando o estado real da infraestrutura diverge do que está registrado no state file do Terraform. Isso acontece quando alguém cria, modifica, ou deleta recursos diretamente no console AWS (ou via CLI/SDK) sem passar pelo Terraform. Na próxima execução de terraform plan, o Terraform detecta a diferença entre o state e o estado real — e pode querer reverter as mudanças manuais, dependendo do que foi alterado.

terraform refresh (ou terraform apply -refresh-only no Terraform 1.1+) sincroniza o state com o estado real sem aplicar mudanças — útil para detectar drift sem corrigi-lo automaticamente. Para recursos criados fora do Terraform que você quer passar a gerenciar, terraform import <resource_type.name> <resource_id> adiciona o recurso ao state sem recriá-lo. A melhor estratégia é preventiva: disciplina de nunca mudar infra fora do Terraform em ambientes gerenciados, e alertas de CloudTrail para mudanças manuais que disparam revisão do state.

Por que nunca usar state local em produção e o que pode acontecer de errado?

State local (o arquivo terraform.tfstate no filesystem do desenvolvedor) tem três problemas críticos em produção: (1) Sem locking — se dois engenheiros executam terraform apply simultaneamente com estados diferentes no laptop de cada um, as mudanças de um podem sobrescrever ou conflitar com as do outro, resultando em infra em estado inconsistente; (2) Single point of failure — se o laptop é perdido, corrompido, ou o arquivo é deletado acidentalmente, o Terraform não sabe mais o que existe na cloud. Na próxima execução com state vazio, ele vai querer criar tudo do zero — o que pode causar conflitos com recursos existentes ou tentativas de deletar e recriar recursos de produção; (3) Sem histórico compartilhado — o state reflete apenas as operações que aquele desenvolvedor específico fez. State remoto com S3 + versionamento resolve os três: locking via DynamoDB, histórico versionado com rollback, e acesso compartilhado por toda a equipe.

Por que o terraform plan no PR é tão crítico e o que ele garante?

O terraform plan gera um diff explícito — recursos que serão criados (+), modificados (~), ou destruídos (-) — sem executar nada. Colocado como comentário automático no PR, ele transforma review de infra de "leia o HCL e imagine o que vai acontecer" para "veja exatamente o que vai mudar". Isso é especialmente crítico porque algumas mudanças em HCL que parecem inocentes causam destroy + recreate de recursos: mudar o nome de um recurso Terraform, mudar a availability zone de uma subnet, ou mudar o tipo de uma instância RDS frequentemente exigem destruição e recriação do recurso — com downtime. Sem o plan no PR, essas destruições acontecem na produção sem aviso. Com o plan, o reviewer vê explicitamente -/+ aws_db_instance.main must be replaced e pode questionar ou bloquear antes do merge. É a diferença entre "eu achei que era uma mudança simples" e "eu vi que ia destruir o banco de produção e parei".

Como OIDC elimina AWS access keys permanentes em CI/CD e por que isso é importante para segurança?

O modelo tradicional de autenticação AWS em CI/CD era criar um usuário IAM com access key permanente, armazená-la como secret no GitHub/GitLab, e usar nas actions. O problema: keys permanentes que vazam (em logs, em PRs, em repositórios acidentalmente públicos) dão acesso permanente à conta AWS até serem revogadas manualmente. E a revogação muitas vezes acontece depois do dano já estar feito.

Com OIDC, o fluxo é diferente: o GitHub (ou GitLab, CircleCI) é configurado como Identity Provider na conta AWS. Durante o workflow, o GitHub emite um token OIDC assinado que declara "este é o workflow X do repositório Y no branch Z". O workflow chama a AWS com esse token; a AWS verifica a assinatura com o GitHub, valida as claims (repositório, branch, workflow), e se a IAM role tem trust policy que aceita aquele claim específico, emite credenciais temporárias de curta duração (1h). Não há secret armazenado em nenhum lugar — o trust é baseado na identidade do workflow, não em uma senha. Se o token OIDC vazar, expira em minutos. A granularidade é alta: você pode configurar que apenas o workflow de deploy do repositório de infra no branch main pode assumir a role de apply, enquanto PRs só podem assumir a role de plan (somente leitura).

Quando Pulumi supera Terraform HCL e quando HCL é suficiente?

HCL é suficiente para a maioria dos casos de IaC: criar VPCs, clusters EKS, buckets S3, databases RDS, configurar security groups e IAM roles. O HCL tem loops (for_each), condicionais (count e dynamic), e módulos — para infra relativamente estática, é expressivo o suficiente e tem o maior ecossistema de providers disponível.

Pulumi supera HCL quando: (1) a configuração de infra precisa de lógica derivada de dados externos — por exemplo, ler uma lista de microsserviços de um arquivo JSON e criar um security group, target group, e record DNS para cada um; em HCL isso vira construções complexas de for_each aninhado; em Python é um loop; (2) você quer testar a lógica de infra com pytest — HCL não é testável unitariamente, Terratest em Go tem curva alta; (3) a equipe já programa em TypeScript/Python/Go e quer reusar abstrações entre código de aplicação e código de infra. O custo do Pulumi é menor adoção de mercado (menos exemplos, menos Stack Overflow, menos engenheiros que já conhecem) e dependência de linguagem — um bug de Python pode ter efeitos incomuns quando o "output" é infraestrutura de produção.

Como praticar

  1. Criar VPC com subnets públicas e privadas + Internet Gateway via Terraform. Configure um backend S3 para state remoto (pode usar LocalStack para não gerar custos). Escreva os recursos de VPC, subnets em múltiplas AZs, Internet Gateway, e route tables. Execute terraform plan e analise o output antes de aplicar.
    Critério: O terraform plan deve mostrar exatamente os recursos que serão criados antes do apply. Após o apply, terraform state list deve listar todos os recursos. Um segundo terraform apply sem mudanças deve retornar "No changes" — confirmando idempotência.
  2. Refatorar código Terraform inline para módulo reutilizável. Pegue um conjunto de recursos relacionados (ex: subnet + route table + association) e extraia para um módulo com variáveis bem definidas e outputs. Instancie o módulo duas vezes com parâmetros diferentes (pública e privada) e verifique que o plan mostra as diferenças corretas.
    Critério: O módulo deve ter variables.tf com tipos e descrições, outputs.tf com os IDs dos recursos criados, e main.tf sem hardcode de valores. O código que usa o módulo deve ser significativamente menor que o original inline. O terraform plan deve mostrar zero mudanças após a refatoração (apenas reorganização, não recriação de recursos).
  3. Configurar CI/CD de Terraform com plan em PR e apply no merge. Em um repositório GitHub, configure OIDC com uma conta AWS (ou LocalStack) e implemente o workflow com dois jobs: plan comentado no PR e apply automático no merge para main. Abra um PR com uma mudança de tag em um recurso existente e verifique que o plan aparece como comentário.
    Critério: O workflow de plan deve rodar em PRs e postar o output como comentário no GitHub. O workflow de apply deve rodar apenas em merges para main, usar credenciais OIDC (sem AWS_ACCESS_KEY_ID nos secrets), e completar com sucesso. Verificar no CloudTrail (ou log do LocalStack) que as credenciais usadas são temporárias (AssumedRole, não IAMUser).
  4. Usar terraform import para trazer recurso existente para o state. Crie manualmente um S3 bucket via AWS CLI (simulando infra não gerenciada). Escreva o recurso correspondente em HCL e execute terraform import aws_s3_bucket.meu_bucket <nome-do-bucket>. Verifique que o plan seguinte não quer recriar o recurso — apenas as configurações que diferem do HCL escrito.
    Critério: Após o import, terraform state show aws_s3_bucket.meu_bucket deve exibir o estado atual do recurso. O terraform plan deve mostrar apenas as diferenças entre o HCL escrito e a configuração real — sem propor destroy + create do bucket inteiro.
  5. Escrever um teste de infra com Terratest ou com terraform test. Para o módulo de VPC do exercício 2, escreva um teste que: cria a infra em uma conta de teste, verifica que as subnets existem e têm os CIDRs corretos, e destrói tudo ao final. Use Terratest (Go) ou o comando nativo terraform test (disponível a partir do Terraform 1.6).
    Critério: O teste deve passar em CI sem intervenção manual. Deve verificar pelo menos um atributo do recurso criado via chamada à API AWS (não apenas verificar que o plan não tem erros). Deve fazer cleanup (defer terraform.Destroy no Terratest) mesmo se o teste falhar — garantindo que recursos de teste não ficam rodando.

Referências para aprofundar

  1. book Terraform: Up & Running (3rd ed.) — Yevgeniy Brikman (O'Reilly, 2022). A referência mais completa de Terraform — módulos, state remoto, workspaces, testes com Terratest, e padrões para equipes grandes. O autor é cofundador da Gruntwork, empresa especializada em infra Terraform. Inclui capítulo dedicado a como estruturar repositórios de IaC para escala.
  2. book Infrastructure as Code (2nd ed.) — Kief Morris (O'Reilly, 2021). O livro de referência conceitual sobre IaC — não específico de Terraform, cobre os princípios que tornam IaC eficaz: idempotência, imutabilidade, design de módulos, e testes. Essencial para entender o "porquê" antes de mergulhar nas ferramentas específicas.
  3. docs Pulumi Documentation — Getting Started. pulumi.com/docs. Guia oficial do Pulumi incluindo comparação com Terraform, tutoriais por linguagem (Python, TypeScript, Go, C#), e exemplos de state self-hosted com S3. A seção de testing documenta como escrever testes unitários e de integração para código Pulumi.
  4. docs AWS CDK Developer Guide. docs.aws.amazon.com/cdk. Documentação oficial do CDK — inclui guia completo de constructs L1/L2/L3, escape hatches, como publicar constructs como bibliotecas npm/PyPI, e o CDK Pipelines para deploy contínuo de infra. A seção de testing documenta o uso de assertions para validar constructs.
  5. article GitLab.com Database Incident — Postmortem (about.gitlab.com, 2017). O postmortem público do incidente de banco da GitLab — 300GB perdidos, 6h de downtime, 5 sistemas de backup que falharam simultaneamente. Leitura obrigatória como motivação para IaC, testes de restore, e automação de operações. A GitLab documentou o incidente em tempo real no Google Doc que ainda está público.
  6. docs OpenTofu — opentofu.org. Fork open source do Terraform mantido pela Linux Foundation após a mudança de licença da HashiCorp em 2023. Compatível com HCL do Terraform, com documentação de migração de Terraform para OpenTofu. O OpenTofu Registry é o equivalente do Terraform Registry para o fork.
  7. docs Terratest — Testing Infrastructure Code — Gruntwork. github.com/gruntwork-io/terratest. Biblioteca Go da Gruntwork para testes de infraestrutura Terraform, Packer, Docker, e Kubernetes. Inclui exemplos de testes que criam infra real, fazem assertions via API AWS, e destroem ao final. É a abordagem de teste de infra mais adotada no ecossistema Terraform.
  8. article Configuring OpenID Connect in Amazon Web Services — GitHub Docs. docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services. Guia oficial de configuração de OIDC entre GitHub Actions e AWS — criação do Identity Provider, trust policy da IAM role, e exemplo de workflow sem access keys permanentes. Inclui exemplos para AWS, GCP, e Azure.
  9. article Terraform Best Practices — HashiCorp Learn. developer.hashicorp.com/terraform/tutorials/recommended-practices. Guia oficial de melhores práticas — estrutura de repositório, naming conventions, uso de módulos, remote state, e workflows de CI/CD. Inclui o guia de migração progressiva de operações manuais para IaC.
  10. article Terraform Modules Patterns — Gruntwork Blog. blog.gruntwork.io. Série de artigos sobre padrões de módulos Terraform em escala — como estruturar módulos reutilizáveis, como versionar módulos, como compor módulos para diferentes ambientes, e os problemas mais comuns de escala com Terraform. A Gruntwork opera infra Terraform para centenas de empresas.
  11. article Infrastructure as Code, Part 1: Create a Reusable Architecture — ThoughtWorks Insights. thoughtworks.com/insights. Série de artigos da ThoughtWorks sobre IaC — princípios de design, como testar infra, e como estruturar pipelines de deploy de infraestrutura. O ThoughtWorks Technology Radar avalia ferramentas de IaC regularmente com análise de adoção e maturidade.
  12. book The DevOps Handbook (2nd ed.) — Kim, Humble, Debois, Willis (IT Revolution, 2021). Capítulos sobre "Infrastructure Enablement" contextualizam IaC como parte do pipeline de deployment completo — como IaC se integra com CI/CD, testes automatizados, e deployment strategies. O livro usa o caso da GitLab e outros incidentes para motivar as práticas.