Fehlerbehebung bei SSH-Verbindungsfehlern in Ansible-Playbooks

Dieser Expertenleitfaden bietet einen systematischen Ansatz zur Fehlerbehebung bei häufigen SSH-Verbindungsfehlern beim Ausführen von Ansible-Playbooks. Erfahren Sie, wie Sie maximale Ausführlichkeit (`-vvv`) zur Diagnose nutzen, Authentifizierungsfehler im Zusammenhang mit privaten Schlüsseln und Berechtigungen beheben, Probleme mit der Überprüfung des Hostschlüssels (`Host key verification failed`) lösen und Netzwerkblockaden diagnostizieren. Praktische Schritte und Befehlszeilenbeispiele helfen Ihnen, die Ursache von Verbindungszeitüberschreitungen und Berechtigungsfehlern schnell zu isolieren und zu beheben, um eine zuverlässige Automatisierung wiederherzustellen.

Fehlerbehebung bei SSH-Verbindungsfehlern in Ansible-Playbooks

Ansible verwendet am häufigsten Secure Shell (SSH), um mit Linux- und Unix-Managed Nodes zu kommunizieren. Es können andere Verbindungs-Plugins verwendet werden, und die Windows-Automatisierung nutzt oft WinRM, aber SSH ist der Pfad, den die meisten Teams täglich debuggen. Wenn ein Ansible-Playbook mit einem Verbindungsfehler fehlschlägt, deutet dies fast immer auf ein zugrunde liegendes Problem in der standardmäßigen SSH-Einrichtung zwischen dem Control-Node und dem Zielhost hin. Zu verstehen, wie man diese Fehler systematisch diagnostiziert, ist entscheidend für die Aufrechterhaltung einer zuverlässigen Automatisierung.

Phase 1: Ausführlichkeit aktivieren und erste Überprüfungen

Der schnellste Weg, um das Rätselraten zu beenden, ist die Erhöhung der Ausführlichkeit der Ausgabe. SSH-Fehler werden oft maskiert, aber maximale Ausführlichkeit zeigt die genauen Parameter, die Ansible verwendet, und die spezifische Fehlermeldung, die vom zugrunde liegenden OpenSSH-Client zurückgegeben wird.

Ausführlichkeitsflags verwenden

Führen Sie Ihren Testbefehl oder Ihr Playbook mit drei oder vier Ausführlichkeitsflags aus (-v, -vv, -vvv, -vvvv). Die meisten Verbindungsprobleme werden durch die Überprüfung der Ausgabe von -vvv gelöst.

# Testen Sie die Konnektivität zu einem Host namens 'webserver', der in Ihrem Inventar definiert ist
ansible webserver -m ansible.builtin.ping -vvv

# Führen Sie ein Playbook mit maximalem Debugging aus
ansible-playbook site.yml -i inventory.ini -vvvv

Inventar und Host-Status überprüfen

Stellen Sie sicher, dass der Zielhost korrekt definiert und erreichbar ist.

  1. Ist der Hostname korrekt? Überprüfen Sie die Schreibweise in Ihrer Inventardatei (/etc/ansible/hosts oder benutzerdefiniertes Inventar).
  2. Ist der Zielhost eingeschaltet? Stellen Sie sicher, dass der Managed Node eingeschaltet und im Netzwerk erreichbar ist.
  3. Sind die Inventarvariablen korrekt? Bestätigen Sie, dass wesentliche Variablen wie ansible_host (IP-Adresse oder Hostname) und ansible_user (Remote-Benutzername) für die Zielgruppe oder den Zielhost korrekt gesetzt sind.
# Beispiel-Inventarausschnitt
[webservers]
web1 ansible_host=192.168.1.100 ansible_user=deploy_user ansible_port=22

Phase 2: Überprüfung der grundlegenden manuellen Konnektivität

Wenn Ansible keine Verbindung herstellen kann, muss der erste Schritt immer sein, zu bestätigen, dass standardmäßiges SSH manuell funktioniert, und zwar mit genau demselben Benutzer, Schlüssel und Port, die auch Ansible verwenden soll.

Manueller SSH-Test

Wenn Sie einen bestimmten Benutzer (ansible_user) und einen bestimmten privaten Schlüssel (ansible_ssh_private_key_file) verwenden, replizieren Sie diese Verbindung manuell.

# Standard-SSH-Test (bei Verwendung von Standard-Port und -Schlüssel)
ssh <ansible_user>@<ansible_host>

# Test mit einem nicht standardmäßigen privaten Schlüssel und Port
ssh -i /pfad/zum/privaten/schlüssel -p 2222 [email protected]

Wenn der manuelle SSH-Test fehlschlägt, beheben Sie zuerst dieses Problem. Ansible kapselt nur denselben SSH-Pfad, daher ist das Debuggen der Playbook-Syntax, bevor SSH funktioniert, normalerweise Zeitverschwendung.

Phase 3: Diagnose von Authentifizierungsfehlern

Authentifizierungsfehler sind die häufigste Ursache für Ansible-Verbindungsprobleme. Diese äußern sich normalerweise als Authentication failed- oder Permission denied-Fehler.

3.1 Schlüsselberechtigungen und -speicherort

Wenn Ansible SSH-Schlüssel verwendet, stellen Sie sicher, dass die private Schlüsseldatei auf dem Control-Node die korrekten, eingeschränkten Berechtigungen hat. SSH lehnt oft Schlüssel ab, die zu freizügig sind.

# Korrekte Berechtigungen für die private Schlüsseldatei setzen
chmod 600 /pfad/zum/privaten/schlüssel

Stellen Sie außerdem sicher, dass Ihr Schlüssel zum SSH-Agenten hinzugefügt wird, falls Sie einen verwenden:

# Agenten starten, falls nötig
eval "$(ssh-agent -s)"
# Schlüssel zum Agenten hinzufügen
ssh-add /pfad/zum/privaten/schlüssel

3.2 Fehler bei der Passwortabfrage (Zeitüberschreitung/fehlendes Passwort)

Wenn Ihre Einrichtung ein Passwort erfordert (nicht für die Produktion empfohlen, aber in Laboren üblich), muss Ansible dieses bereitgestellt bekommen. Wenn die Verbindung hängt oder eine Zeitüberschreitung auftritt, wartet Ansible wahrscheinlich auf ein Passwort, das nie bereitgestellt wurde.

Verwenden Sie das Flag --ask-pass oder -k, um nach dem SSH-Verbindungspasswort zu fragen:

ansible webserver -m ansible.builtin.ping -k

3.3 Autorisierte Schlüssel auf dem Remote-System

Überprüfen Sie, ob der öffentliche Schlüssel, der Ihrem privaten Schlüssel entspricht, korrekt in der Datei ~/.ssh/authorized_keys auf dem Managed Node installiert ist und dass die Datei- und Verzeichnisberechtigungen auf der Remote-Seite korrekt sind (700 für .ssh und 600 für authorized_keys).

Phase 4: Behebung von Hostschlüssel-Fehlern

Ansible respektiert die known_hosts-Datei, die den digitalen Fingerabdruck von Remote-Servern speichert. Wenn sich der Hostschlüssel eines Managed Nodes ändert (z. B. aufgrund eines Neubaus oder einer IP-Neuzuweisung), schlagen SSH-Verbindungsversuche mit einer Warnung fehl, die wie ein Man-in-the-Middle-Angriff aussieht.

Der Fehler Host key verification failed

Wenn dieser Fehler auftritt, müssen Sie den widersprüchlichen Schlüsseleintrag aktualisieren oder entfernen.

  1. Identifizieren Sie die Zeilennummer in ~/.ssh/known_hosts, die in der Fehlerausgabe erwähnt wird.
  2. Entfernen Sie den Eintrag mit ssh-keygen.
# Ersetzen Sie <hostname_oder_ip> durch den tatsächlich fehlschlagenden Host
ssh-keygen -R <hostname_oder_ip>

⚠️ Sicherheitswarnung: Deaktivieren der Host-Überprüfung

Für temporäre Tests oder in stark kontrollierten Laborumgebungen, in denen Host-Instabilität erwartet wird, können Sie Ansible so konfigurieren, dass die Hostschlüssel-Überprüfung ignoriert wird. Dies wird für Produktionsumgebungen dringend abgeraten, da es Sie MITM-Angriffen aussetzt.

In Ihrer ansible.cfg (oder temporären Umgebungsvariablen):

[defaults]
host_key_checking = False

Phase 5: Netzwerk-, Firewall- und Remote-Umgebungsprobleme

Manchmal stellt SSH eine Verbindung her, aber die Verbindung stockt oder schlägt aufgrund von Netzwerkkonfiguration oder Einschränkungen auf dem Zielrechner fehl.

5.1 Firewall-Blockade

Wenn die Verbindung ohne Aufforderung eine Zeitüberschreitung aufweist, blockiert wahrscheinlich eine Firewall den Verbindungsversuch. Überprüfen Sie die Firewall an drei Punkten:

  1. Lokal (Control-Node): Stellen Sie sicher, dass ausgehender Verkehr auf Port 22 (oder benutzerdefiniertem Port) erlaubt ist.
  2. Netzwerkpfad: Stellen Sie sicher, dass keine zwischengeschalteten Netzwerk-ACLs oder Unternehmensfirewalls den Verkehr blockieren.
  3. Remote (Managed Node): Überprüfen Sie, ob die Firewall des Remote-Hosts (firewalld, ufw usw.) SSH (normalerweise Port 22) geöffnet und für das richtige Netzwerkinterface konfiguriert hat.

5.2 Python-Interpreter-Fehler

Ansible benötigt einen Python-Interpreter auf dem Managed Node, um Module auszuführen. Obwohl dies streng genommen kein SSH-Fehler ist, umfasst die anfängliche Verbindungsphase von Ansible das Sammeln von Fakten, was eine Python-Skriptausführung ist. Wenn der Zielrechner eine minimale Installation ohne Python 3 ist, kann die Verbindung während der Setup-Phase fehlschlagen.

Wenn Ihr Ziel Python 3 verwendet, der Interpreter-Pfad jedoch nicht standardmäßig ist (z. B. python3.8 anstelle von python3), geben Sie den korrekten Pfad in Ihrem Inventar an:

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

5.3 SELinux- oder AppArmor-Kontext

In seltenen Fällen können zu strenge Sicherheitsmodule wie SELinux (auf RHEL/CentOS/Fedora) oder AppArmor (auf Ubuntu/Debian) verhindern, dass das Shell-Profil des Remote-Benutzers oder die Verzeichnisberechtigungen während der SSH-Sitzung korrekt zugegriffen werden. Überprüfen Sie die Audit-Logs des Remote-Hosts (/var/log/audit/audit.log oder Äquivalent) auf AVC-Verweigerungen im Zusammenhang mit SSH oder dem Zugriff auf das Home-Verzeichnis des Benutzers.

Häufige Muster aus realen Ansible-Fehlern

Der Fehlertext verrät normalerweise, welche Ebene Sie überprüfen müssen. UNREACHABLE! mit Permission denied (publickey) ist nicht dasselbe Problem wie Failed to connect to the host via ssh: Connection timed out. Ersteres bedeutet, dass der SSH-Daemon geantwortet hat, aber den Berechtigungsnachweis nicht akzeptiert hat. Zweiteres bedeutet, dass die TCP-Verbindung nicht abgeschlossen wurde oder eine Firewall sie stillschweigend verworfen hat.

Wenn Sie Cloud-Instanzen verwalten, überprüfen Sie den Standard-Benutzernamen, bevor Sie Schlüssel ändern. Amazon Linux verwendet üblicherweise ec2-user, Ubuntu verwendet ubuntu, Debian verwendet oft admin oder debian, und benutzerdefinierte Images können etwas völlig anderes verwenden. Ein gültiger Schlüssel mit dem falschen Remote-Benutzernamen führt dennoch zu einem Fehler des öffentlichen Schlüssels. Der schnellste Check ist:

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

Für Bastion-Hosts machen Sie den Sprungpfad im Inventar explizit, damit jeder Durchlauf dieselbe Route verwendet:

[private_web]
web1 ansible_host=10.0.10.25 ansible_user=ubuntu

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

Wenn das auf Ihrem Laptop funktioniert, aber in CI fehlschlägt, vergleichen Sie die SSH-Version des CI-Runners, die Berechtigungen des privaten Schlüssels, die known_hosts-Datei und ob der Runner die Bastion erreichen kann. CI-Fehler sind oft überhaupt keine Ansible-Probleme; der Runner hat einfach nicht denselben Netzwerkpfad oder denselben im Agenten geladenen Schlüssel.

Ein weiteres Muster ist, dass die Privilegienausweitung mit einem Verbindungsfehler verwechselt wird. SSH gelingt, dann hängt das Playbook, weil become ein sudo-Passwort benötigt oder weil der Remote-Benutzer nicht berechtigt ist, den Befehl auszuführen. Testen Sie dies separat:

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

Wenn der erste Befehl den Anmeldebenutzer zurückgibt und der zweite fehlschlägt, ist die SSH-Ebene gesund. Beheben Sie sudoers, ansible_become_password oder Ihr Privilegienmodell, anstatt Schlüssel zu bearbeiten.

Inventarvariablen, die eine doppelte Überprüfung wert sind

Ansible hat mehrere Variablennamen, die ähnlich klingen, und ältere Beispiele im Internet können dies noch unübersichtlicher machen. Bevorzugen Sie die aktuellen Namen ansible_user, ansible_host, ansible_port, ansible_private_key_file und ansible_ssh_common_args in neuen Inventaren. Wenn das Inventar sowohl alte als auch neue Namen enthält oder derselbe Host in mehreren Gruppen vorkommt, verwenden Sie ansible-inventory --host web1, um das aufgelöste Ergebnis zu sehen, anstatt Dateien manuell zu lesen.

Überprüfen Sie auch, ob ansible_connection irgendwo unerwartet gesetzt wurde. Netzwerkgeräte, Container, lokale Bereitstellungsaufgaben und Windows-Hosts können andere Verbindungs-Plugins als das standardmäßige SSH verwenden. Ein Host mit ansible_connection=local wird kein Remote-SSH testen. Ein Windows-Host, der WinRM verwendet, sollte nicht als SSH-Problem debuggt werden, es sei denn, Sie haben OpenSSH auf Windows absichtlich konfiguriert.

Isolieren Sie bei großen Inventaren einen Host, bevor Sie das gesamte Playbook ausführen:

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

Das hält die Ausgabe lesbar und verhindert, dass ein lauter Batch-Durchlauf die eine relevante Zeile verdeckt.

Zusammenfassung häufiger Verbindungsfehler und Lösungen

Fehlermeldung Wahrscheinliche Ursache Umsetzbare Lösung
Permission denied (publickey). Schlüssel nicht erkannt oder falsche Schlüsselberechtigungen. chmod 600 auf privatem Schlüssel; öffentlichen Schlüssel auf dem Remote-Host überprüfen.
Host key verification failed. Hostschlüssel geändert oder known_hosts-Datei beschädigt. Verwenden Sie ssh-keygen -R hostname, um den alten Eintrag zu entfernen.
Connection timed out. Firewall-Blockade oder Host ist ausgeschaltet/nicht erreichbar. Manuelle Konnektivität prüfen (ping, ssh); Firewall-Regeln auf dem Zielhost überprüfen.
Verbindung hängt/stockt. Warten auf Passworteingabe, die nicht bereitgestellt wurde. Mit -k ausführen oder schlüsselbasierte Authentifizierung konfigurieren.

Eine praktische Vorgehensweise

Wenn ich Ansible-SSH-Fehler debugge, versuche ich, eine Ebene nach der anderen zu beweisen. Zuerst führe ich ansible-inventory --host <name> oder ansible-inventory --graph aus, damit ich weiß, welche Variablen Ansible tatsächlich sieht. Inventar-Überraschungen sind häufig: Eine Gruppenvariable überschreibt ansible_user, ein dynamisches Inventar gibt eine private Adresse zurück, oder ein Host wurde in eine Gruppe mit einem anderen ansible_port verschoben.

Dann kopiere ich den genauen SSH-Befehl, der von -vvv impliziert wird. Wenn die Ausgabe -o Port=2222 -o IdentityFile=/keys/deploy.pem -l ubuntu 10.0.4.18 zeigt, teste ich diese genaue Kombination manuell. Ein erfolgreiches ssh [email protected] reicht nicht aus, wenn Ansible einen anderen Schlüssel, Port, Hostnamen oder eine andere SSH-Konfiguration verwendet.

Wenn manuelles SSH funktioniert, aber Ansible fehlschlägt, suche ich nach Ansible-spezifischem Verhalten: veraltete SSH-Multiplexing-Sockets unter ~/.ansible/cp, eine Inventarvariable, die auf den falschen Interpreter zeigt, eine become-Eingabeaufforderung, die fälschlicherweise für ein Verbindungs-Hängen gehalten wird, oder ein Playbook, das von CI ausgeführt wird, ohne denselben SSH-Agenten, der auf meinem Laptop existiert. Das Entfernen von ~/.ansible/cp/* ist ein sicherer Test, wenn die Debug-Ausgabe ControlMaster oder ControlPath erwähnt; es erzwingt eine neue SSH-Sitzung.

Ein nützlicher Trick ist, die Verbindung von der Modulausführung zu trennen. ansible host -m ansible.builtin.raw -a "whoami" -vvv benötigt weniger Remote-Python-Unterstützung als normale Module. Wenn raw funktioniert, aber ping fehlschlägt, sind Ihr Netzwerk und Ihr SSH-Pfad wahrscheinlich in Ordnung, und das Problem liegt wahrscheinlich in der Python-Erkennung, den Berechtigungen oder einem Shell-Umgebungsproblem auf dem Zielsystem.

Dokumentieren Sie für Produktionsinventare die Verbindungsannahmen neben der Host-Gruppe: erwarteter Remote-Benutzer, Schlüsselquelle, Bastion-Pfad, SSH-Port und ob die Hostschlüssel-Überprüfung erzwungen wird. Der nächste Ausfall ist einfacher, wenn jeder den fehlgeschlagenen Lauf mit dem beabsichtigten Pfad vergleichen kann, anstatt ihn aus Debug-Logs zurückzuentwickeln.