Aller au contenu
Infrastructure as Code medium

Debug des premières erreurs Ansible : Permission denied, MODULE FAILURE, YAML

11 min de lecture

Logo Ansible

Quand un playbook échoue, le message d’erreur Ansible peut paraître impénétrable. En réalité, 80 % des erreurs des débutants tombent dans 10 catégories récurrentes — toujours les mêmes — qui se diagnostiquent en quelques minutes une fois qu’on connaît les bons réflexes. Cette page liste ces 10 erreurs avec symptôme → cause probable → fix immédiat, et finit par le workflow de debug générique (-vvv, ansible-config dump, ansible-inventory --graph) qui résout 95 % des cas restants.

Gardez cette page ouverte pendant vos premiers playbooks — c’est exactement le réflexe que vous aurez plus tard sur une fleet de production quand un cron de nuit casse à 3 h du matin.

  • Identifier rapidement la catégorie d’erreur à partir du message brut ;
  • Corriger chaque cas avec une commande ou une modification ciblée ;
  • Lancer le mode verbeux (-v, -vv, -vvv, -vvvv) pour récupérer les détails utiles ;
  • Inspecter la configuration active et l’inventaire vu par Ansible avec ansible-config dump et ansible-inventory --graph ;
  • Prévenir les erreurs structurelles via ansible-lint et yamllint.
SymptômeCatégorieCause probableFix express
Permission denied (publickey)SSHClé publique absente côté managed nodessh-copy-id ou re-provisionner
Permissions 0644 for 'id_ed25519' are too openSSHClé privée trop permissivechmod 0600 ssh/id_ed25519
Failed to connect to the host via ssh: Connection timed outSSHFirewall, IP fausse, hijacking ~/.ssh/configssh -vvv ansible@IP
Host key verification failedSSHknown_hosts incohérent (VM recréée)ssh-keygen -R IP ou host_key_checking = False
sudo: a password is requiredSudoNOPASSWD absent côté managed nodeVérifier /etc/sudoers.d/ ou ajouter --ask-become-pass
MODULE FAILURE: No module named ansiblePythonPython 3 absent côté managed nodeBootstrap via module raw
MODULE FAILURE: No module named 'firewall'CollectionBinding Python du module manquantdnf install python3-firewall
mapping values are not allowed hereYAMLIndentation incohérente, deux-points dans une stringyamllint + corriger
Could not match supplied host patternInventaireHôte ou groupe inexistant dans l’inventaireansible-inventory --graph
[WARNING]: ansible_python_interpreter discoveryPythonInterpréteur Python ambigu sur l’hôtePoser ansible_python_interpreter explicitement

Suivent les sections détaillées pour les cas qui demandent un développement.

Message complet :

fatal: [web1.lab]: UNREACHABLE! => changed=false
msg: 'Failed to connect to the host via ssh: ansible@10.10.20.21: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).'
unreachable: true

Causes possibles :

  • La clé publique n’a jamais été déposée dans ~/.ssh/authorized_keys côté managed node.
  • L’utilisateur Ansible n’est pas celui que vous croyez (ansible_user mal défini).
  • La clé privée utilisée par Ansible n’est pas celle qui a été déployée.
  • Les permissions de ~/.ssh/ (0700) ou ~/.ssh/authorized_keys (0600) sont fausses côté managed node.

Diagnostic :

Fenêtre de terminal
ssh -vvv -i ssh/id_ed25519 ansible@10.10.20.21 2>&1 | grep -E "Authenticating|Offering|Authentications"

Vous verrez quelle clé Ansible essaie d’utiliser et quelle réponse le serveur retourne.

Fix :

Fenêtre de terminal
# Si lab : régénérer le lab proprement
make destroy && make bootstrap && make provision
# Si fleet existante : redéployer la clé
ssh-copy-id -i ssh/id_ed25519.pub ansible@10.10.20.21

Message :

fatal: [web1.lab]: FAILED! => changed=false
module_stderr: |-
sudo: a password is required
msg: 'MODULE FAILURE: sudo: a password is required'

Cause : votre playbook a become: true mais le compte côté managed node n’a pas de NOPASSWD dans /etc/sudoers.d/. Le cloud-init du lab pose ansible ALL=(ALL) NOPASSWD:ALL automatiquement ; sur une fleet existante, vous devez le poser manuellement.

Fix temporaire : lancer avec --ask-become-pass (ou -K) qui demande le mot de passe sudo une fois :

Fenêtre de terminal
ansible-playbook site.yml --ask-become-pass

Fix durable : poser un fichier /etc/sudoers.d/ansible côté managed nodes via un premier playbook de bootstrap (qui peut utiliser --ask-become-pass une fois).

Trois variantes selon ce qui manque :

No module named ansible ou ImportError: No module named 'ansible'

Section intitulée « No module named ansible ou ImportError: No module named 'ansible' »

Le Python 3 n’est pas installé sur le managed node, ou n’est pas accessible à Ansible. Sur une image RHEL UBI minimale, par exemple, Python est absent par défaut.

Fix : un play de bootstrap qui utilise le module raw (pas de Python requis) pour installer Python 3, suivi de plays normaux. Cf. la section Bootstrap d’un host sans Python 3.

Le module ansible.posix.firewalld a besoin du binding Python python3-firewall côté cible. Sans lui, l’erreur tombe au runtime malgré firewalld installé.

Fix : ajouter python3-firewall à votre playbook de préparation (déjà fait dans labs/bootstrap/prepare-managed-nodes/playbook.yml).

Idem côté SELinux : il faut python3-libselinux côté managed node pour que les modules Ansible respectent le contexte SELinux quand ils créent des fichiers.

Message typique :

ERROR! Syntax Error while loading YAML.
mapping values are not allowed here
The error appears to be in '/home/bob/Projets/ansible-training/site.yml': line 12, column 19

Cause : un deux-points (:) dans une chaîne non quotée, ou une indentation incohérente. C’est le piège YAML n°1.

Exemples de YAML cassé :

- name: Configurer un site: prod # ← le deuxième `:` casse tout
- name: "Configurer un site: prod" # ← OK avec quotes

Fix : lancer yamllint sur le fichier avant ansible-playbook :

Fenêtre de terminal
yamllint site.yml

Et systématiquement quoter les chaînes qui contiennent :, #, ou commencent par un caractère ambigu (*, &, !, ?, |, >).

Message :

[WARNING]: Could not match supplied host pattern, ignoring: webservr

Cause : typo sur le nom du groupe ou de l’hôte. Le pattern webservr n’existe pas, Ansible l’ignore silencieusement et finit par ne rien faire.

Diagnostic immédiat :

Fenêtre de terminal
ansible-inventory --graph

Affiche l’arbre exact des groupes et hôtes vus par Ansible. Comparez avec votre commande.

Fix : corriger la typo. Pour éviter le piège, intégrez ansible-inventory --graph dans votre workflow avant d’écrire un nouveau pattern.

6. Failed to connect to the host via ssh: Connection timed out

Section intitulée « 6. Failed to connect to the host via ssh: Connection timed out »

Causes possibles :

  • Firewall côté managed node (port 22 fermé) ;
  • IP dans l’inventaire ne correspond plus à l’hôte (DHCP changé) ;
  • ~/.ssh/config local avec un Host 10.* ProxyJump qui hijack la connexion ;
  • VM éteinte ou crashée.

Diagnostic :

Fenêtre de terminal
# 1. La VM est-elle up et joignable en ICMP ?
ping -c 1 10.10.20.21
# 2. Le port 22 est-il ouvert ?
nc -z 10.10.20.21 22 && echo OK || echo BLOCKED
# 3. SSH tente la bonne IP ?
ssh -vvv ansible@10.10.20.21 2>&1 | grep "Connecting to"

Si la troisième commande affiche une IP différente de 10.10.20.21, votre ~/.ssh/config redirige la connexion (hijacking).

Fix : poser un bloc spécifique dans ~/.ssh/config.d/ qui surcharge le générique :

Host 10.10.20.*
ProxyCommand none
ProxyJump none
IdentityFile ~/Projets/ansible-training/ssh/id_ed25519
User ansible

7. [WARNING]: ansible_python_interpreter discovery

Section intitulée « 7. [WARNING]: ansible_python_interpreter discovery »

Message :

[WARNING]: Platform linux on host web1.lab is using the discovered Python interpreter at
/usr/bin/python3.12, but future installation of another Python interpreter could change the
meaning of that path.

Cause : Ansible a deviné l’interpréteur Python à utiliser, mais signale que ça pourrait changer si vous installez un autre Python.

Fix : poser explicitement ansible_python_interpreter dans votre inventaire ou variables de groupe :

all:
vars:
ansible_python_interpreter: /usr/bin/python3.12

C’est ce que fait l’inventaire du lab — pas de warning et un comportement déterministe.

Quand un message ne suffit pas, augmentez la verbosité :

NiveauEffet
-vSortie verbose des modules
-vvDétails de connexion, paths résolus
-vvvTrace SSH complète (commandes envoyées)
-vvvvVerbosité maximale + debug Python sur la cible

Pour comprendre quelle config Ansible utilise réellement :

Fenêtre de terminal
ansible-config dump --only-changed

Liste les paramètres qui diffèrent des défauts, avec leur source (variable d’environnement, fichier ansible.cfg, etc.). Indispensable quand un comportement vous surprend.

Pour comprendre quels hôtes Ansible voit :

Fenêtre de terminal
ansible-inventory --graph # vue arborescente
ansible-inventory --host web1.lab # variables résolues sur un hôte
ansible-inventory --list --yaml # vue exhaustive

Trois outils à intégrer dans votre workflow dès le premier playbook :

  • yamllint sur tous vos fichiers YAML — détecte les indentations cassées et les : non quotés ;
  • ansible-lint sur vos playbooks — détecte les anti-patterns Ansible (modules command/shell non gardés par creates:, tâches sans name:, modules dépréciés) ;
  • ansible-playbook --check --diff avant la vraie exécution — dry-run + affichage des diffs.

Intégrés en CI, ces trois commandes éliminent 80 % des erreurs structurelles avant qu’elles n’atteignent vos managed nodes.

  • 80 % des erreurs débutant tombent dans 10 catégories : SSH, sudo, Python, YAML, inventaire, connexion réseau.
  • Le réflexe n°1 : augmenter la verbosité avec -vvv pour voir les détails de connexion SSH.
  • ansible-config dump --only-changed + ansible-inventory --graph résolvent la majorité des cas où le comportement surprend.
  • yamllint + ansible-lint + --check en CI préviennent les erreurs structurelles avant la production.
  • Les permissions Unix sur ~/.ssh/ (0700) et authorized_keys (0600) sont strictement requises — OpenSSH refuse silencieusement sinon.
  • Sur une fleet où Python 3 manque, bootstrappez via le module raw avant les modules normaux.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn