Gerenciamento de estado
Esta aula aborda o gerenciamento de estado no Terraform, explicando por que o state é crucial, como configurar um backend remoto para armazenamento seguro e compartilhado, a importância do locking para evitar conflitos e os cuidados necessários para manter a integridade do estado.
O gerenciamento de estado é um dos conceitos mais importantes no uso do Terraform. O estado é um arquivo que registra o mapeamento entre os recursos definidos no código e os recursos reais criados na infraestrutura. Sem ele, o Terraform não saberia o que já foi criado, o que precisa ser alterado ou destruído. Nesta aula, vamos explorar por que o state é fundamental, como movê-lo para um backend remoto, como o locking protege contra operações concorrentes e quais cuidados devemos tomar para evitar problemas.
O state do Terraform contém dados sensíveis, como IPs, IDs de recursos e até mesmo segredos. Portanto, seu armazenamento e gerenciamento devem ser tratados com atenção. Vamos ver na prática como configurar um backend remoto (como S3) e habilitar o locking com DynamoDB, além de discutir boas práticas para evitar corrupção ou perda de dados.
Por que o state importa
O arquivo de estado (terraform.tfstate) é o coração do Terraform. Ele mantém um inventário de todos os recursos gerenciados, permitindo que o Terraform planeje e aplique alterações de forma incremental. Sem o state, o Terraform não teria como saber se um recurso já existe, qual é a sua configuração atual e como ele se relaciona com outros recursos.
Além disso, o state é essencial para operações como terraform destroy, que precisa saber exatamente quais recursos devem ser destruídos. Ele também armazena metadados, como dependências entre recursos, o que permite ao Terraform ordenar corretamente as operações. Outro ponto crucial é que o state pode conter informações sensíveis (senhas, chaves), portanto, deve ser protegido e acessível apenas a quem precisa.
Vamos ver um exemplo simples: ao criar uma instância EC2, o Terraform registra seu ID no state. Quando você altera o código (por exemplo, muda o tipo de instância), o Terraform consulta o state para saber que a instância já existe e planeja uma atualização, em vez de tentar criar uma nova.
# Exemplo de conteúdo de um arquivo de estado (simplificado)
{
"version": 4,
"terraform_version": "1.5.0",
"resources": [
{
"module": "",
"mode": "managed",
"type": "aws_instance",
"name": "web",
"instances": [
{
"attributes": {
"id": "i-1234567890abcdef0",
"instance_type": "t2.micro",
"ami": "ami-0c55b159cbfafe1f0"
}
}
]
}
]
}O state também permite o uso de data sources e expressões que dependem de recursos existentes. Sem ele, o Terraform seria apenas um orquestrador de criação de recursos, sem capacidade de gerenciar o ciclo de vida completo.
Backend remoto
Por padrão, o Terraform armazena o estado em um arquivo local. Em projetos pessoais, isso pode ser suficiente, mas em equipes ou ambientes corporativos, o estado local é problemático: não é compartilhado, não é versionado e não é seguro. A solução é usar um backend remoto, que armazena o estado em um serviço externo, como AWS S3, Azure Storage, Google Cloud Storage ou Terraform Cloud.
O backend remoto oferece várias vantagens: permite que todos os membros da equipe acessem o mesmo estado, evita conflitos de versão, fornece um histórico de alterações e possibilita o locking (que veremos a seguir). Além disso, o estado fica centralizado e pode ser protegido com políticas de acesso.
Vamos configurar um backend S3 na AWS. Primeiro, precisamos de um bucket S3 e, opcionalmente, uma tabela DynamoDB para locking. O bloco terraform no código define o backend:
terraform {
backend "s3" {
bucket = "meu-bucket-estado"
key = "prod/infra/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}Após adicionar esse bloco, você precisa executar terraform init para inicializar o backend. O Terraform detectará a configuração e fará a migração do estado local para o remoto, se existir. A partir daí, todos os comandos (plan, apply, destroy) usarão o estado remoto.
É importante que o bucket S3 tenha versionamento habilitado para permitir recuperação de versões antigas do estado, e que a tabela DynamoDB seja criada com uma chave primária chamada LockID (tipo string). O Terraform usa essa tabela para adquirir locks, como veremos na próxima seção.
Locking
O locking é um mecanismo que impede que duas pessoas (ou processos) executem terraform apply simultaneamente sobre o mesmo estado. Sem locking, haveria corrida de dados: um usuário poderia sobrescrever as alterações do outro, resultando em estado corrompido ou inconsistente.
O Terraform implementa locking por meio de um recurso de backend. No caso do S3, ele usa uma tabela DynamoDB para registrar a operação em andamento. Quando um terraform apply é iniciado, o Terraform tenta criar um item na tabela com um ID único. Se o item já existir, significa que outra operação está em andamento, e o Terraform bloqueia a execução até que o lock seja liberado.
Vamos ver como isso funciona na prática. Suponha que dois desenvolvedores executem terraform apply ao mesmo tempo. O primeiro adquire o lock e começa a modificar a infraestrutura. O segundo tentará adquirir o lock, mas falhará, recebendo uma mensagem de erro:
Error: Error acquiring the state lock
Error message: ConditionalCheckFailedException: The conditional request failed
Lock Info:
ID: abc123...
Path: meu-bucket-estado/prod/infra/terraform.tfstate
Operation: OperationTypeApply
Who: dev@example.com
Created: 2023-10-01 12:00:00
Terraform acquires a state lock to protect the state from being written
by multiple users at the same time. Please resolve the issue above and try
again. For most commands, a lock can be disabled with the -lock=false flag,
but this is not recommended.Para evitar esse problema, o segundo desenvolvedor deve aguardar o término do primeiro. O lock é liberado automaticamente ao final da operação (apply, plan, destroy). Em caso de falha, o lock pode ficar preso; nesse caso, é possível forçar a liberação com terraform force-unlock <LOCK_ID>, mas isso deve ser feito com cautela.
O locking é essencial em ambientes colaborativos, e o backend remoto com locking é considerado uma boa prática em qualquer projeto que envolva mais de uma pessoa.
Cuidados
Embora o gerenciamento de estado seja poderoso, ele requer cuidados para evitar problemas graves. Aqui estão alguns pontos críticos:
- Nunca edite o arquivo de estado manualmente: O estado é um arquivo JSON que deve ser modificado apenas pelo Terraform. Alterações manuais podem causar divergências e erros imprevisíveis.
- Proteja o estado: Como o estado pode conter dados sensíveis, use criptografia em repouso (por exemplo, S3 com SSE) e restrinja o acesso por meio de políticas IAM.
- Habilite o versionamento do backend: Isso permite recuperar versões anteriores do estado em caso de corrupção ou exclusão acidental.
- Use workspaces ou separação por ambiente: Crie estados separados para produção, desenvolvimento e staging, evitando misturar recursos e reduzindo o risco de alterações indesejadas.
- Evite o
-lock=false: Desabilitar o lock pode levar a conflitos e corrupção. Use apenas em situações de emergência, como quando um lock está preso. - Faça backup regular do estado: Mesmo com versionamento, é prudente ter cópias externas em locais seguros.
Além disso, ao usar backends remotos, é importante garantir que a configuração do backend seja idêntica para todos os membros da equipe. Variações podem causar a criação de estados separados, o que é um erro comum.
Outra boa prática é usar o comando terraform state list e terraform state show para inspecionar o estado, e terraform state pull e terraform state push para manipular o estado quando necessário, mas sempre com cuidado.
Boas práticas e observações finais
Para encerrar, resumimos algumas recomendações:
- Configure um backend remoto desde o início do projeto, mesmo em projetos pessoais, para se acostumar.
- Use uma solução de locking sempre que o backend suportar (S3 + DynamoDB, Terraform Cloud, etc.).
- Documente a configuração do backend e os procedimentos de recuperação em caso de desastres.
- Considere usar o Terraform Cloud ou o Enterprise, que oferecem gerenciamento de estado gerenciado e histórico de execuções.
- Revise periodicamente o estado para garantir que não há recursos órfãos ou divergências.
Lembre-se de que o estado é um ativo crítico: perda ou corrupção pode significar perda de controle sobre a infraestrutura. Portanto, trate-o com a mesma seriedade que trataria um banco de dados de produção.
Exercícios
- Explique por que o arquivo de estado é necessário para o funcionamento do Terraform e o que aconteceria se ele fosse excluído.
- Descreva as vantagens de usar um backend remoto em comparação com o estado local.
- Como o locking evita problemas em ambientes colaborativos? Dê um exemplo de uma situação sem locking.
- Cite três cuidados que você deve ter ao gerenciar o estado do Terraform.
- Escreva um bloco de configuração de backend para S3 com locking via DynamoDB, explicando cada parâmetro.
terraform {
backend "s3" {
bucket = "meu-bucket-estado"
key = "prod/infra/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-locks"
}
}O parâmetro `bucket` define o nome do bucket S3 onde o estado será armazenado. `key` é o caminho dentro do bucket. `region` especifica a região AWS. `dynamodb_table` é o nome da tabela DynamoDB usada para locking; ela deve ter uma chave primária chamada `LockID`.