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.
- O Nome do Host está Correto? Verifique novamente a ortografia em seu arquivo de inventário (
/etc/ansible/hostsou inventário personalizado). - O Alvo está Ativo? Certifique-se de que o nó gerenciado está ligado e acessível na rede.
- As Variáveis de Inventário estão Corretas? Confirme se variáveis essenciais como
ansible_host(endereço IP ou nome do host) eansible_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.
- Identifique o número da linha em
~/.ssh/known_hostsmencionado na saída do erro. - 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:
- Local (Máquina de Controle): Certifique-se de que o tráfego de saída na porta 22 (ou porta personalizada) seja permitido.
- Caminho de Rede: Certifique-se de que nenhum ACL de rede intermediário ou firewall corporativo esteja bloqueando o tráfego.
- 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.