Pular para o conteúdo

Terraform

Antes de IaC, provisionar era clicar em consoles ou rodar scripts imperativos — processo não reprodutível, sem histórico e sujeito a snowflake servers (cada ambiente ligeiramente diferente). IaC trata a infraestrutura como artefato de software:

  • Versionamento: a infra vive no Git, com histórico, blame e a possibilidade de reverter.
  • Revisão: mudanças passam por Pull Request e code review, exatamente como o código de aplicação.
  • Reprodutibilidade: o mesmo .tf recria ambientes idênticos (dev, staging, prod) — adeus “funciona na minha conta”.

Este é o ponto-chave: os princípios de código limpo — legibilidade, DRY (via módulos), pequenas mudanças revisáveis — aplicam-se diretamente à infraestrutura quando ela é código.

Aspecto Imperativo (bash/SDK) Declarativo (Terraform)
O que você escreve O passo a passo (“crie, depois faça”) O estado final desejado
Idempotência Você garante manualmente Nativa: reaplicar não recria o que já existe
Rodar duas vezes Pode falhar/duplicar Converge para o mesmo estado (no-op)
Detecção de drift Não há plan mostra o diff estado real vs. desejado

Um script imperativo diz “execute aws ec2 run-instances. Terraform diz “deve existir uma instância com estas propriedades” — e ele decide se cria, atualiza ou não faz nada. Essa é a base da idempotência.

Plugin que ensina o Terraform a falar com uma API (AWS, GCP, Azure, Cloudflare, Kubernetes…). Traduz recursos HCL em chamadas de API.

A unidade básica: um objeto de infra (um bucket, uma instância, uma zona DNS). Você declara seu tipo e atributos desejados.

Terraform mantém um arquivo de estado (terraform.tfstate) que mapeia os recursos do HCL para os objetos reais no provedor. É como ele sabe o que já existe e o que mudou.

Por que o state remoto importa:

  • Fonte única da verdade em equipe. State local no laptop de um dev é um desastre: dois apply simultâneos corrompem tudo.
  • State locking. Backends remotos (S3 + DynamoDB, Terraform Cloud) travam o state durante um apply, evitando concorrência.
  • Segurança. O state pode conter segredos (senhas, chaves); remoto permite criptografia e controle de acesso, fora do Git.
  • Colaboração e CI. Um pipeline de CI - GitHub Actions roda plan/apply contra o mesmo state compartilhado.
  • terraform plan: mostra o diff entre o desejado (HCL) e o real (state/API). É o “dry-run” revisável — o equivalente a ler um PR antes de mergear.
  • terraform apply: executa as mudanças para convergir ao estado desejado.

Empacotam um conjunto de recursos reutilizável e parametrizável (ex.: um módulo “vpc-padrão”). São o DRY da infraestrutura e a expressão de código limpo em IaC: abstração, entradas/saídas claras, reuso entre ambientes.

Um bucket S3 versionado, provisionado de forma declarativa:

# Backend remoto: state compartilhado, com locking via DynamoDB
terraform {
required_version = ">= 1.6"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "minha-org-terraform-state"
key = "prod/app/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks" # state locking
encrypt = true
}
}
# Provider: como falar com a AWS
provider "aws" {
region = var.regiao
}
# Variável de entrada — parametriza o módulo/ambiente
variable "regiao" {
type = string
default = "us-east-1"
}
# Resource: o estado DESEJADO de um bucket (declarativo)
resource "aws_s3_bucket" "estaticos" {
bucket = "minha-org-assets-estaticos"
tags = {
Ambiente = "prod"
Gerido = "terraform" # deixa claro que é IaC, não clique manual
}
}
# Versionamento do bucket como recurso separado (idempotente)
resource "aws_s3_bucket_versioning" "estaticos" {
bucket = aws_s3_bucket.estaticos.id
versioning_configuration {
status = "Enabled"
}
}
# Output: expõe um valor para outros módulos ou para o operador
output "bucket_arn" {
value = aws_s3_bucket.estaticos.arn
}

Rodar terraform apply duas vezes: na primeira ele cria os recursos; na segunda, o plan mostra “No changes” — idempotência em ação.

flowchart TB
    W[Escreve/edita .tf<br/>HCL declarativo] --> PR[Pull Request<br/>revisão + Git]
    PR --> INIT["terraform init<br/>baixa providers + backend"]
    INIT --> PLAN["terraform plan<br/>diff desejado x real"]
    PLAN -->|revisado no PR| APPLY["terraform apply<br/>converge ao estado"]
    APPLY --> STATE[(State remoto<br/>S3 + lock)]
    STATE -.consultado por.-> PLAN
    APPLY --> CLOUD[Infra provisionada<br/>AWS / etc.]
    CLOUD -.drift detectado.-> PLAN
    style STATE fill:#155e75,color:#fff
    style PLAN fill:#166534,color:#fff
    style APPLY fill:#854d0e,color:#fff
  • State local em equipe. Sem backend remoto e locking, dois apply concorrentes corrompem o state. Sempre use backend remoto com lock.
  • Commitar terraform.tfstate no Git. Contém segredos e vira fonte de conflito. State vai para backend remoto, não para o repositório.
  • ClickOps sobre recursos gerenciados. Alterar no console algo que o Terraform gerencia gera drift e o próximo apply reverte (ou quebra). A infra gerenciada por IaC muda por IaC.
  • Fazer apply sem ler o plan. O plan é a revisão da mudança; ignorá-lo é mergear sem revisar. Cuidado especial com mudanças que forçam replace (destroem e recriam).
  • Um único arquivo/estado monolítico. Todo o mundo em um .tf gigante torna o plan lento e arriscado. Divida por domínio/ambiente e use módulos.
  • Hardcode de segredos no HCL. Chaves em texto plano no código versionado. Use variáveis, cofres (Secrets Manager, Vault) e evite segredos no state quando possível.
  • Versões de provider não fixadas. Sem ~>/lockfile, um init futuro traz uma versão incompatível e quebra o build.
  1. Por que o state remoto é essencial em um time, e o que o state locking previne?
Resposta

O state é a fonte da verdade que mapeia HCL para recursos reais. Remoto, ele é compartilhado e seguro (criptografado, fora do Git). O state locking (ex.: S3 + DynamoDB) impede dois apply concorrentes de corromperem o state, além de proteger segredos e permitir uso em CI.

  1. Qual a diferença entre declarativo e imperativo, e como isso se conecta à idempotência?
Resposta

Imperativo descreve os passos (“crie X, depois Y”); rodar de novo pode duplicar ou falhar. Declarativo (Terraform) descreve o estado final desejado; o Terraform calcula o diff e converge. Por isso é idempotente: reaplicar sobre um estado já correto resulta em “no changes”.

  1. Como o IaC traz práticas de código limpo para a infraestrutura?
Resposta

Tratando a infra como código versionado no Git: histórico e reversão, revisão em Pull Request, reprodutibilidade entre ambientes e DRY via módulos (abstrações reutilizáveis com entradas/saídas claras). Mudanças pequenas e revisáveis substituem cliques manuais irreproduzíveis.

  1. O que é drift e por que alterar recursos gerenciados direto no console é um anti-padrão?
Resposta

Drift é a divergência entre o estado real da infra e o descrito no HCL/state. Alterar no console (ClickOps) algo gerenciado pelo Terraform cria drift: o próximo plan/apply tenta reverter a mudança manual (ou quebra). A regra é que infra gerenciada por IaC só muda via IaC.