1. Provisionar não é configurar
No artigo anterior desta série, vimos o OpenTofu como uma alternativa (ou substituto direto) ao Terraform para a tarefa de provisionar infraestrutura — criar VMs, redes, bancos de dados gerenciados, buckets. Mas provisionar um servidor é só o primeiro passo: depois que a VM existe, alguém precisa instalar pacotes, configurar usuários, aplicar hardening, subir a aplicação e manter tudo isso consistente ao longo do tempo. É nesse espaço que o Ansible entra — e é comum ver os dois trabalhando juntos no mesmo pipeline, não como concorrentes.
2. Onde o Terraform para e o Ansible começa
A distinção mais útil na prática é:
- Terraform (e OpenTofu) são ferramentas de provisionamento: elas conversam com APIs de nuvem para criar, atualizar ou destruir recursos. O modelo mental é declarativo e orientado a estado desejado do recurso: “quero uma VM com esse tipo de instância, nessa rede, com esse disco”.
- Ansible é uma ferramenta de gerenciamento de configuração: ela conecta em máquinas já existentes (via SSH, sem precisar de agente instalado) e executa tarefas para deixá-las em um estado desejado: “quero o Nginx instalado, essa versão, esse arquivo de configuração, esse serviço rodando”.
Não é incomum ver os dois no mesmo pipeline: o Terraform cria a VM e expõe o IP como output; o Ansible usa esse IP para conectar e configurar o que está dentro dela. Um cuida do “hardware” (ainda que virtual), o outro do “software”.
3. Conceitos fundamentais do Ansible
Antes de ver exemplos reais, vale fixar o vocabulário:
-
Inventory: a lista de máquinas que o Ansible gerencia, agrupadas logicamente (por exemplo,
webservers,databases). Pode ser um arquivo estático (INI ou YAML) ou gerado dinamicamente (ex.: a partir de tags de uma conta AWS). -
Playbook: um arquivo YAML que descreve, em ordem, quais tarefas (
tasks) devem ser executadas em quais grupos de máquinas do inventory. -
Module: a unidade de trabalho executada por uma tarefa — existem módulos prontos para praticamente tudo (
apt,yum,copy,service,user,template, módulos específicos de nuvem, etc.). -
Role: uma forma de empacotar playbooks, variáveis, templates e arquivos relacionados a uma responsabilidade específica (ex.: uma role
nginxque sabe instalar e configurar o Nginx), reutilizável entre projetos. -
Idempotência: assim como o Terraform, o Ansible é projetado para que rodar o mesmo playbook várias vezes produza o mesmo resultado final, sem efeitos colaterais — se um pacote já está instalado, o módulo
aptsimplesmente não faz nada na segunda execução. - Agentless: ao contrário de ferramentas como Puppet ou Chef, o Ansible não exige instalar um agente permanente na máquina gerenciada — ele conecta via SSH (ou WinRM, no caso do Windows), copia os módulos necessários, executa e limpa depois. Isso simplifica bastante o setup inicial.
4. Inventory na prática
# inventory/hosts.ini
[webservers]
web1 ansible_host=10.0.1.10
web2 ansible_host=10.0.1.11
[databases]
db1 ansible_host=10.0.2.10
[webservers:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/deploy_key
Enter fullscreen mode Exit fullscreen mode
5. Um playbook real: configurando um servidor web após o provisionamento
Este exemplo assume que a VM já existe (criada por Terraform/OpenTofu) e foca só na parte de configuração: instalar Nginx, criar um usuário de deploy, copiar um arquivo de configuração e garantir que o firewall libere a porta certa.
# playbook-webserver.yml
- name: Configurar servidor web
hosts: webservers
become: true
vars:
app_port: 8080
tasks:
- name: Atualizar cache de pacotes
apt:
update_cache: true
cache_valid_time: 3600
- name: Instalar Nginx
apt:
name: nginx
state: present
- name: Criar usuário de deploy
user:
name: deploy
shell: /bin/bash
groups: www-data
append: true
- name: Copiar configuração customizada do Nginx
template:
src: templates/nginx-site.conf.j2
dest: /etc/nginx/sites-available/app
owner: root
group: root
mode: "0644"
notify: Recarregar Nginx
- name: Habilitar o site
file:
src: /etc/nginx/sites-available/app
dest: /etc/nginx/sites-enabled/app
state: link
notify: Recarregar Nginx
- name: Liberar porta HTTP no firewall (ufw)
ufw:
rule: allow
port: "80"
proto: tcp
- name: Garantir que o Nginx está rodando e habilitado no boot
service:
name: nginx
state: started
enabled: true
handlers:
- name: Recarregar Nginx
service:
name: nginx
state: reloaded
Enter fullscreen mode Exit fullscreen mode
O template referenciado usa variáveis Jinja2, o mesmo motor de templates usado internamente pelo Ansible:
# templates/nginx-site.conf.j2
server {
listen 80;
server_name {{ inventory_hostname }};
location / {
proxy_pass http://127.0.0.1:{{ app_port }};
proxy_set_header Host $host;
}
}
Enter fullscreen mode Exit fullscreen mode
Executando o playbook:
ansible-playbook -i inventory/hosts.ini playbook-webserver.yml
Enter fullscreen mode Exit fullscreen mode
Note o uso de notify/handlers: a tarefa de copiar o template e a de habilitar o site notificam o handler Recarregar Nginx, que só roda uma vez ao final, mesmo que múltiplas tarefas o disparem — evitando reiniciar o serviço várias vezes desnecessariamente numa mesma execução.
6. Integrando Terraform e Ansible no mesmo fluxo
Uma forma comum de conectar as duas ferramentas é usar o output do Terraform para gerar o inventory do Ansible dinamicamente, em vez de manter os IPs hardcoded:
# outputs.tf
output "web_ips" {
value = aws_instance.web[*].public_ip
}
Enter fullscreen mode Exit fullscreen mode
# Gera o inventory a partir do output do Terraform
terraform output -json web_ips | jq -r '.[]' > inventory/hosts_dynamic.txt
ansible-playbook -i inventory/hosts_dynamic.txt playbook-webserver.yml
Enter fullscreen mode Exit fullscreen mode
Em pipelines mais maduros, isso costuma virar um plugin de inventory dinâmico (o Ansible tem plugins oficiais para AWS EC2, Azure, GCP, etc.), eliminando esse passo manual de exportar e converter outputs.
7. O Ansible pode substituir o Terraform?
Tecnicamente, o Ansible tem módulos de cloud (amazon.aws.ec2_instance, azure.azcollection.azure_rm_virtualmachine, etc.) que conseguem criar recursos de infraestrutura, não só configurá-los. Na prática, isso é usado com menos frequência, por alguns motivos:
- O Terraform mantém um state explícito e trata drift de forma mais robusta — ele sabe exatamente o que criou e detecta divergências. Módulos de cloud do Ansible tendem a ser mais imperativos, sem esse rastreamento nativo.
- O ecossistema de providers do Terraform (e OpenTofu) para APIs de nuvem é mais completo e atualizado que os módulos de cloud do Ansible.
- Misturar as responsabilidades — usar Ansible tanto para criar quanto para configurar — tende a deixar o pipeline mais difícil de raciocinar sobre “o que existe” versus “como está configurado”.
Por isso, a combinação mais comum no mercado continua sendo: Terraform (ou OpenTofu) provisiona, Ansible configura.
8. Conclusão
O Ansible não compete com o Terraform — ele resolve um problema diferente e complementar: o que fazer depois que a infraestrutura já existe. Inventory, playbooks, módulos e idempotência são os blocos fundamentais para automatizar de forma confiável a configuração de servidores, e a integração com o output do Terraform fecha o ciclo completo de provisionamento + configuração. No próximo e último artigo desta série, mudamos de assunto: como testar código Terraform antes de rodar apply em produção, usando Terratest, checkov e tflint.
Imagem de capa: Logo oficial do Terraform — Wikimedia Commons
Referências: