Como configurar a opção gather_facts em um playbook Ansible

AnsibleBeginner
Pratique Agora

Introdução

Ansible é uma ferramenta poderosa de automação de TI que auxilia administradores de sistemas e desenvolvedores a gerenciar a infraestrutura de forma eficiente. Uma de suas principais características é a capacidade de coletar informações sobre os sistemas alvo, conhecidas como "fatos" (facts). A opção gather_facts no Ansible determina se e como essa informação é coletada durante a execução do playbook.

Neste laboratório prático, você aprenderá como configurar a opção gather_facts em playbooks Ansible. Você explorará diferentes configurações, entenderá quando habilitar ou desabilitar a coleta de fatos e descobrirá como usar os fatos coletados para tornar seus playbooks mais dinâmicos e eficientes. Ao final deste laboratório, você será capaz de otimizar seus fluxos de trabalho Ansible controlando o processo de coleta de fatos de acordo com suas necessidades específicas.

Instalando o Ansible e explorando a opção gather_facts

Vamos começar instalando o Ansible e explorando o que a opção gather_facts faz. Nesta etapa, instalaremos o Ansible, criaremos um inventário simples e executaremos um comando para ver quais fatos são coletados.

Instalando o Ansible

Primeiro, vamos instalar o Ansible em nosso sistema:

sudo apt update
sudo apt install -y ansible

Após a conclusão da instalação, verifique se o Ansible foi instalado corretamente:

ansible --version

Você deve ver uma saída semelhante a esta:

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, Aug 14 2022, 00:00:00) [GCC 11.2.0]
  jinja version = 3.0.3
  libyaml = True

Criando um inventário simples

Agora, vamos criar um arquivo de inventário simples para trabalhar. O arquivo de inventário define os hosts que o Ansible irá gerenciar. Para este laboratório, criaremos um inventário local:

mkdir -p ~/project/ansible
cd ~/project/ansible

Crie um arquivo de inventário chamado hosts usando o editor:

  1. Clique no ícone Explorer no WebIDE
  2. Navegue até o diretório /home/labex/project/ansible
  3. Clique com o botão direito e selecione "Novo Arquivo"
  4. Nomeie o arquivo hosts
  5. Adicione o seguinte conteúdo:
[local]
localhost ansible_connection=local

Este inventário configura um grupo chamado local com apenas um host - localhost. O parâmetro ansible_connection=local informa ao Ansible para executar comandos diretamente na máquina local sem usar SSH.

Explorando gather_facts

Vamos executar um comando Ansible simples para ver quais fatos são coletados por padrão:

cd ~/project/ansible
ansible local -i hosts -m setup

O comando acima usa:

  • local: o grupo do nosso inventário
  • -i hosts: especifica nosso arquivo de inventário
  • -m setup: executa o módulo setup, que coleta fatos

Você verá uma grande saída JSON com informações detalhadas sobre seu sistema, incluindo:

  • Informações de hardware (CPU, memória)
  • Configuração de rede
  • Detalhes do sistema operacional
  • Variáveis de ambiente
  • E muito mais

Esta informação é o que o Ansible coleta quando gather_facts está habilitado (que é o comportamento padrão). Esses fatos podem ser usados em playbooks para tomar decisões ou personalizar tarefas com base nas características do sistema alvo.

Criando um playbook básico com coleta de fatos padrão

Nesta etapa, criaremos um playbook Ansible básico que usa o comportamento padrão de coleta de fatos e exibe algumas das informações coletadas.

Entendendo playbooks Ansible

Um playbook Ansible é um arquivo YAML contendo uma lista de tarefas a serem executadas em hosts gerenciados. Playbooks fornecem uma maneira de definir configuração, implantação e etapas de orquestração em um formato simples e legível por humanos.

Criando seu primeiro playbook

Vamos criar um playbook simples que exibirá alguns dos fatos que o Ansible coleta por padrão:

  1. No WebIDE, navegue até o diretório /home/labex/project/ansible
  2. Crie um novo arquivo chamado facts_playbook.yml
  3. Adicione o seguinte conteúdo:
---
- name: Show System Facts
  hosts: local
  ## By default, gather_facts is set to 'true'

  tasks:
    - name: Display operating system
      debug:
        msg: "Operating System: {{ ansible_distribution }} {{ ansible_distribution_version }}"

    - name: Display CPU information
      debug:
        msg: "CPU: {{ ansible_processor[1] }} with {{ ansible_processor_cores }} cores"

    - name: Display memory information
      debug:
        msg: "Total Memory: {{ ansible_memtotal_mb }} MB"

    - name: Display Python version
      debug:
        msg: "Python version: {{ ansible_python_version }}"

Este playbook:

  • Destina-se ao grupo local definido em nosso inventário
  • Habilita implicitamente a coleta de fatos (comportamento padrão)
  • Contém quatro tarefas que exibem diferentes informações coletadas pelo Ansible

Executando o playbook

Agora, vamos executar o playbook para ver os fatos coletados em ação:

cd ~/project/ansible
ansible-playbook -i hosts facts_playbook.yml

Você deve ver uma saída semelhante a esta:

PLAY [Show System Facts] *****************************************************

TASK [Gathering Facts] *******************************************************
ok: [localhost]

TASK [Display operating system] **********************************************
ok: [localhost] => {
    "msg": "Operating System: Ubuntu 22.04"
}

TASK [Display CPU information] ***********************************************
ok: [localhost] => {
    "msg": "CPU: Intel(R) Xeon(R) CPU with 2 cores"
}

TASK [Display memory information] ********************************************
ok: [localhost] => {
    "msg": "Total Memory: 3907 MB"
}

TASK [Display Python version] ************************************************
ok: [localhost] => {
    "msg": "Python version: 3.10.6"
}

PLAY RECAP *******************************************************************
localhost                  : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Observe a primeira tarefa na saída: TASK [Gathering Facts]. Este é o Ansible coletando automaticamente fatos antes de executar qualquer uma de nossas tarefas definidas, porque o valor padrão de gather_facts é true.

O playbook então exibe com sucesso informações sobre seu sistema usando os fatos coletados. Cada fato é referenciado usando uma variável com o prefixo ansible_.

Desabilitando a coleta de fatos para melhorar o desempenho

Nesta etapa, aprenderemos como desabilitar a coleta de fatos para melhorar o desempenho do playbook em situações em que os fatos não são necessários.

Entendendo quando desabilitar a coleta de fatos

Embora a coleta de fatos seja útil, ela pode adicionar sobrecarga desnecessária em certos cenários:

  • Quando você está executando tarefas simples que não exigem informações do sistema
  • Quando você está executando playbooks com frequência e os fatos não mudam
  • Quando você deseja otimizar o tempo de execução do playbook

Desabilitar a coleta de fatos pode melhorar significativamente a velocidade de execução do playbook, especialmente ao gerenciar muitos hosts.

Criando um playbook com coleta de fatos desabilitada

Vamos criar um novo playbook que tenha a coleta de fatos desabilitada:

  1. No WebIDE, navegue até o diretório /home/labex/project/ansible
  2. Crie um novo arquivo chamado no_facts_playbook.yml
  3. Adicione o seguinte conteúdo:
---
- name: Playbook with Disabled Fact Gathering
  hosts: local
  gather_facts: false

  tasks:
    - name: Display current time
      command: date
      register: current_time

    - name: Show the current time
      debug:
        msg: "Current time is: {{ current_time.stdout }}"

    - name: List files in the project directory
      command: ls -la ~/project
      register: file_list

    - name: Show file list
      debug:
        msg: "Project directory contents:\n{{ file_list.stdout }}"

Este playbook:

  • Desabilita explicitamente a coleta de fatos com gather_facts: false
  • Executa comandos que não dependem de fatos do sistema
  • Usa a palavra-chave register para capturar as saídas dos comandos
  • Exibe as informações capturadas usando o módulo debug

Executando o playbook com coleta de fatos desabilitada

Vamos executar o playbook e observar as diferenças:

cd ~/project/ansible
ansible-playbook -i hosts no_facts_playbook.yml

Você deve ver uma saída semelhante a esta:

PLAY [Playbook with Disabled Fact Gathering] *********************************

TASK [Display current time] **************************************************
changed: [localhost]

TASK [Show the current time] *************************************************
ok: [localhost] => {
    "msg": "Current time is: Wed May 17 15:30:45 UTC 2023"
}

TASK [List files in the project directory] ***********************************
changed: [localhost]

TASK [Show file list] ********************************************************
ok: [localhost] => {
    "msg": "Project directory contents:\ntotal 20\ndrwxr-xr-x 3 labex labex 4096 May 17 15:25 .\ndrwxr-xr-x 4 labex labex 4096 May 17 15:20 ..\ndrwxr-xr-x 2 labex labex 4096 May 17 15:25 ansible\n"
}

PLAY RECAP *******************************************************************
localhost                  : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Observe que não há a tarefa Gathering Facts na saída desta vez. O playbook começa diretamente com nossa primeira tarefa definida.

Comparando tempos de execução

Para ver a diferença de desempenho, vamos criar um script de temporização simples:

  1. No WebIDE, navegue até o diretório /home/labex/project/ansible
  2. Crie um novo arquivo chamado compare_timing.sh
  3. Adicione o seguinte conteúdo:
#!/bin/bash

echo "Running playbook with fact gathering enabled..."
time ansible-playbook -i hosts facts_playbook.yml > /dev/null

echo -e "\nRunning playbook with fact gathering disabled..."
time ansible-playbook -i hosts no_facts_playbook.yml > /dev/null
  1. Torne o script executável:
chmod +x compare_timing.sh
  1. Execute o script de comparação:
./compare_timing.sh

Você deve ver a saída mostrando que o playbook com a coleta de fatos desabilitada é executado mais rápido do que aquele com a coleta de fatos habilitada. A diferença pode ser pequena em nosso exemplo simples, mas pode ser significativa ao executar playbooks complexos em vários hosts remotos.

Usando a coleta seletiva de fatos

Em alguns casos, você pode precisar apenas de fatos específicos em vez de todas as informações do sistema. O Ansible permite a coleta seletiva de fatos para otimizar o desempenho, mantendo a coleta das informações necessárias.

Entendendo subconjuntos de fatos

O Ansible organiza os fatos em subconjuntos, como:

  • all: Todos os fatos (padrão)
  • min / minimal: Um conjunto mínimo de fatos
  • hardware: CPU, memória e informações do dispositivo
  • network: Interface de rede e informações de roteamento
  • virtual: Detalhes de virtualização
  • ohai: Fatos do Ohai (se disponível)
  • facter: Fatos do Facter (se disponível)

Ao selecionar apenas os fatos de que você precisa, você pode melhorar o desempenho do playbook, ainda tendo acesso às informações necessárias.

Criando um playbook com coleta seletiva de fatos

Vamos criar um playbook que coleta apenas fatos relacionados ao hardware:

  1. No WebIDE, navegue até o diretório /home/labex/project/ansible
  2. Crie um novo arquivo chamado selective_facts_playbook.yml
  3. Adicione o seguinte conteúdo:
---
- name: Selective Fact Gathering
  hosts: local
  gather_facts: true
  gather_subset:
    - "!all" ## Exclude all facts by default
    - "hardware" ## Then include only hardware facts

  tasks:
    - name: Display CPU information
      debug:
        msg: "CPU: {{ ansible_processor[1] }} with {{ ansible_processor_cores }} cores"

    - name: Display memory information
      debug:
        msg: "Total Memory: {{ ansible_memtotal_mb }} MB"

    - name: Try to access network facts (should fail)
      debug:
        msg: "Default IPv4 Address: {{ ansible_default_ipv4.address }}"
      ignore_errors: true

Este playbook:

  • Habilita a coleta de fatos com gather_facts: true
  • Usa gather_subset para restringir quais fatos são coletados
  • Primeiro exclui todos os fatos com !all
  • Em seguida, inclui apenas fatos de hardware com hardware
  • Tenta acessar fatos de rede (que não foram coletados) para demonstrar a limitação

Executando o playbook com coleta seletiva de fatos

Vamos executar o playbook para ver a coleta seletiva de fatos em ação:

cd ~/project/ansible
ansible-playbook -i hosts selective_facts_playbook.yml

Você deve ver uma saída semelhante a esta:

PLAY [Selective Fact Gathering] **********************************************

TASK [Gathering Facts] *******************************************************
ok: [localhost]

TASK [Display CPU information] ***********************************************
ok: [localhost] => {
    "msg": "CPU: Intel(R) Xeon(R) CPU with 2 cores"
}

TASK [Display memory information] ********************************************
ok: [localhost] => {
    "msg": "Total Memory: 3907 MB"
}

TASK [Try to access network facts (should fail)] *****************************
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'address'..."}
...ignoring

PLAY RECAP *******************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1

Observe que as duas primeiras tarefas são bem-sucedidas porque acessam fatos de hardware que foram coletados, mas a terceira tarefa falha porque os fatos de rede não foram coletados. Usamos ignore_errors: true para continuar a execução do playbook, apesar desse erro.

Criando um playbook com múltiplos subconjuntos de fatos

Agora, vamos criar um playbook que coleta fatos de hardware e rede:

  1. No WebIDE, crie um novo arquivo chamado multiple_subsets_playbook.yml
  2. Adicione o seguinte conteúdo:
---
- name: Multiple Fact Subsets
  hosts: local
  gather_facts: true
  gather_subset:
    - "!all" ## Exclude all facts by default
    - "hardware" ## Include hardware facts
    - "network" ## Include network facts

  tasks:
    - name: Display CPU information
      debug:
        msg: "CPU: {{ ansible_processor[1] }} with {{ ansible_processor_cores }} cores"

    - name: Display memory information
      debug:
        msg: "Total Memory: {{ ansible_memtotal_mb }} MB"

    - name: Display network information
      debug:
        msg: "Default IPv4 Address: {{ ansible_default_ipv4.address }}"

Execute este playbook:

ansible-playbook -i hosts multiple_subsets_playbook.yml

Desta vez, todas as tarefas devem ser bem-sucedidas porque coletamos fatos de hardware e rede.

Usando fatos coletados em tarefas condicionais

Um dos usos mais poderosos dos fatos coletados é a implementação de lógica condicional em seus playbooks. Nesta etapa, criaremos um playbook que usa fatos para tomar decisões sobre quais tarefas executar.

Entendendo tarefas condicionais no Ansible

O Ansible permite que você use a palavra-chave when para executar tarefas condicionalmente com base em variáveis, fatos ou resultados de tarefas. Isso permite que você crie playbooks mais dinâmicos e adaptáveis.

Criando um playbook com tarefas condicionais

Vamos criar um playbook que realiza ações diferentes com base no sistema operacional:

  1. No WebIDE, navegue até o diretório /home/labex/project/ansible
  2. Crie um novo arquivo chamado conditional_facts_playbook.yml
  3. Adicione o seguinte conteúdo:
---
- name: Conditional Tasks Based on Facts
  hosts: local
  gather_facts: true

  tasks:
    - name: Display OS information
      debug:
        msg: "Running on {{ ansible_distribution }} {{ ansible_distribution_version }}"

    - name: Task for Ubuntu systems
      debug:
        msg: "This is an Ubuntu system. Would run apt commands here."
      when: ansible_distribution == "Ubuntu"

    - name: Task for CentOS systems
      debug:
        msg: "This is a CentOS system. Would run yum commands here."
      when: ansible_distribution == "CentOS"

    - name: Task for systems with at least 2GB RAM
      debug:
        msg: "This system has {{ ansible_memtotal_mb }} MB RAM, which is sufficient for our application."
      when: ansible_memtotal_mb >= 2048

    - name: Task for systems with less than 2GB RAM
      debug:
        msg: "This system has only {{ ansible_memtotal_mb }} MB RAM, which may not be sufficient."
      when: ansible_memtotal_mb < 2048

Este playbook:

  • Coleta todos os fatos sobre o sistema
  • Exibe as informações do sistema operacional
  • Executa tarefas condicionalmente com base no tipo de sistema operacional
  • Executa tarefas condicionalmente com base na quantidade de RAM

Executando o playbook condicional

Vamos executar o playbook para ver as tarefas condicionais em ação:

cd ~/project/ansible
ansible-playbook -i hosts conditional_facts_playbook.yml

Como estamos executando no Ubuntu, você deve ver uma saída semelhante a esta:

PLAY [Conditional Tasks Based on Facts] **************************************

TASK [Gathering Facts] *******************************************************
ok: [localhost]

TASK [Display OS information] ************************************************
ok: [localhost] => {
    "msg": "Running on Ubuntu 22.04"
}

TASK [Task for Ubuntu systems] ***********************************************
ok: [localhost] => {
    "msg": "This is an Ubuntu system. Would run apt commands here."
}

TASK [Task for CentOS systems] ***********************************************
skipping: [localhost]

TASK [Task for systems with at least 2GB RAM] ********************************
ok: [localhost] => {
    "msg": "This system has 3907 MB RAM, which is sufficient for our application."
}

TASK [Task for systems with less than 2GB RAM] *******************************
skipping: [localhost]

PLAY RECAP *******************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0

Observe como algumas tarefas são executadas enquanto outras são ignoradas com base nas condições. A tarefa do CentOS é ignorada porque estamos executando no Ubuntu, e a tarefa "menos de 2GB RAM" é ignorada porque nosso sistema tem mais de 2GB de RAM.

Criando um exemplo mais prático

Agora, vamos criar um exemplo mais prático que pode ser usado em um ambiente real:

  1. No WebIDE, crie um novo arquivo chamado practical_conditional_playbook.yml
  2. Adicione o seguinte conteúdo:
---
- name: Practical Conditional Playbook
  hosts: local
  gather_facts: true

  vars:
    app_dir: "/home/labex/project/app"

  tasks:
    - name: Create application directory
      file:
        path: "{{ app_dir }}"
        state: directory
        mode: "0755"

    - name: Configure for production environment
      copy:
        dest: "{{ app_dir }}/config.yml"
        content: |
          environment: production
          memory_limit: high
          debug: false
      when: ansible_memtotal_mb >= 4096

    - name: Configure for development environment
      copy:
        dest: "{{ app_dir }}/config.yml"
        content: |
          environment: development
          memory_limit: low
          debug: true
      when: ansible_memtotal_mb < 4096

    - name: Display configuration
      command: cat {{ app_dir }}/config.yml
      register: config_content

    - name: Show configuration
      debug:
        msg: "{{ config_content.stdout_lines }}"

Este playbook:

  • Cria um diretório para um aplicativo
  • Escreve um arquivo de configuração diferente com base na memória do sistema disponível
  • Exibe a configuração resultante

Execute o playbook prático:

ansible-playbook -i hosts practical_conditional_playbook.yml

Este exemplo demonstra como você pode usar fatos coletados para adaptar automaticamente as configurações com base nas características do sistema.

Resumo

Neste laboratório, você aprendeu como configurar e usar efetivamente a opção gather_facts em playbooks do Ansible. Aqui está um resumo do que você realizou:

  1. Coleta básica de fatos: Você instalou o Ansible e explorou o comportamento padrão de coleta de fatos, vendo a ampla gama de informações do sistema que o Ansible coleta.

  2. Desabilitando a coleta de fatos: Você aprendeu como desabilitar a coleta de fatos para melhorar o desempenho do playbook quando os fatos não são necessários.

  3. Coleta seletiva de fatos: Você descobriu como coletar apenas subconjuntos específicos de fatos para equilibrar desempenho e ter as informações necessárias.

  4. Tarefas condicionais: Você implementou lógica condicional em seus playbooks com base nos fatos coletados, permitindo um comportamento dinâmico dependendo das características do sistema.

  5. Aplicações práticas: Você criou exemplos práticos que demonstram como usar fatos coletados em cenários do mundo real.

Ao dominar a opção gather_facts, você pode otimizar seus playbooks do Ansible para melhor desempenho, ainda tendo acesso às informações do sistema de que você precisa. Esse conhecimento o ajudará a criar fluxos de trabalho de automação mais eficientes, flexíveis e poderosos.

Algumas melhores práticas para lembrar:

  • Habilite a coleta de fatos somente quando necessário
  • Use a coleta seletiva de fatos quando precisar apenas de informações específicas
  • Aproveite os fatos coletados para tarefas condicionais para tornar seus playbooks mais adaptáveis
  • Considere o cache de fatos ao executar playbooks com frequência nos mesmos hosts

Com essas habilidades, você está bem equipado para criar uma automação Ansible mais sofisticada e eficiente para suas necessidades de gerenciamento de infraestrutura.