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
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
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;
}
}
Executando o playbook:
ansible-playbook -i inventory/hosts.ini playbook-webserver.yml
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
}
# 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
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:
Top comments (0)