Déboguer vos playbooks Ansible

Dans ce chapitre, nous allons apprendre différentes façons de déboguer nos Playbooks Ansible.

Introduction

Lors du dépannage des problèmes Ansible, il est utile de savoir comment tester votre playbook en toute sécurité, activer le mode de débogage et augmenter le niveau de verbosité. Nous allons apprendre à faire tout cela dans ce chapitre.

Les différentes manières de débogage

Mode vérification

Des fois, vous aurez besoin de vérifier si une tâche est fonctionnelle sur vos serveurs distants sans avoir à effectuer de modifications sur vos systèmes distants. Pour ce cas d'utilisation, il faut penser à l'option --check de la commande ansible-playbook.

ansible-playbook main.yml --check

Parfois, vous souhaiterez peut-être enter en mode de vérification sur des tâches individuelles. Cela peut se faire via l'instruction check_mode, qui peut être ajoutée à vos tâches, comme suit :

tasks:
  - name: Add test text in /home/hatim/hatim.txt
    lineinfile:
        line: "test"
        dest: /home/hatim/hatim.txt
        state: present
    check_mode: yes

Si vous souhaitez utiliser l'option --check et ignorer les erreurs sur certaines tâches en mode vérification, vous pouvez utiliser la variable booléenne ansible_check_mode qui aura comme valeur True pendant le mode vérification :

tasks:
  - name: Add test text in /home/hatim/notfound.txt
    lineinfile:
        line: "test"
        dest: /home/hatim/notfound.txt
        state: present
    ignore_errors: '{{ ansible_check_mode }}'
    # Vous pouvez aussi l'instruction suivante: when: not ansible_check_mode
  
  - debug: msg="Si vous voyez ce message c'est que la tâche précédente a été ignorée"

Exécutons le playbook pour voir le résultat :

ansible-playbook main.yml --check

Résultat :

TASK [Add test text in /home/hatim/notfound.txt] ************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Destination /home/hatim/notfound.txt does not exist !", "rc": 257}
...ignoring

TASK [debug] *******************
ok: [localhost] => {
    "msg": "Si vous voyez ce message c'est que la tâche précédente a été ignorée"
}

Mode différenciation

C'est bien beau tout ça, mais ça serait mieux si Ansible nous avertit des modifications qu'il est supposé apporter sur la machine cible. Pour cela il existe l'option --diff qui est principalement utilisée dans les modules qui manipulent des fichiers, mais d'autres modules peuvent également afficher des informations «avant et après» (par exemple, le module user). D'ailleurs, elle fonctionne très bien avec l'option --check :

Information

Étant donné que l'option diff produit une grande quantité de sortie, il est préférable de l'utiliser lors de la vérification d'un seul hôte à la fois

Reprenons l'exécution de notre exemple précédent :

tasks:
  - name: Add test text in /home/hatim/hatim.txt
    lineinfile:
        line: "test"
        dest: /home/hatim/hatim.txt
        state: present
ansible-playbook main.yml --check --diff

Résultat :

TASK [Add test text in /home/hatim/hatim.txt] *********************************************
--- before: /home/hatim/hatim.txt (content)
+++ after: /home/hatim/hatim.txt (content)
@@ -0,0 +1 @@
+test

changed: [localhost]

Si vous souhaitez activer la différence sur une tâche particulière, vous pouvez utiliser l'instruction booléenne diff. Selon comment vous lancez votre playbook, vous pouvez déclencher les comportements suivants :

  • Si vous n'êtes pas en mode différenciation et que l'instruction diff est à True alors seule la tâche exécutant cette instruction entrera en mode différenciation.
  • Si êtes en mode différenciation et que l'instruction diff est à False alors seule la tâche exécutant cette instruction ignorera le mode différenciation.

Voici comment elle s'intègre dans un playbook :

tasks:
  - name: Add test text in /home/hatim/hatim.txt
    lineinfile:
        line: "test"
        dest: /home/hatim/hatim.txt
        state: present
    diff: no

Le debugger des playbooks

Ansible inclut un débogueur, ce débogueur vous permet de déboguer vos tâches, c'est-à-dire que vous avez accès à toutes les fonctionnalités du débogueur dans le contexte de la tâche. Vous pouvez par exemple, vérifier ou modifier la valeur des variables de votre playbook, mettre à jour les arguments de votre module/tâche et relancer votre tâche avec les nouvelles variables et les nouveaux arguments pour vous aider à résoudre la cause de l'échec.

Pour utiliser le débogueur d'Ansible vous devez utiliser l'instruction debugger qui peut prendre les valeurs suivantes :

  • always: appeler toujours le débogueur, quel que soit le résultat.
  • never: n'invoquer jamais le débogueur, quel que soit le résultat.
  • on_failed: n'appeler le débogueur qu'en cas d'échec d'une tâche.
  • on_unreachable: n'appeler le débogueur que si l'hôte a est inaccessible.
  • on_skipped: n'appeler le débogueur uniquement si la tâche est ignorée.

L'instruction debugger peut être utilisée sur une tâche particulière ou pour toutes vos tâches.

Pour une tâche particulière :

- name: Execute a command
  command: ls -l /home/hatim
  debugger: on_failed

Pour toutes vos tâches :

- hosts: all
  debugger: on_failed
  tasks:
    - name: Execute a command
      command: ls -l /home/hatim

Quand vous entrez en mode debug vous pouvez utiliser différentes commandes :

  • p task/task_vars/host/result: affiche des informations utilisées pendant l'exécution par votre tâche module(le p équivaut au print).
  • task.args[key] = value: met à jour l'argument du module.
  • task_vars[key] = value: met à jour les variables de votre playbook.
  • update_task: si vous modifiez les task_vars alors utilisez cette commande pour recréer la tâche à partir de votre nouvelle structure de données.
  • redo: exécutez à nouveau la tâche.
  • continue: passe à la tâche suivante.
  • quit: quitte le débogueur. L'exécution du playbook est abandonnée.

Voici ci-dessous un exemple d'utilisation, je vais intentionnellement utiliser le module lineinfile avec un fichier qui n'existe pas, et par la suite je vais déboguer cette tâche pour remettre le bon chemin de mon fichier. Voici déjà à quoi ressemble mon playbook avec notre mauvaise valorisation :

tasks:
  - name: Add test text in /home/hatim/hatim.txt
    lineinfile:
        line: "test"
        dest: /home/hatim/hatim_fault.txt
        state: present
    debugger: on_failed

En exécutant notre playbook, nous nous retrouverons en mode debug :

ansible-playbook main.yml

Résultat :

TASK [Add test text in /home/hatim/hatim.txt] **************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Destination /home/hatim/hatim_fault.txt does not exist !", "rc": 257}
[localhost] TASK: Add test text in /home/hatim/hatim.txt (debug)>

Nous savons par avance que l'erreur vient de la mauvaise valorisation du paramètre dest, nous allons donc modifier sa valeur dans notre débogueur. Voici la démarche que je vais suivre pour arriver à notre but :

  • Afficher plus d'informations sur notre erreur.
  • Afficher les valeurs des différents arguments de notre tâche.
  • Modifier la valeur de notre paramètre dest.
  • Afficher la nouvelle valeur de notre paramètre dest.
  • Exécuter de nouveau notre tâche.

Si nous transformons notre démarche sous forme de commandes dans notre outil de débogage, nous taperons les commandes suivantes :

(debug)> p result._result
{'_ansible_no_log': False,
 '_ansible_parsed': True,
 'changed': False,
 u'failed': True,
 u'invocation': {u'module_args': {u'attributes': None,
                                  ...
                                  u'delimiter': None,
                                  u'dest': u'/home/hatim/hatim_fault.txt',
                                  u'directory_mode': None,
                                  ...
 u'msg': u'Destination /home/hatim/hatim_fault.txt does not exist !',
 u'rc': 257}

(debug)> p task.args
{'_ansible_check_mode': False,
 ...
 u'dest': u'/home/hatim/hatim_fault.txt',
 u'line': u'test',
 u'state': u'present'}

(debug)> task.args['dest'] = '/home/hatim/hatim.txt'

(debug)> p task.args['dest']
'/home/hatim/hatim.txt'

(debug)> redo
changed: [localhost]

PLAY RECAP ****************************************************************************
localhost : ok=1    changed=1    unreachable=0    failed=0

Enfin vous pouvez activer le mode débogage pour chaque exécution de votre playbook en mettant la variable enable_task_debugger à True dans le fichier ansible.cfg:

[defaults]
enable_task_debugger = True

La verbosité dans Ansible

Pour comprendre ce qui se passe lorsque vous exécutez le playbook, vous pouvez exécuter la commande ansible-playbook avec l' option verbose -v. Chaque "v" supplémentaire fournira à l'utilisateur final plus de sortie de débogage (vous pouvez aller jusqu'à 4 niveaux de verbosité) :

# verbosité niveau 0
ansible-playbook main.yml

# verbosité niveau 1
ansible-playbook -v main.yml

# verbosité niveau 2
ansible-playbook -vv main.yml

# verbosité niveau 3
ansible-playbook -vvv main.yml

# verbosité niveau 4
ansible-playbook -vvvv main.yml

Vous pouvez également modifier la fichier ansible.cfg pour appliquer un niveau de verbosité pour chaque exécution de vos playbooks :

[defaults]
verbosity  = 3

Conclusion

Nous avons étudié de nombreuses manières de procéder à des tests sécurisés de vos playbooks , et vous avez désormais tous les outils à votre disposition pour identifier et corriger vos bogues à partir de votre playbook. Rendez-vous au prochain chapitre où nous aborderons la notion de performance pour nos playbooks.

Espace commentaire

Écrire un commentaire

Rejoignez la discussion

Vous devez être connecté pour poster un message.

28 commentaires

ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

N'oubliez pas que le debugger ne remplace pas une bonne lecture des logs. Si vous avez des problèmes récurrents, commencez par -vvv avant de sortir l'artillerie lourde du debugger.

03/03/2020 à 11:08
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Utilise la variable ansible_check_mode comme ceci :

- name: Tache risquée
  command: /usr/bin/false
  ignore_errors: "{{ ansible_check_mode }}"
03/03/2020 à 04:39
thomas-tristan
Membre Actif
Avatar de thomas-tristan
thomas-tristan
Membre Actif

Comment faire pour ignorer une erreur seulement quand on est en mode check ?

02/03/2020 à 21:06
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Exact. Ne jamais partager de logs en -vvvv sur un forum public. Nettoie toujours les infos sensibles avant de poster un debug.

02/03/2020 à 13:49
olecomte
Membre Actif
Avatar de olecomte
olecomte
Membre Actif

Le -vvvv c'est trop verbeux, ça affiche les clés privées SSH parfois, attention aux logs !

02/03/2020 à 06:54
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Oui, il suffit de mettre debugger: never sur la tâche en question. Ça prendra le pas sur la configuration globale.

02/03/2020 à 02:00
nguyen-christiane
Membre Actif
Avatar de nguyen-christiane
nguyen-christiane
Membre Actif

Peut-on désactiver le debugger pour une tâche précise alors qu'il est activé globalement ?

01/03/2020 à 21:12
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Assure-toi que tu as bien placé la config dans le bon fichier, celui qui est lu par ton projet (ansible.cfg local). Vérifie avec ansible --version quel fichier de config est utilisé.

01/03/2020 à 16:25
rmoreno
Membre Actif
Avatar de rmoreno
rmoreno
Membre Actif

J'ai activé enable_task_debugger = True dans ansible.cfg mais rien ne se passe. Je suis sur une version récente.

01/03/2020 à 12:14
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Pas forcément. Si ton module custom n'a pas été codé pour supporter le check_mode, il risque de ne rien faire ou de planter. Vérifie la doc de ton module.

01/03/2020 à 07:04
edouard21
Membre Actif
Avatar de edouard21
edouard21
Membre Actif

Le mode --check est-il fiable avec les modules custom ?

01/03/2020 à 03:04
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

task.args c'est ce que tu as défini dans ton YAML. result._result c'est ce que le module a retourné après l'exécution. C'est là que tu vois pourquoi ça a réellement merdé.

29/02/2020 à 21:29
wjoubert
Membre Actif
Avatar de wjoubert
wjoubert
Membre Actif

Je ne comprends pas bien la différence entre p task.args et p result._result dans le debugger.

29/02/2020 à 16:26
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Oui, tu peux définir debugger: on_failed au niveau de la définition du block dans ton playbook. Ça héritera sur toutes les tâches du bloc.

29/02/2020 à 09:49
ghubert
Membre Actif
Avatar de ghubert
ghubert
Membre Actif

Est-ce qu'on peut utiliser debugger sur un bloc entier ?

29/02/2020 à 05:00
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

C'est typique d'un fichier absent. Ansible essaie de lire le statut avant modification. Vérifie tes chemins et tes droits d'accès avec un simple ls -l sur la machine cible avant de relancer.

28/02/2020 à 23:53
imoreno
Membre Actif
Avatar de imoreno
imoreno
Membre Actif

J'ai une erreur rc: 257 quand je check un fichier. C'est lié à Ansible ou à mes droits sur le serveur ?

28/02/2020 à 17:42
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Tu peux mettre verbosity = 1 dans la section [defaults]. Ça suffit largement pour voir quel module est en train de tourner sans avoir le dump complet de la connexion SSH.

28/02/2020 à 12:14
margaux45
Membre Actif
Avatar de margaux45
margaux45
Membre Actif

Quelqu'un sait comment augmenter la verbosité via le fichier ansible.cfg sans tout spammer ?

28/02/2020 à 06:39
honore-lopes
Membre Actif
Avatar de honore-lopes
honore-lopes
Membre Actif

Merci pour le tuto. Le mode --check m'a sauvé d'un désastre en prod hier.

28/02/2020 à 00:12
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

T'as bien tapé update_task après avoir modifié tes variables ?

Le debugger ne prend pas en compte les changements en temps réel dans le contexte de la tâche en cours sans cette commande de synchronisation.

27/02/2020 à 19:13
emile12
Membre
Avatar de emile12
emile12
Membre

J'ai testé le debugger mais je n'arrive pas à modifier les variables dynamiquement avec task_vars[key] = value. Ça me jette une erreur.

27/02/2020 à 14:30
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Comme indiqué, utilise --diff uniquement sur un hôte à la fois avec --limit. Sinon, tu peux désactiver le diff sur des tâches spécifiques via diff: no dans tes fichiers de tâches pour nettoyer la sortie.

27/02/2020 à 06:36
jperrin
Membre
Avatar de jperrin
jperrin
Membre

Le mode --diff c'est la vie. Par contre, sur des gros playbooks, ça pollue le terminal. Y a moyen de filtrer ?

27/02/2020 à 00:04
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Vérifie bien que ton ansible.cfg n'a pas une directive qui écrase ton comportement ou que tu n'as pas activé le debugger de manière globale via enable_task_debugger = True.

Si tu veux forcer le debug sur une tâche, assure-toi que la syntaxe est bien indentée sous le nom de la tâche :

- name: Ma tache
  debug: msg="test"
  debugger: on_failed
26/02/2020 à 19:47

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire
An Error Occurred: Internal Server Error

Oops! An Error Occurred

The server returned a "500 Internal Server Error".

Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.