Ansible
Terraform provisiona o que não existe; Ansible configura o que já existe. A diferença explica onde cada um ganha: criar a VM, a rede e o balanceador é trabalho do primeiro; instalar pacote, ajustar arquivo de configuração, aplicar baseline de segurança e orquestrar um procedimento em várias máquinas é do segundo.
Ansible ainda é a resposta certa em três cenários muito comuns no Brasil: parque de servidores que não vai para container tão cedo, equipamento e appliance sem API declarativa, e procedimentos operacionais que precisam de ordem entre máquinas. Ele funciona por SSH, sem agente instalado — o que reduz a barreira em ambiente legado.
Inventário e grupos
Seção intitulada “Inventário e grupos”O inventário descreve o parque. Comece estático, vá para dinâmico quando a nuvem for a fonte da verdade.
all: children: web: hosts: web-01: { ansible_host: 10.0.1.11 } web-02: { ansible_host: 10.0.1.12 } vars: porta_app: 8080 banco: hosts: db-01: { ansible_host: 10.0.2.21 } vars: ansible_user: deploy ansible_python_interpreter: /usr/bin/python3ansible-inventory -i inventario/prod.yml --graphansible web -i inventario/prod.yml -m ping # conectividade antes de qualquer coisaVariáveis vivem em group_vars/ e host_vars/, não espalhadas nos playbooks. Segredo vai
para ansible-vault ou, melhor, para um cofre externo consultado em tempo de execução.
Playbooks, tasks e handlers
Seção intitulada “Playbooks, tasks e handlers”- name: Configurar servidores web hosts: web become: true serial: 1 # uma máquina por vez: o resto continua atendendo max_fail_percentage: 0 tasks: - name: Instalar nginx ansible.builtin.package: name: nginx state: present
- name: Publicar configuração do site ansible.builtin.template: src: templates/site.conf.j2 dest: /etc/nginx/conf.d/site.conf owner: root mode: "0644" validate: "nginx -t -c %s" # não publica configuração que não passa no teste notify: recarregar nginx
- name: Garantir serviço ativo e habilitado ansible.builtin.service: name: nginx state: started enabled: true
handlers: - name: recarregar nginx ansible.builtin.service: { name: nginx, state: reloaded }Handler roda uma vez, no fim, e só se alguma task notificou — é o que evita recarregar
o serviço a cada mudança. serial: 1 transforma o playbook em atualização progressiva:
com balanceador na frente, ninguém percebe.
Roles e reuso
Seção intitulada “Roles e reuso”Role é o módulo do Ansible: estrutura previsível (tasks/, templates/, defaults/,
handlers/) que outros projetos consomem por versão.
# requirements.yml — dependências versionadas, como qualquer bibliotecaroles: - src: https://github.com/empresa/ansible-role-nginx.git version: v1.4.0collections: - { name: community.general, version: ">=9.0.0" }Valores em defaults/main.yml (fáceis de sobrescrever) e não em vars/main.yml (difíceis)
— a precedência de variáveis do Ansible é a principal fonte de confusão para quem começa.
Idempotência: verifique, não presuma
Seção intitulada “Idempotência: verifique, não presuma”O relatório final é o seu teste: rodar o playbook duas vezes deve terminar com
changed=0 na segunda.
ansible-playbook -i inventario/prod.yml site.yml --check --diff # simulaçãoansible-playbook -i inventario/prod.yml site.ymlansible-playbook -i inventario/prod.yml site.yml | grep -E "changed=[1-9]" # deve sair vazioQuem quebra a idempotência é quase sempre command ou shell sem guarda. Use o módulo
específico quando existir; quando não existir, torne a execução condicional:
- name: Inicializar o cluster apenas uma vez ansible.builtin.command: /opt/app/bin/init-cluster args: creates: /var/lib/app/.inicializado # não roda se o arquivo já existe changed_when: false # ou defina o critério real de mudançaAtive --check no CI contra um ambiente de homologação: um playbook que não passa em
simulação não deveria chegar a produção.
Ansible e Terraform juntos
Seção intitulada “Ansible e Terraform juntos”A divisão que funciona: Terraform cria a máquina, entrega IP e tags; Ansible configura o sistema operacional e a aplicação. Ligue os dois pelo inventário dinâmico, lendo tags da nuvem, e não por lista escrita à mão.
# inventario/aws_ec2.yml — plugin de inventário dinâmicoplugin: amazon.aws.aws_ec2regions: [sa-east-1]filters: tag:ambiente: prodkeyed_groups: - key: tags.papel # tag "papel: web" vira o grupo "web" prefix: "" separator: ""Evite local-exec chamando ansible-playbook dentro do Terraform: a execução deixa de ser
idempotente, o erro fica ilegível e o state passa a depender de algo que ele não controla.
Orquestre os dois pelo pipeline, em etapas separadas.
Quando a máquina puder ser descartável, considere o passo seguinte: usar Ansible para construir a imagem (com Packer) em vez de configurar servidores vivos — você ganha infraestrutura imutável sem reescrever o que já tem.
Próximo passo: para IaC escrita em linguagem de programação, veja Pulumi e CDK.