Ansible na Prática: Automatizando Servidores Linux
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
--checke--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
- Instalar Ansible
# Ubuntu / Debian
sudo apt update && sudo apt install -y ansible
ansible --version # deve exibir 2.15.x ou superior
- Criar diretório de trabalho
mkdir -p /home/luiz/ansible-lab/{inventories,playbooks,roles}
cd /home/luiz/ansible-lab
- Configurar SSH – copie sua chave pública (
~/.ssh/id_rsa.pub) para~/.ssh/authorized_keysnos dois servidores. - Definir variáveis de conexão (opcional) – crie
ansible.cfgno 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
- Arquivo
site.yml
- hosts: webservers
become: true
roles:
- common
- nginx
- Execução
ansible-playbook -i inventories/hosts.yml playbooks/site.yml
- 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_keysou usuário errado. - Diagnóstico:
ansible -m ping webservers -vvvmostra tentativa de login. - Solução: Copie a chave (
ssh-copy-id -i ~/.ssh/id_rsa.pub ubuntu@srv01.example.com). Verifiqueansible_userno 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:
python3oupython3‑aptnã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
rawoubootstrap.ymlpara garantir dependências.
Sintoma 3 – Handler not triggered despite file change
- Possível causa:
notifyestá dentro de bloco condicional que nunca executa. - Diagnóstico:
ansible-playbook -vvvmostra se o handler foi notificado. - Solução: Mova
notifypara a tarefa detemplateou uselistenno handler. - Prevenção: Sempre teste com
--checkpara garantir que a mudança será percebida.
Sintoma 4 – Package manager lock (dpkg) is held
- Possível causa: Outra operação
aptrodando 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
aptcomlock_timeout: 30no módulo.
# Segurança
- Never store passwords in inventory – use
ansible-vault encrypt_stringpara 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: trueapenas nas tarefas que realmente precisam. - Audite logs – habilite
log_path = /var/log/ansible.logemansible.cfgpara 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-linteansible-testantes de aplicar. - Check mode – sempre execute
--check --diffem 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:
