Infraestrutura como código promete duas coisas: ambientes reprodutíveis e mudanças revisáveis. Entregar isso é bem menos automático do que parece. O que vemos com frequência são repositórios de Terraform com três cópias quase idênticas do mesmo ambiente, arquivos de estado versionados junto do código, e playbooks de Ansible que ninguém roda mais porque "quebram tudo". O problema quase nunca é a ferramenta — é a falta de uma divisão clara de responsabilidade e de umas poucas disciplinas.
A divisão de papéis que evita 80% da confusão
Terraform e Ansible resolvem problemas diferentes, e usar um no lugar do outro é a origem mais comum de bagunça.
Terraform provisiona recursos. Ele é declarativo e guarda estado: sabe o que criou, compara com o que você descreveu e calcula a diferença. É a ferramenta certa para VM, rede, disco, registro de DNS, regra de firewall, banco gerenciado — coisas que têm ciclo de vida de criação e destruição.
Ansible configura sistemas. Ele não guarda estado: conecta na máquina e garante que ela esteja como descrito. É a ferramenta certa para pacote instalado, arquivo de configuração, serviço rodando, usuário criado, ajuste de kernel.
A fronteira prática: o Terraform entrega a máquina de pé com acesso; o Ansible faz dela o que ela precisa ser. Quem usa Terraform para instalar pacote via script de inicialização descobre que não tem como reaplicar sem recriar a VM. Quem usa Ansible para criar VMs descobre que não tem como saber o que existe nem destruir com segurança.
O estado do Terraform é o ativo mais delicado
O arquivo de estado é o que liga o seu código aos recursos reais. Ele merece três cuidados, e falhar em qualquer um deles gera incidente sério.
- Estado remoto, sempre. Estado no laptop significa que só uma pessoa consegue aplicar, e que um disco perdido leva embora o mapeamento. Guarde em armazenamento compartilhado — bucket S3-compatível, por exemplo — com versionamento ativado.
- Travamento. Sem trava, duas pessoas aplicando ao mesmo tempo corrompem o estado. Todo backend sério suporta trava; confirme que a sua está ativa.
- Nunca no Git. O estado contém valores sensíveis em texto claro, inclusive senhas geradas. Estado versionado é vazamento de credencial esperando ser descoberto. Se já está no histórico, considere as credenciais comprometidas e rotacione.
Um quarto cuidado, menos óbvio: estado separado por ambiente. Produção e desenvolvimento no mesmo estado significa que um comando mal digitado em desenvolvimento pode destruir produção. A separação física do estado é a barreira mais eficaz que existe.
Estrutura: comece simples e resista à abstração precoce
A tentação de criar módulos genéricos e parametrizáveis para tudo aparece cedo e custa caro. Módulo com trinta variáveis para atender a cinco casos hipotéticos é mais difícil de entender do que a duplicação que ele evita.
Uma estrutura que funciona bem na maioria dos casos:
- Um diretório por ambiente, com o seu próprio estado e as suas variáveis.
- Módulos apenas para o que se repete de verdade, três vezes ou mais. Antes disso, duplicar é mais honesto.
- Módulos versionados, referenciados por tag e não por branch. Módulo referenciado por branch muda debaixo de você e transforma um
applyde rotina em surpresa. - Nomes previsíveis, derivados de ambiente e função, para que o recurso no painel seja identificável sem consulta.
E um cuidado com ambientes: usar o mesmo código para produção e desenvolvimento é ótimo em teoria e vira problema quando os ambientes divergem por necessidade legítima — produção tem réplica, desenvolvimento não. Trate essas diferenças como parâmetros explícitos, não como condicionais espalhadas pelo código.
Desvio manual: a doença que mata IaC
O código descreve a infraestrutura. Alguém entra no painel às duas da manhã, muda uma regra de firewall para resolver um incidente e não conta a ninguém. Agora o código mente.
O próximo apply vai desfazer aquela correção — provavelmente reabrindo o incidente — ou vai falhar de forma confusa. E, mais grave: a equipe aprende que aplicar Terraform é arriscado, e passa a fazer tudo à mão. A infraestrutura como código morre nesse ponto, e o repositório vira documentação desatualizada.
O que sustenta a disciplina:
- Regra explícita: mudança em produção acontece pelo código. Correção emergencial no painel é aceitável, com a obrigação de refletir no código no mesmo dia.
- Detecção de desvio, rodando periodicamente para mostrar diferenças entre código e realidade. Achar o desvio em uma execução agendada é muito melhor que achá-lo durante um
applyurgente. - Acesso de escrita restrito. Se todo mundo tem permissão de alterar direto, alguém vai alterar. Deixar o caminho do código ser o mais fácil ajuda mais que qualquer política escrita.
Ansible: idempotência é a única regra que importa
O valor do Ansible está em poder rodar o mesmo playbook dez vezes com o mesmo resultado. Perder isso é perder a ferramenta.
O que costuma destruir a idempotência:
- Comando de shell onde existe módulo. O módulo sabe verificar antes de agir; o comando executa sempre. Quando o shell é inevitável, defina uma condição de guarda que evite a reexecução.
- Ordem implícita. Playbook que só funciona se rodado depois de outro é armadilha. Cada playbook deve ser aplicável isoladamente.
- Estado acumulado. Tarefa que adiciona linha a arquivo sem verificar duplicidade produz um arquivo com a linha vinte vezes depois de vinte execuções.
Duas outras práticas fazem diferença. Use inventário dinâmico, gerado a partir da fonte real — o Proxmox ou o provedor de nuvem — em vez de manter lista manual que envelhece. E organize em papéis por função, não por servidor: um papel de "servidor web" aplicável a qualquer host vale mais que um playbook por máquina.
Como as duas ferramentas se conectam
| Responsabilidade | Ferramenta | Observação |
|---|---|---|
| Criar VM, rede, disco, DNS | Terraform | Guarda estado, sabe destruir |
| Acesso inicial à máquina | Terraform via cloud-init | Chave SSH e usuário, nada além |
| Pacotes e configuração do sistema | Ansible | Idempotente, reaplicável |
| Implantar aplicação | Pipeline de CI/CD | Nem Terraform nem Ansible |
| Inventário de hosts | Dinâmico, a partir da realidade | Nunca lista manual |
| Segredos | Cofre externo | Nunca no repositório |
O encadeamento limpo é: Terraform cria a VM e injeta a chave via cloud-init; o inventário dinâmico do Ansible descobre a máquina; o Ansible a configura. Cada etapa é reexecutável sozinha.
Revisão e aplicação controladas
Infraestrutura como código só entrega o benefício de "mudança revisável" se a mudança for de fato revisada. O fluxo mínimo:
- O plano roda automaticamente no pedido de alteração, e o resultado fica visível para quem revisa. Ler o plano é o momento em que se percebe que uma alteração aparentemente simples vai recriar o banco de dados.
- A aplicação em produção é controlada, com aprovação humana. Aplicar automaticamente ao aprovar um merge é confortável e concentra risco.
- Atenção a tudo que aparece como recriação. Recurso que será destruído e criado de novo é a origem quase universal dos acidentes com Terraform. Recriação de VM de produção precisa ser decisão consciente, não descoberta.
- Credenciais do pipeline sem senha de longa duração, usando identidade federada quando o provedor suportar.
O caminho de adoção em ambiente que já existe
Ninguém começa no vazio. Para trazer um parque existente para IaC sem parar a operação:
- Comece pelo que é novo. Todo recurso criado de hoje em diante nasce por código. Isso já interrompe o crescimento do problema.
- Importe por domínio, não tudo de uma vez. Escolha uma área com fronteira clara — DNS é um bom primeiro passo, de baixo risco e alto valor.
- Descreva antes de importar, e confirme que o plano não indica mudança. Plano limpo é a prova de que o código descreve a realidade.
- Deixe o mais crítico para depois, quando a equipe já tiver confiança na ferramenta e no fluxo.
- Aceite conviver com os dois modelos por um período. Migração de tudo de uma vez é o cenário em que se abandona a iniciativa no meio.
Erros comuns
- Usar Terraform para configurar sistema operacional, sem poder reaplicar.
- Arquivo de estado versionado no Git, com credenciais em texto claro.
- Estado único compartilhado entre produção e desenvolvimento.
- Módulos genéricos demais antes de haver repetição real.
- Módulo referenciado por branch em vez de tag.
- Correção manual no painel que nunca volta para o código.
- Comando de shell no Ansible onde existe módulo idempotente.
- Inventário estático mantido à mão.
- Aplicar em produção automaticamente, sem ler o plano.
- Ignorar avisos de recriação de recurso.
Onde a Solvefy/Cloud entra
Em consultoria DevOps, essa é uma das frentes mais pedidas — e boa parte do trabalho é organizar o que já existe, não começar de zero. Definimos a fronteira entre provisionamento e configuração, estruturamos o estado remoto com travamento e separação por ambiente, montamos o fluxo de revisão e aplicação no pipeline e trazemos o parque existente para o código por domínios, começando pelo de menor risco. Também treinamos a equipe, porque IaC que só uma pessoa entende é um ponto único de falha com outro nome.
Quer organizar a sua infraestrutura como código? Fazemos um diagnóstico gratuito, sem compromisso, em solvefy.cloud.
Solvefy/Cloud — Infraestrutura que cresce com você.