Resolução de Falhas de Conexão SSH em Playbooks Ansible

Este guia especializado fornece uma abordagem sistemática para solucionar falhas comuns de conexão SSH ao executar playbooks Ansible. Aprenda a usar a verbosidade máxima (`-vvv`) para diagnóstico, resolver erros de autenticação relacionados a chaves privadas e permissões, corrigir problemas de 'Host key verification failed' e diagnosticar bloqueios de rede. Etapas práticas e exemplos de linha de comando garantem que você possa isolar e resolver rapidamente a causa raiz de timeouts de conexão e mensagens de permissão negada, restaurando a automação confiável.

Resolução de Falhas de Conexão SSH em Playbooks Ansible

O Ansible usa mais comumente o Secure Shell (SSH) para se comunicar com nós gerenciados Linux e Unix. Ele pode usar outros plugins de conexão, e a automação do Windows geralmente usa WinRM, mas o SSH é o caminho que a maioria das equipes depura no dia a dia. Quando um playbook do Ansible falha com um erro de conectividade, quase sempre aponta para um problema subjacente na configuração padrão do SSH entre a máquina de controle e o host de destino. Entender como diagnosticar sistematicamente essas falhas é crucial para manter uma automação confiável.

Fase 1: Ativando a Verbosidade e Verificações Iniciais

A maneira mais rápida de parar de adivinhar é aumentar a verbosidade da saída. Os erros de SSH geralmente são mascarados, mas a verbosidade máxima revela os parâmetros exatos que o Ansible está usando e a mensagem de erro específica retornada pelo cliente OpenSSH subjacente.

Use Flags de Verbosidade

Execute seu comando de teste ou playbook com três ou quatro flags de verbosidade (-v, -vv, -vvv, -vvvv). A maioria dos problemas de conexão é resolvida revisando a saída de -vvv.

# Teste a conectividade com um host chamado 'webserver' definido em seu inventário
ansible webserver -m ansible.builtin.ping -vvv

# Execute um playbook com depuração máxima
ansible-playbook site.yml -i inventory.ini -vvvv

Verifique o Inventário e o Status do Host

Certifique-se de que o host que você está segmentando está definido corretamente e é acessível.

  1. O Nome do Host está Correto? Verifique novamente a ortografia em seu arquivo de inventário (/etc/ansible/hosts ou inventário personalizado).
  2. O Alvo está Ativo? Certifique-se de que o nó gerenciado está ligado e acessível na rede.
  3. As Variáveis de Inventário estão Corretas? Confirme se variáveis essenciais como ansible_host (endereço IP ou nome do host) e ansible_user (nome de usuário remoto) estão definidas corretamente para o grupo ou host de destino.
# Exemplo de Trecho de Inventário
[webservers]
web1 ansible_host=192.168.1.100 ansible_user=deploy_user ansible_port=22

Fase 2: Verificando a Conectividade Manual Básica

Se o Ansible não conseguir conectar, o primeiro passo deve ser sempre confirmar se o SSH padrão funciona manualmente, usando exatamente o mesmo usuário, chave e porta que o Ansible está configurado para usar.

Teste SSH Manual

Se você estiver usando um usuário específico (ansible_user) e uma chave privada específica (ansible_ssh_private_key_file), replique essa conexão manualmente.

# Teste SSH padrão (se estiver usando porta e chave padrão)
ssh <ansible_user>@<ansible_host>

# Teste usando uma chave privada e porta não padrão
ssh -i /caminho/para/chave/privada -p 2222 [email protected]

Se o teste SSH manual falhar, corrija isso primeiro. O Ansible está apenas encapsulando o mesmo caminho SSH, então depurar a sintaxe do playbook antes de o SSH funcionar geralmente é perda de tempo.

Fase 3: Diagnosticando Falhas de Autenticação

Falhas de autenticação são a causa mais comum de problemas de conexão do Ansible. Elas geralmente se manifestam como erros Authentication failed ou Permission denied.

3.1 Permissões e Localização da Chave

Se o Ansible estiver usando chaves SSH, certifique-se de que o arquivo de chave privada tenha as permissões corretas e restritas na máquina de controle. O SSH geralmente rejeita chaves que são muito permissivas.

# Defina as permissões corretas no arquivo de chave privada
chmod 600 /caminho/para/chave/privada

Além disso, se você usar um Agente SSH, certifique-se de que sua chave foi adicionada:

# Inicie o agente, se necessário
eval "$(ssh-agent -s)"
# Adicione sua chave ao agente
ssh-add /caminho/para/chave/privada

3.2 Falhas de Solicitação de Senha (Timeout/Senha Ausente)

Se sua configuração exigir uma senha (não recomendado para produção, mas comum em laboratórios), o Ansible precisa recebê-la. Se a conexão travar ou expirar, o Ansible provavelmente está aguardando uma senha que nunca foi fornecida.

Use a flag --ask-pass ou -k para solicitar a senha de conexão SSH:

ansible webserver -m ansible.builtin.ping -k

3.3 Chaves Autorizadas Remotas

Verifique se a chave pública correspondente à sua chave privada está instalada corretamente no arquivo ~/.ssh/authorized_keys no nó gerenciado e se as permissões do arquivo e diretório no lado remoto estão corretas (700 para .ssh e 600 para authorized_keys).

Fase 4: Resolvendo Erros de Chave do Host

O Ansible respeita o arquivo known_hosts, que armazena a impressão digital dos servidores remotos. Se a chave do host de um nó gerenciado mudar (por exemplo, devido a uma reconstrução ou reatribuição de IP), as tentativas de conexão SSH falharão com um aviso que se parece com um ataque Man-in-the-Middle.

O Erro Host key verification failed

Quando esse erro ocorrer, você deve atualizar ou remover a entrada de chave conflitante.

  1. Identifique o número da linha em ~/.ssh/known_hosts mencionado na saída do erro.
  2. Remova a entrada usando ssh-keygen.
# Substitua <hostname_or_ip> pelo host real que está falhando
ssh-keygen -R <hostname_or_ip>

⚠️ Aviso de Segurança: Desabilitando a Verificação de Host

Para testes temporários ou em ambientes de laboratório altamente controlados onde a instabilidade do host é esperada, você pode configurar o Ansible para ignorar a verificação de chave do host. Isso é fortemente desencorajado para ambientes de produção, pois expõe você a ataques MITM.

Em seu ansible.cfg (ou variável de ambiente temporária):

[defaults]
host_key_checking = False

Fase 5: Problemas de Rede, Firewall e Ambiente Remoto

Às vezes, o SSH conecta, mas a conexão para ou falha devido à configuração de rede ou restrições na máquina de destino.

5.1 Bloqueio de Firewall

Se a conexão expirar sem um prompt, um firewall provavelmente está bloqueando a tentativa de conexão. Verifique o firewall em três pontos:

  1. Local (Máquina de Controle): Certifique-se de que o tráfego de saída na porta 22 (ou porta personalizada) seja permitido.
  2. Caminho de Rede: Certifique-se de que nenhum ACL de rede intermediário ou firewall corporativo esteja bloqueando o tráfego.
  3. Remoto (Nó Gerenciado): Verifique se o firewall do host remoto (firewalld, ufw, etc.) tem o SSH (geralmente porta 22) aberto e configurado para a interface de rede correta.

5.2 Erros do Interpretador Python

O Ansible requer um interpretador Python no nó gerenciado para executar módulos. Embora não seja estritamente uma falha de SSH, a fase de conexão inicial do Ansible envolve a coleta de fatos, que é uma execução de script Python. Se a máquina de destino for uma instalação mínima sem Python 3, a conexão pode falhar durante a fase de configuração.

Se seu destino usar Python 3, mas o caminho do interpretador não for padrão (por exemplo, python3.8 em vez de python3), especifique o caminho correto em seu inventário:

[target_host]
ansible_python_interpreter=/usr/bin/python3.8

5.3 Contexto SELinux ou AppArmor

Em casos raros, módulos de segurança excessivamente restritivos como SELinux (no RHEL/CentOS/Fedora) ou AppArmor (no Ubuntu/Debian) podem impedir que o perfil do shell do usuário remoto ou as permissões de diretório sejam acessados corretamente durante a sessão SSH. Verifique os logs de auditoria do host remoto (/var/log/audit/audit.log ou equivalente) em busca de negações AVC relacionadas ao SSH ou ao acesso ao diretório inicial do usuário.

Padrões comuns de falhas reais do Ansible

O texto do erro geralmente indica qual camada inspecionar. UNREACHABLE! com Permission denied (publickey) não é o mesmo problema que Failed to connect to the host via ssh: Connection timed out. O primeiro significa que o daemon SSH respondeu, mas não aceitou o caminho da credencial. O segundo significa que a conexão TCP não foi concluída ou um firewall a descartou silenciosamente.

Se você gerencia instâncias em nuvem, verifique o nome de usuário padrão antes de alterar as chaves. O Amazon Linux geralmente usa ec2-user, o Ubuntu usa ubuntu, o Debian geralmente usa admin ou debian, e imagens personalizadas podem usar algo totalmente diferente. Uma chave válida com o nome de usuário remoto errado ainda resulta em uma falha de chave pública. A verificação mais rápida é:

ssh -i key.pem [email protected]
ssh -i key.pem [email protected]

Para hosts bastiões, torne o caminho de salto explícito no inventário para que cada execução use a mesma rota:

[private_web]
web1 ansible_host=10.0.10.25 ansible_user=ubuntu

[private_web:vars]
ansible_ssh_common_args='-o [email protected]'

Se isso funcionar no seu laptop, mas falhar no CI, compare a versão do SSH do runner do CI, as permissões da chave privada, o arquivo known_hosts e se o runner pode alcançar o bastião. As falhas de CI geralmente não são problemas do Ansible; o runner simplesmente não tem o mesmo caminho de rede ou chave carregada no agente.

Outro padrão é a escalação de privilégio ser confundida com falha de conexão. O SSH é bem-sucedido, então o playbook trava porque become precisa de uma senha sudo ou porque o usuário remoto não tem permissão para executar o comando. Teste isso separadamente:

ansible web1 -m ansible.builtin.command -a "whoami" -vvv
ansible web1 -b -m ansible.builtin.command -a "whoami" -vvv

Se o primeiro comando retornar o usuário de login e o segundo falhar, a camada SSH está saudável. Corrija o sudoers, ansible_become_password ou seu modelo de privilégio em vez de editar chaves.

Variáveis de inventário que valem a pena verificar duas vezes

O Ansible tem vários nomes de variáveis que soam semelhantes, e exemplos mais antigos na internet podem tornar isso mais confuso. Prefira os nomes atuais ansible_user, ansible_host, ansible_port, ansible_private_key_file e ansible_ssh_common_args em novos inventários. Se o inventário tiver nomes antigos e novos, ou o mesmo host aparecer em vários grupos, use ansible-inventory --host web1 para ver o resultado resolvido em vez de ler arquivos manualmente.

Verifique também se ansible_connection foi definido em algum lugar inesperado. Dispositivos de rede, contêineres, tarefas de provisionamento local e hosts Windows podem usar plugins de conexão diferentes do SSH padrão. Um host com ansible_connection=local não testará o SSH remoto. Um host Windows usando WinRM não deve ser depurado como um problema de SSH, a menos que você tenha configurado intencionalmente o OpenSSH no Windows.

Para inventários grandes, isole um host antes de executar o playbook completo:

ansible web1 -i inventory.ini -m ansible.builtin.ping -vvv
ansible-playbook site.yml -i inventory.ini --limit web1 --check -vvv

Isso mantém a saída legível e evita que uma execução em lote barulhenta esconda a única linha que importa.

Resumo de Erros de Conexão Comuns e Soluções

Mensagem de Erro Causa Provável Correção Acionável
Permission denied (publickey). Chave não reconhecida ou permissões de chave ruins. chmod 600 na chave privada; verifique a chave pública no host remoto.
Host key verification failed. Chave do host alterada ou arquivo known_hosts corrompido. Use ssh-keygen -R hostname para remover a entrada antiga.
Connection timed out. Bloqueio de firewall ou host inativo/inacessível. Verifique a conectividade manual (ping, ssh); verifique as regras de firewall no host de destino.
Conexão trava/para. Aguardando entrada de senha que não foi fornecida. Execute com -k ou configure a autenticação baseada em chave.

Uma ordem prática de operações

Quando depuro falhas de SSH do Ansible, tento provar uma camada de cada vez. Primeiro, executo ansible-inventory --host <nome> ou ansible-inventory --graph para saber quais variáveis o Ansible realmente vê. Surpresas de inventário são comuns: uma variável de grupo substitui ansible_user, um inventário dinâmico retorna um endereço privado ou um host foi movido para um grupo com um ansible_port diferente.

Em seguida, copio o comando SSH exato implícito por -vvv. Se a saída mostrar -o Port=2222 -o IdentityFile=/keys/deploy.pem -l ubuntu 10.0.4.18, testo essa combinação exata manualmente. Um ssh [email protected] bem-sucedido não é suficiente se o Ansible estiver usando uma chave, porta, nome de host ou configuração SSH diferente.

Se o SSH manual funcionar, mas o Ansible falhar, procuro por comportamento específico do Ansible: sockets de multiplexação SSH obsoletos em ~/.ansible/cp, uma variável de inventário apontando para o interpretador errado, um prompt become que está sendo confundido com uma parada de conexão ou um playbook sendo executado do CI sem o mesmo agente SSH que existe no meu laptop. Remover ~/.ansible/cp/* é um teste seguro quando a saída de depuração menciona ControlMaster ou ControlPath; isso força uma nova sessão SSH.

Um truque útil é separar a conexão da execução do módulo. ansible host -m ansible.builtin.raw -a "whoami" -vvv precisa de menos suporte Python remoto do que os módulos normais. Se raw funcionar, mas ping falhar, sua rede e caminho SSH provavelmente estão bons, e o problema é provavelmente descoberta de Python, permissões ou um problema de ambiente de shell no destino.

Para inventários de produção, documente as suposições de conexão ao lado do grupo de hosts: usuário remoto esperado, origem da chave, caminho do bastião, porta SSH e se a verificação de chave do host é aplicada. A próxima interrupção é mais fácil quando todos podem comparar a execução com falha com o caminho pretendido, em vez de fazer engenharia reversa a partir de logs de depuração.