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?
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
-vvvv
à l'appel ansible
/ansible-playbook
force le journal à inclure les informations de débogage pour les connexions.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, python
ferme 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()
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.
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: debug
dans 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.
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
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.