DEV Community

Cover image for IaC além do Terraform - Ansible para provisionamento e configuração
Rafael Dutra for apsis-cc

Posted on

IaC além do Terraform - Ansible para provisionamento e configuração

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 nginx que 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 apt simplesmente 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:

  1. Ansible Documentation
  2. Ansible — Intro to Playbooks

Top comments (0)