Migrar o backend de state do Terraform para S3

TLDR: Mover todo o state do Terraform do bucket compatível com S3 da DigitalOcean para um S3 nativo na conta AWS shared, atualizando o backend.tf de cada stack (infraestrutura e todos os projetos) e cada terraform_remote_state — a última dependência de DigitalOcean na camada de IaC.

Contexto

Todo stack guarda state no Spaces da DigitalOcean (compatível com S3): endpoints.s3 = https://sfo3.digitaloceanspaces.com, bucket = wehive-terraform-states, com as chaves do Spaces em AWS_ACCESS_KEY_ID/SECRET. Com a DigitalOcean sendo descontinuada, esse bucket precisa ir para S3 nativo na conta shared.

Isso toca o backend de ~8 stacks de infraestrutura, mais todos os projetos (marketing, gateway, onion-backend) e todos os data sources terraform_remote_state entre stacks.

⚠️ É a mudança de maior raio de impacto de toda a descontinuação. Um erro órfã state. Fazer com cuidado, um stack por vez, com backup.

Objetivos

  • Um bucket S3 na conta shared (versionamento + encriptação + mecanismo de lock) contendo todo o state.
  • Todo backend.tf apontando para S3 nativo — sem endpoints customizado, sem flag skip_* — usando a credencial da conta shared.
  • Todo terraform_remote_state atualizado para o bucket e as chaves novos.
  • Nenhum state restando no Spaces; o bucket antigo aposentado.

Fora de escopo

  • Renomear as chaves de state. Os caminhos de chave são mantidos, para minimizar churn.

Mudanças

Novo: o bucket

Um stack próprio (por exemplo src/shared/state) com aws_s3_bucket, versionamento, SSE, bloqueio de acesso público e um mecanismo de lock (lockfile nativo do S3 no Terraform 1.10+, ou uma tabela DynamoDB).

O state deste stack não pode viver no bucket que ele cria. Ele bootstrapa com backend local, igual ao bootstrap original do bucket antigo.

Migrar cada stack, um por vez

  1. terraform state pull → backup local do state atual.
  2. Copiar o objeto de state do bucket antigo para o S3 (aws s3 cp com cada endpoint), ou re-init com -migrate-state depois de editar o backend.tf.
  3. Reescrever o backend.tf: remover endpoints, skip_credentials_validation, skip_metadata_api_check, skip_region_validation e skip_requesting_account_id; definir region, bucket e key reais. Autenticação pela credencial da conta shared, não pelas chaves do Spaces.
  4. terraform init -migrate-state e terraform plan → tem que dar No changes. É isso que prova que o state foi intacto.

Referências entre stacks

Todo data "terraform_remote_state" em infraestrutura e nos projetos recebe a mesma reescrita de backend. Nos vaults do ward, a variável de credencial de backend passa das chaves do Spaces para as da conta shared (ou um usuário dedicado ao S3).

Repos em escopo

Repo O que muda
infrastructure 8 stacks: platform/{network,registry}, shared/{github,network,kubernetes/aws,messagebroker,registry} e as chaves sob stacks/*
marketing, gateway, onion-backend backend.tf + os blocos remote_state de data.tf

Como verificar

  • Cada stack, depois de migrado: terraform plan = No changes.
  • aws s3 ls s3://<bucket>/ (nativo) lista todas as chaves; o bucket antigo fica vazio.
  • Uma leitura entre stacks (o gateway lendo os outputs do kubernetes, por exemplo) continua resolvendo.

Documentação

— (não registrado na spec original)

Notas de execução: o nome wehive-terraform-states pode não ser globalmente único no S3 — checar e ajustar. Fazer os stacks de infraestrutura primeiro, depois cada projeto. O bucket antigo é aposentado só no fim, depois de cluster, registry e droplet já terem saído.