Ce billet se base sur l'article suivant: https://www.ansible.com/blog/ansible-best-practices-essentials
dans
les gros titres. Cependant je me suis permis d'ajouter des remarques
personnelles. Selon mon expérience et la compréhension que j'ai eu. Si
vous pensez que je fais fausse route n'hésitez pas à commenter.
------------
La complexité tue la productivité
Ansible
indique par ce titre que ce n'est pas un simple slogan marketing qu'ils
avancent. Ils prétendent qu'ils se sont efforcé de réduire la
complexité dans la façon dont ils ont créer les outils Ansible. Ils
encouragent les utilisateurs à faire pareil, c'est à dire simplifier ce
que l'utilisateur automatise.
Optimiser ses contenus Ansible
C'est à dire :
- l'organisation de la structure des dossiers
- le classement des machines (qualification, pré-production, production)
- gestion fine des variables associées (group_vars)
- la hiérarchisation et le classement des playbooks et roles la plus fine
Si
cela est fait correctement dés le début de votre projet, votre code
peut devenir la documentation de votre cycle d'automatisation.
En
gros : privilégier le moins de code possible. Eviter le plus possible
la redondance de rôle et de playbook. Les playbooks doivent être commun
pour tous les environnements (ppd, prd, etc). Seule les variables
doivent différer.
Penser "déclaratif"
Ansible
est déclaratif, ce n'est pas un langage de programmation. Si on tente
de le tordre pour faire de la programmation avec des playbooks YAML,
nous allons vite être limité et allons créer de la complexité. Les
playbooks YAML n'a pas été conçu pour ça.
Voir Ansible comme un couteau suisse du Devops
Ansible est capable de gérer de1) Nommer ses playbooks et tâches.
Toujours nommer les playbooks et tâches. Mettre des descriptions compréhensibles par un humain.Prenons l'exemple ci-dessous :
- hosts: web
tasks:
- yum:
name: httpd
state: latest
- service:
name: httpd
state: started
enabled: yes
PLAY [web] ******************************************************Sans connaitre exactements les plays il n'est pas possible en regardant les logs quels sont les actions effectuées, seule les modules et les hosts sont précisés.
TASK [setup] ****************************************************
ok: [web1]
TASK [yum] ******************************************************
ok: [web1]
TASK [service] **************************************************
ok: [web1]
Maintenant prenons l'exemple ci-dessous :
- hosts: web
name: installs and starts apache
tasks:
- name: install apache packages
yum:
name: httpd
state: latest
- name: starts apache service
service:
name: httpd
state: started
enabled: yes
PLAY [install and starts apache] ***********************************C'est tout de suite plus claire. On comprend en regardant d'un seul coup d'oeil ce qu'il se passe.
TASK [setup] *******************************************************
ok: [web1]
TASK [install apache packages] *************************************
ok: [web1]
TASK [starts apache service] ***************************************
ok: [web1]
2) Utiliser des préfixes et des noms compréhensibles avec les variables
Ansible dispose d'un système de variable assez puissant qui collecte des metadonnées provenant de différentes sources. Cependant il faut déployer beaucoup d'effort faire simple et le plus transparent pour l'utilisateur.Le système de variable a été intentionnellement limité pour faciliter la compréhension et le débogage.
Cependant il faut bien nommer ses variables pour éviter toute confusion.
Exemple :
sshd_port: 22
apache_port: 80
tomcat_port: 8080
En préfixant avec le nom du produit, protocole ou usage, on voit dans cet exemple tout de suite de quoi on parle.
3) Utiliser la syntaxe YAML native
Le lanceur de playbook Ansible est essentiellement un analyseur YAML avec nue logique supplémentaire telle que des raccourcis en ligne de commande.Bien que pratique lors de la création d'un playbook, ce style de formatage réduit la lisibilité.
Il est donc recommandé d'éviter l'utilisation de ce genre de raccourci (même avec le style "plié" YAML).
Voici un exemple de tâche tuilisant le raccourci clé=valeur (key=value) :
- name: install telegrafVoici la même chose en YAML natif :
yum:
name: telegraf-{{ telegraf_version }} state=present update_cache=yes disable_gpg_check=yes enablerepo=telegraf
notify: restart telegraf
- name: configure telegraf
template: src=telegraf.conf.j2 dest=/etc/telegraf/telegraf.conf
notify: restart telegraf
- name: start telegraf
service: name=telegraf state=started enabled=yes
- name: install telegrafNous pourrions nous dire qu'il y a plus de ligne en YAML. Cependant des lignes sont plus courtes et réduisent le scrolling horizontal.
yum: telegraf-{{ telegraf_version }}
state: present
update_cache: yes
disable_gpg_check: yes
enablerepo: telegraf
notify: restart telegraf
- name: configure telegraf
template:
src: telegraf.conf.j2
dest: /etc/telegraf/telegraf.conf
notify: restart telegraf
- name: start telegraf
service:
name: telegraf
state: started
enabled: yes
La lisibilité est meilleure et en plus il y a une coloration syntaxique dans la plus part des éditeurs (VIM, atom, VSCode, etc)
De plus les raccourcis sont me semble-t-il dépréciés par Ansible, pure hypotèse: donc potentiellement retiré dans la version majeurs à venir.
4) Utiliser les modules avant les Run Commands
Les "Run Commands" sont les modules command, shell, raw et script que les utilisateurs peuvent activer lors de l'exécution de playbook ansible.C'est un mécanisme qui fonctionne et permet d'obtenir des résultats mais il convient de les utilisé parcimonie et en dernier recours. Les raisons sont nombreuses et variées.
Exemple :
- name: Change file ownership and group
command: chown foo:foo /etc/foo.conf
- name: Change permissions
command: chmod 0644 /etc/foo.conf
Peut être remplacer par le module file :
- name: Change file ownership, group and permissions
file:
path: /etc/foo.conf
owner: foo
group: foo
mode: '0644'
La surutilisation de "Run Commands" est commune à ceux qui débutent avec Ansible et qui ne sont pas familiers des modules. Ils utilisent le module shell pour lancer une commande Bash qu'ils connaissent déjà.
Cela fonctionne au début et cela peut être utile quand on a des scripts Shell de déploiement à porter sur Ansible. Mais cela nuit à l'utilité à la pertinence de l'utilisation d'Ansible.
Si on utilise Ansible autant utiliser les modules que celui-ci offre. Si effectivement il n'y a pas de module pour ce que l'on veut faire, nous pouvons nous tourner vers les "Run Commands". Mais en dernier recours. D'ailleurs la meilleurs façon de savoir s'il existe un module est de consulter la documentation: https://docs.ansible.com/ansible/latest/modules/modules_by_category.html
Pour les plus chevronnés qui n'ont pas trouver leur bonheur parmi les modules existant, on peut considérer la possibilité de développer son propre module et le partager à la communauté si celui-ci peut être partagé. http://docs.ansible.com/ansible/developing_modules.html
5) Faire le ménage dans les messages de déboggage
Il est parfois utile d'utiliser le mode debug d'ansible pour par exemple afficher le contenu d'une variable pendant l'exécution d'un playbook. Cependant lorsqu'il y a trop de message cela peut être désagréable. Ansible conseille d'utiliser le paramètre "verbosity" qui permet de choisir le volume de message que l'on souhaite.Exemple :
- debug:
msg: "This always displays"
- debug:
msg: "This only displays with ansible-playbook -vv+"
verbosity: 2
Désormais l'utilisateur du playbook ansible peut choisir s'il veut ou non avoir le message de debug.