Pular para o conteúdo

Recuperar um state quebrado

Avançado14 min de leituraiac

State quebrado tem três formas: lock preso (ninguém consegue aplicar), divergência (o state não corresponde à realidade) e corrupção (o arquivo está inválido ou truncado). Cada uma tem um caminho, e todos começam do mesmo lugar.

Sem exceção, mesmo com pressa.

Janela do terminal
terraform state pull > backup-$(date +%F-%H%M%S).tfstate
wc -c backup-*.tfstate # confirme que não veio vazio

Se o backend for S3 com versionamento ativo (e deveria ser), você já tem uma rede de segurança adicional — o passo 4 usa isso.

Janela do terminal
terraform plan
# Error: Error acquiring the state lock
# ID: 8f2a... Who: ana@notebook Created: 2026-09-04 09:12

Antes de forçar, confirme que nenhum apply está em execução: pergunte à pessoa indicada, e verifique se há job rodando no CI. Destravar durante um apply ativo é o caminho mais rápido para corromper o state de verdade.

Janela do terminal
terraform force-unlock 8f2a... # só depois de confirmar

Quando o state não corresponde à realidade (alguém mexeu no console, um apply morreu no meio):

Janela do terminal
terraform plan -refresh-only # mostra o que mudou fora do código
terraform apply -refresh-only # atualiza o state, sem alterar infraestrutura
terraform plan # agora o plano reflete a diferença real

-refresh-only só atualiza o state; ele nunca cria nem destrói. Leia cada mudança proposta antes de aceitar.

Para corrupção ou remoção acidental, o caminho mais rápido é voltar no tempo:

Janela do terminal
aws s3api list-object-versions --bucket empresa-tfstate-prod \
--prefix loja/prod/terraform.tfstate \
--query 'Versions[:5].[VersionId,LastModified]' --output table
aws s3api get-object --bucket empresa-tfstate-prod \
--key loja/prod/terraform.tfstate --version-id <ID> restaurado.tfstate
terraform state push restaurado.tfstate
terraform plan # confirme que o plano faz sentido antes de qualquer apply

Se o push recusar por causa do serial, é proteção contra sobrescrita: incremente o campo serial no JSON restaurado e tente de novo — com a certeza de que ninguém mais está aplicando.

Útil quando um recurso foi apagado por fora, ou vai passar para outro state.

Janela do terminal
terraform state list | grep aws_db_instance
terraform state rm aws_db_instance.legado # esquece; NÃO destrói nada na nuvem
Janela do terminal
terraform import aws_s3_bucket.relatorios empresa-relatorios-prod
terraform plan # o alvo continua sendo: "No changes"

Para renomear um recurso no código sem recriar:

Janela do terminal
terraform state mv aws_s3_bucket.antigo aws_s3_bucket.novo
# ou, melhor porque é versionado e revisável:
# moved { from = aws_s3_bucket.antigo to = aws_s3_bucket.novo }

Depois de estabilizar, ataque a causa. As recorrentes são poucas:

  • Sem locking → habilite (use_lockfile no S3, ou tabela DynamoDB).
  • Sem versionamento no bucket do state → ative agora; é a diferença entre dez minutos e um dia de trabalho.
  • Apply da máquina de alguém → mova para o pipeline, com credencial só lá.
  • State único e gigante → veja dividir um state.
  • Alteração manual no console → detecção diária de drift, com alerta.
Janela do terminal
# job diário: plano não vazio vira alerta
terraform plan -detailed-exitcode -lock=false || echo "drift detectado"
Sintoma O que fazer
state snapshot was created by Terraform vX Versão do binário mais antiga que a do state; use a mesma versão
Failed to load state: unexpected EOF Arquivo truncado — restaure a versão anterior
Duplicate resource após push O state restaurado tem recurso já reimportado; remova um dos dois
Plano quer criar o que já existe State perdeu o recurso — reimporte
Plano quer destruir tudo Provavelmente você está no diretório ou workspace errado. Pare.

O último merece a pausa: confirme terraform workspace show, o backend configurado e a conta (aws sts get-caller-identity) antes de qualquer coisa.

  • Backup do state feito antes de intervir.
  • Lock liberado só após confirmar que ninguém aplica.
  • terraform plan limpo, sem criações nem destruições inesperadas.
  • Nenhum recurso órfão deixado para trás.
  • Locking e versionamento habilitados no backend.
  • Causa registrada e corrigida (pipeline, drift, divisão de state).