Ansible na Prática: Automatizando Servidores Linux

setembro 1, 2026 · 9 min de leitura · Luiz Seabra

Ansible na Prática: Automatizando Servidores Linux

Introdução

Administrar dezenas ou centenas de servidores manualmente é inviável – configurações divergem, “funciona na minha máquina” se torna rotina e patches ficam atrasados. Ansible resolve esse problema ao trazer Infrastructure as Code (IaC) leve, agente‑less e baseado em SSH. Neste artigo, você vai descobrir como definir hosts, escrever playbooks, usar módulos essenciais e organizar código em roles. Ao final, será capaz de provisionar dois servidores Linux, instalar Nginx, distribuir um index.html customizado e comprovar a idempotência (a segunda execução não altera nada).

O que você vai aprender

  • Estrutura de inventário (INI e YAML) e grupos.
  • Execução ad‑hoc de módulos simples.
  • Criação de playbooks completos (hosts, become, tasks, handlers, vars, templates).
  • Uso de módulos essenciais (apt, service, copy, template, user).
  • Conceitos de handlers, variables, facts e register.
  • Organização em roles padrão (tasks, handlers, templates, vars, defaults).
  • Como validar idempotência com --check e --diff.

Pré‑requisitos

  • Dois servidores Linux (Ubuntu 22.04 ou Debian) com acesso root via SSH.
  • Chave SSH configurada (sem senha) – veja nosso artigo anterior 04 ssh linux.
  • Controle local (máquina com Ansible 2.15+ instalado).
  • Conhecimento básico de YAML.

Conceitos fundamentais

Conceito Definição
Inventário Lista (arquivo) de hosts e grupos que o Ansible pode gerenciar.
Playbook Arquivo YAML contendo uma ou mais plays que descrevem what deve ser feito em which hosts.
Módulo Unidade de ação (ex.: apt, service, copy). Cada módulo é idempotente por padrão.
Handler Tarefa que só executa quando notificada (ex.: reiniciar serviço após mudança de configuração).
Fact Dados coletados automaticamente do host (ansible_facts).
Role Estrutura de diretórios que encapsula tasks, handlers, templates, vars etc., facilitando reuso.

Preparação do ambiente

  1. Instalar Ansible
# Ubuntu / Debian
sudo apt update && sudo apt install -y ansible
ansible --version   # deve exibir 2.15.x ou superior
  1. Criar diretório de trabalho
mkdir -p /home/luiz/ansible-lab/{inventories,playbooks,roles}
cd /home/luiz/ansible-lab
  1. Configurar SSH – copie sua chave pública (~/.ssh/id_rsa.pub) para ~/.ssh/authorized_keys nos dois servidores.
  2. Definir variáveis de conexão (opcional) – crie ansible.cfg no diretório:
[defaults]
inventory = inventories/hosts.yml
host_key_checking = False
interpreter_python = /usr/bin/python3

Tutorial passo a passo

1. Inventário em YAML

Objetivo: Listar os hosts em grupos lógicos.

# inventories/hosts.yml
all:
  children:
    webservers:
      hosts:
        srv01.example.com:
          ansible_user: ubuntu
        srv02.example.com:
          ansible_user: ubuntu
    dbservers:
      hosts: {}

Explicação: webservers contém dois nós que receberão o Nginx. ansible_user define o usuário SSH.
Resultado esperado: ansible -i inventories/hosts.yml webservers -m ping retorna pong de ambos.

2. Execução ad‑hoc – teste de conectividade

ansible webservers -m ping

Resultado esperado: Saída srv01.example.com | SUCCESS => {"changed": false, "ping": "pong"}.

3. Playbook básico – instalar Nginx

Objetivo: Provisionar Nginx, garantir que o serviço esteja ativo e publicar um index.html customizado.

# playbooks/setup-nginx.yml
- name: Configurar Nginx em servidores web
  hosts: webservers
  become: true            # uso sudo
  vars:
    nginx_port: 80
    index_template: "index.html.j2"
  tasks:
    - name: Instalar pacote nginx
      apt:
        name: nginx
        state: present
        update_cache: yes
      notify: Restart nginx

    - name: Copiar página inicial personalizada
      template:
        src: "templates/{{ index_template }}"
        dest: "/var/www/html/index.html"
        mode: "0644"

    - name: Garantir que nginx está rodando e habilitado
      service:
        name: nginx
        state: started
        enabled: true

  handlers:
    - name: Restart nginx
      service:
        name: nginx
        state: restarted

Explicação:
– apt garante a presença do pacote (idempotente).
– template usa Jinja2 para inserir variáveis ({{ ansible_hostname }}).
– notify dispara o handler apenas se o arquivo mudar.
Resultado esperado: Após ansible-playbook playbooks/setup-nginx.yml, ambos os hosts têm Nginx instalado, em execução e exibindo a página customizada.

4. Template Jinja2 para index.html

<!-- templates/index.html.j2 -->
<!doctype html>
<html lang="pt-BR">
<head>
  <meta charset="UTF-8">
  <title>Bem‑vindo ao {{ ansible_hostname }}</title>
</head>
<body>
  <h1>Servidor {{ ansible_hostname }}</h1>
  <p>Esta página foi provisionada por <strong>Ansible</strong> em {{ ansible_date_time.iso8601 }}</p>
</body>
</html>

Explicação: {{ ansible_hostname }} vem de facts coletados automaticamente; {{ ansible_date_time.iso8601 }} fornece data/hora.

5. Validando idempotência – execução dupla

ansible-playbook playbooks/setup-nginx.yml
ansible-playbook playbooks/setup-nginx.yml

Resultado esperado:
– Primeira execução => changed em várias tarefas.
– Segunda execução => todas as tarefas retornam ok (nenhuma mudança). Isso demonstra idempotência.

6. Uso de --check e --diff

ansible-playbook playbooks/setup-nginx.yml --check --diff

Objetivo: Simular mudanças sem aplicar, exibindo diferenças reais nos arquivos alterados.
Resultado esperado: Saída indica que index.html seria alterado, mas nada é escrito.

7. Criar Role “common”

Objetivo: Reutilizar tarefas de configuração comum (update e timezone).

cd roles
ansible-galaxy init common

Estrutura gerada (roles/common/tasks/main.yml).

# roles/common/tasks/main.yml
- name: Atualizar cache apt
  apt:
    update_cache: yes
    cache_valid_time: 3600

- name: Definir fuso horário
  timezone:
    name: America/Sao_Paulo

No playbook principal, inclua a role:

- hosts: webservers
  become: true
  roles:
    - common
    - nginx   # role que iremos criar a seguir

8. Role “nginx” – encapsulando o setup anterior

ansible-galaxy init nginx

Edite roles/nginx/tasks/main.yml:

- name: Instalar nginx
  apt:
    name: nginx
    state: present
    update_cache: yes
  notify: Restart nginx

- name: Deploy index.html via template
  template:
    src: "templates/index.html.j2"
    dest: "/var/www/html/index.html"
    mode: "0644"

- name: Garantir serviço ativo
  service:
    name: nginx
    state: started
    enabled: true

handlers:
  - name: Restart nginx
    service:
      name: nginx
      state: restarted

Copie o template templates/index.html.j2 para roles/nginx/templates/.
Resultado esperado: ansible-playbook site.yml (playbook que inclui as duas roles) provisiona Nginx com as mesmas garantias, mas com código modular.

Laboratório

Cenário completo – Dois servidores (srv01, srv02) com playbook modularizado.
1. Estrutura de diretórios

tree -L 3
.
├── inventories
│   └── hosts.yml
├── playbooks
│   └── site.yml
└── roles
    ├── common
    │   ├── tasks
    │   │   └── main.yml
    │   └── templates
    └── nginx
        ├── tasks
        │   └── main.yml
        └── templates
            └── index.html.j2
  1. Arquivo site.yml
- hosts: webservers
  become: true
  roles:
    - common
    - nginx
  1. Execução
ansible-playbook -i inventories/hosts.yml playbooks/site.yml
  1. Verificação
curl http://srv01.example.com
curl http://srv02.example.com

Resultado esperado: Cada servidor responde com a página HTML que exibe seu hostname.

# Troubleshooting: problemas comuns e como resolver

Sintoma 1 – Unreachable – SSH authentication failed

  • Possível causa: chave pública não está na authorized_keys ou usuário errado.
  • Diagnóstico: ansible -m ping webservers -vvv mostra tentativa de login.
  • Solução: Copie a chave (ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@srv01.example.com). Verifique ansible_user no inventário.
  • Prevenção: Centralize chaves em SSH‑config e use ansible_ssh_private_key_file.

Sintoma 2 – Failed to download the required facts – packages missing

  • Possível causa: python3 ou python3‑apt não instalados nos hosts.
  • Diagnóstico: ansible -m setup srv01 -a "filter=ansible_os_family" falha.
  • Solução: Instale python3 (ex.: sudo apt install -y python3-minimal). Ansible instalará o módulo de fato automaticamente.
  • Prevenção: Use raw ou bootstrap.yml para garantir dependências.

Sintoma 3 – Handler not triggered despite file change

  • Possível causa: notify está dentro de bloco condicional que nunca executa.
  • Diagnóstico: ansible-playbook -vvv mostra se o handler foi notificado.
  • Solução: Mova notify para a tarefa de template ou use listen no handler.
  • Prevenção: Sempre teste com --check para garantir que a mudança será percebida.

Sintoma 4 – Package manager lock (dpkg) is held

  • Possível causa: Outra operação apt rodando em background (ex.: unattended-upgrades).
  • Diagnóstico: sudo lsof /var/lib/dpkg/lock-frontend.
  • Solução: Aguarde ou mate o processo, depois rode novamente.
  • Prevenção: Use apt com lock_timeout: 30 no módulo.

# Segurança

  • Never store passwords in inventory – use ansible-vault encrypt_string para variáveis sensíveis.
  • Restrinja acesso ao controle – keep the control node behind firewall, use OS‑level users with limited sudo.
  • Use SSH keys – desative autenticação por senha no /etc/ssh/sshd_config.
  • Limite privilégio – no playbook, use become: true apenas nas tarefas que realmente precisam.
  • Audite logs – habilite log_path = /var/log/ansible.log em ansible.cfg para rastrear mudanças.

# Boas práticas

  • Estrutura de diretórios – siga a convenção inventories/, playbooks/, roles/.
  • Roles reutilizáveis – publique no Ansible Galaxy ou em repositório interno.
  • Versionamento – mantenha playbooks em Git, use branches para mudanças.
  • Testes – rode ansible-lint e ansible-test antes de aplicar.
  • Check mode – sempre execute --check --diff em ambientes críticos.
  • Tags – marque tarefas (tags: packages) para rodar partes rápidas (--tags packages).

Comparação de ferramentas de automação

Ferramenta Arquitetura Agente Idempotência Learning Curve
Ansible Push via SSH Nenhum (agentless) Sim (módulos) Médio (YAML)
Chef Pull (client) Chef‑client Sim (recipes) Alto (Ruby DSL)
Puppet Pull (agent) Puppet‑agent Sim (manifests) Médio‑alto (Puppet DSL)
SaltStack Push/Pull Salt‑minion Sim (states) Médio (YAML/Jinja)

Conclusão

Ansible oferece a combinação ideal de simplicidade, idempotência e agente‑less para automatizar servidores Linux. Ao organizar playbooks em roles, você cria código reutilizável, versionável e fácil de auditar. Combine com boas práticas de segurança (SSH, vault) e controle de mudanças (Git) e terá um pipeline de automação robusto.

Perguntas frequentes

Q: Posso usar Ansible em Windows?
A: Sim, mas requer o módulo winrm e playbooks diferentes – não coberto neste guia.

Q: Por que o módulo apt é idempotente?
A: Ele verifica o estado atual do pacote antes de instalar/remover, garantindo que a mesma execução não mude nada se o pacote já estiver no estado desejado.

Próximo passo

Agora que você domina Ansible Na Pratica, o próximo passo lógico da nossa trilha de aprendizado é continuar desenvolvendo suas habilidades.

→ Continue: Terraform para Infraestrutura

Artigos relacionados

Estes artigos complementam o conteúdo apresentado:

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Rolar para cima