Post

Guia Completo de Playbooks no Ansible: Estrutura, Modularização e Práticas Avançadas

Guia Completo de Playbooks no Ansible: Estrutura, Modularização e Práticas Avançadas

Introdução Geral

Os playbooks são o coração da automação no Ansible, permitindo definir e organizar tarefas para configurar e gerenciar sistemas de maneira eficiente e reproduzível. Neste guia completo, abordaremos desde os conceitos básicos de criação de playbooks até técnicas avançadas de segurança, modularização e boas práticas para ambientes complexos. Com um foco especial em segurança e organização, este tutorial é ideal tanto para iniciantes que desejam entender a estrutura de um playbook quanto para profissionais que buscam aprimorar suas habilidades com Ansible.


Tabela de Conteúdo


1. Introdução ao Conceito de Playbooks no Ansible

Objetivo

Apresentar o conceito de playbooks e destacar sua importância na automação de tarefas, diferenciando-os de comandos ad-hoc e detalhando suas vantagens na organização e automação de configurações complexas.


Conteúdo

  1. O que São Playbooks no Ansible?

    No Ansible, os playbooks são arquivos escritos em YAML que definem uma ou mais “plays” (conjuntos de instruções) para execução em hosts gerenciados. Em um playbook, cada play contém tarefas (tasks) que especificam ações para configurar sistemas, implantar aplicativos e gerenciar ambientes complexos.

    Resumo:

    • Formato YAML: Simples e legível, usado para definir a sequência de tarefas.
    • Estrutura Modulada: Contém uma ou mais “plays”, onde cada play define um conjunto de tarefas a serem executadas em um ou mais hosts.
    • Automação Completa: Permite combinar tarefas sequenciais e condicionais, oferecendo automação robusta.
  2. Como os Playbooks Facilitam a Automação de Tarefas Complexas

    A principal vantagem dos playbooks é a capacidade de definir workflows automatizados e consistentes. Diferente de comandos ad-hoc, que são executados uma única vez para tarefas pontuais, os playbooks documentam e organizam fluxos completos, permitindo repetir e rastrear cada passo.

    Principais Benefícios:

    • Automação Reprodutível: A execução de um playbook garante que todos os passos sejam realizados da mesma forma em cada execução.
    • Controle de Fluxo e Condições: Permite o uso de condicionais (when), loops (with_items, loop), variáveis, e módulos de controle de fluxo (como block e rescue).
    • Documentação e Manutenção: O próprio playbook serve como uma documentação dos procedimentos, facilitando o compartilhamento e a manutenção das tarefas automatizadas.
  3. Diferença entre Comandos Ad-Hoc e Playbooks

    • Comandos Ad-Hoc: Executam uma única tarefa rápida e pontual diretamente na linha de comando.
    • Playbooks: Estruturam múltiplas tarefas sequenciais e interdependentes. São reutilizáveis, documentam cada passo e incluem configurações como variáveis e roles.

    Exemplo:

    • Comando Ad-Hoc: ansible all -m apt -a "name=nginx state=present" -b
      • Instala o pacote nginx em todos os hosts de uma vez, mas não define uma sequência.
    • Playbook: Um playbook permite definir múltiplas tarefas — como instalação, configuração de arquivos e reinício do serviço — com passos organizados e interdependentes.
  4. Vantagens de Usar Playbooks para Organização e Automação de Configurações

    Com playbooks, é possível automatizar cenários complexos em que múltiplos servidores, variáveis e condições estão envolvidos. Isso traz uma série de vantagens para o gerenciamento de infraestrutura:

    • Consistência e Confiabilidade: O playbook garante que cada tarefa será executada da mesma forma em cada execução, eliminando variações que ocorrem em execuções manuais.
    • Escalabilidade: Com playbooks, a automação pode facilmente ser escalada para centenas de servidores com uma única execução.
    • Flexibilidade e Modularidade: Playbooks permitem organizar tarefas em blocos lógicos (como block e handlers), com opções para tratamento de erros, reuso de tarefas, e integração com roles (papéis) que encapsulam configurações específicas de cada serviço.
  5. Exemplo Simples de Playbook para Instalação de Pacotes

    Abaixo está um exemplo básico de um playbook que instala o pacote nginx e configura o serviço para iniciar automaticamente em servidores de um grupo de hosts chamado webservers:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    ---
    - name: Configuração de Servidor Web com Nginx
      hosts: webservers
      become: yes
    
      tasks:
        - name: Instalar o pacote nginx
          apt:
            name: nginx
            state: present
          when: ansible_os_family == "Debian"
    
        - name: Iniciar e habilitar o serviço nginx
          service:
            name: nginx
            state: started
            enabled: yes
    

    Explicação:

    • name: Fornece um título descritivo para o play e para cada tarefa.
    • hosts: Define o grupo de hosts onde o play será executado (webservers).
    • become: Permite a execução com privilégios elevados.
    • tasks: Lista de tarefas a serem executadas, incluindo a instalação e ativação do serviço nginx.

Resumo

Playbooks são a ferramenta central do Ansible para automação de tarefas complexas, proporcionando uma estrutura organizada, flexível e robusta. Ao contrário dos comandos ad-hoc, os playbooks permitem controlar fluxos, definir dependências e incluir condições de execução, facilitando a automação de ambientes de TI modernos.

Na próxima seção, exploraremos a estrutura e sintaxe básica dos playbooks, detalhando a formatação YAML e os principais componentes para começar a criar playbooks funcionais no Ansible.


2. Estrutura e Sintaxe de um Playbook Ansible

Objetivo

Explicar a estrutura básica de um playbook no Ansible e apresentar suas principais diretivas, para que o leitor compreenda a organização e a formatação de um playbook simples.


Conteúdo

  1. Estrutura Básica do Playbook em YAML

    Playbooks no Ansible são escritos em YAML, um formato de dados simples e legível que usa indentação para organizar as informações. Alguns pontos importantes sobre a sintaxe YAML para playbooks incluem:

    • Indentação: No YAML, a indentação define a estrutura e deve ser consistente (espaços, não tabulações).
    • Listas e Pares Chave-Valor: Playbooks são compostos por listas (- item) e pares chave-valor (chave: valor).
    • Organização em Níveis: Cada seção do playbook é organizada em níveis, como hosts, tasks, vars, etc., com indentação para separar as subtarefas e opções.

    Exemplo Básico de Estrutura YAML:

    1
    2
    3
    4
    5
    6
    7
    8
    
    - name: Exemplo de playbook
      hosts: all
      become: yes
      tasks:
        - name: Instalar o Apache
          apt:
            name: apache2
            state: present
    
  2. Componentes Principais de um Playbook

    Um playbook básico contém alguns componentes essenciais que definem o escopo e a execução das tarefas:

    • hosts: Define em quais servidores as tarefas serão executadas (ex.: all, webservers).
    • tasks: Uma lista de tarefas que serão executadas sequencialmente.
    • vars: Variáveis definidas dentro do playbook para uso nas tarefas, tornando-o mais dinâmico.
    • handlers: Tarefas especiais que só são acionadas se notificadas por outras tarefas (úteis para reiniciar serviços após alterações de configuração).
  3. Diretivas Principais de um Playbook

    • hosts: Especifica o(s) grupo(s) de hosts no qual o playbook será executado.
      1
      
      hosts: webservers
      
    • become: Define se a execução deve ocorrer com privilégios elevados (yes para ativar sudo).
      1
      
      become: yes
      
    • tasks: Lista de ações a serem executadas sequencialmente, com uma estrutura chave-valor. ```yaml tasks:
      • name: Instalar nginx apt: name: nginx state: latest ```
    • vars: Define variáveis específicas do playbook, permitindo reuso de valores e personalização.
      1
      2
      3
      
      vars:
        web_package: nginx
        version: latest
      
    • handlers: Tarefas executadas em resposta a notificações de outras tarefas. ```yaml handlers:
      • name: Reiniciar o nginx service: name: nginx state: restarted ```
  4. Exemplo de um Playbook Básico para Instalação de Pacotes

    Vamos montar um exemplo de playbook que instala e configura o serviço nginx em servidores de um grupo chamado webservers. Esse exemplo inclui o uso de uma variável e um handler:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    ---
    - name: Instalação e Configuração do Nginx
      hosts: webservers
      become: yes
    
      vars:
        web_package: nginx
    
      tasks:
        - name: Instalar o pacote Nginx
          apt:
            name: "{{ web_package }}"
            state: present
          when: ansible_os_family == "Debian"
          notify: Reiniciar o Nginx
    
        - name: Configurar arquivo de boas-vindas
          copy:
            content: "Bem-vindo ao servidor Nginx!"
            dest: /var/www/html/index.html
    
      handlers:
        - name: Reiniciar o Nginx
          service:
            name: nginx
            state: restarted
    

    Explicação:

    • Play: Chama-se “Instalação e Configuração do Nginx” e aplica as tarefas no grupo webservers.
    • Variável web_package: Define o nome do pacote como nginx, permitindo que o playbook seja mais fácil de modificar se o pacote mudar.
    • Tarefa de Instalação: Usa o módulo apt para instalar o Nginx e só executa em sistemas Debian (when: ansible_os_family == "Debian").
    • Tarefa de Configuração: Usa o módulo copy para criar um arquivo de boas-vindas.
    • Handler: Reinicia o serviço nginx se notificado, o que ocorre após a instalação do pacote.
  5. Resumo dos Componentes com uma Tabela de Referência

    ComponenteFunçãoExemplo de Uso
    hostsDefine os hosts onde o play será executado.hosts: webservers
    becomeDefine se as tarefas devem ser executadas com sudo.become: yes
    tasksLista de tarefas que o play executará.tasks: - name: Instalar nginx ...
    varsDefine variáveis usadas no playbook.vars: web_package: nginx
    handlersTarefas executadas sob demanda após uma notificação.notify: Reiniciar o Nginx

Resumo

A estrutura e sintaxe de um playbook Ansible são baseadas em YAML e incluem componentes essenciais como hosts, tasks, vars e handlers. Com esses elementos, é possível criar playbooks simples e organizados, que permitem a execução sequencial de tarefas em um ou mais hosts de forma automatizada.

Na próxima seção, abordaremos a execução de tarefas com tasks e a modularização com handlers, avançando na construção de playbooks mais robustos e organizados.


3. Execução de Tarefas com tasks e Modularização com handlers

Objetivo

Demonstrar como definir tarefas (tasks) sequenciais e modularizar a execução com handlers, garantindo que as tarefas sejam executadas de forma organizada e que ações específicas, como reiniciar serviços, só ocorram quando necessário.


Conteúdo

  1. Configuração de tasks para Execução de Tarefas Sequenciais

    Em um playbook Ansible, o componente tasks contém a lista de ações que serão executadas em sequência. Cada task é uma ação que utiliza módulos do Ansible, como apt, yum, service, copy, entre outros, para realizar operações de instalação, configuração e monitoramento. Cada tarefa recebe um nome descritivo e pode ser parametrizada com variáveis e condicionais.

    Exemplo de Tarefa Simples:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    tasks:
      - name: Instalar o pacote nginx
        apt:
          name: nginx
          state: present
      - name: Copiar arquivo de configuração customizado
        copy:
          src: /local/path/nginx.conf
          dest: /etc/nginx/nginx.conf
    
    • name: Descrição da tarefa, facilitando a leitura do playbook e a depuração da execução.
    • apt e copy: Módulos específicos que executam operações (instalação de pacote e cópia de arquivo).
  2. Modularização com handlers para Ações Sob Demanda

    Um handler é uma tarefa que só é executada quando notificada por outra tarefa. Isso é útil para tarefas como reiniciar serviços ou atualizar configurações, que não precisam ser executadas sempre, mas somente após uma mudança relevante.

    • Quando usar handlers: handlers são ideais para tarefas que devem ocorrer apenas quando uma alteração acontece, como reiniciar um serviço após modificar um arquivo de configuração.
    • Sintaxe de notify: Dentro da tarefa que requer o handler, utilize notify: <nome_do_handler> para chamar o handler apenas se a tarefa provocar alguma mudança no sistema.

    Exemplo de Uso de handlers para Reiniciar um Serviço após Configuração

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    tasks:
      - name: Instalar o nginx
        apt:
          name: nginx
          state: present
        notify: Reiniciar o nginx
    
      - name: Copiar configuração do nginx
        copy:
          src: /local/path/nginx.conf
          dest: /etc/nginx/nginx.conf
        notify: Reiniciar o nginx
    
    handlers:
      - name: Reiniciar o nginx
        service:
          name: nginx
          state: restarted
    
    • Explicação:
      • As tarefas Instalar o nginx e Copiar configuração do nginx notificam o handler Reiniciar o nginx.
      • O handler Reiniciar o nginx só será executado se alguma das tarefas acima provocar uma mudança (ex.: se o arquivo de configuração foi atualizado).
  3. Usando Condicionais com when para Executar Tarefas Sob Condição

    Condicionais permitem que uma tarefa seja executada apenas se uma condição específica for atendida. Isso pode ser útil para evitar erros de execução em sistemas incompatíveis ou para adaptar o playbook para diferentes ambientes.

    Exemplo de Uso de when para Condicionar a Execução em Sistemas Debian

    1
    2
    3
    4
    5
    6
    
    tasks:
      - name: Instalar o nginx apenas em Debian
        apt:
          name: nginx
          state: present
        when: ansible_os_family == "Debian"
    
    • Explicação:
      • when: ansible_os_family == "Debian": Condiciona a tarefa para ser executada apenas em hosts com sistema operacional da família Debian.
  4. Exemplo Prático de um Playbook com tasks e handlers

    O exemplo a seguir mostra um playbook que instala o Nginx, copia uma configuração e reinicia o serviço Nginx apenas se a configuração for alterada:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    ---
    - name: Configuração do Servidor Web com Nginx
      hosts: webservers
      become: yes
    
      tasks:
        - name: Instalar o pacote Nginx
          apt:
            name: nginx
            state: present
          when: ansible_os_family == "Debian"
          notify: Reiniciar o Nginx
    
        - name: Copiar arquivo de configuração do Nginx
          copy:
            src: /local/path/nginx.conf
            dest: /etc/nginx/nginx.conf
          notify: Reiniciar o Nginx
    
      handlers:
        - name: Reiniciar o Nginx
          service:
            name: nginx
            state: restarted
    

    Explicação do Exemplo:

    • Tarefas: Instala o Nginx e copia o arquivo de configuração.
    • Condição: A instalação ocorre apenas em sistemas da família Debian.
    • Notificação e Handler: As tarefas de instalação e configuração notificam o handler Reiniciar o Nginx, que só é executado se houver uma mudança.
  5. Tabela de Referência: Principais Opções de tasks e handlers

    ParâmetroDescriçãoExemplo
    nameNome descritivo para a tarefa ou handlername: Instalar nginx
    notifyChama um handler caso haja mudançanotify: Reiniciar o nginx
    whenCondiciona a execução da tarefawhen: ansible_os_family == "Debian"
    handlersDefine tarefas que respondem a notificaçõeshandlers: - name: Reiniciar o nginx ...

Resumo

O uso de tasks e handlers permite organizar as tarefas do playbook de forma sequencial e condicional, criando um fluxo de execução mais eficiente e modular. A notificação de handlers permite que ações sensíveis, como reiniciar serviços, ocorram apenas quando necessário, enquanto as condicionais controlam a execução com base em critérios específicos.

Na próxima seção, exploraremos como definir e utilizar variáveis em playbooks, o que facilita a personalização e reutilização de playbooks em diferentes ambientes e configurações.


4. Uso de Variáveis em Playbooks

Objetivo

Explicar como definir e utilizar variáveis em playbooks para torná-los dinâmicos e personalizáveis. Essa prática ajuda a adaptar o mesmo playbook a diferentes ambientes e configurações.


Conteúdo

  1. Declaração de Variáveis no Playbook

    No Ansible, as variáveis permitem que um playbook seja mais flexível e adaptável, removendo a necessidade de valores fixos e facilitando o reuso. As variáveis podem ser declaradas diretamente no playbook usando a diretiva vars.

    Exemplo de Declaração Simples com vars:

    1
    2
    3
    
    vars:
      web_package: nginx
      web_port: 80
    
    • Explicação:
      • web_package: Nome do pacote a ser instalado, permitindo a fácil substituição por outro servidor web se necessário.
      • web_port: Porta a ser configurada, útil para definir diferentes portas em diferentes ambientes.
  2. Uso de Variáveis do Inventário e Arquivos Externos

    Além de declarar variáveis no próprio playbook, você pode definir variáveis no inventário (inventory) ou em arquivos externos (vars_files). Essa prática é útil para separar configurações e personalizar variáveis por host ou grupo.

    Exemplo de Variáveis no Inventário:

    1
    2
    3
    
    [webservers]
    server1 ansible_host=192.168.1.10 web_port=8080
    server2 ansible_host=192.168.1.11 web_port=8081
    
    • Explicação:
      • Cada servidor tem uma configuração personalizada de web_port, que pode ser acessada no playbook usando {{ web_port }}.

    Exemplo de Uso de vars_files para Importar Variáveis de Arquivos Externos:

    1
    2
    
    vars_files:
      - vars/web_config.yml
    

    O conteúdo de web_config.yml pode ser algo como:

    1
    2
    
    web_package: apache2
    max_clients: 200
    
  3. Utilizando Variáveis no Playbook

    Para usar uma variável em um playbook, utilize a sintaxe {{ variavel }}, com o valor da variável sendo automaticamente substituído no momento da execução.

    Exemplo de Uso de Variáveis em Tarefas:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    - name: Instalar o servidor web definido
      apt:
        name: "{{ web_package }}"
        state: present
    
    - name: Configurar a porta do servidor
      lineinfile:
        path: /etc/nginx/nginx.conf
        regexp: 'listen'
        line: "listen {{ web_port }};"
    
    • Explicação:
      • {{ web_package }}: O Ansible substitui web_package pelo valor configurado (nginx ou apache2).
      • {{ web_port }}: Define a porta no arquivo de configuração com base no valor da variável.
  4. Ordem de Precedência das Variáveis

    O Ansible aplica variáveis em uma ordem de precedência que determina qual valor será usado em caso de conflitos. A ordem das variáveis (da mais baixa para a mais alta prioridade) é:

    • Variáveis padrão definidas em roles.
    • Variáveis definidas em group_vars ou host_vars.
    • Variáveis de inventário.
    • Variáveis de linha de comando (-e).

    Exemplo de Sobrescrita de Variáveis:

    1
    
    ansible-playbook playbook.yml -e "web_port=8080"
    
    • Explicação:
      • A variável web_port definida na linha de comando substitui qualquer valor anterior da mesma variável no playbook.
  5. Exemplo Prático: Configurando um Servidor Web com Variáveis Personalizáveis

    O exemplo abaixo mostra um playbook que usa variáveis para definir o pacote do servidor web, a porta de escuta e o diretório raiz:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
    ---
    - name: Configuração Personalizada do Servidor Web
      hosts: webservers
      become: yes
    
      vars:
        web_package: nginx
        web_port: 8080
        web_root: /var/www/html
    
      tasks:
        - name: Instalar o servidor web
          apt:
            name: "{{ web_package }}"
            state: present
          when: ansible_os_family == "Debian"
    
        - name: Configurar a porta de escuta
          lineinfile:
            path: /etc/nginx/nginx.conf
            regexp: 'listen'
            line: "listen {{ web_port }};"
          notify: Reiniciar o serviço nginx
    
        - name: Definir o diretório raiz
          file:
            path: "{{ web_root }}"
            state: directory
            owner: www-data
            group: www-data
            mode: '0755'
    
      handlers:
        - name: Reiniciar o serviço nginx
          service:
            name: nginx
            state: restarted
    
    • Explicação do Exemplo:
      • As variáveis web_package, web_port e web_root permitem modificar facilmente o comportamento do playbook sem precisar editar as tarefas.
      • Cada variável é utilizada na tarefa correspondente, facilitando a personalização do servidor web.
  6. Tabela de Referência para o Uso de Variáveis em Playbooks

    LocalDescriçãoExemplo
    varsVariáveis definidas diretamente no playbookvars: web_package: nginx
    inventoryDefinidas por host ou grupo no inventárioserver1 ansible_host=192.168.1.10 ...
    vars_filesImporta variáveis de um arquivo externovars_files: - vars/config.yml
    Linha de comandoVariáveis de alta prioridade-e "web_port=8080"

Resumo

O uso de variáveis permite que playbooks sejam dinâmicos e facilmente adaptáveis a diferentes configurações e ambientes. Declarar variáveis diretamente no playbook, no inventário ou em arquivos externos torna o gerenciamento de configurações mais flexível e organizado. A compreensão da precedência das variáveis também ajuda a evitar conflitos e definir corretamente os valores de execução.

Na próxima seção, vamos explorar o uso de loops e iterações, facilitando a execução de tarefas repetitivas e otimizando a configuração de múltiplos itens com uma única tarefa.


5. Loops e Iterações em Tarefas

Objetivo

Demonstrar como executar tarefas repetitivas usando loops no Ansible para otimizar a configuração de múltiplos itens com uma única tarefa.


Conteúdo

  1. Introdução aos Loops no Ansible

    Loops permitem que uma mesma tarefa seja executada repetidamente para uma lista de itens, o que é útil para configurações em lote, como instalação de pacotes, criação de múltiplos usuários ou configuração de arquivos em série. O Ansible oferece várias diretivas para loops, incluindo loop, with_items e with_dict, cada uma apropriada para tipos de dados específicos.

  2. Uso de loop para Listas Simples

    A diretiva loop é uma das maneiras mais flexíveis de iterar sobre listas. Ela permite repetir uma tarefa para cada item de uma lista, substituindo o item atual com a variável {{ item }}.

    Exemplo: Instalação de Múltiplos Pacotes Usando loop

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    tasks:
      - name: Instalar pacotes necessários
        apt:
          name: "{{ item }}"
          state: present
        loop:
          - nginx
          - git
          - curl
    
    • Explicação:
      • loop: Itera sobre a lista de pacotes (nginx, git, curl), instalando cada um.
      • {{ item }}: Referencia o item atual do loop, permitindo a execução repetida da tarefa para cada pacote.
  3. Usando with_items para Iteração sobre Listas

    A diretiva with_items é similar ao loop e permite a execução da tarefa para cada item de uma lista. Embora o loop tenha substituído muitos usos do with_items, este último ainda é útil para versões anteriores do Ansible.

    Exemplo: Configurar Vários Arquivos Usando with_items

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    tasks:
      - name: Configurar múltiplos arquivos
        copy:
          src: "/configuracoes/{{ item }}.conf"
          dest: "/etc/{{ item }}.conf"
        with_items:
          - app1
          - app2
          - app3
    
    • Explicação:
      • with_items: Itera sobre a lista (app1, app2, app3).
      • src e dest: Copiam arquivos específicos com base no valor atual de {{ item }}.
  4. Uso de Loops com Dicionários (with_dict)

    Em casos onde precisamos iterar sobre um conjunto de pares chave-valor, o Ansible oferece a diretiva with_dict, que facilita o gerenciamento de configurações complexas.

    Exemplo: Configuração de Usuários e Senhas Usando with_dict

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    tasks:
      - name: Criar usuários com senhas
        user:
          name: "{{ item.key }}"
          password: "{{ item.value }}"
          state: present
        with_dict:
          users:
            alice: "{{ 'senha1' | password_hash('sha512') }}"
            bob: "{{ 'senha2' | password_hash('sha512') }}"
    
    • Explicação:
      • with_dict: Itera sobre o dicionário users, onde alice e bob são chaves (nomes de usuário) e os valores são suas senhas criptografadas.
      • item.key e item.value: Referenciam o nome e a senha de cada usuário.
  5. Looping com Variáveis em Objetos Complexos

    É possível usar loops com listas complexas, iterando sobre propriedades específicas dos objetos.

    Exemplo: Configurar Vários Usuários com Permissões e Senhas

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    vars:
      usuarios:
        - nome: alice
          senha: "{{ 'senhaAlice' | password_hash('sha512') }}"
          shell: /bin/bash
        - nome: bob
          senha: "{{ 'senhaBob' | password_hash('sha512') }}"
          shell: /bin/zsh
    
    tasks:
      - name: Criar múltiplos usuários com configurações específicas
        user:
          name: "{{ item.nome }}"
          password: "{{ item.senha }}"
          shell: "{{ item.shell }}"
          state: present
        loop: "{{ usuarios }}"
    
    • Explicação:
      • loop: "{{ usuarios }}": Itera sobre a lista de usuarios.
      • Cada usuário tem um nome, senha, e shell definidos individualmente.
  6. Exemplo Prático: Instalação de Pacotes e Configuração de Múltiplos Serviços

    O exemplo abaixo mostra um playbook que instala pacotes, configura arquivos e cria usuários, usando loops para otimizar o processo.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    
    ---
    - name: Configuração Completa de Servidores
      hosts: all
      become: yes
    
      vars:
        pacotes_necessarios:
          - nginx
          - git
          - curl
    
        usuarios:
          - nome: carlos
            senha: "{{ 'senhaCarlos' | password_hash('sha512') }}"
            shell: /bin/bash
          - nome: debora
            senha: "{{ 'senhaDebora' | password_hash('sha512') }}"
            shell: /bin/zsh
    
      tasks:
        - name: Instalar pacotes essenciais
          apt:
            name: "{{ item }}"
            state: present
          loop: "{{ pacotes_necessarios }}"
          when: ansible_os_family == "Debian"
    
        - name: Configurar diretório de arquivos temporários
          file:
            path: "/tmp/{{ item }}"
            state: directory
          loop:
            - logs
            - backups
            - temp
    
        - name: Criar usuários com configurações personalizadas
          user:
            name: "{{ item.nome }}"
            password: "{{ item.senha }}"
            shell: "{{ item.shell }}"
            state: present
          loop: "{{ usuarios }}"
    
    • Explicação do Exemplo:
      • Pacotes: Instala pacotes essenciais, utilizando um loop com a lista pacotes_necessarios.
      • Diretórios: Configura três diretórios (logs, backups, temp) dentro de /tmp.
      • Usuários: Cria usuários personalizados com nome, senha criptografada e shell preferido.
  7. Tabela de Referência: Principais Opções de Loops no Ansible

    DiretivaFunçãoExemplo
    loopIteração simples sobre listas e variáveis complexasloop: "{{ lista_de_itens }}"
    with_itemsItera sobre listas de valoreswith_items: - item1 - item2
    with_dictItera sobre pares chave-valor em dicionárioswith_dict: dict_variavel
    item.keyAcessa a chave em um par chave-valor (with_dict)name: "{{ item.key }}"
    item.valueAcessa o valor em um par chave-valor (with_dict)password: "{{ item.value }}"

Resumo

O uso de loops no Ansible permite simplificar e otimizar o código, eliminando a necessidade de duplicação de tarefas para ações repetitivas. Com loop, with_items e with_dict, é possível realizar operações em massa, tornando a execução de playbooks mais eficiente e escalável.

Na próxima seção, vamos explorar o uso de filtros no Ansible para manipulação de variáveis, ajudando a adaptar e transformar dados diretamente no playbook.


6. Uso de Filtros para Manipulação de Variáveis

Objetivo

Explicar como usar filtros do Jinja2 para manipular e transformar dados em variáveis do Ansible, proporcionando mais flexibilidade e evitando erros comuns de formatação.


Conteúdo

  1. Introdução aos Filtros no Ansible

    No Ansible, os filtros Jinja2 são utilizados para modificar o valor de variáveis, aplicando transformações ou operações que ajustem os dados conforme necessário. Os filtros ajudam a padronizar valores, gerenciar strings e garantir que as variáveis atendam a determinados requisitos antes da execução da tarefa.

  2. Aplicação Básica de Filtros em Playbooks

    Filtros são aplicados a variáveis usando a sintaxe {{ variavel | filtro }}, onde filtro é o nome do filtro aplicado à variável.

    Exemplo de Filtros Básicos:

    • | lower: Converte uma string para letras minúsculas.
    • | upper: Converte uma string para letras maiúsculas.
    • | default: Define um valor padrão caso a variável não esteja definida.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    vars:
      nome_usuario: "Carlos"
      arquivo_log: ""
    
    tasks:
      - name: Criar diretório para o usuário em minúsculas
        file:
          path: "/home/{{ nome_usuario | lower }}"
          state: directory
    
      - name: Definir arquivo de log padrão se não especificado
        debug:
          msg: "Arquivo de log: {{ arquivo_log | default('/var/log/default.log') }}"
    
    • Explicação:
      • {{ nome_usuario | lower }}: Converte Carlos para carlos, criando o diretório /home/carlos.
      • {{ arquivo_log | default('/var/log/default.log') }}: Usa o valor padrão /var/log/default.log caso arquivo_log não esteja definido.
  3. Manipulação de Strings com Filtros

    Para operações com strings, os filtros podem realizar substituições, remoção de caracteres ou validações de formatação.

    Exemplo: Substituir e Remover Caracteres com replace e trim

    1
    2
    3
    4
    5
    6
    7
    8
    
    vars:
      nome_arquivo: "backup   "
      extensao: "txt"
    
    tasks:
      - name: Substituir extensão do arquivo
        debug:
          msg: "{{ nome_arquivo | trim }}.{{ extensao | replace('txt', 'log') }}"
    
    • Explicação:
      • trim: Remove espaços em branco extras na variável nome_arquivo.
      • replace('txt', 'log'): Substitui .txt por .log na variável extensao.
  4. Filtros Numéricos e Lógicos para Controle de Valores

    Filtros como int e round são úteis para manipular números. Eles podem converter strings numéricas em inteiros ou arredondar valores, facilitando cálculos e validações de requisitos.

    Exemplo de Uso de Filtros Numéricos:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    vars:
      cpu_requerida: "2.5"
      cpu_disponivel: 4
    
    tasks:
      - name: Verificar se a CPU disponível atende o requisito
        debug:
          msg: "CPU atende o requisito"
        when: cpu_disponivel >= (cpu_requerida | float | round(0, 'ceil'))
    
    • Explicação:
      • float: Converte cpu_requerida em um número decimal para comparação.
      • round(0, 'ceil'): Arredonda cpu_requerida para cima, garantindo que a comparação seja precisa.
  5. Filtros de Listas e Dicionários para Estruturas Complexas

    O Ansible também permite aplicar filtros a listas e dicionários, facilitando operações como ordenação e busca de elementos específicos.

    Exemplo de Ordenação e Busca em Listas:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    vars:
      usuarios:
        - "carlos"
        - "ana"
        - "beatriz"
        - "joao"
    
    tasks:
      - name: Exibir lista de usuários em ordem alfabética
        debug:
          msg: "{{ usuarios | sort }}"
    
    • Explicação:
      • sort: Ordena a lista de usuarios em ordem alfabética.
  6. Exemplo Prático de Uso de Filtros para Configuração Personalizada

    No exemplo abaixo, o playbook utiliza filtros para criar um diretório com o nome do usuário em letras minúsculas e definir uma configuração de log padrão.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    ---
    - name: Configuração do Servidor com Filtros
      hosts: all
      become: yes
    
      vars:
        usuario: "Carlos"
        porta: "8080"
        caminho_log: ""
    
      tasks:
        - name: Criar diretório do usuário em minúsculas
          file:
            path: "/home/{{ usuario | lower }}"
            state: directory
    
        - name: Configurar porta padrão
          lineinfile:
            path: /etc/myapp/config.cfg
            regexp: 'port='
            line: "port={{ porta | int }}"
    
        - name: Definir arquivo de log padrão se vazio
          debug:
            msg: "Caminho do log: {{ caminho_log | default('/var/log/myapp.log') }}"
    
    • Explicação do Exemplo:
      • usuario | lower: Garante que o diretório seja criado com o nome do usuário em minúsculas.
      • porta | int: Converte a porta para um número inteiro, assegurando que esteja no formato correto.
      • caminho_log | default('/var/log/myapp.log'): Define um caminho de log padrão se o valor estiver vazio.
  7. Tabela de Referência dos Filtros Comuns

    FiltroFunçãoExemplo
    lowerConverte string para minúsculas{{ nome | lower }}
    upperConverte string para maiúsculas{{ nome | upper }}
    defaultDefine um valor padrão{{ valor | default('padrão') }}
    replaceSubstitui valores na string{{ texto | replace('a', 'e') }}
    int / floatConverte para inteiro ou decimal{{ valor | int }}
    sortOrdena uma lista{{ lista | sort }}
    roundArredonda números{{ numero | round(0, 'ceil') }}
    trimRemove espaços em branco da string{{ texto | trim }}

Resumo

Filtros no Ansible fornecem uma forma eficiente de manipular variáveis, garantindo que os dados estejam no formato correto e que os playbooks sejam mais flexíveis e robustos. Com filtros como default, replace, sort, e int, é possível ajustar variáveis conforme a necessidade, evitando erros comuns de formatação e validação.

Na próxima seção, vamos explorar o uso de condicionais com when para executar tarefas apenas em condições específicas, tornando os playbooks ainda mais adaptáveis a diferentes cenários e ambientes.


7. Condicionais com when para Controle de Execução

Objetivo

Demonstrar como usar a diretiva when para controlar a execução condicional de tarefas no Ansible, permitindo uma maior adaptabilidade dos playbooks para diferentes cenários e ambientes.


Conteúdo

  1. Introdução ao Uso de Condicionais com when

    A diretiva when permite que uma tarefa seja executada somente se uma condição for verdadeira. Isso possibilita a criação de playbooks mais inteligentes, adaptando-os a diferentes sistemas operacionais, versões de software e ambientes. As condições são expressas em expressões Jinja2, que podem incluir comparações e combinações de variáveis.

    Exemplo Simples de Condição when:

    1
    2
    3
    4
    5
    6
    
    tasks:
      - name: Instalar Nginx em sistemas Debian
        apt:
          name: nginx
          state: present
        when: ansible_os_family == "Debian"
    
    • Explicação:
      • A tarefa de instalação do Nginx será executada apenas se o host pertencer à família de sistemas Debian.
  2. Usando Condicionais para Diferentes Sistemas Operacionais

    Condicionais são especialmente úteis ao criar playbooks para múltiplos sistemas operacionais. Abaixo, vemos um exemplo de instalação do Nginx que verifica o sistema operacional e adapta o módulo (apt para Debian e yum para Red Hat).

    Exemplo de Condicionais para Instalação em Diferentes Sistemas:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    tasks:
      - name: Instalar Nginx em Debian
        apt:
          name: nginx
          state: present
        when: ansible_os_family == "Debian"
    
      - name: Instalar Nginx em Red Hat
        yum:
          name: nginx
          state: present
        when: ansible_os_family == "RedHat"
    
    • Explicação:
      • A primeira tarefa é executada apenas em sistemas Debian, enquanto a segunda é executada apenas em sistemas Red Hat.
  3. Combinação de Condições Usando Operadores Lógicos

    Você pode combinar múltiplas condições usando operadores lógicos (and, or, not). Isso ajuda a especificar cenários mais complexos e a adaptar o comportamento do playbook a requisitos específicos.

    Exemplo: Condição Baseada em Sistema e Versão:

    1
    2
    3
    4
    5
    6
    
    tasks:
      - name: Instalar uma versão específica do MySQL em Debian 10
        apt:
          name: mysql-server
          state: present
        when: ansible_os_family == "Debian" and ansible_distribution_version == "10"
    
    • Explicação:
      • A tarefa é executada apenas em hosts Debian que estejam na versão 10.
  4. Uso de Variáveis e Filtros em Condicionais

    É possível utilizar variáveis e filtros para tornar as condições ainda mais dinâmicas, como verificar a presença de um valor específico antes de executar a tarefa.

    Exemplo: Executar Tarefa Somente se Variável Estiver Definida e em Maiúsculas

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    vars:
      nome_arquivo: ""
    
    tasks:
      - name: Criar arquivo se o nome estiver definido e em maiúsculas
        file:
          path: "/tmp/{{ nome_arquivo }}"
          state: touch
        when: nome_arquivo | default("") | upper == nome_arquivo
    
    • Explicação:
      • A tarefa será executada apenas se nome_arquivo estiver definido e em letras maiúsculas.
  5. Controle Condicional para Grupos e Tags de Hosts

    Além de variáveis e sistema operacional, as condições também podem ser aplicadas com base nos grupos ou tags definidas para os hosts, permitindo uma configuração ainda mais segmentada.

    Exemplo: Executar Tarefa Apenas em Servidores com a Tag webserver

    1
    2
    3
    4
    5
    
    tasks:
      - name: Atualizar pacotes em servidores web
        apt:
          upgrade: dist
        when: "'webserver' in group_names"
    
    • Explicação:
      • A tarefa será executada apenas se o host pertencer ao grupo webserver.
  6. Exemplo Prático de Controle Condicional no Playbook

    No exemplo a seguir, o playbook configura o Apache em diferentes distribuições Linux e ajusta o firewall apenas se o sistema suportar o ufw.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    ---
    - name: Configuração Condicional de Servidor Web
      hosts: webservers
      become: yes
    
      tasks:
        - name: Instalar Apache em Debian
          apt:
            name: apache2
            state: present
          when: ansible_os_family == "Debian"
    
        - name: Instalar Apache em Red Hat
          yum:
            name: httpd
            state: present
          when: ansible_os_family == "RedHat"
    
        - name: Configurar firewall se o UFW estiver disponível
          ufw:
            rule: allow
            name: "Apache"
          when: ansible_facts['pkg_mgr'] == "apt"
    
    • Explicação do Exemplo:
      • A primeira tarefa instala o Apache em Debian e a segunda, em Red Hat, utilizando módulos específicos.
      • A última tarefa configura o firewall ufw apenas em sistemas Debian, onde ufw é suportado.
  7. Tabela de Referência: Operadores e Sintaxe para when

    OperadorDescriçãoExemplo
    ==Igual aansible_os_family == "Debian"
    !=Diferente deansible_os_family != "RedHat"
    andTodas as condições devem ser verdadeirascondicao1 and condicao2
    orPelo menos uma condição deve ser verdadeiracondicao1 or condicao2
    notInverte a condiçãonot condicao
    inVerifica a existência em uma lista"'web' in group_names"

Resumo

As condicionais when no Ansible tornam os playbooks mais flexíveis e adaptáveis a diferentes cenários e ambientes. Usando when com operadores lógicos, variáveis e filtros, você pode controlar com precisão a execução de tarefas, garantindo que elas ocorram apenas em situações específicas.

Na próxima seção, exploraremos o uso de blocos (block) e tratamento de erros com rescue, facilitando o controle de execução e a recuperação de erros durante a execução dos playbooks.


8. Uso de Blocos (block) e Tratamento de Erros com rescue

Objetivo

Explicar como agrupar tarefas com block e gerenciar erros com rescue, criando um fluxo de execução que permite tratamento de falhas e recuperação de tarefas no Ansible.


Conteúdo

  1. Introdução ao Uso de Blocos (block)

    O Ansible permite agrupar tarefas em blocos (block), o que facilita a organização de tarefas e o controle de execuções específicas. Com block, você pode aplicar condicionais e permissões a um grupo inteiro de tarefas, simplificando a estrutura do playbook. Além disso, block permite definir ações de rescue (para quando ocorre um erro) e always (executado sempre, independentemente de erros).

    Exemplo Básico de block:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    tasks:
      - block:
          - name: Instalar pacotes necessários
            apt:
              name: "{{ item }}"
              state: present
            loop:
              - nginx
              - git
        when: ansible_os_family == "Debian"
    
    • Explicação:
      • O bloco é executado apenas se a condição ansible_os_family == "Debian" for verdadeira, aplicando a condição a todas as tarefas internas.
  2. Tratamento de Erros com rescue

    O rescue é um bloco que define tarefas a serem executadas quando ocorre um erro em alguma das tarefas do block. Isso é útil para tentar outras alternativas ou realizar ações corretivas em caso de falha.

    Exemplo de Uso de rescue para Alternativa de Instalação

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    tasks:
      - block:
          - name: Tentar instalar o pacote do repositório oficial
            apt:
              name: nginx
              state: present
        rescue:
          - name: Tentar instalação manual
            command: wget -q -O- http://nginx.org/keys/nginx_signing.key | apt-key add -
    
    • Explicação:
      • Se a instalação do nginx falhar, o bloco rescue tenta instalar o pacote a partir de uma chave externa.
  3. Execução Incondicional com always

    O always define tarefas que devem ser executadas independentemente do sucesso ou falha das tarefas anteriores. Ele é útil para tarefas de limpeza, envio de logs ou notificações.

    Exemplo de Uso de always para Limpeza Após Tentativas

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    tasks:
      - block:
          - name: Instalar pacotes críticos
            apt:
              name: "{{ item }}"
              state: present
            loop:
              - apache2
              - mysql-server
        rescue:
          - name: Registrar falha de instalação
            debug:
              msg: "Falha na instalação dos pacotes críticos"
        always:
          - name: Limpar cache de pacotes
            command: apt-get clean
    
    • Explicação:
      • Se a instalação falhar, a tarefa de rescue registra a falha.
      • Independente do resultado, always limpa o cache de pacotes.
  4. Exemplo Prático de Uso de block, rescue e always para Recuperação de Erros

    O exemplo abaixo configura um servidor web e tenta corrigir a instalação caso ela falhe, registrando o status final no final.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    
    ---
    - name: Configuração Completa do Servidor Web com Tratamento de Erros
      hosts: webservers
      become: yes
    
      tasks:
        - block:
            - name: Instalar Nginx
              apt:
                name: nginx
                state: present
    
            - name: Copiar configuração do Nginx
              copy:
                src: /local/path/nginx.conf
                dest: /etc/nginx/nginx.conf
              notify: Reiniciar Nginx
    
          rescue:
            - name: Tentar outra versão do Nginx
              apt:
                name: nginx=1.18.*
                state: present
            - name: Registrar falha na instalação padrão
              debug:
                msg: "Instalação padrão do Nginx falhou, tentando versão alternativa."
    
          always:
            - name: Verificar status do Nginx
              service:
                name: nginx
                state: started
    
        handlers:
          - name: Reiniciar Nginx
            service:
              name: nginx
              state: restarted
    
    • Explicação do Exemplo:
      • O bloco block executa a instalação e configuração do Nginx.
      • Se a instalação falhar, o rescue tenta instalar uma versão alternativa e registra a tentativa.
      • O always garante que o serviço Nginx seja iniciado após a execução das tarefas.
  5. Tabela de Referência dos Elementos de Controle em Blocos

    ElementoFunçãoExemplo
    blockAgrupa tarefas e aplica condições a todas elas- block: - name: Instalar ...
    rescueExecuta tarefas alternativas se houver erro nas tarefas do blockrescue: - name: Tentar alternativa ...
    alwaysExecuta tarefas independentemente do sucesso ou falhaalways: - name: Limpar cache

Resumo

Com block, rescue, e always, você pode organizar tarefas e definir fluxos alternativos para recuperação de erros, garantindo que seu playbook seja resiliente e adaptável a diferentes condições e falhas. Essas funcionalidades permitem maior controle sobre o fluxo de execução e são essenciais para a robustez de playbooks em ambientes complexos.

Na próxima seção, veremos como modularizar tarefas usando include e import_tasks, facilitando a organização de playbooks maiores e a reutilização de tarefas em diferentes cenários.


9. Uso de Arquivos Include e Modularização com import_tasks

Objetivo

Demonstrar como modularizar tarefas com include e import_tasks no Ansible, organizando tarefas em arquivos separados e facilitando a reutilização em playbooks complexos.


Conteúdo

  1. Por que Modularizar Tarefas?

    Em playbooks complexos, modularizar tarefas melhora a legibilidade, facilita a manutenção e permite reutilizar tarefas em diferentes cenários. Com include e import_tasks, é possível separar funcionalidades específicas em arquivos distintos, que podem ser incluídos ou importados conforme necessário no playbook principal.

  2. Diferença entre include_tasks e import_tasks

    • include_tasks: Inclui tarefas dinamicamente durante a execução, permitindo controle condicional (when) ou uso de loops. A inclusão é processada em tempo de execução.
    • import_tasks: Importa tarefas de forma estática e imediata, semelhante a copiar o conteúdo do arquivo para o playbook no momento da execução.

    Resumo:

    • include_tasks é processado durante a execução e permite condições dinâmicas.
    • import_tasks é processado no início e não permite ajustes dinâmicos durante a execução.
  3. Exemplo de Uso de include_tasks com Condicional

    Estrutura de Arquivos:

    1
    2
    3
    4
    
    ├── playbook.yml
    ├── tasks/
    │   ├── instalar_apache.yml
    │   └── instalar_nginx.yml
    
    • instalar_apache.yml:

      1
      2
      3
      4
      
      - name: Instalar Apache
        apt:
          name: apache2
          state: present
      
    • instalar_nginx.yml:

      1
      2
      3
      4
      
      - name: Instalar Nginx
        apt:
          name: nginx
          state: present
      
    • Playbook principal (playbook.yml):

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
      ---
      - name: Configuração Condicional do Servidor Web
        hosts: webservers
        become: yes
      
        tasks:
          - name: Incluir tarefas para Apache
            include_tasks: tasks/instalar_apache.yml
            when: ansible_os_family == "Debian" and web_server == "apache"
      
          - name: Incluir tarefas para Nginx
            include_tasks: tasks/instalar_nginx.yml
            when: ansible_os_family == "Debian" and web_server == "nginx"
      
    • Explicação:

      • As tarefas de instalação do Apache e Nginx foram movidas para arquivos distintos na pasta tasks.
      • O playbook principal inclui cada arquivo de tarefa com include_tasks, condicionado à variável web_server, permitindo a escolha dinâmica entre Apache e Nginx.
  4. Uso de import_tasks para Importação Estática

    Estrutura de Arquivos:

    1
    2
    3
    4
    
    ├── playbook.yml
    ├── tasks/
    │   ├── config_apache.yml
    │   └── config_nginx.yml
    
    • config_apache.yml:

      1
      2
      3
      4
      
      - name: Configurar Apache
        lineinfile:
          path: /etc/apache2/apache2.conf
          line: "Timeout 300"
      
    • config_nginx.yml:

      1
      2
      3
      4
      
      - name: Configurar Nginx
        lineinfile:
          path: /etc/nginx/nginx.conf
          line: "keepalive_timeout 65"
      
    • Playbook principal (playbook.yml):

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      ---
      - name: Importar Configuração do Servidor Web
        hosts: webservers
        become: yes
      
        tasks:
          - import_tasks: tasks/config_apache.yml
            when: web_server == "apache"
      
          - import_tasks: tasks/config_nginx.yml
            when: web_server == "nginx"
      
    • Explicação:

      • import_tasks carrega as tarefas de configuração para Apache ou Nginx de forma estática.
      • A execução condicional com when define qual configuração será aplicada.
  5. Organização Modular para Estruturas Complexas

    Modularizar tarefas torna playbooks complexos mais gerenciáveis. Uma estrutura de diretórios bem organizada pode ajudar a manter o projeto limpo e intuitivo.

    Exemplo de Estrutura Modular:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    ├── site.yml                   # Playbook principal
    ├── webservers.yml              # Playbook para servidores web
    ├── dbservers.yml               # Playbook para servidores de banco de dados
    ├── tasks/
    │   ├── install/
    │   │   ├── apache.yml
    │   │   └── nginx.yml
    │   ├── config/
    │   │   ├── apache_config.yml
    │   │   └── nginx_config.yml
    └── handlers/
        └── restart_services.yml    # Handlers centralizados para reiniciar serviços
    
    • Explicação:
      • Arquivos de instalação (install/) e configuração (config/) são organizados por tipo de serviço.
      • handlers/restart_services.yml contém handlers centralizados para reiniciar serviços, reutilizáveis em diferentes playbooks.
  6. Exemplo Completo de Modularização com include_tasks e import_tasks

    O exemplo a seguir usa include_tasks para incluir uma tarefa de instalação e import_tasks para aplicar uma configuração específica, com um handler centralizado para reiniciar o serviço.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    ---
    - name: Configuração Modular do Servidor Web
      hosts: webservers
      become: yes
    
      tasks:
        - name: Incluir instalação de Apache ou Nginx
          include_tasks: "tasks/install/{{ web_server }}.yml"
          when: ansible_os_family == "Debian"
    
        - name: Importar configuração de Apache ou Nginx
          import_tasks: "tasks/config/{{ web_server }}_config.yml"
          when: ansible_os_family == "Debian"
    
      handlers:
        - import_tasks: handlers/restart_services.yml
    
    • Explicação:
      • A tarefa include_tasks inclui dinamicamente o arquivo de instalação de acordo com o valor da variável web_server.
      • A tarefa import_tasks carrega a configuração para o servidor web especificado.
      • Handlers são centralizados e importados de restart_services.yml, mantendo o playbook principal mais limpo.
  7. Tabela de Referência para Modularização com include_tasks e import_tasks

    DiretivaDescriçãoExemplo de Uso
    include_tasksInclui tarefas dinamicamente, permitindo condicionais e loopsinclude_tasks: tasks/config_nginx.yml
    import_tasksImporta tarefas estaticamente, sem ajustes dinâmicos durante execuçãoimport_tasks: tasks/install_nginx.yml
    HandlersPode ser centralizado e incluído para múltiplos playbooks- import_tasks: handlers/restart_services.yml

Resumo

O uso de include_tasks e import_tasks permite modularizar playbooks no Ansible, criando uma estrutura organizada, legível e fácil de manter. Com essa abordagem, é possível dividir tarefas complexas em arquivos menores, reutilizar componentes e tornar o gerenciamento de grandes ambientes mais eficiente.

Na próxima seção, vamos explorar o uso de roles, uma funcionalidade avançada para organizar playbooks em componentes reutilizáveis e modularizados.


10. Estrutura e Uso de Roles em Playbooks

Objetivo

Explicar como organizar e reutilizar configurações complexas com roles, permitindo que playbooks sejam mais modulares e reutilizáveis.


Conteúdo

  1. Introdução às Roles

    Roles são componentes modulares e reutilizáveis no Ansible, usadas para organizar tarefas, variáveis, handlers, templates e arquivos necessários para configurar uma aplicação ou serviço específico. As roles facilitam a manutenção e permitem compartilhar configurações em múltiplos playbooks ou ambientes.

    Principais Características das Roles:

    • Estrutura organizada que separa tarefas, handlers, arquivos, templates e variáveis.
    • Reutilizáveis em diferentes projetos, ambientes e playbooks.
    • Facilitam a colaboração e o compartilhamento de configurações.
  2. Estrutura de Diretórios de uma Role

    A estrutura padrão de uma role é organizada em diretórios específicos, onde cada um possui uma função bem definida. Ao criar uma role, o Ansible organiza automaticamente os diretórios da seguinte forma:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    └── nome_da_role/
        ├── defaults/           # Variáveis padrão
        │   └── main.yml
        ├── files/              # Arquivos estáticos
        ├── handlers/           # Handlers para notificações
        │   └── main.yml
        ├── meta/               # Metadados da role (dependências)
        │   └── main.yml
        ├── tasks/              # Tarefas principais
        │   └── main.yml
        ├── templates/          # Templates (arquivos Jinja2)
        ├── vars/               # Variáveis personalizadas
        │   └── main.yml
        └── README.md           # Documentação da role
    
    • defaults: Define variáveis padrão, que podem ser sobrescritas.
    • files: Contém arquivos a serem copiados para os hosts.
    • handlers: Define handlers que podem ser chamados por tarefas.
    • meta: Contém metadados, como dependências de outras roles.
    • tasks: Diretório onde as tarefas principais são definidas (arquivo main.yml).
    • templates: Armazena templates Jinja2.
    • vars: Define variáveis específicas da role, com maior precedência que defaults.
  3. Criando uma Role com o Comando ansible-galaxy

    O Ansible facilita a criação de roles com o comando ansible-galaxy init, que gera automaticamente a estrutura de diretórios necessária.

    Comando para Criar uma Role:

    1
    
    ansible-galaxy init nome_da_role
    

    Exemplo:

    1
    
    ansible-galaxy init apache
    
    • Isso criará uma pasta apache com toda a estrutura padrão para a role de configuração do Apache.
  4. Configurando Tarefas e Variáveis em uma Role

    Para definir as tarefas e variáveis principais de uma role, você deve configurar os arquivos no diretório tasks e vars.

    Exemplo de Role para Configuração do Apache:

    • tasks/main.yml:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
      ---
      - name: Instalar o Apache
        apt:
          name: apache2
          state: present
        notify: Reiniciar Apache
      
      - name: Copiar arquivo de configuração do Apache
        template:
          src: apache2.conf.j2
          dest: /etc/apache2/apache2.conf
        notify: Reiniciar Apache
      
    • handlers/main.yml:

      1
      2
      3
      4
      5
      
      ---
      - name: Reiniciar Apache
        service:
          name: apache2
          state: restarted
      
    • templates/apache2.conf.j2:

      1
      2
      
      # Configuração do Apache
      ServerName {{ ansible_hostname }}
      
    • defaults/main.yml:

      1
      2
      
      ---
      apache_port: 80
      
    • Explicação:

      • As tarefas instalam o Apache e copiam o arquivo de configuração personalizado.
      • Um template apache2.conf.j2 usa a variável ansible_hostname para definir o ServerName.
      • Um handler reinicia o Apache quando notificado após mudanças.
  5. Usando Roles em Playbooks

    Uma vez criada, a role pode ser incluída em qualquer playbook com a diretiva roles. Isso permite aplicar a role aos hosts definidos no playbook de maneira simples.

    Exemplo de Playbook Usando a Role apache:

    1
    2
    3
    4
    5
    6
    
    ---
    - name: Configuração de Servidores Web
      hosts: webservers
      become: yes
      roles:
        - apache
    
    • Explicação:
      • O playbook aplica a role apache em todos os hosts do grupo webservers.
  6. Usando Dependências de Roles com meta/main.yml

    No arquivo meta/main.yml da role, você pode definir dependências de outras roles, fazendo com que o Ansible carregue automaticamente roles adicionais conforme necessário.

    Exemplo de Dependências em meta/main.yml:

    1
    2
    3
    4
    5
    6
    7
    
    ---
    dependencies:
      - role: firewall
        vars:
          firewall_ports:
            - "80"
            - "443"
    
    • Explicação:
      • Define que a role firewall deve ser aplicada antes da role atual, com a configuração de variáveis adicionais.
  7. Exemplo Completo de Uso de Roles para Configuração de Servidores Web

    Este exemplo mostra um playbook que usa duas roles, apache e firewall, para configurar um servidor web seguro.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    
    ---
    - name: Configuração Completa do Servidor Web
      hosts: webservers
      become: yes
    
      roles:
        - role: apache
        - role: firewall
          vars:
            firewall_ports:
              - "80"
              - "443"
    
    • Explicação:
      • A role apache instala e configura o Apache.
      • A role firewall abre as portas 80 e 443, garantindo que o servidor esteja acessível.
  8. Tabela de Referência para Estrutura de Roles

    DiretórioFunçãoExemplo de Conteúdo
    tasksDefine as tarefas principais da roletasks/main.yml
    handlersDefine handlers para notificaçõeshandlers/main.yml
    varsVariáveis específicas da rolevars/main.yml
    defaultsVariáveis padrão, substituíveisdefaults/main.yml
    filesArmazena arquivos estáticosfiles/index.html
    templatesArmazena templates Jinja2 para personalização dinâmicatemplates/apache2.conf.j2
    metaDefine metadados e dependênciasmeta/main.yml

Resumo

Roles são uma das melhores práticas para organizar e reutilizar configurações no Ansible. Com uma estrutura organizada de diretórios, roles permitem encapsular a lógica de configuração de serviços específicos e compartilhar essas configurações em múltiplos playbooks e ambientes.

Na próxima seção, abordaremos práticas de segurança em playbooks, garantindo a proteção de senhas, credenciais e informações sensíveis com o uso do vault do Ansible e outras práticas recomendadas.


11. Segurança em Playbooks

Objetivo

Apresentar práticas recomendadas de segurança para proteger informações sensíveis em playbooks, como senhas, chaves SSH e variáveis críticas. Isso inclui o uso de Ansible Vault e outras técnicas para proteger dados em ambientes de produção.


Conteúdo

  1. Introdução à Segurança em Playbooks

    Segurança é essencial no uso de playbooks, especialmente quando incluem informações sensíveis como senhas, chaves API e credenciais. O Ansible fornece o Ansible Vault para criptografar dados críticos e manter a segurança em playbooks compartilhados entre equipes ou armazenados em repositórios.

  2. Protegendo Informações com Ansible Vault

    O Ansible Vault é uma ferramenta integrada ao Ansible que permite criptografar arquivos e variáveis, garantindo que dados sensíveis fiquem protegidos. É possível usá-lo para proteger variáveis, arquivos de configuração e até playbooks inteiros.

    Comando para Criar um Arquivo Criptografado com Vault:

    1
    
    ansible-vault create secrets.yml
    

    Esse comando abre um editor de texto para você inserir variáveis e outros dados sensíveis. Ao salvar e fechar o editor, o conteúdo será criptografado.

    Exemplo de Variáveis em secrets.yml:

    1
    2
    
    db_password: super_secreta123
    api_key: abcd1234apikey
    
  3. Editando e Exibindo Arquivos Criptografados com Vault

    • Editar: Para modificar um arquivo criptografado, use o comando:

      1
      
      ansible-vault edit secrets.yml
      
    • Exibir: Para visualizar o conteúdo de um arquivo criptografado, use:

      1
      
      ansible-vault view secrets.yml
      
  4. Usando Arquivos Criptografados em Playbooks

    Uma vez criado o arquivo criptografado, você pode incluí-lo diretamente no playbook usando vars_files. Ao executar o playbook, forneça a senha do Vault para descriptografar as variáveis.

    Exemplo de Playbook com vars_files Criptografado:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    ---
    - name: Configuração do Banco de Dados com Segurança
      hosts: dbservers
      become: yes
      vars_files:
        - secrets.yml
    
      tasks:
        - name: Configurar o banco de dados
          mysql_user:
            name: appuser
            password: "{{ db_password }}"
            state: present
    

    Executando o Playbook com Vault:

    1
    
    ansible-playbook playbook.yml --ask-vault-pass
    
    • Explicação:
      • --ask-vault-pass: Solicita a senha para descriptografar secrets.yml durante a execução.
  5. Recriptografando e Alterando a Senha do Vault

    Para recriptografar um arquivo com uma nova senha, use o comando rekey:

    1
    
    ansible-vault rekey secrets.yml
    
  6. Uso de Variáveis Ambientais para Segurança Adicional

    Variáveis ambientais são outra forma de proteger dados sensíveis, especialmente em integrações de CI/CD onde a senha do Vault é configurada diretamente no ambiente, evitando exposição em scripts ou arquivos.

    Exemplo: Usar Variável de Ambiente para a Senha do Vault

    1
    
    export ANSIBLE_VAULT_PASSWORD_FILE=~/.vault_pass
    
    • Explicação:
      • ANSIBLE_VAULT_PASSWORD_FILE: Define um arquivo com a senha do Vault, evitando inserir a senha manualmente a cada execução.
  7. Práticas de Segurança no Uso de Chaves SSH e Credenciais

    Além do Vault, o Ansible oferece boas práticas para proteger o uso de chaves SSH e outras credenciais.

    • Armazene Chaves SSH em Diretórios Protegidos: As chaves privadas devem estar em diretórios com permissões restritas e não devem ser incluídas diretamente no playbook.
    • Use SSH Agent para Carregar Chaves: Carregar chaves SSH no ssh-agent evita que as credenciais fiquem expostas.
    • Evite Variáveis Sensíveis em group_vars e host_vars: Variáveis sensíveis devem ser mantidas em arquivos criptografados com Vault em vez de group_vars e host_vars.
  8. Exemplo Completo de Playbook com Vault e Boas Práticas de Segurança

    O exemplo a seguir mostra um playbook que configura o banco de dados e usa variáveis criptografadas para proteger a senha do banco.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    ---
    - name: Configuração Segura do Banco de Dados
      hosts: dbservers
      become: yes
      vars_files:
        - secrets.yml
    
      tasks:
        - name: Criar usuário de banco de dados
          mysql_user:
            name: dbuser
            password: "{{ db_password }}"
            priv: "*.*:ALL"
            state: present
    
        - name: Configurar parâmetros de segurança
          lineinfile:
            path: /etc/mysql/my.cnf
            regexp: '^bind-address'
            line: 'bind-address = 127.0.0.1'
          notify: Reiniciar MySQL
    
      handlers:
        - name: Reiniciar MySQL
          service:
            name: mysql
            state: restarted
    
    • Explicação:
      • A senha do usuário do banco (db_password) está armazenada no arquivo secrets.yml, criptografado com Vault.
      • Um handler reinicia o MySQL após a alteração da configuração.
  9. Tabela de Referência: Comandos do Ansible Vault

    ComandoDescriçãoExemplo
    ansible-vault createCria um novo arquivo criptografadoansible-vault create secrets.yml
    ansible-vault editEdita um arquivo criptografadoansible-vault edit secrets.yml
    ansible-vault viewExibe o conteúdo de um arquivo criptografadoansible-vault view secrets.yml
    ansible-vault encryptCriptografa um arquivo existenteansible-vault encrypt vars.yml
    ansible-vault decryptDescriptografa um arquivo existenteansible-vault decrypt vars.yml
    ansible-vault rekeyRecriptografa um arquivo com nova senhaansible-vault rekey secrets.yml

Resumo

Garantir a segurança em playbooks é essencial para proteger dados críticos, especialmente em ambientes de produção. O Ansible Vault fornece criptografia para variáveis e arquivos sensíveis, enquanto variáveis de ambiente e práticas seguras no uso de chaves SSH reforçam a proteção dos dados. Com essas práticas, é possível automatizar tarefas no Ansible com segurança, minimizando o risco de exposição de informações confidenciais.

Na próxima seção, vamos explorar ferramentas de debugging e testes, incluindo ansible-lint e molecule, que ajudam a verificar a qualidade e a funcionalidade dos playbooks antes da execução em ambientes de produção.


12. Ferramentas de Debugging e Testes

Objetivo

Apresentar ferramentas para verificação, validação e testes de playbooks no Ansible, permitindo identificar problemas e garantir que os playbooks atendam às melhores práticas e funcionem corretamente em ambientes de produção.


Conteúdo

  1. Introdução à Importância do Debugging e Testes

    Debugging e testes são etapas fundamentais para garantir a qualidade dos playbooks. Eles permitem identificar erros de sintaxe, validação de variáveis e possíveis falhas de execução antes de aplicar o playbook em ambientes críticos. O Ansible oferece ferramentas como ansible-lint para verificar boas práticas e molecule para testar playbooks em ambientes simulados.

  2. Uso de ansible-lint para Verificação de Boas Práticas

    O ansible-lint é uma ferramenta que verifica os playbooks quanto ao uso de boas práticas e padronizações. Ele analisa o código em busca de problemas comuns, como falta de variáveis padronizadas, uso incorreto de módulos e configurações inseguras.

    Instalação do ansible-lint:

    1
    
    pip install ansible-lint
    

    Executando o ansible-lint em um Playbook:

    1
    
    ansible-lint playbook.yml
    
    • Explicação:
      • O comando examina o playbook playbook.yml e lista quaisquer erros ou avisos que violam as melhores práticas.
  3. Mensagens Comuns do ansible-lint e Correções

    Exemplo de Erros e Soluções Comuns:

    • Erro: “Use ‘state’ when installing a package.”
      • Causa: A ausência de state (como present) ao instalar um pacote.
      • Correção: Adicionar state: present ao módulo de instalação de pacotes.
    • Erro: “No ‘become’ statement in playbook with tasks requiring elevated privileges.”
      • Causa: Falta de become: yes em tarefas que requerem sudo.
      • Correção: Adicionar become: yes no play ou nas tarefas.
  4. Uso de Debugging em Playbooks com o Módulo debug

    O módulo debug é uma ferramenta útil para exibir valores de variáveis, confirmar saídas e validar informações em tempo de execução, facilitando a depuração e compreensão dos dados que estão sendo processados.

    Exemplo de Uso do Módulo debug:

    1
    2
    3
    4
    
    tasks:
      - name: Exibir valor da variável db_user
        debug:
          msg: "O usuário do banco de dados é: {{ db_user }}"
    
    • Explicação:
      • A tarefa exibe o valor da variável db_user no console durante a execução, permitindo validar seu conteúdo.
  5. Testes Automatizados de Playbooks com molecule

    O molecule é uma ferramenta avançada para testes de roles e playbooks, permitindo criar ambientes virtuais e testar playbooks em cenários simulados, como contêineres ou máquinas virtuais.

    Instalação do molecule:

    1
    
    pip install molecule[docker]
    

    Criando um Novo Teste com molecule init:

    1
    
    molecule init role nome_da_role
    

    Esse comando cria a estrutura de testes para a role, incluindo cenários de execução e arquivos de configuração de ambiente.

  6. Executando Testes de Role com molecule

    O molecule permite criar e destruir ambientes de teste, executar a role e verificar os resultados. A seguir, os comandos básicos para testar a execução da role em um ambiente simulado.

    Exemplo de Fluxo de Testes com molecule:

    • Criar o Ambiente de Teste:

      1
      
      molecule create
      
    • Aplicar a Role:

      1
      
      molecule converge
      
    • Executar Testes de Validação:

      1
      
      molecule verify
      
    • Destruir o Ambiente Após o Teste:

      1
      
      molecule destroy
      

    Explicação do Fluxo:

    • create: Prepara o ambiente de teste (como um contêiner Docker ou máquina virtual).
    • converge: Aplica a role no ambiente.
    • verify: Executa testes de validação (usualmente scripts de verificação).
    • destroy: Remove o ambiente após a execução dos testes.
  7. Integração com Testes Automatizados de CI/CD

    Integrar ansible-lint e molecule em pipelines de CI/CD ajuda a garantir que as modificações em playbooks ou roles sejam testadas e validadas antes de serem implementadas em produção.

    Exemplo de Pipeline de CI/CD Simples com Lint e Testes:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    stages:
      - lint
      - test
    
    lint:
      script:
        - ansible-lint playbook.yml
    
    test:
      script:
        - molecule test
    
    • Explicação:
      • A primeira etapa (lint) executa o ansible-lint para verificar as boas práticas.
      • A segunda etapa (test) executa os testes do molecule para validar a role.
  8. Exemplo Completo de um Playbook com debug e Testes

    O exemplo abaixo mostra um playbook com tarefas para configurar um banco de dados, usando debug para exibir o nome do banco de dados e uma configuração de molecule para testes da role.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    ---
    - name: Configuração do Banco de Dados com Debug
      hosts: dbservers
      become: yes
    
      vars:
        db_name: exemplo_db
        db_user: exemplo_user
    
      tasks:
        - name: Criar banco de dados
          mysql_db:
            name: "{{ db_name }}"
            state: present
    
        - name: Exibir nome do banco de dados
          debug:
            msg: "Banco de dados configurado: {{ db_name }}"
    

    Configuração de Teste com Molecule:

    1
    2
    3
    4
    5
    6
    7
    8
    
    # molecule/default/molecule.yml
    driver:
      name: docker
    
    platforms:
      - name: instance
        image: geerlingguy/docker-debian10-ansible
        pre_build_image: true
    
    • Explicação:
      • O playbook usa debug para exibir o nome do banco de dados configurado.
      • A configuração molecule.yml define uma plataforma Docker com Debian para teste.
  9. Tabela de Referência: Comandos de Debugging e Testes

    ComandoDescriçãoExemplo
    ansible-lintVerifica o playbook quanto a boas práticasansible-lint playbook.yml
    debugExibe informações de variáveis e mensagensdebug: msg: "Valor: {{ variavel }}"
    molecule createCria o ambiente de testemolecule create
    molecule convergeAplica a role no ambiente de testemolecule converge
    molecule verifyExecuta os testes de validaçãomolecule verify
    molecule destroyDestrói o ambiente de teste após a execuçãomolecule destroy

Resumo

Ferramentas de debugging e testes como ansible-lint e molecule ajudam a garantir a qualidade e segurança dos playbooks antes de sua execução em produção. Usar debug facilita o diagnóstico de variáveis, enquanto o molecule oferece um ambiente seguro para testar roles de forma completa. Com a integração dessas ferramentas em pipelines CI/CD, é possível automatizar a validação e manter a consistência dos playbooks.

Na próxima seção, vamos explorar a execução de playbooks com parâmetros avançados, como -i para inventário e --check para testes em modo de simulação, ajudando a otimizar a administração de playbooks em diferentes cenários.


13. Execução de Playbooks e Parâmetros Comuns

Objetivo

Explicar como executar playbooks com parâmetros comuns e opções avançadas, como inventários personalizados, execução simulada (--check) e níveis de verbosidade. Isso ajuda a otimizar a administração de playbooks em diferentes cenários e ambientes.


Conteúdo

  1. Execução Básica de Playbooks com ansible-playbook

    O comando ansible-playbook é utilizado para executar playbooks no Ansible. Sua sintaxe básica requer apenas o caminho do playbook a ser executado, mas ele possui uma série de parâmetros úteis para customizar a execução.

    Exemplo de Execução Básica:

    1
    
    ansible-playbook playbook.yml
    
  2. Especificando Inventários com -i

    O parâmetro -i permite especificar um inventário customizado para a execução. É útil quando você possui múltiplos ambientes ou diferentes grupos de hosts.

    Exemplo: Usando um Inventário Personalizado:

    1
    
    ansible-playbook playbook.yml -i inventarios/producao
    
    • Explicação: Define o inventário inventarios/producao para a execução, aplicando o playbook aos hosts especificados nesse arquivo.
  3. Execução com Usuários e Sudo (-u e -b)

    Os parâmetros -u e -b são usados para definir o usuário remoto e habilitar sudo, respectivamente.

    Exemplo: Executar com um Usuário Específico e Privilégios Elevados:

    1
    
    ansible-playbook playbook.yml -u deploy -b
    
    • Explicação: Executa o playbook com o usuário deploy e eleva os privilégios com sudo.
  4. Modo de Simulação com --check

    O parâmetro --check executa o playbook em modo de simulação, mostrando o que seria alterado sem fazer modificações. Esse modo é útil para testar a execução e verificar o impacto das mudanças.

    Exemplo de Execução em Modo de Simulação:

    1
    
    ansible-playbook playbook.yml --check
    
    • Explicação: Exibe as alterações que o playbook faria sem aplicá-las de fato, permitindo uma pré-visualização.
  5. Testando o Playbook com --syntax-check

    O parâmetro --syntax-check verifica a sintaxe do playbook, identificando erros de estrutura ou formatação.

    Exemplo: Verificar a Sintaxe de um Playbook:

    1
    
    ansible-playbook playbook.yml --syntax-check
    
    • Explicação: Realiza uma verificação de sintaxe para garantir que o playbook está corretamente estruturado antes da execução.
  6. Listando Hosts e Tarefas com --list-hosts e --list-tasks

    • --list-hosts: Exibe a lista de hosts onde o playbook será aplicado, sem executar as tarefas.
    • --list-tasks: Exibe a lista de tarefas que serão executadas, proporcionando uma visão geral do que o playbook fará.

    Exemplo de Uso:

    1
    2
    
    ansible-playbook playbook.yml --list-hosts
    ansible-playbook playbook.yml --list-tasks
    
  7. Modos Verbosos com -v, -vv, -vvv, -vvvv

    A opção -v aumenta a verbosidade, exibindo mais detalhes da execução. Com múltiplos v (de um a quatro), você pode controlar o nível de detalhe, sendo -vvvv o nível máximo, útil para diagnóstico completo.

    Exemplo de Execução com Verbosidade Máxima:

    1
    
    ansible-playbook playbook.yml -vvvv
    
    • Explicação: Exibe detalhes completos da execução, incluindo mensagens de depuração e comunicações com os hosts.
  8. Forçando Atualizações com --diff

    O parâmetro --diff mostra as mudanças específicas em arquivos de configuração, indicando exatamente quais linhas foram adicionadas, removidas ou alteradas. É especialmente útil para tarefas que envolvem templates ou alterações de arquivos.

    Exemplo: Visualizar Diferenças em Arquivos:

    1
    
    ansible-playbook playbook.yml --diff
    
    • Explicação: Exibe as diferenças antes de aplicar as mudanças, útil para verificar edições em arquivos de configuração.
  9. Exemplo Completo de Execução com Parâmetros Avançados

    O exemplo abaixo utiliza vários parâmetros para uma execução completa, que inclui inventário personalizado, usuário específico, sudo, verbosidade, simulação e controle de mudanças.

    1
    
    ansible-playbook playbook.yml -i inventarios/producao -u deploy -b --check -vv --diff
    
    • Explicação:
      • -i inventarios/producao: Usa o inventário de produção.
      • -u deploy -b: Executa com o usuário deploy e ativa sudo.
      • --check: Simula a execução sem aplicar mudanças.
      • -vv: Define o nível de verbosidade.
      • --diff: Mostra as diferenças que seriam aplicadas aos arquivos.
  10. Tabela de Referência para Parâmetros Comuns do ansible-playbook

ParâmetroFunçãoExemplo
-iDefine o inventário personalizado-i inventarios/producao
-uDefine o usuário remoto-u deploy
-bHabilita sudo para execução com privilégios elevados-b
--checkExecuta em modo de simulação--check
--syntax-checkVerifica a sintaxe do playbook--syntax-check
--list-hostsLista os hosts de execução sem executar--list-hosts
--list-tasksLista as tarefas do playbook sem executar--list-tasks
-v, -vv, -vvv, -vvvvDefine o nível de verbosidade-vv
--diffExibe as mudanças de arquivos--diff

Resumo

Com esses parâmetros, você pode executar playbooks de forma flexível e adaptada a diferentes cenários, desde execução simulada para validação de mudanças até análise detalhada de execução com níveis de verbosidade. Isso permite maior controle e visibilidade sobre a administração de sistemas, otimizando o uso de playbooks em ambientes variados.

Na próxima seção, vamos explorar boas práticas para organização e manutenção de playbooks, proporcionando uma estrutura mais eficiente e fácil de gerenciar para operações em ambientes complexos.


14. Boas Práticas para Organização e Manutenção de Playbooks

Objetivo

Fornecer um conjunto de boas práticas para organizar e manter playbooks Ansible, visando facilitar a administração, segurança e reutilização de configurações em ambientes complexos.


Conteúdo

  1. Estrutura de Diretórios para Playbooks

    Manter uma estrutura de diretórios organizada facilita a navegação e o entendimento do projeto. Em ambientes com múltiplos playbooks, roles e inventários, uma estrutura bem definida é essencial.

    Exemplo de Estrutura de Diretórios:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    ├── playbooks/
    │   ├── site.yml              # Playbook principal
    │   ├── webservers.yml         # Playbook específico para servidores web
    │   ├── dbservers.yml          # Playbook para servidores de banco de dados
    ├── inventories/
    │   ├── production/
    │   │   ├── hosts              # Inventário de produção
    │   │   └── group_vars/        # Variáveis por grupo de produção
    │   └── staging/
    │       ├── hosts              # Inventário de staging
    │       └── group_vars/        # Variáveis por grupo de staging
    ├── roles/
    │   ├── apache/                # Role para configurar Apache
    │   └── mysql/                 # Role para configurar MySQL
    ├── group_vars/
    │   └── all.yml                # Variáveis comuns a todos os grupos
    ├── host_vars/
    │   └── db1.yml                # Variáveis específicas do host db1
    └── files/                     # Arquivos estáticos (ex.: templates, configs)
    
    • Explicação: Cada componente tem seu próprio diretório (playbooks, inventories, roles), facilitando o gerenciamento e a escalabilidade do projeto.
  2. Documentação de Playbooks e Tarefas

    Cada playbook deve ter uma documentação clara, incluindo comentários que descrevam o propósito de cada play e tarefa. Isso é importante para facilitar o entendimento e a manutenção, especialmente em equipes.

    • Exemplo de Comentários no Playbook:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      ---
      - name: Configuração de Servidor Web
        hosts: webservers
        become: yes
        tasks:
          - name: Instalar o Apache
            apt:
              name: apache2
              state: present
            # Este handler será chamado se o Apache precisar ser reiniciado.
            notify: Reiniciar Apache
      
  3. Nomeação Descritiva de Variáveis e Tarefas

    Nomes descritivos para variáveis e tarefas ajudam a identificar facilmente o objetivo de cada ação no playbook, reduzindo a chance de erro e melhorando a legibilidade.

    Exemplo de Variáveis com Nome Descritivo:

    1
    2
    3
    
    vars:
      apache_package_name: apache2
      apache_config_file: /etc/apache2/apache2.conf
    
  4. Uso de Roles para Reutilização e Modularidade

    Sempre que possível, modularize funcionalidades em roles. Isso permite a reutilização de configurações e tarefas, além de facilitar a aplicação de configurações semelhantes em diferentes ambientes e playbooks.

    • Exemplo de Inclusão de Role em um Playbook:

      1
      2
      3
      4
      5
      6
      7
      
      ---
      - name: Configuração Completa do Servidor
        hosts: all
        become: yes
        roles:
          - apache
          - mysql
      
  5. Isolamento de Variáveis Sensíveis com Ansible Vault

    Armazene variáveis sensíveis, como senhas e chaves API, em arquivos criptografados com Ansible Vault. Evite incluir informações confidenciais diretamente em arquivos de inventário ou playbooks.

    Exemplo de Configuração com vars_files Criptografado:

    1
    2
    
    vars_files:
      - vault.yml
    
  6. Validação Regular com ansible-lint e molecule

    Integrar ansible-lint e molecule ao processo de desenvolvimento ajuda a garantir que os playbooks estão em conformidade com as boas práticas e que as roles são testadas em ambientes controlados antes da execução em produção.

  7. Automação de Execuções com Pipelines CI/CD

    Configurar um pipeline de CI/CD permite executar playbooks automaticamente em ambientes de teste ou produção, além de aplicar verificações automáticas de sintaxe, segurança e testes funcionais.

    Exemplo de Pipeline Básico com ansible-lint e molecule:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    stages:
      - lint
      - test
    
    lint:
      script:
        - ansible-lint playbook.yml
    
    test:
      script:
        - molecule test
    
  8. Exemplo Completo de Playbook com Boas Práticas

    O exemplo abaixo segue algumas das boas práticas abordadas, com estrutura organizada, nomes descritivos, documentação e modularização em roles.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    ---
    - name: Configuração Completa de Servidor Web
      hosts: webservers
      become: yes
      vars_files:
        - vault.yml  # Arquivo criptografado com variáveis sensíveis
    
      roles:
        - apache
        - firewall
    
      tasks:
        - name: Exibir a configuração atual do Apache
          debug:
            msg: "Apache configurado no servidor {{ ansible_hostname }}"
    
  9. Checklist de Boas Práticas para Manutenção de Playbooks

    • Estrutura de Diretórios: Separar playbooks, inventários e roles em diretórios específicos.
    • Documentação: Adicionar descrições em todos os playbooks, plays e tarefas.
    • Nomeação Descritiva: Nomear variáveis, playbooks e tarefas de forma clara e direta.
    • Uso de Roles: Modularizar configurações em roles reutilizáveis.
    • Segurança: Usar Ansible Vault para variáveis sensíveis.
    • Validação Contínua: Integrar ansible-lint e molecule ao fluxo de desenvolvimento.
    • Automação: Configurar pipelines CI/CD para deploy e validação automática de playbooks.

Resumo

Seguir boas práticas na organização e manutenção de playbooks Ansible torna os projetos mais seguros, modulares e fáceis de entender e atualizar. Com uma estrutura organizada, documentação adequada e integração com ferramentas de teste e CI/CD, os playbooks podem ser gerenciados de maneira eficiente e escalável em ambientes de produção complexos.

Na próxima seção, vamos concluir o tutorial com uma visão geral dos tópicos abordados e recomendações finais para o uso do Ansible em projetos de automação e gerenciamento de configurações.


Conclusão

Neste tutorial, exploramos uma ampla gama de funcionalidades e boas práticas para o uso de playbooks no Ansible, desde a criação de tarefas básicas até configurações avançadas de segurança, modularização e testes. Vamos resumir os principais pontos abordados e destacar as recomendações para otimizar o uso do Ansible em projetos de automação.


Resumo dos Tópicos Principais

  1. Introdução aos Playbooks:
    • Compreendemos o conceito de playbooks como uma maneira de definir tarefas de automação em YAML, com organização e controle em vários níveis.
  2. Estrutura e Sintaxe:
    • Detalhamos os principais elementos de um playbook, incluindo hosts, tasks, vars, handlers e a estrutura básica para definir fluxos de execução.
  3. Controle Avançado de Tarefas:
    • Vimos como utilizar when para execução condicional, block para agrupar tarefas e rescue para tratamento de erros, aumentando a robustez dos playbooks.
  4. Modularização com include_tasks, import_tasks e Roles:
    • Exploramos maneiras de modularizar e reutilizar tarefas, criando uma estrutura mais organizada e facilitando o gerenciamento de configurações complexas em ambientes variados.
  5. Segurança e Armazenamento de Variáveis Sensíveis:
    • O Ansible Vault se mostrou fundamental para proteger informações críticas, enquanto práticas como isolamento de chaves SSH e o uso de variáveis de ambiente aumentaram a segurança dos dados sensíveis.
  6. Ferramentas de Debugging e Testes:
    • Ferramentas como ansible-lint e molecule garantem a qualidade dos playbooks, permitindo identificar problemas antes da execução em produção.
  7. Execução de Playbooks e Parâmetros Avançados:
    • A execução de playbooks com parâmetros avançados, como --check para simulação e --diff para verificação de mudanças, permite um controle maior sobre o comportamento e impacto das execuções.
  8. Boas Práticas para Manutenção e Estruturação:
    • Discutimos uma série de boas práticas para garantir que os playbooks sejam modulares, seguros e fáceis de entender e manter, facilitando o trabalho em equipe e o escalonamento das configurações.

Recomendações Finais

  1. Organize e Modularize:
    • Estruturar playbooks em arquivos bem organizados, roles e módulos reutilizáveis é essencial para a escalabilidade e manutenção dos projetos.
  2. Use o Ansible Vault para Segurança:
    • Proteger variáveis sensíveis deve ser uma prioridade, especialmente em ambientes de produção.
  3. Valide e Teste Regularmente:
    • Integrar ferramentas de validação e teste contínuo, como ansible-lint e molecule, ao fluxo de trabalho ajuda a evitar erros e mantém a qualidade dos playbooks.
  4. Documente Cada Etapa:
    • Documentar o propósito de cada tarefa, variáveis e roles garante que os playbooks sejam claros para todos os membros da equipe, facilitando colaborações e futuras revisões.
  5. Automatize com CI/CD:
    • Um pipeline de CI/CD permite que alterações em playbooks sejam testadas automaticamente antes de serem aplicadas em produção, garantindo consistência e segurança em cada mudança.

Este guia completo sobre o uso de playbooks no Ansible oferece uma base sólida para criar, organizar e manter automações robustas e escaláveis em ambientes complexos. A adoção dessas práticas não só melhora a eficiência e a segurança, mas também contribui para uma infraestrutura mais resiliente e preparada para atender às demandas da equipe e dos sistemas que a sustentam.

Com essa compreensão, você está preparado para aproveitar o poder dos playbooks do Ansible e aplicá-los em seus projetos de automação e gestão de configurações. Boa sorte, e que seus playbooks sejam sempre executados com sucesso!

This post is licensed under CC BY 4.0 by the author.