web-dev-qa-db-fra.com

Comment déboguer les problèmes Ansible?

Parfois, ansible ne fait pas ce que vous voulez. Et augmenter la verbosité n'aide pas. Par exemple, j'essaie maintenant de démarrer le serveur coturn, qui vient avec le script init sur le système d'exploitation systemd (Debian Jessie). Ansible le considère en cours d'exécution, mais ce n'est pas le cas. Comment puis-je regarder ce qui se passe sous le capot? Quelles commandes sont exécutées et quel code de sortie/sortie?

14
x-yuri

Modules de débogage

  • Le moyen le plus simple consiste à exécuter ansible/ansible-playbook avec un niveau de verbosité accru en ajoutant -vvv à la ligne d'exécution.

  • La méthode la plus complète pour les modules écrits en Python (Linux/Unix) consiste à exécuter ansible/ansible-playbook avec une variable d'environnement ANSIBLE_KEEP_REMOTE_FILES définie sur 1 (sur l'ordinateur de contrôle).

    Ansible laisse ainsi la copie exacte des scripts Python qu'il a exécutés (avec succès ou non) sur la machine cible.

    Le chemin d'accès aux scripts est imprimé dans le journal Ansible. Pour les tâches courantes, ils sont stockés dans le répertoire de base de l'utilisateur SSH: ~/.ansible/tmp/.

    La logique exacte est intégrée aux scripts et dépend de chaque module. Certains utilisent Python avec des bibliothèques standard ou externes, d'autres appellent des commandes externes.

Débogage des playbooks

  • De la même manière que le débogage de modules augmentant le niveau de verbosité avec le paramètre -vvv, davantage de données seront imprimées dans le journal Ansible.

  • Depuis Ansible 2.1, le Playbook Debugger permet de déboguer de manière interactive des tâches en échec: vérifier, modifier les données; réexécutez la tâche.

Débogage des connexions

  • L'ajout du paramètre -vvvv à l'appel ansible/ansible-playbook force le journal à inclure les informations de débogage pour les connexions.
17
techraf

Voici ce que je suis venu avec.

Ansible envoie des modules au système cible et les exécute à cet emplacement. Par conséquent, si vous changez de module localement, vos modifications prendront effet lors de l'exécution de playbook. Sur ma machine, les modules sont à /usr/lib/python2.7/site-packages/ansible/modules (ansible-2.1.2.0). Et le module service est à core/system/service.py . Anisble modules (instances de AnsibleModule la classe déclarée à module_utils/basic.py) a la méthode log , qui envoie des messages au journal systemd s'il est disponible, ou revient à syslog Exécutez donc journalctl -f sur le système cible, ajoutez des instructions de débogage (module.log(msg='test')) au module localement et exécutez votre playbook. Vous verrez les instructions de débogage sous ansible-basic.py nom de l'unité.

En outre, lorsque vous exécutez ansible-playbook avec -vvv, vous pouvez voir des résultats de débogage dans le journal systemd, au moins des messages d'appel et des messages d'erreur éventuels.

Une dernière chose, si vous essayez de déboguer du code qui s'exécute localement avec pdb (import pdb; pdb.set_trace()), vous aurez probablement une exception BdbQuit. En effet, pythonferme stdin lors de la création d'un thread (ansible worker). La solution ici est de rouvrir stdin avant d'exécuter pdb.set_trace() comme suggéré ici :

sys.stdin = open('/dev/tty')
import pdb; pdb.set_trace()
7
x-yuri

Débogage des tâches Ansible peut être presque impossible si les tâches ne sont pas les vôtres. Contrairement à ce que dit le site Web Ansible.

Aucune compétence particulière en codage requise

Ansible nécessite une programmation hautement spécialisée des compétences car ce n'est ni YAML ni Python, c'est un mélange désordonné des deux. 

L'idée d'utiliser des langages de balisage pour la programmation a déjà été essayée. XML était très populaire dans la communauté Java à une époque. XSLT est également un bon exemple. 

Au fur et à mesure que les projets Ansible se développent, la complexité augmente de manière exponentielle. Prenez par exemple le projet OpenShift Ansible qui a la tâche suivante:

- name: Create the master server certificate
  command: >
    {{ hostvars[openshift_ca_Host]['first_master_client_binary'] }} adm ca create-server-cert
    {% for named_ca_certificate in openshift.master.named_certificates | default([]) | lib_utils_oo_collect('cafile') %}
    --certificate-authority {{ named_ca_certificate }}
    {% endfor %}
    {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | lib_utils_oo_collect('path') %}
    --certificate-authority {{ legacy_ca_certificate }}
    {% endfor %}
    --hostnames={{ hostvars[item].openshift.common.all_hostnames | join(',') }}
    --cert={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.crt
    --key={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.key
    --expire-days={{ openshift_master_cert_expire_days }}
    --signer-cert={{ openshift_ca_cert }}
    --signer-key={{ openshift_ca_key }}
    --signer-serial={{ openshift_ca_serial }}
    --overwrite=false
  when: item != openshift_ca_Host
  with_items: "{{ hostvars
                  | lib_utils_oo_select_keys(groups['oo_masters_to_config'])
                  | lib_utils_oo_collect(attribute='inventory_hostname', filters={'master_certs_missing':True}) }}"
  delegate_to: "{{ openshift_ca_Host }}"
  run_once: true

Je pense que nous pouvons tous convenir qu'il s'agit d'une programmation en YAML. Ce n'est pas une bonne idée. Cet extrait de code spécifique peut échouer avec un message comme 

fatal: [master0]: ECHEC! => {"msg": "La vérification conditionnelle 'item! = openshift_ca_Host' a échoué. L'erreur était: erreur lors de l'évaluation de conditionnel (item! = openshift_ca_Host): 'item' n'est pas défini\nThe __. erreur semble avoir été dans '/home/user/openshift-ansible/roles/openshift_master_certificates/tasks/main.yml': Ligne 39, colonne 3, mais peut\ntre ailleurs dans le fichier en fonction sur le problème de syntaxe exacte.\n\nLa ligne incriminée semble être:\n\n\n - name: créez le certificat de serveur maître\n ^ ici\n "} 

Si vous frappez un tel message, vous êtes condamné. Mais nous avons le débogueur non? Ok, regardons ce qui se passe.

master0] TASK: openshift_master_certificates : Create the master server certificate (debug)> p task.args
{u'_raw_params': u"{{ hostvars[openshift_ca_Host]['first_master_client_binary'] }} adm ca create-server-cert {% for named_ca_certificate in openshift.master.named_certificates | default([]) | lib_utils_oo_collect('cafile') %} --certificate-authority {{ named_ca_certificate }} {% endfor %} {% for legacy_ca_certificate in g_master_legacy_ca_result.files | default([]) | lib_utils_oo_collect('path') %} --certificate-authority {{ legacy_ca_certificate }} {% endfor %} --hostnames={{ hostvars[item].openshift.common.all_hostnames | join(',') }} --cert={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.crt --key={{ openshift_generated_configs_dir }}/master-{{ hostvars[item].openshift.common.hostname }}/master.server.key --expire-days={{ openshift_master_cert_expire_days }} --signer-cert={{ openshift_ca_cert }} --signer-key={{ openshift_ca_key }} --signer-serial={{ openshift_ca_serial }} --overwrite=false"}
[master0] TASK: openshift_master_certificates : Create the master server certificate (debug)> exit

Comment ça aide? Ce n'est pas. 

Le point ici est que c’est une très mauvaise idée d’utiliser YAML comme langage de programmation. C'est le bordel. Et les symptômes du gâchis que nous créons sont partout. 

Quelques faits supplémentaires. La mise à disposition de la phase de prérequis sur Azure of Openshift Ansible prend +50 minutes. La phase de déploiement prend plus de 70 minutes. Chaque fois! Premier passage ou suivants. Et il n'y a aucun moyen de limiter la fourniture à un seul nœud. Ce problème limit faisait partie de Ansible en 2012 et fait toujours partie de Ansible aujourd'hui. Ce fait nous dit quelque chose.

Le point ici est que Ansible doit être utilisé comme prévu. Pour des tâches simples sans la programmation YAML. Parfait pour de nombreux serveurs, mais il ne devrait pas être utilisé pour des tâches de gestion de configuration complexes. 

Ansible est un outil non-infrastructure en tant que code (IaC). 

Si vous demandez comment déboguer des problèmes Ansible, vous l'utilisez d'une manière inattendue. Ne l'utilisez pas comme un outil IaC. 

4
onknows

Rôles de débogage/playbooks

En gros, le débogage d’une automatisation sur des stocks importants sur de grands réseaux n’est autre que le débogage d’une application réseau distribuée. Cela peut être très fastidieux et délicat, et il n'y a pas assez d'outils conviviaux.

Ainsi, je crois que la réponse à votre question est également une union de toutes les réponses avant le mien + petit ajout. Alors voici:

  • absolument obligatoire: vous devez vouloir savoir ce qui se passe, c’est-à-dire ce que vous automatisez, ce que vous attendez. par exemple. échec de la détection du service avec l’unité systemd en cours d’exécution ou de l’arrêt signifie généralement un bogue dans le fichier ou le module de service de l’unité de service. avec TODO et lien vers un bug. 4. Quand un bogue est corrigé - supprimez votre solution de contournement

  • pour faciliter le débogage de votre code, utilisez autant que possible les modules

  • donnez à toutes les tâches et variables des noms significatifs.

  • utilisez des outils d'analyse de code statique comme ansible-lint. Cela vous évite de petites erreurs vraiment stupides.

  • utiliser les drapeaux de verbosité et le chemin du journal

  • utiliser le module debug à bon escient

  • "Connais tes faits" - il est parfois utile de vider les faits de la machine cible dans un fichier et de les tirer vers un maître

    • utilisez strategy: debugdans certains cas, vous pouvez tomber dans un débogueur de tâches par erreur. Vous pouvez ensuite évaluer tous les paramètres utilisés par la tâche et décider quoi faire ensuite.

    • le dernier recours consisterait à utiliser le débogueur Python, en le reliant à l'exécution locale ansible et/ou à Python distant exécutant les modules. Ceci est généralement délicat: vous devez autoriser l’ouverture d’un port supplémentaire sur la machine et si le code qui ouvre le port est celui qui cause le problème?

De plus, il est parfois utile de "regarder de côté" - connectez-vous à vos hôtes cibles et augmentez leur capacité de débogage (journalisation plus détaillée)

Bien entendu, la collecte de journaux facilite le suivi des modifications résultant d’opérations possibles.

Comme vous pouvez le constater, comme pour toutes les autres applications et infrastructures distribuées, la capacité de débogage n’est toujours pas celle que nous souhaiterions.

Filtres/plugins

Ceci est essentiellement le développement Python, déboguer comme n'importe quelle application Python

Modules

En fonction de la technologie et du fait que vous avez besoin de savoir ce qui se passe localement et à distance, il vaut mieux choisir une langue assez facile à déboguer à distance.

2
mvk_il

Vous pouvez utiliser le module register et le module debug pour imprimer les valeurs de retour. Par exemple, je veux savoir quel est le code de retour de mon exécution de script appelé "somescript.sh", de sorte que mes tâches à l'intérieur de la pièce seront telles que:

- name: my task
  Shell: "bash somescript.sh"
  register: output

- debug:
  msg: "{{ output.rc }}"

Pour connaître les valeurs de retour complètes auxquelles vous pouvez accéder dans Ansible, vous pouvez consulter cette page: http://docs.ansible.com/ansible/latest/common_return_values.html

2
K.T.

Vous aurez peut-être besoin de plusieurs niveaux de débogage, mais le plus simple consiste à ajouter la variable d'environnement ANSIBLE_STRATEGY=debug, qui activera le débogueur à la première erreur.

1
sorin