Maximizando o Desempenho do Ansible com ControlPersist e Pipelining

Aumente significativamente o desempenho dos seus playbooks Ansible ativando a reutilização da conexão SSH com ControlPersist e simplificando a execução de módulos via Pipelining. Este guia fornece insights essenciais e configurações práticas para reduzir os tempos de execução, especialmente em ambientes de grande escala. Saiba como ajustar seu `ansible.cfg` para uma automação de TI mais rápida e eficiente.

37 visualizações

Maximizando o Desempenho do Ansible com ControlPersist e Pipelining

Ansible é uma ferramenta poderosa para automatizar a infraestrutura de TI, permitindo o gerenciamento de configurações e a implantação de aplicações em escala. No entanto, em ambientes de alto volume ou ao gerenciar um grande número de nós, a sobrecarga inerente ao estabelecimento de conexões SSH para cada tarefa pode se tornar um gargalo significativo. Isso pode levar a tempos de execução de playbooks dolorosamente lentos. Felizmente, o Ansible oferece duas funcionalidades poderosas, ControlPersist e Pipelining, que podem melhorar drasticamente o desempenho otimizando a forma como o Ansible se comunica com os nós gerenciados.

Este guia o conduzirá pelo entendimento e implementação de ControlPersist e Pipelining. Ao aproveitar essas técnicas, você pode reduzir significativamente os tempos de execução, tornando sua automação Ansible mais eficiente e responsiva, especialmente em ambientes com centenas ou milhares de hosts. Dominar essas otimizações é crucial para qualquer pessoa que busca escalar suas implantações de Ansible de forma eficaz.

Entendendo o Comportamento de Conexão Padrão do Ansible

Por padrão, o Ansible estabelece uma nova conexão SSH para cada host gerenciado a cada tarefa executada dentro de um playbook. Para cada conexão, ele executa várias etapas:

  1. Iniciar conexão SSH: Uma nova conexão SSH é estabelecida.
  2. Transferir módulos: O Ansible transfere os módulos Python necessários (ou outros arquivos relevantes) para o host remoto.
  3. Executar módulo: O módulo é executado no host remoto.
  4. Receber saída: O Ansible recupera os resultados da execução.
  5. Fechar conexão: A conexão SSH é encerrada.

Embora essa abordagem seja robusta e garanta um estado limpo para cada tarefa, o processo repetido de conexão e transferência de módulos consome um tempo considerável, especialmente ao lidar com inúmeras tarefas ou um grande inventário.

Otimizando Conexões com ControlPersist

ControlPersist é um recurso SSH que permite manter as conexões SSH abertas por um período especificado, mesmo após o comando inicial ter terminado. Isso significa que tarefas Ansible subsequentes que visam o mesmo host podem reutilizar a conexão existente e aberta em vez de estabelecer uma nova. Isso reduz significativamente a latência associada à configuração de sessões SSH.

Como o ControlPersist Funciona

Quando ativado, ControlPersist instrui o cliente SSH a manter uma conexão mestre de controle. Conexões SSH subsequentes para o mesmo host usando as mesmas credenciais e opções podem então ser multiplexadas sobre esta conexão mestre. O Ansible aproveita isso definindo as opções ControlPath e ControlPersist em sua configuração SSH.

Habilitando o ControlPersist no Ansible

Você pode habilitar o ControlPersist de várias maneiras:

  1. Via ansible.cfg (Recomendado para configurações globais ou específicas do projeto):
    Edite ou crie seu arquivo ansible.cfg (localizado no diretório do seu projeto Ansible, ~/.ansible.cfg, ou /etc/ansible/ansible.cfg). Adicione a seguinte configuração à seção [ssh_connection]:

    ini [ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p

    • -o ControlMaster=auto: Habilita o compartilhamento de conexão. Se uma conexão mestre existir, use-a; caso contrário, crie uma.
    • -o ControlPersist=600: Mantém a conexão de controle aberta por 600 segundos (10 minutos). Ajuste este valor com base no seu fluxo de trabalho e políticas de segurança. Uma duração maior significa mais potencial de reutilização, mas também mais recursos mantidos abertos.
    • -o ControlPath=~/.ssh/ansible_control_%r@%h:%p: Define o caminho para o socket de controle. %r é o nome de usuário remoto, %h é o nome do host e %p é a porta. Isso garante sockets únicos para diferentes conexões.
  2. Via Variável de Ambiente:
    Você pode definir os argumentos SSH diretamente usando uma variável de ambiente:

    bash export ANSIBLE_SSH_ARGS='-o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p' ansible-playbook your_playbook.yml

  3. Via Playbook (menos comum para esta configuração):
    Embora seja possível, geralmente não é recomendado definir opções SSH persistentes dentro de um playbook em si, pois é uma configuração de nível de conexão. No entanto, para fins de completude, você poderia usar ansible.builtin.set_fact ou similar para influenciá-lo, mas ansible.cfg é preferido.

Considerações para ControlPersist

  • Segurança: Garanta que o ControlPath esteja seguro para que apenas usuários autorizados possam acessar os sockets de controle. O caminho padrão no exemplo é geralmente seguro para configurações de nível de usuário.
  • Uso de Recursos: Manter as conexões abertas consome recursos tanto no nó de controle quanto nos nós gerenciados. Monitore o uso de recursos se você tiver um grande número de conexões persistentes.
  • Redefinição de Conexão: Se um dispositivo de rede intermediário ou o servidor SSH remoto impuser tempos limite de conexão menores que ControlPersist, a conexão ainda poderá cair. O ControlPersist funciona melhor em ambientes de rede estáveis.

Otimizando a Execução de Módulos com Pipelining

Pipelining é outra poderosa otimização do Ansible que reduz ainda mais a sobrecarga da execução de tarefas. Em vez de transferir módulos para o host remoto, executá-los e, em seguida, recuperar a saída, o pipelining transmite comandos diretamente pela conexão SSH. Isso significa que o Ansible não precisa colocar módulos no sistema de arquivos remoto ou criar arquivos temporários para a saída.

Como o Pipelining Funciona

Quando o pipelining está ativado, o Ansible executa módulos diretamente via ssh no host remoto. A saída padrão e o erro padrão do módulo são transmitidos de volta ao Ansible pela mesma conexão SSH. Isso elimina a necessidade de o Ansible gravar arquivos no sistema de arquivos remoto (como /usr/bin/ansible_module_name ou arquivos temporários) e depois executá-los. Isso é particularmente eficaz para módulos que não exigem escalonamento de privilégios ou interação significativa com o sistema de arquivos remoto.

Habilitando o Pipelining no Ansible

O pipelining é habilitado via arquivo ansible.cfg ou variáveis de ambiente.

  1. Via ansible.cfg:
    Adicione ou modifique a seção [ssh_connection]:

    ini [ssh_connection] pipelining = True

  2. Via Variável de Ambiente:
    bash export ANSIBLE_PIPELINING=True ansible-playbook your_playbook.yml

Considerações para Pipelining

  • Escalonamento de Privilégios: O pipelining funciona melhor com módulos que não exigem escalonamento de privilégios (por exemplo, usando become: yes ou sudo). Quando become é usado, o Ansible geralmente precisa copiar arquivos para o sistema remoto. Se você usa become com frequência, o pipelining pode não oferecer tantos benefícios ou pode até causar problemas com certos tipos de módulos.
  • Compatibilidade de Módulos: A maioria dos módulos Ansible incorporados funciona bem com pipelining. No entanto, módulos personalizados ou aqueles que dependem fortemente de operações no sistema de arquivos remoto podem se comportar de forma diferente. Teste exaustivamente.
  • Estabilidade da Conexão: Uma conexão SSH estável é crucial para que o pipelining funcione corretamente.
  • Configuração SSH requiretty: O pipelining é incompatível com a opção SSH requiretty no servidor remoto. Se o seu servidor SSH tiver Defaults requiretty em /etc/sudoers, pode ser necessário desativá-lo ou usar !requiretty para o usuário específico com o qual o Ansible se conecta.

Combinando ControlPersist e Pipelining para Máximo Desempenho

Para os ganhos de desempenho mais significativos, é altamente recomendável habilitar tanto o ControlPersist quanto o Pipelining. Essa combinação aborda as duas principais sobrecargas: estabelecimento de conexão e execução de módulos.

Veja como seu ansible.cfg pode parecer com ambos habilitados:

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p
pipelining = True

Quando ambos estão ativos:

  1. O Ansible inicia uma conexão SSH e estabelece um ControlMaster se um não existir (ControlPersist).
  2. Para tarefas subsequentes, a conexão existente e aberta é reutilizada.
  3. Os módulos são executados diretamente sobre o fluxo sem serem copiados para o sistema de arquivos (Pipelining).

Essa sinergia reduz drasticamente o tempo que o Ansible gasta se comunicando com cada nó gerenciado, resultando em execuções de playbooks muito mais rápidas.

Cenário de Exemplo Prático

Vamos imaginar um playbook que precisa executar 10 tarefas simples em 100 hosts.

Sem otimizações:
Cada tarefa requer uma nova conexão SSH, transferência de módulo, execução e fechamento da conexão. Isso totaliza 100 hosts * 10 tarefas * (tempo_de_conexão + tempo_de_transferência_de_módulo). Se o tempo_de_conexão for 0,5 segundos e o tempo_de_transferência_de_módulo for 0,2 segundos, isso significa 100 * 10 * 0,7 = 700 segundos de sobrecarga apenas para comunicação e transferências, sem incluir a execução real do módulo.

Com ControlPersist e Pipelining habilitados:

  1. A primeira tarefa em cada host estabelece a conexão inicial e configura o ControlMaster.
  2. Todas as 9 tarefas subsequentes nesse host reutilizam a conexão aberta e transmitem a execução do módulo.

A sobrecarga por host se aproxima de tempo_de_conexão + (9 * sobrecarga_mínima_de_streaming). O tempo total é significativamente reduzido, com a maior parte do tempo de execução do playbook dedicada ao trabalho real que os módulos realizam, em vez da mecânica de comunicação.

Quando Ser Cauteloso

Embora essas otimizações sejam poderosas, elas não são universalmente aplicáveis sem consideração:

  • Ambientes com Firewalls Rígidos ou Restrições de Rede: Quedas frequentes de conexão ou inspeção de estado podem interferir no ControlPersist.
  • Ambientes de Alta Segurança: Conexões SSH de vida útil mais longa podem ser uma preocupação de segurança em ambientes altamente regulamentados. Ajuste a duração do ControlPersist de acordo.
  • Playbooks que dependem fortemente de become e operações de arquivo: A eficácia do Pipelining é reduzida quando become é usado consistentemente, pois muitas vezes isso exige operações de arquivo. Teste o impacto no desempenho.

Conclusão

Otimizar a comunicação do Ansible com os nós gerenciados é um passo fundamental para uma automação eficiente e escalável. Ao entender e implementar ControlPersist e Pipelining, você pode reduzir drasticamente os tempos de execução do playbook. O ControlPersist mantém as conexões SSH ativas, reduzindo a sobrecarga de conexão, enquanto o Pipelining transmite a execução do módulo, eliminando a necessidade de transferências de arquivos. A combinação dessas duas configurações, principalmente através do ansible.cfg, é uma prática recomendada para qualquer usuário Ansible que gerencia um número significativo de hosts ou executa playbooks complexos. Sempre teste essas configurações em seu ambiente específico para otimizar o desempenho e garantir a compatibilidade.