DevOps Admin

Ansible Fundamentos: Inventário, Playbooks e Módulos na Prática Já leu

Ansible Fundamentos: Inventário, Playbooks e Módulos Ansible é uma ferramenta de automação de infraestrutura que revoluciona a forma como gerenciamos servidores e ambientes. Diferente de outras soluções que exigem agentes instalados em cada máquina, Ansible utiliza SSH para se comunicar com seus hosts, tornando a implementação simples e segura. Neste artigo, você aprenderá os três pilares do Ansible: como organizar seus hosts através de inventários, como orquestrar tarefas com playbooks e como executar operações específicas usando módulos. O aprendizado deve ser progressivo. Começaremos entendendo como estruturar um inventário adequado, depois exploraremos a sintaxe e lógica dos playbooks, e finalmente mergulharemos nos módulos que realizam o trabalho pesado. Todos esses conceitos se conectam de forma orgânica — um inventário bem estruturado facilita a escrita de playbooks reutilizáveis, e playbooks eficientes dependem do conhecimento profundo dos módulos disponíveis. Inventário: Organizando sua Infraestrutura Entendendo o Propósito do Inventário O inventário é o mapa de sua infraestrutura dentro do Ansible. Ele define quais máquinas

Ansible Fundamentos: Inventário, Playbooks e Módulos

Ansible é uma ferramenta de automação de infraestrutura que revoluciona a forma como gerenciamos servidores e ambientes. Diferente de outras soluções que exigem agentes instalados em cada máquina, Ansible utiliza SSH para se comunicar com seus hosts, tornando a implementação simples e segura. Neste artigo, você aprenderá os três pilares do Ansible: como organizar seus hosts através de inventários, como orquestrar tarefas com playbooks e como executar operações específicas usando módulos.

O aprendizado deve ser progressivo. Começaremos entendendo como estruturar um inventário adequado, depois exploraremos a sintaxe e lógica dos playbooks, e finalmente mergulharemos nos módulos que realizam o trabalho pesado. Todos esses conceitos se conectam de forma orgânica — um inventário bem estruturado facilita a escrita de playbooks reutilizáveis, e playbooks eficientes dependem do conhecimento profundo dos módulos disponíveis.

Inventário: Organizando sua Infraestrutura

Entendendo o Propósito do Inventário

O inventário é o mapa de sua infraestrutura dentro do Ansible. Ele define quais máquinas você deseja gerenciar, como agrupá-las logicamente e quais variáveis associar a cada host ou grupo. Sem um inventário bem estruturado, seus playbooks se tornam frágeis e difíceis de manter. O inventário responde perguntas fundamentais: quais são meus servidores web? Quais máquinas rodam banco de dados? Quais credenciais usar para cada grupo?

Existem dois formatos principais para inventários: INI (tradicional e simples) e YAML (mais poderoso e legível). A escolha entre eles depende da complexidade de sua infraestrutura. Para pequenos ambientes, INI é suficiente. Para infraestruturas complexas com muitas variáveis e hierarquias, YAML é o caminho certo.

Inventário em Formato INI

O formato INI é direto e intuitivo. Você define grupos entre colchetes e lista os hosts dentro deles. Variáveis podem ser associadas a hosts individuais ou a grupos inteiros através de seções especiais.

# /etc/ansible/hosts ou seu_inventario.ini

[webservers]
web1.example.com ansible_user=ubuntu
web2.example.com ansible_user=ubuntu
192.168.1.10 ansible_port=2222

[databases]
db1.example.com ansible_user=deploy
db2.example.com ansible_user=deploy

[all:vars]
ansible_connection=ssh
ansible_become=yes
ansible_become_user=root

[webservers:vars]
server_role=frontend
http_port=80

Neste exemplo, criamos dois grupos: webservers e databases. Os hosts podem ser especificados por FQDN ou IP. As variáveis como ansible_user definem como Ansible se conectará. A seção [all:vars] aplica variáveis a todos os hosts, enquanto [webservers:vars] aplica apenas ao grupo webservers.

Inventário em Formato YAML

YAML permite uma estrutura mais clara e hierárquica. É ideal quando você precisa de várias variáveis por host ou quando quer organizar inventários dinâmicos.

# inventario.yml

all:
  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_user: ubuntu
          server_role: frontend
          http_port: 80
        web2.example.com:
          ansible_user: ubuntu
          server_role: frontend
          http_port: 80
      vars:
        environment: production

    databases:
      hosts:
        db1.example.com:
          ansible_user: deploy
          db_type: postgresql
        db2.example.com:
          ansible_user: deploy
          db_type: mysql
      vars:
        backup_enabled: true

  vars:
    ansible_connection: ssh
    ansible_become: yes

A estrutura YAML é aninhada e clara. children define subgrupos, hosts lista as máquinas, e vars aplica variáveis. Este formato é especialmente útil em ambientes grandes onde a clareza estrutural facilita a manutenção.

Testando e Validando seu Inventário

Antes de executar qualquer playbook, verifique se seu inventário está correto. Ansible oferece comandos simples para isso.

# Listar todos os hosts
ansible-inventory -i inventario.yml --list

# Listar hosts de um grupo específico
ansible-inventory -i inventario.yml --graph

# Testar conectividade com todos os hosts
ansible all -i inventario.yml -m ping

# Executar um comando simples em um grupo
ansible webservers -i inventario.yml -m command -a "hostname"

O módulo ping verifica se Ansible consegue se conectar aos hosts. Se receber um erro, verifique as credenciais, conectividade de rede e acesso SSH.

Playbooks: Orquestrando Automação

Estrutura e Anatomia de um Playbook

Um playbook é um arquivo YAML que define uma sequência de tarefas (tasks) a serem executadas em hosts específicos. A estrutura fundamental consiste em uma lista de plays, onde cada play mapeia um conjunto de tarefas a um grupo de hosts. Um playbook pode conter um ou múltiplos plays, permitindo orquestração complexa de múltiplos grupos de máquinas.

A beleza do Ansible está em sua sintaxe declarativa. Você descreve o estado desejado, não os passos imperativos para alcançá-lo. Isso torna playbooks idempotentes: executá-los múltiplas vezes leva ao mesmo resultado final.

Seu Primeiro Playbook

Vamos criar um playbook prático que configura um servidor web básico.

---
- name: Configurar servidores web
  hosts: webservers
  become: yes

  vars:
    nginx_port: 80
    nginx_user: www-data

  tasks:
    - name: Atualizar cache de pacotes
      apt:
        update_cache: yes
        cache_valid_time: 3600
      when: ansible_os_family == "Debian"

    - name: Instalar Nginx
      apt:
        name: nginx
        state: present
      when: ansible_os_family == "Debian"

    - name: Criar diretório de conteúdo
      file:
        path: /var/www/meu_site
        state: directory
        owner: "{{ nginx_user }}"
        group: "{{ nginx_user }}"
        mode: '0755'

    - name: Copiar arquivo index.html
      copy:
        content: |
          <!DOCTYPE html>
          <html>
          <body>
          <h1>Bem-vindo!</h1>
          <p>Servidor configurado pelo Ansible</p>
          </body>
          </html>
        dest: /var/www/meu_site/index.html
        owner: "{{ nginx_user }}"
        mode: '0644'

    - name: Configurar Nginx
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/sites-available/default
        backup: yes
      notify: reiniciar nginx

    - name: Ativar Nginx
      systemd:
        name: nginx
        enabled: yes
        state: started

  handlers:
    - name: reiniciar nginx
      systemd:
        name: nginx
        state: restarted

Este playbook demonstra conceitos-chave: hosts especifica o grupo alvo, vars define variáveis, tasks lista as ações. Cada tarefa tem um nome descritivo (boa prática) e um módulo com seus parâmetros. A cláusula when adiciona condicionalidade — a tarefa só executa se a condição for verdadeira. Handlers são disparados por notificações — neste caso, Nginx reinicia apenas se sua configuração mudou.

Playbooks Avançados: Variáveis e Lógica

Playbooks reais precisam lidar com complexidade. Variáveis permitem reutilização, loops processam listas, e condicionais tratam diferentes cenários.

---
- name: Deploy da aplicação web
  hosts: webservers
  become: yes

  vars:
    app_version: "1.2.3"
    app_port: 8080
    deploy_user: deployer
    required_packages:
      - git
      - python3
      - python3-pip
      - curl

  tasks:
    - name: Instalar pacotes obrigatórios
      apt:
        name: "{{ item }}"
        state: present
      loop: "{{ required_packages }}"

    - name: Criar usuário de deploy
      user:
        name: "{{ deploy_user }}"
        shell: /bin/bash
        createhome: yes

    - name: Clonar repositório da aplicação
      git:
        repo: https://github.com/usuario/app.git
        dest: /opt/app
        version: "v{{ app_version }}"
      become_user: "{{ deploy_user }}"

    - name: Instalar dependências Python
      pip:
        requirements: /opt/app/requirements.txt
        virtualenv: /opt/app/venv
        virtualenv_command: python3 -m venv
      become_user: "{{ deploy_user }}"

    - name: Gerar configuração da aplicação
      template:
        src: app_config.j2
        dest: /opt/app/config.yml
      become_user: "{{ deploy_user }}"

    - name: Iniciar serviço da aplicação
      systemd:
        name: app
        state: started
        enabled: yes
        daemon_reload: yes
      register: service_status

    - name: Verificar saúde da aplicação
      uri:
        url: "http://localhost:{{ app_port }}/health"
        method: GET
        status_code: 200
      retries: 3
      delay: 5
      until: result.status == 200

    - name: Exibir mensagem de sucesso
      debug:
        msg: "Aplicação v{{ app_version }} deployada com sucesso!"
      when: service_status.changed

Aqui utilizamos loop para iterar sobre uma lista de pacotes. register captura a saída de uma tarefa em uma variável (service_status), permitindo verificar se houve mudanças. retries e until implementam retry logic — útil ao aguardar que um serviço fique disponível. uri testa endpoints HTTP, validando que a aplicação está saudável.

Módulos: Os Executores do Trabalho

Entendendo Módulos

Módulos são os blocos de construção do Ansible. Cada módulo encapsula uma funcionalidade específica: instalar pacotes, gerenciar arquivos, reiniciar serviços, executar comandos. Ansible vem com centenas de módulos built-in, e você pode criar módulos customizados em Python ou qualquer linguagem que gere JSON.

A chave para dominar Ansible é conhecer os módulos relevantes para seu trabalho. Não é necessário decorar todos, mas você deve saber quais existem, o que fazem, e como utilizá-los. A documentação oficial é excelente — ansible-doc nome_do_modulo exibe documentação completa no terminal.

Módulos Essenciais para Administração

---
- name: Exemplo de módulos essenciais
  hosts: all
  become: yes

  tasks:
    # Módulo command: executar comandos shell
    - name: Executar comando shell
      command: /usr/bin/uptime
      register: uptime_output

    - name: Exibir resultado do comando
      debug:
        var: uptime_output.stdout

    # Módulo shell: similar a command, mas com pipes e redirecionamento
    - name: Processar saída com pipes
      shell: |
        ps aux | grep nginx | wc -l
      register: nginx_processes

    # Módulo file: gerenciar arquivos e diretórios
    - name: Criar diretório
      file:
        path: /opt/app/data
        state: directory
        owner: app
        group: app
        mode: '0755'

    - name: Remover arquivo antigo
      file:
        path: /var/log/old_app.log
        state: absent

    - name: Criar link simbólico
      file:
        src: /opt/app/current
        dest: /opt/app/latest
        state: link

    # Módulo copy: copiar arquivos locais para hosts remotos
    - name: Copiar arquivo de configuração
      copy:
        src: /local/path/config.yml
        dest: /etc/myapp/config.yml
        owner: root
        group: root
        mode: '0600'
        backup: yes

    # Módulo template: processar Jinja2 e copiar
    - name: Gerar config com variáveis
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
        validate: /usr/sbin/nginx -t -c %s
      notify: restart nginx

    # Módulo lineinfile: modificar linhas em arquivos
    - name: Adicionar linha ao arquivo
      lineinfile:
        path: /etc/hosts
        line: "192.168.1.100 myserver.local"
        state: present

    - name: Modificar parâmetro em arquivo de configuração
      lineinfile:
        path: /etc/ssh/sshd_config
        regexp: '^#?PermitRootLogin'
        line: 'PermitRootLogin no'
        state: present
      notify: restart sshd

    # Módulo apt/yum: gerenciar pacotes
    - name: Instalar múltiplos pacotes
      apt:
        name: ['curl', 'wget', 'git', 'vim']
        state: present
        update_cache: yes

    - name: Remover pacote
      apt:
        name: apache2
        state: absent

    # Módulo systemd: gerenciar serviços
    - name: Iniciar e ativar serviço
      systemd:
        name: nginx
        state: started
        enabled: yes
        daemon_reload: yes

    - name: Reiniciar serviço se necessário
      systemd:
        name: mysql
        state: restarted
      when: database_config_changed

    # Módulo user: gerenciar usuários
    - name: Criar usuário do sistema
      user:
        name: appuser
        shell: /bin/bash
        home: /opt/app
        createhome: yes
        state: present

    - name: Adicionar chave SSH pública
      authorized_key:
        user: appuser
        key: "{{ lookup('file', '/local/ssh_key.pub') }}"
        state: present

    # Módulo cron: gerenciar agendamentos
    - name: Agendar backup diário
      cron:
        name: "Daily backup"
        hour: "2"
        minute: "0"
        job: "/opt/scripts/backup.sh > /dev/null 2>&1"
        user: root

  handlers:
    - name: restart nginx
      systemd:
        name: nginx
        state: restarted

    - name: restart sshd
      systemd:
        name: sshd
        state: restarted

Estes módulos cobrem 80% das tarefas de administração. command executa comandos sem processamento shell, enquanto shell permite pipes e redirecionamento. file é versátil para criar, remover e gerenciar permissões. lineinfile é perfeito para modificações cirurgicais em arquivos de configuração. systemd é o padrão moderno para gerenciar serviços em distribuições Linux atuais.

Módulos Avançados para Aplicações

---
- name: Deploy e configuração de aplicação
  hosts: webservers

  tasks:
    # Módulo git: clonar e atualizar repositórios
    - name: Clonar repositório
      git:
        repo: https://github.com/usuario/projeto.git
        dest: /opt/projeto
        version: main
        depth: 1
      become: yes

    # Módulo pip: gerenciar pacotes Python
    - name: Instalar dependências Python
      pip:
        requirements: /opt/projeto/requirements.txt
        virtualenv: /opt/projeto/venv
        virtualenv_command: python3 -m venv

    # Módulo mysql_db: gerenciar bancos de dados MySQL
    - name: Criar banco de dados
      mysql_db:
        name: myapp_db
        state: present
        login_user: root
        login_password: "{{ mysql_root_password }}"

    # Módulo postgresql_db: gerenciar bancos PostgreSQL
    - name: Criar usuário PostgreSQL
      postgresql_user:
        name: appuser
        password: "{{ db_password }}"
        state: present
      become_user: postgres

    # Módulo docker_container: gerenciar containers Docker
    - name: Executar container da aplicação
      docker_container:
        name: myapp
        image: "myapp:{{ app_version }}"
        state: started
        restart_policy: always
        ports:
          - "8080:8080"
        env:
          DATABASE_URL: "{{ database_url }}"

    # Módulo uri: fazer requisições HTTP
    - name: Testar endpoint da API
      uri:
        url: "http://localhost:8080/api/status"
        method: GET
        status_code: 200
      retries: 5
      delay: 10
      until: result.status == 200

    # Módulo assert: validações customizadas
    - name: Validar versão da aplicação
      assert:
        that:
          - app_version is defined
          - app_version | length > 0
        fail_msg: "app_version deve ser definido e não vazio"

Estes módulos lidam com cenários mais específicos: repositories, dependências de linguagem, bancos de dados, containers e validações.

Documentação e Descoberta de Módulos

Nunca tente memorizar todos os módulos. Use a documentação disponível.

# Listar todos os módulos instalados
ansible-doc -l

# Ver documentação de um módulo específico
ansible-doc apt

# Buscar módulos por palavra-chave
ansible-doc -l | grep user

# Ver exemplos práticos
ansible-doc -s user

A flag -s mostra o "snippet" — estrutura básica com parâmetros principais. Sempre consulte a documentação quando tiver dúvidas sobre sintaxe ou comportamento de um módulo.

Conclusão

Você aprendeu que Ansible funciona em três camadas interdependentes: o inventário define sua infraestrutura, playbooks orquestram o fluxo de trabalho, e módulos executam as ações concretas. Uma das lições mais importantes é que Ansible é declarativo, não imperativo — você descreve o estado desejado, e Ansible converge para ele. Isso torna sua automação robusta e reutilizável.

O terceiro ponto crucial é que a maestria em Ansible vem da prática e do conhecimento dos módulos disponíveis. Você não precisa decorar tudo no início — precisa saber onde procurar e como estruturar seu código para ser mantível. Invista tempo em escrever playbooks claros, use nomes descritivos para tarefas, organize seu inventário logicamente, e consulte a documentação frequentemente. Comece com playbooks simples, evolua para orquestrações complexas, e nunca deixe de testar sua automação múltiplas vezes antes de usar em produção.

Referências


Artigos relacionados