Introduction
Ansible est un outil puissant d'automatisation de l'infrastructure qui simplifie la gestion des environnements informatiques complexes. Cependant, les utilisateurs rencontrent souvent l'erreur 'UNREACHABLE!', ce qui peut perturber les flux de travail d'automatisation. Cette erreur se produit généralement lorsque Ansible ne peut pas établir de connexion avec les hôtes cibles. Dans ce lab, vous apprendrez à identifier, dépanner et prévenir l'erreur 'UNREACHABLE!' dans vos déploiements Ansible.
À la fin de ce lab, vous comprendrez les causes courantes des problèmes de connectivité dans Ansible et serez capable de mettre en œuvre des solutions efficaces pour garantir le bon fonctionnement de votre automatisation.
Configuration de l'environnement Ansible
Dans cette étape, nous allons configurer un environnement Ansible de base pour travailler. Nous installerons Ansible, configurerons les fichiers essentiels et nous assurerons que tout est prêt pour notre expérimentation.
Installation d'Ansible
Tout d'abord, installons Ansible sur la VM LabEx en utilisant les commandes suivantes :
sudo apt update
sudo apt install -y ansible
Cela installera la dernière version d'Ansible disponible dans les référentiels Ubuntu. Une fois l'installation terminée, vérifiez l'installation en vérifiant la version d'Ansible :
ansible --version
Vous devriez voir une sortie similaire à la suivante, montrant la version d'Ansible et les détails de configuration :
ansible [core 2.12.x]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.10.x (default, Apr 8 2022, 09:04:19) [GCC 11.2.0]
jinja version = 3.0.3
libyaml = True
Création d'un répertoire de travail
Créons un répertoire dédié à notre travail Ansible :
mkdir -p ~/project/ansible-lab
cd ~/project/ansible-lab
Création du fichier de configuration Ansible
Maintenant, créons un fichier de configuration Ansible de base dans notre répertoire de projet :
cat > ansible.cfg << 'EOF'
[defaults]
inventory = ./inventory
host_key_checking = False
remote_user = labex
EOF
Ce fichier de configuration :
- Spécifie l'emplacement de notre fichier d'inventaire
- Désactive la vérification des clés d'hôte SSH (utile pour les environnements de lab)
- Définit l'utilisateur distant par défaut sur 'labex'
Création du fichier d'inventaire
Le fichier d'inventaire définit les hôtes qu'Ansible gérera. Créons un fichier d'inventaire simple :
cat > inventory << 'EOF'
[local]
localhost ansible_connection=local
[virtual]
virtual-host ansible_host=10.10.10.10
EOF
Cet inventaire contient deux groupes :
local: Contient uniquement localhost, qui utilise une connexion localevirtual: Contient un hôte virtuel que nous utiliserons pour démontrer l'erreur 'UNREACHABLE!'
Le virtual-host est configuré avec une adresse IP (10.10.10.10) qui n'existe pas dans notre environnement, ce qui nous aidera à générer l'erreur 'UNREACHABLE!'.
Test d'Ansible
Testons notre configuration Ansible en exécutant une simple commande ping contre l'hôte local :
ansible local -m ping
Vous devriez voir une réponse réussie comme :
localhost | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
Cela confirme qu'Ansible fonctionne correctement pour la connexion locale. Maintenant, essayons de pinger l'hôte virtuel, ce qui devrait échouer :
ansible virtual -m ping
Cela produira l'erreur 'UNREACHABLE!' car l'hôte n'existe pas :
virtual-host | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: ssh: connect to host 10.10.10.10 port 22: Connection timed out",
"unreachable": true
}
Vous avez maintenant configuré avec succès Ansible et créé un scénario où l'erreur 'UNREACHABLE!' se produit, que nous étudierons à l'étape suivante.
Comprendre l'erreur 'UNREACHABLE!'
Dans l'étape précédente, nous avons rencontré l'erreur 'UNREACHABLE!' en essayant de nous connecter à un hôte inexistant. Maintenant, comprenons l'erreur plus en détail et explorons les causes courantes.
Analyse du message d'erreur
Examinons le message d'erreur que nous avons reçu :
virtual-host | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: ssh: connect to host 10.10.10.10 port 22: Connection timed out",
"unreachable": true
}
Le message d'erreur fournit des informations précieuses :
UNREACHABLE!indique qu'Ansible n'a pas pu établir de connexion avec l'hôte- Le champ
msgnous dit pourquoi : "Failed to connect to the host via ssh" (Échec de la connexion à l'hôte via ssh) - L'erreur spécifique est "Connection timed out" (Délai de connexion dépassé), ce qui signifie qu'Ansible a essayé de se connecter mais n'a reçu aucune réponse
Causes courantes des erreurs 'UNREACHABLE!'
L'erreur 'UNREACHABLE!' peut se produire pour plusieurs raisons :
- Problèmes de réseau : L'hôte peut être derrière un pare-feu, ou il peut y avoir des problèmes de connectivité réseau.
- Informations d'hôte incorrectes : Le nom d'hôte ou l'adresse IP dans l'inventaire peuvent être incorrects.
- Configuration SSH : SSH peut ne pas être configuré correctement sur l'hôte cible.
- Problèmes d'authentification : La clé SSH ou le mot de passe peuvent être incorrects.
- Indisponibilité de l'hôte : L'hôte peut être hors service ou inaccessible.
Création d'un playbook de test
Créons un playbook simple pour démontrer davantage l'erreur :
cat > test_playbook.yml << 'EOF'
---
- name: Test Connectivity
hosts: all
gather_facts: no
tasks:
- name: Ping the hosts
ping:
EOF
Ce playbook tente de pinger tous les hôtes définis dans notre inventaire. Exécutons-le :
ansible-playbook test_playbook.yml
Vous devriez voir une sortie similaire à :
PLAY [Test Connectivity] ************************************************
TASK [Ping the hosts] ***************************************************
ok: [localhost]
fatal: [virtual-host]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 10.10.10.10 port 22: Connection timed out", "unreachable": true}
PLAY RECAP *************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
virtual-host : ok=0 changed=0 unreachable=1 failed=0 skipped=0 rescued=0 ignored=0
Le playbook a réussi pour localhost mais a échoué pour virtual-host avec l'erreur 'UNREACHABLE!'.
Inspection des niveaux de verbosité Ansible
Ansible fournit différents niveaux de verbosité pour aider à diagnostiquer les problèmes. Essayons d'exécuter le playbook avec une verbosité accrue :
ansible-playbook test_playbook.yml -v
Pour une sortie encore plus détaillée, utilisez -vv ou -vvv :
ansible-playbook test_playbook.yml -vvv
L'option -vvv fournit la sortie la plus détaillée, montrant les commandes SSH exactes qu'Ansible essaie d'utiliser :
<virtual-host> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o User=labex -o ConnectTimeout=10 -o ControlPath=/home/labex/.ansible/cp/ansible-ssh-%h-%p-%r 10.10.10.10 '/bin/sh -c '"'"'echo ~labex && sleep 0'"'"''
Ce niveau de détail peut être inestimable pour le dépannage des problèmes de connexion SSH.
Utilisation de l'option --limit
Lorsque vous travaillez avec un grand inventaire, vous pouvez limiter Ansible à l'exécution de commandes contre des hôtes ou des groupes spécifiques en utilisant l'option --limit :
ansible-playbook test_playbook.yml --limit localhost
Cette commande n'exécutera le playbook que contre localhost, évitant l'erreur 'UNREACHABLE!' de virtual-host.
Maintenant que nous comprenons mieux l'erreur 'UNREACHABLE!', passons au dépannage et à la résolution de ces problèmes à l'étape suivante.
Dépannage et résolution des erreurs 'UNREACHABLE!'
Maintenant que nous comprenons ce qui cause les erreurs 'UNREACHABLE!', apprenons à les dépanner et à les corriger. Nous utiliserons diverses approches pour diagnostiquer et résoudre les problèmes de connectivité.
Correction des problèmes d'inventaire
L'une des causes les plus courantes des erreurs 'UNREACHABLE!' est une information d'inventaire incorrecte. Corrigeons notre fichier d'inventaire :
cd ~/project/ansible-lab
Tout d'abord, mettons à jour notre fichier d'inventaire pour inclure un hôte valide. Dans cet environnement de lab, nous nous concentrerons sur l'utilisation de localhost avec différentes méthodes de connexion pour démontrer les techniques de dépannage :
cat > inventory << 'EOF'
[local]
localhost ansible_connection=local
[ssh_local]
local-ssh ansible_host=127.0.0.1 ansible_connection=ssh
[virtual]
virtual-host ansible_host=10.10.10.10
EOF
Nous avons ajouté un nouveau groupe ssh_local avec un hôte qui tentera de se connecter à localhost via SSH au lieu de la méthode de connexion locale.
Test de la connectivité SSH directement
Avant d'utiliser Ansible, il est toujours bon de tester la connectivité SSH directement :
ssh 127.0.0.1
Vous pouvez être invité à entrer un mot de passe ou voir un message concernant la clé d'hôte. C'est bon signe car cela signifie que la connectivité SSH fonctionne, mais vous devrez peut-être configurer SSH correctement pour Ansible.
Appuyez sur Ctrl+C pour quitter si vous êtes bloqué à l'invite de mot de passe.
Configuration des clés SSH pour l'authentification sans mot de passe
Ansible utilise généralement des clés SSH pour l'authentification. Configurer l'accès SSH sans mot de passe à localhost :
## Générer une clé SSH si vous n'en avez pas
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
## Ajouter la clé à authorized_keys
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
## Définir les permissions appropriées
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Maintenant, essayez de vous connecter à localhost via SSH :
ssh 127.0.0.1
Vous devriez pouvoir vous connecter sans être invité à entrer un mot de passe. Tapez exit pour revenir à votre session d'origine.
Test d'Ansible avec la connexion SSH
Maintenant, testons Ansible avec la connexion SSH à localhost :
ansible ssh_local -m ping
Si la configuration SSH est correcte, vous devriez voir une réponse réussie :
local-ssh | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
Si vous voyez toujours une erreur 'UNREACHABLE!', ajoutons plus de paramètres de connexion à notre fichier d'inventaire :
cat > inventory << 'EOF'
[local]
localhost ansible_connection=local
[ssh_local]
local-ssh ansible_host=127.0.0.1 ansible_connection=ssh ansible_user=labex ansible_ssh_private_key_file=~/.ssh/id_rsa
[virtual]
virtual-host ansible_host=10.10.10.10
EOF
Essayez à nouveau la commande ping :
ansible ssh_local -m ping
Utilisation d'Ansible avec une configuration SSH personnalisée
Parfois, vous avez besoin de configurations SSH plus complexes. Créons un fichier de configuration SSH personnalisé :
mkdir -p ~/.ssh
cat > ~/.ssh/config << 'EOF'
Host local-ssh
HostName 127.0.0.1
User labex
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
EOF
## Définir les permissions appropriées
chmod 600 ~/.ssh/config
Mettez à jour l'inventaire pour utiliser l'entrée de configuration SSH :
cat > inventory << 'EOF'
[local]
localhost ansible_connection=local
[ssh_local]
local-ssh
[virtual]
virtual-host ansible_host=10.10.10.10
EOF
Testez à nouveau la connexion :
ansible ssh_local -m ping
Création d'un playbook pour tester toutes les connexions
Créons un playbook complet pour tester toutes nos connexions :
cat > connection_test.yml << 'EOF'
---
- name: Test Local Connection
hosts: local
gather_facts: no
tasks:
- name: Ping local
ping:
register: local_ping
- name: Display local ping result
debug:
var: local_ping
- name: Test SSH Connection
hosts: ssh_local
gather_facts: no
tasks:
- name: Ping via SSH
ping:
register: ssh_ping
- name: Display SSH ping result
debug:
var: ssh_ping
EOF
Exécutez le playbook :
ansible-playbook connection_test.yml
Vous devriez voir des connexions réussies aux hôtes local et SSH :
PLAY [Test Local Connection] ********************************************
TASK [Ping local] ******************************************************
ok: [localhost]
TASK [Display local ping result] ****************************************
ok: [localhost] => {
"local_ping": {
"changed": false,
"ping": "pong"
}
}
PLAY [Test SSH Connection] **********************************************
TASK [Ping via SSH] ****************************************************
ok: [local-ssh]
TASK [Display SSH ping result] *****************************************
ok: [local-ssh] => {
"ssh_ping": {
"changed": false,
"ping": "pong"
}
}
PLAY RECAP *************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
local-ssh : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
La sortie réussie confirme que nous avons corrigé les erreurs 'UNREACHABLE!' pour nos hôtes valides. Le seul hôte qui reste inaccessible est virtual-host, ce qui est intentionnel puisqu'il n'existe pas.
Vous avez maintenant réussi à diagnostiquer et à corriger les erreurs 'UNREACHABLE!' en :
- Testant la connectivité SSH directe
- Configurant les clés SSH pour l'authentification sans mot de passe
- Configurant l'inventaire Ansible avec les paramètres de connexion appropriés
- Utilisant une configuration SSH personnalisée
- Vérifiant la connectivité avec un playbook complet
Mise en œuvre des meilleures pratiques pour prévenir les erreurs 'UNREACHABLE!'
Maintenant que nous avons corrigé les erreurs 'UNREACHABLE!' immédiates, concentrons-nous sur les meilleures pratiques pour les prévenir à l'avenir. Cela implique une gestion appropriée de l'inventaire, des configurations de connexion et des techniques de gestion des erreurs.
Création d'une structure d'inventaire robuste
Un inventaire bien organisé facilite le dépannage. Créons un répertoire d'inventaire plus structuré :
cd ~/project/ansible-lab
mkdir -p inventory/{group_vars,host_vars}
Maintenant, créons un fichier d'inventaire principal :
cat > inventory/hosts << 'EOF'
## Production Servers
[production]
## prod-server ansible_host=prod.example.com
## Development Servers
[development]
## dev-server ansible_host=dev.example.com
## Local Connections
[local]
localhost ansible_connection=local
## SSH Connections
[ssh_local]
local-ssh ansible_host=127.0.0.1
EOF
Ensuite, créons des variables de groupe pour le groupe de connexion SSH :
cat > inventory/group_vars/ssh_local.yml << 'EOF'
---
ansible_connection: ssh
ansible_user: labex
ansible_ssh_private_key_file: ~/.ssh/id_rsa
ansible_ssh_common_args: '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
EOF
Mettez à jour la configuration Ansible pour utiliser le nouveau répertoire d'inventaire :
cat > ansible.cfg << 'EOF'
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
retry_files_enabled = True
retry_files_save_path = ~/.ansible/retry-files
timeout = 30
connect_timeout = 30
command_timeout = 30
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
control_path_dir = ~/.ansible/cp
EOF
Création d'un playbook de test de connexion avec une logique de nouvelle tentative
Ansible vous permet de réessayer les tâches ayant échoué. Créons un playbook avec une logique de nouvelle tentative :
cat > connection_test_with_retry.yml << 'EOF'
---
- name: Test All Connections
hosts: all
gather_facts: no
tasks:
- name: Ping hosts
ping:
register: ping_result
retries: 3
delay: 5
until: ping_result is not failed
ignore_unreachable: yes
- name: Display ping status
debug:
msg: "Connection to {{ inventory_hostname }} was successful"
when: ping_result is success
- name: Report unreachable hosts
debug:
msg: "Host {{ inventory_hostname }} is unreachable"
when: ping_result is unreachable
EOF
Exécutez le playbook avec notre nouvelle structure d'inventaire :
ansible-playbook connection_test_with_retry.yml
Vous devriez voir une sortie montrant les connexions réussies à localhost et local-ssh.
Gestion des erreurs 'UNREACHABLE!' avec élégance
Créons un playbook plus avancé qui gère les erreurs 'UNREACHABLE!' avec élégance et génère un rapport :
cat > connection_report.yml << 'EOF'
---
- name: Test Connections and Generate Report
hosts: all
gather_facts: no
tasks:
- name: Try to connect to hosts
ping:
register: ping_result
ignore_unreachable: yes
- name: Create reachable hosts list
set_fact:
reachable_hosts: "{{ (reachable_hosts | default([])) + [inventory_hostname] }}"
when: ping_result is success
delegate_to: localhost
delegate_facts: true
- name: Create unreachable hosts list
set_fact:
unreachable_hosts: "{{ (unreachable_hosts | default([])) + [inventory_hostname] }}"
when: ping_result is unreachable
delegate_to: localhost
delegate_facts: true
- name: Generate Connection Report
hosts: localhost
gather_facts: no
tasks:
- name: Display reachable hosts
debug:
msg: "Reachable hosts: {{ reachable_hosts | default([]) | join(', ') }}"
- name: Display unreachable hosts
debug:
msg: "Unreachable hosts: {{ unreachable_hosts | default([]) | join(', ') }}"
- name: Write report to file
copy:
content: |
Connection Report
-----------------
Reachable hosts: {{ reachable_hosts | default([]) | join(', ') }}
Unreachable hosts: {{ unreachable_hosts | default([]) | join(', ') }}
Generated on: {{ ansible_date_time.iso8601 }}
dest: ~/project/ansible-lab/connection_report.txt
register: report
- name: Show report location
debug:
msg: "Report saved to {{ report.dest }}"
EOF
Exécutez le playbook de rapport :
ansible-playbook connection_report.yml
Vérifions le rapport :
cat ~/project/ansible-lab/connection_report.txt
Vous devriez voir un rapport listant les hôtes accessibles et inaccessibles.
Utilisation des plugins d'inventaire Ansible
Ansible fournit des plugins d'inventaire pour gérer dynamiquement les hôtes. Créons un script simple pour le démontrer :
cat > inventory_script.py << 'EOF'
#!/usr/bin/env python3
import json
import socket
def is_host_reachable(host, port=22, timeout=1):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(timeout)
result = sock.connect_ex((host, port))
sock.close()
return result == 0
except:
return False
## Define our hosts
hosts = {
'localhost': '127.0.0.1',
'local-ssh': '127.0.0.1',
'virtual-host': '10.10.10.10'
}
## Check reachability and build inventory
inventory = {
'all': {
'hosts': list(hosts.keys())
},
'reachable': {
'hosts': []
},
'unreachable': {
'hosts': []
},
'_meta': {
'hostvars': {}
}
}
for hostname, ip in hosts.items():
reachable = is_host_reachable(ip)
group = 'reachable' if reachable else 'unreachable'
inventory[group]['hosts'].append(hostname)
inventory['_meta']['hostvars'][hostname] = {
'ansible_host': ip,
'reachability_checked': True,
'is_reachable': reachable
}
print(json.dumps(inventory, indent=2))
EOF
chmod +x inventory_script.py
Testez le script d'inventaire dynamique :
./inventory_script.py
Vous devriez voir une sortie JSON montrant les hôtes classés comme accessibles ou inaccessibles.
Exécutons un playbook en utilisant cet inventaire dynamique :
ansible-playbook -i ./inventory_script.py connection_test.yml --limit reachable
Cela tentera uniquement de se connecter aux hôtes que le script a déterminés comme étant accessibles, ce qui vous aidera à éviter complètement les erreurs 'UNREACHABLE!'.
Ces meilleures pratiques fournissent un cadre robuste pour gérer la connectivité Ansible et prévenir les erreurs 'UNREACHABLE!' dans les environnements de production.
Résumé
Dans ce lab, vous avez appris à identifier, dépanner et prévenir l'erreur 'UNREACHABLE!' dans Ansible. Vous avez :
Mis en place un environnement Ansible de base et rencontré l'erreur 'UNREACHABLE!' directement
Analysé le message d'erreur et compris les causes courantes des problèmes de connectivité
Utilisé diverses techniques de dépannage pour diagnostiquer les problèmes de connexion
Mis en œuvre des solutions pour corriger les erreurs, notamment :
- Configuration des clés SSH pour l'authentification sans mot de passe
- Configuration de fichiers d'inventaire appropriés
- Utilisation des options de configuration SSH
Appliqué les meilleures pratiques pour prévenir les futures erreurs 'UNREACHABLE!', telles que :
- Création d'une organisation d'inventaire structurée
- Mise en œuvre d'une logique de nouvelle tentative
- Développement de stratégies de gestion des erreurs
- Utilisation de scripts d'inventaire dynamiques pour vérifier l'accessibilité des hôtes
Ces compétences vous aideront à maintenir des déploiements Ansible fiables et à résoudre rapidement tous les problèmes de connectivité qui se présentent. En comprenant les causes sous-jacentes des erreurs 'UNREACHABLE!' et en mettant en œuvre des mesures préventives appropriées, vous pouvez vous assurer que l'automatisation de votre infrastructure fonctionne de manière fluide et efficace.


