Solución de problemas de fallos de conexión SSH en playbooks de Ansible

Esta guía experta proporciona un enfoque sistemático para solucionar problemas comunes de fallos de conexión SSH al ejecutar playbooks de Ansible. Aprenda a aprovechar la verbosidad máxima (`-vvv`) para el diagnóstico, resolver errores de autenticación relacionados con claves privadas y permisos, solucionar problemas de `Host key verification failed` y diagnosticar bloqueos de red. Pasos prácticos y ejemplos de línea de comandos le permitirán aislar y resolver rápidamente la causa raíz de los tiempos de espera de conexión y los mensajes de permiso denegado, restaurando la automatización confiable.

Solución de problemas de fallos de conexión SSH en playbooks de Ansible

Ansible utiliza más comúnmente Secure Shell (SSH) para comunicarse con nodos gestionados Linux y Unix. Puede usar otros plugins de conexión, y la automatización de Windows a menudo usa WinRM, pero SSH es el camino que la mayoría de los equipos depuran día a día. Cuando un playbook de Ansible falla con un error de conectividad, casi siempre apunta a un problema subyacente en la configuración SSH estándar entre la máquina de control y el host de destino. Comprender cómo diagnosticar sistemáticamente estos fallos es crucial para mantener una automatización confiable.

Fase 1: Habilitar la verbosidad y comprobaciones iniciales

La forma más rápida de dejar de adivinar es aumentar la verbosidad de la salida. Los errores de SSH a menudo están enmascarados, pero la verbosidad máxima revela los parámetros exactos que Ansible está utilizando y el mensaje de error específico devuelto por el cliente OpenSSH subyacente.

Usar banderas de verbosidad

Ejecute su comando de prueba o playbook con tres o cuatro banderas de verbosidad (-v, -vv, -vvv, -vvvv). La mayoría de los problemas de conexión se resuelven revisando la salida de -vvv.

# Probar conectividad a un host llamado 'webserver' definido en su inventario
ansible webserver -m ansible.builtin.ping -vvv

# Ejecutar un playbook con depuración máxima
ansible-playbook site.yml -i inventory.ini -vvvv

Verificar el inventario y el estado del host

Asegúrese de que el host al que se dirige esté correctamente definido y sea accesible.

  1. ¿El nombre del host es correcto? Verifique la ortografía en su archivo de inventario (/etc/ansible/hosts o inventario personalizado).
  2. ¿El destino está activo? Asegúrese de que el nodo gestionado esté encendido y accesible en la red.
  3. ¿Las variables de inventario son correctas? Confirme que las variables esenciales como ansible_host (dirección IP o nombre de host) y ansible_user (nombre de usuario remoto) estén configuradas correctamente para el grupo o host de destino.
# Ejemplo de fragmento de inventario
[webservers]
web1 ansible_host=192.168.1.100 ansible_user=deploy_user ansible_port=22

Fase 2: Verificar la conectividad manual básica

Si Ansible no puede conectarse, el primer paso siempre debe ser confirmar que SSH estándar funciona manualmente, utilizando exactamente el mismo usuario, clave y puerto que Ansible está configurado para usar.

Prueba SSH manual

Si está utilizando un usuario específico (ansible_user) y una clave privada específica (ansible_ssh_private_key_file), replique esa conexión manualmente.

# Prueba SSH estándar (si se usa el puerto y la clave predeterminados)
ssh <ansible_user>@<ansible_host>

# Prueba usando una clave privada y un puerto no predeterminados
ssh -i /path/to/private/key -p 2222 [email protected]

Si la prueba SSH manual falla, arréglela primero. Ansible solo está envolviendo la misma ruta SSH, por lo que depurar la sintaxis del playbook antes de que funcione SSH generalmente pierde tiempo.

Fase 3: Diagnosticar fallos de autenticación

Los fallos de autenticación son la causa más común de problemas de conexión de Ansible. Estos generalmente se manifiestan como errores de Authentication failed o Permission denied.

3.1 Permisos y ubicación de la clave

Si Ansible está usando claves SSH, asegúrese de que el archivo de clave privada tenga los permisos correctos y restringidos en la máquina de control. SSH a menudo rechazará claves que sean demasiado permisivas.

# Establecer permisos correctos en el archivo de clave privada
chmod 600 /path/to/private/key

Adicionalmente, si usa un Agente SSH, asegúrese de que su clave esté agregada:

# Iniciar el agente si es necesario
eval "$(ssh-agent -s)"
# Agregar su clave al agente
ssh-add /path/to/private/key

3.2 Fallos de solicitud de contraseña (tiempo de espera/contraseña faltante)

Si su configuración requiere una contraseña (no recomendado para producción pero común en laboratorios), Ansible necesita que se le proporcione. Si la conexión se cuelga o se agota el tiempo de espera, es probable que Ansible esté esperando una contraseña que nunca se proporcionó.

Use la bandera --ask-pass o -k para solicitar la contraseña de conexión SSH:

ansible webserver -m ansible.builtin.ping -k

3.3 Claves autorizadas remotas

Verifique que la clave pública correspondiente a su clave privada esté instalada correctamente en el archivo ~/.ssh/authorized_keys en el nodo gestionado, y que los permisos del archivo y directorio en el lado remoto sean correctos (700 para .ssh y 600 para authorized_keys).

Fase 4: Resolver errores de clave de host

Ansible respeta el archivo known_hosts, que almacena la huella digital de los servidores remotos. Si la clave de host de un nodo gestionado cambia (por ejemplo, debido a una reconstrucción o reasignación de IP), los intentos de conexión SSH fallarán con una advertencia que parece un ataque de intermediario.

El error Host key verification failed

Cuando ocurre este error, debe actualizar o eliminar la entrada de clave conflictiva.

  1. Identifique el número de línea en ~/.ssh/known_hosts mencionado en la salida del error.
  2. Elimine la entrada usando ssh-keygen.
# Reemplace <hostname_or_ip> con el host real que falla
ssh-keygen -R <hostname_or_ip>

⚠️ Advertencia de seguridad: Deshabilitar la verificación de host

Para pruebas temporales o en entornos de laboratorio altamente controlados donde se espera inestabilidad del host, puede configurar Ansible para ignorar la verificación de clave de host. Esto está fuertemente desaconsejado para entornos de producción, ya que lo expone a ataques MITM.

En su ansible.cfg (o variable de entorno temporal):

[defaults]
host_key_checking = False

Fase 5: Red, cortafuegos y problemas del entorno remoto

A veces SSH se conecta, pero la conexión se detiene o falla debido a la configuración de red o restricciones en la máquina de destino.

5.1 Bloqueo del cortafuegos

Si la conexión se agota sin un aviso, es probable que un cortafuegos esté bloqueando el intento de conexión. Verifique el cortafuegos en tres puntos:

  1. Local (Máquina de control): Asegúrese de que el tráfico saliente en el puerto 22 (o puerto personalizado) esté permitido.
  2. Ruta de red: Asegúrese de que no haya ACL de red intermedias o cortafuegos corporativos bloqueando el tráfico.
  3. Remoto (Nodo gestionado): Verifique que el cortafuegos del host remoto (firewalld, ufw, etc.) tenga SSH (generalmente puerto 22) abierto y configurado para la interfaz de red correcta.

5.2 Errores del intérprete de Python

Ansible requiere un intérprete de Python en el nodo gestionado para ejecutar módulos. Si bien no es estrictamente un fallo de SSH, la fase de conexión inicial de Ansible implica la recopilación de hechos, que es una ejecución de script de Python. Si la máquina de destino es una instalación mínima sin Python 3, la conexión puede fallar durante la fase de configuración.

Si su destino usa Python 3 pero la ruta del intérprete no es estándar (por ejemplo, python3.8 en lugar de python3), especifique la ruta correcta en su inventario:

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

5.3 Contexto SELinux o AppArmor

En casos raros, módulos de seguridad demasiado estrictos como SELinux (en RHEL/CentOS/Fedora) o AppArmor (en Ubuntu/Debian) pueden impedir que el perfil de shell del usuario remoto o los permisos del directorio se accedan correctamente durante la sesión SSH. Verifique los registros de auditoría del host remoto (/var/log/audit/audit.log o equivalente) en busca de denegaciones AVC relacionadas con SSH o el acceso al directorio de inicio del usuario.

Patrones comunes de fallos reales de Ansible

El texto del error generalmente le indica qué capa inspeccionar. UNREACHABLE! con Permission denied (publickey) no es el mismo problema que Failed to connect to the host via ssh: Connection timed out. El primero significa que el demonio SSH respondió pero no aceptó la ruta de credenciales. El segundo significa que la conexión TCP no se completó, o un cortafuegos la descartó silenciosamente.

Si gestiona instancias en la nube, verifique el nombre de usuario predeterminado antes de cambiar las claves. Amazon Linux comúnmente usa ec2-user, Ubuntu usa ubuntu, Debian a menudo usa admin o debian, y las imágenes personalizadas pueden usar algo completamente diferente. Una clave válida con el nombre de usuario remoto incorrecto aún le dará un fallo de clave pública. La verificación más rápida es:

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

Para hosts bastión, haga explícita la ruta de salto en el inventario para que cada ejecución use la misma ruta:

[private_web]
web1 ansible_host=10.0.10.25 ansible_user=ubuntu

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

Si eso funciona en su computadora portátil pero falla en CI, compare la versión SSH del ejecutor de CI, los permisos de la clave privada, el archivo known_hosts y si el ejecutor puede alcanzar el bastión. Los fallos de CI a menudo no son problemas de Ansible en absoluto; el ejecutor simplemente no tiene la misma ruta de red o clave cargada en el agente.

Otro patrón es que la escalada de privilegios se confunda con un fallo de conexión. SSH tiene éxito, luego el playbook se cuelga porque become necesita una contraseña de sudo o porque el usuario remoto no tiene permitido ejecutar el comando. Pruebe esto por separado:

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

Si el primer comando devuelve el usuario de inicio de sesión y el segundo falla, la capa SSH está saludable. Arregle sudoers, ansible_become_password o su modelo de privilegios en lugar de editar claves.

Variables de inventario que vale la pena verificar dos veces

Ansible tiene varios nombres de variables que suenan similares, y los ejemplos antiguos en Internet pueden hacer esto más complicado. Prefiera los nombres actuales ansible_user, ansible_host, ansible_port, ansible_private_key_file y ansible_ssh_common_args en los nuevos inventarios. Si el inventario tiene nombres antiguos y nuevos, o el mismo host aparece en múltiples grupos, use ansible-inventory --host web1 para ver el resultado resuelto en lugar de leer archivos a simple vista.

También verifique si ansible_connection se ha establecido en algún lugar inesperado. Los dispositivos de red, contenedores, tareas de aprovisionamiento local y hosts de Windows pueden usar plugins de conexión diferentes al SSH predeterminado. Un host con ansible_connection=local no probará SSH remoto en absoluto. Un host de Windows que use WinRM no debe depurarse como un problema SSH a menos que haya configurado intencionalmente OpenSSH en Windows.

Para inventarios grandes, aísle un host antes de ejecutar el playbook completo:

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

Eso mantiene la salida legible y evita que una ejecución por lotes ruidosa oculte la única línea que importa.

Resumen de errores de conexión comunes y soluciones

Mensaje de error Causa probable Solución práctica
Permission denied (publickey). Clave no reconocida o permisos de clave incorrectos. chmod 600 en la clave privada; verifique la clave pública en el host remoto.
Host key verification failed. La clave del host cambió o el archivo known_hosts está corrupto. Use ssh-keygen -R hostname para eliminar la entrada antigua.
Connection timed out. Bloqueo del cortafuegos o el host está caído/inaccesible. Verifique la conectividad manual (ping, ssh); verifique las reglas del cortafuegos en el host de destino.
La conexión se cuelga/se detiene. Esperando la entrada de contraseña que no se proporcionó. Ejecute con -k o configure la autenticación basada en clave.

Un orden práctico de operaciones

Cuando depuro fallos SSH de Ansible, intento probar una capa a la vez. Primero ejecuto ansible-inventory --host <name> o ansible-inventory --graph para saber qué variables ve realmente Ansible. Las sorpresas de inventario son comunes: una variable de grupo anula ansible_user, un inventario dinámico devuelve una dirección privada, o un host se movió a un grupo con un ansible_port diferente.

Luego copio el comando SSH exacto implícito en -vvv. Si la salida muestra -o Port=2222 -o IdentityFile=/keys/deploy.pem -l ubuntu 10.0.4.18, pruebo esa combinación exacta manualmente. Un ssh [email protected] exitoso no es suficiente si Ansible está usando una clave, puerto, nombre de host o configuración SSH diferente.

Si SSH manual funciona pero Ansible falla, busco comportamiento específico de Ansible: sockets de multiplexación SSH obsoletos en ~/.ansible/cp, una variable de inventario que apunta al intérprete incorrecto, un aviso de become que se confunde con una suspensión de conexión, o un playbook que se ejecuta desde CI sin el mismo agente SSH que existe en mi computadora portátil. Eliminar ~/.ansible/cp/* es una prueba segura cuando la salida de depuración menciona ControlMaster o ControlPath; fuerza una nueva sesión SSH.

Un truco útil es separar la conexión de la ejecución del módulo. ansible host -m ansible.builtin.raw -a "whoami" -vvv necesita menos soporte remoto de Python que los módulos normales. Si raw funciona pero ping falla, su red y ruta SSH probablemente están bien, y el problema es probablemente el descubrimiento de Python, permisos o un problema de entorno de shell en el destino.

Para inventarios de producción, documente las suposiciones de conexión junto al grupo de hosts: usuario remoto esperado, fuente de clave, ruta del bastión, puerto SSH y si la verificación de clave de host está aplicada. La próxima interrupción es más fácil cuando todos pueden comparar la ejecución fallida con la ruta prevista en lugar de realizar ingeniería inversa a partir de registros de depuración.