Il peut être difficile de débuguer son code avec Ansible. Etant donné que tout est YAML, comment fait-on pour y voir plus clair ? C’est ce que nous verrons dans cet article.

Contexte

J’ai écrit un playbook, son exécution dure 10 minutes (oui oui, 10 min), mais j’ai une erreur en plein milieu.

Ce genre de situation peut vous arriver, et corriger un problème peut être un vrai calvaire. Ansible fournit quelques outils, et avec un peu de malice, on arrive toujours à ses fins, mais à quel prix : le temps.

Les erreurs

Ansible affiche les erreurs, mais elles ne sont jamais complètement claires et explicitent :

  • Une erreur de syntaxe : la ligne incriminée n’est pas précise, car elle désigne le bloc YAML en cause (plutôt compliqué avec une grande section).
  • Une erreur de templating : la structure entière du template est affichée, parfois celle en cause est donnée, mais encore faut-il la retrouver (notamment dans des structures conséquentes de plusieurs dizaines d’items).
  • etc…

Les outils fournis par Ansible

Ansible fournit quelques outils qui permettent d’aider au débug.

Mode verbose

Le mode verbose augmente la verbosité dans l’affichage

Ce mode s’utilise à l’aide d’un flag à ajouter à la commande ansible ou ansible-playbooks :

  • -v ou --verbose

Le mode verbose possède plusieurs niveaux de logs :

  • -v : mode warning
  • -vv : mode info
  • -vvv : mode debug
  • -vvvv : mode trace

L’intérêt du mode verbose est d’afficher de plus amples informations sur les taches exécutées, ce qui permet de valider les variables injectées dans le module et de s’assurer que le comportement constaté est bien celui attendu.

Les tags

Les tags exécutent les tâches ayant le (ou les) tag(s) mentionné(s).

Ce mode s’utilise avec un paramètre (–key value) à ajouter à la commande ansible ou ansible-playbooks :

  • --tags ou -t ou --skip-tags

Les tags s’utilisent comme ceci :

  • -t install : exécute les tâches ayant le tag install
  • -t '!scripts' : exécute toutes les tâches exceptées celles avec les tags “scripts”
  • -t 'install,!config' : exécute les tâches “linux” exceptées celles avec le tag “config”
  • --skip-tags config : exécute les tâches exceptées celles avec le tag “config”

L’intérêt des tags est d’exécuter les tâches qui vous intéressent, pour passer les étapes qui ne vous sont d’aucune utilité dans la phase de debug mais tout en conservant les taches relatives au debug, occasionnellement connexes et liées à la tâche incriminée.

Les limits

Les limits exécutent les tâches sur les hosts précisés en argument du paramètre.

Ce mode s’utilise avec un paramètre (–key value) à ajouter à la commande ansible ou ansible-playbooks :

  • --limit ou -l

Les limits s’utilisent comme ceci :

  • -l linux : exécute les tâches sur les hosts du groupe “linux” de l’inventaire
  • -l 'linux,!suse' : exécute les tâches sur les hosts du groupe “linux” excepté “suse” de l’inventaire
  • -l 'debian,ubuntu' : exécute les tâches sur les hosts du groupe “debian” additionné à celui de “ubuntu” de l’inventaire (debian + ubuntu)
  • -l 'linux:&debian' : exécute les tâches sur les hosts issus de l’intersection des groupes “linux” et “debian” de l’inventaire (linux ET debian)
  • -l 'linux:!ubuntu' : exécute les tâches sur les hosts issus de la différence entre les groupes “linux” et “ubuntu” de l’inventaire (linux MAIS SANS ubuntu)

Le démarrage par une tâche précise

Le démarrage par une tâche exécute un playbook en commençant par la tache portant le nom indiqué.

Ce mode s’utilise avec un paramètre (–key value) à ajouter à la commande ansible ou ansible-playbooks :

  • --start-at-task : exécuter le playbook à partir de la tache spécifiée

Le “start at task” s’utilise comme ceci :

  • –start-at-task “Start apache server” : Démarre le playbook à partir de la tache “Start apache server”

L’intérêt du démarrage à tâche est de mieux cibler les tâches qu’on souhaite investiguer en commençant par celle qui nous intéresse.

Le dump des facts

Le dump des facts permet l’affichage des facts contextualisées durant l’exécution d’Ansible.

Ce mode s’utilise sur les commandes adhoc ou en tant que tache avec le module debug.

  • Commande adhoc : -m setup
  • Tache : module debug: (voir ci-dessous)
- debug:

Il faut garder en tête que l’affichage des facts correspondent à un host dans le playbook. Si vous avez 3 hosts, le dump de vars s’affichera 3 fois (1 fois pour chaque host).

L’intérêt du dump des facts est de scruter l’état des facts, à un instant T dans un playbook pour un serveur précis.

Le dump des vars

Le dump des vars permet d’afficher une variable à n’importe quel moment d’un playbook.

Ce mode s’utilise sur les commandes adhoc ou en tant que tache avec le module debug.

  • Commande adhoc : -m setup -a "var=my_var"
  • Tache : module debug: (voir ci-dessous)
- debug:
    var: my_var

- debug:
    msg: "{{ my_var }}"

- debug:
    msg:
      - "{{ my_var }}"
      - "{{ another_var }}"

L’intérêt du dump des vars est de scruter l’état des vars, à un instant T dans un playbook (pour un serveur précis).

Les outils construits avec Ansible

Ansible affiche les erreurs, mais elles ne sont pas toujours parlantes. Il est parfois préférable de simuler la situation plutôt que de relancer le playbook entier.

Pour reproduire la situation, il faut l’isoler et l’écrire dans un playbook dédiée, nettement plus petit qui ne contient que les taches dont nous avons besoin. Tant que vous respectez les paramètres de votre play (hosts, groupes, vars), vous ne devriez pas avoir de surprises.

Playbook de debug

Ce petit playbook me suis partout, il me permet d’afficher des valeurs sans délai et sans dépendances.

---
- hosts: all
  vars:
    mystring: "Hello World!"
  tasks:
    - debug:
      msg:
        - "{{ mystring }}"

Avec ce playbook de debug, vous pouvez afficher toutes les valeurs possibles : string, scalar, list, dict. Vous pouvez également faire du templating en ajoutant une simple tâche.

Bien entendu, si vous nécessitez de plus de contexte, veillez à customiser ce mini-playbook pour qu’il reflète votre use case :

  • Mieux cibler les serveurs (attribut hosts) pour charger les group_vars associés.
  • Ajouter une tache de dépendance qui impacte le résultat de votre variable.
  • (ou tout simplement) S’amuser avec le templating Jinja sur un format inline.