Rôles
Les rôles Ansible sont des ensembles de tâches réutilisables.
Un rôle doit correspondre a un cas d’usage, flexible, mais unique.
Par exemple :
- La configuration de firewalld
- L’installation et la configuration d’un moteur PostgreSQL
- L’installation d’une application
- La gestion d’un serveur OpenSSH
- La gestion d’un serveur NTP
- …
L’idée de fond étant que plus le rôle est « atomique », plus il pourra être imbriqué avec d’autres rôles dans un même playbook.
Prenons un cas concret : On souhaite installer une application (wordpress pour l’exemple), on peut identifier assez facilement plusieurs choses à faire :
- Installer et configurer la partie serveur web
- Installer et configurer la partie base de données
- Déployer l’application
- Configurer le firewall pour permettre l’accès à l’application depuis l’extérieur de la machine
On voit donc quatre axes se dégager.
Si on considère les tâches « génériques » on dégage facilement trois rôles :
- Le serveur Web
- La base de données
- Le firewall
La dernière tâche qui consiste en le déploiement de l’application est plus tendancieuse.
On pourrait l’intégrer dans un playbook dévolu à cette partie, et à ce niveau il faudrait dupliquer le playbook pour
multiplier les déploiements.
Ou on crée un rôle pour traiter ce déploiement, afin de pouvoir le réutiliser de multiples fois sans avoir à dupliquer
le playbook.
Structure des rôles
Section titled “Structure des rôles”Les rôles Ansible ont une structure de dossier définie.
Cette structure est la suivante :
Directorymon_role/
Directorydefaults/
- …
Directoryfiles/
- …
Directoryhandlers/
- …
Directorylibrary/
- …
Directorylookup_plugins/
- …
Directorymeta/
- …
Directorymodule_utils/
- …
Directorytasks/
- …
Directorytemplates/
- …
Directorytests/
- …
Directoryvars/
- …
Vous pouvez utiliser une commande pour générer un nouveau rôle afin d’obtenir automatiquement la structure minimale pour un rôle Ansible :
ansible-galaxy init monroleConcrètement, à quoi sert chaque dossier :
| Dossier | Usage |
|---|---|
defaults |
Contient des fichiers de variables. |
files |
Contient des fichiers statiques devant être déployé. |
handlers |
Contient les handlers. |
library |
Contient des plugins (modules) propre au rôle. |
lookup_plugins |
Contient des plugins de lookup pour Ansible propre au rôle. |
meta |
Contient les métadonnées du rôle. |
module_utils |
Contient des utilitaires pour vos modules et lookups. |
tasks |
Contient les tâches à exécuter. |
templates |
Contient les fichiers de template à déployer. |
tests |
Contient les tâches de test du rôle. |
vars |
Contient des fichiers de constantes. |
À savoir qu’à l’exception du dossier tasks l’ensemble des dossiers ne sont pas obligatoire pour un rôle.
Vous pouvez très bien vous limiter aux dossiers uniquement utilisés dans le cadre de votre rôle.
Ceci étant dit, je vous enjoins fortement à garder et utiliser à minima les dossiers suivants :
defaults: Pour stocker les variables et leurs valeurs par défauthandlers: Dans le cas où vous avez besoin d’exécuter des handlersmeta: Pour les métadonnées de votre rôletemplates: Si vous avez des fichiers à déployervars: Pour définir des constantes que vous utilisez plusieurs fois dans votre rôle
Contenu
Section titled “Contenu”defaults / vars
Section titled “defaults / vars”Dans les dossiers defaults et vars vous trouverez quasi systématiquement un fichier main.yaml.
Ce fichier est le point d’entrée générique de ces dossiers.
Il est possible de trouver d’autres fichiers que le main, ce seront des fichiers chargés explicitement par une ou des
tâches pendant le déroulé de votre rôle.
Pour ma part, je les considère comme suivant :
- Ce qui se trouve dans le dossier
defaultssont des variables, et donc sont surchargeables dans l’inventaire. - Ce qui se trouve dans le dossier
varsest considéré comme « constante ». Ce sont des variables qui seront utilisées dans le rôle, mais qui n’ont pas vocation à être surchargé à l’exécution. (Même si dans les faits ça reste possible.)
Le contenu de ses fichiers est assez basique, c’est du YAML tout ce qu’il y a de plus standard.
Par exemple :
---monrole_version: '1.2.3'monrole_install_path: '/opt/monrole'---monrole_packages: - vim - githandlers / tasks
Section titled “handlers / tasks”Les handlers et les tasks sont exactement basées sur le même principe que ce que l’on a pu voir dans un plakbook basique et les handlers.
Pour vous redonner un exemple :
---- name: 'Installation apache2' become: true notify: 'Restart apache2' ansible.builtin.apt: name: apache2 state: present---- name: 'Restart apache2' become: true ansible.builtin.systemd: name: apache2 state: restarted enabled: truetemplates
Section titled “templates”Les templates sont rédigés en format Jinja2.
Ils permettent de déposer des fichiers sur les cibles en incluant une notion de dynamisme du contenu.
Le format Jinja2 est assez flexible pour permettre divers paramétrages et conditions.
Par exemple un template Jinja2 pour la configuration du daemon chronyd :
# {{ ansible_managed }}
{% for server in ntp_servers %}server {{ server }} minpoll {{ ntp_server_minpoll }} maxpoll {{ ntp_server_maxpoll }} iburst{% endfor %}ntsdumpdir /var/lib/chrony
driftfile /var/lib/chrony/driftmakestep {{ ntp_makestep_threshold }} {{ ntp_makestep_limit }}
minsources {{ ntp_min_sources }}
rtcsyncleapsectz right/UTC
bindaddress {{ ntp_server_bind_address }}{% for allowed in ntp_server_allowed %}allow {{ allowed }}{% endfor %}local stratum {{ ntp_server_local_stratum }}
logdir /var/log/chronylog {{ ntp_log_directives | join (' ') }}
keyfile /etc/chrony.keysOn remarque ici des boucles for délimitées par {% for ... %} et {% endfor %}, ainsi que l’utilisation de
variables encadrées par des {{ … }} (par exemple {{ ntp_min_sources }}).
Celà permet de rendre de façon dynamique le fichier en substituant les variables en fonction du template de référence.
Les métadonnées d’un rôle Ansible sont utiles à plusieurs égards :
- Elles permettent expliciter ce que fait le rôle et dans quelles conditions il peut être utilisé
- Elles définissent des informations sur la licence, les sources, l’auteur, …
- Elles permettent également de définir une validation des variables par défaut au travers d’un fichier spécifique
(
argument_specs.yaml)
Fichier meta.yaml
Section titled “Fichier meta.yaml”Le fichier meta.yaml est le fichier permettant la définition des informations des deux premiers points cités plus
haut.
Il a un formalisme définit pour le fichier meta.yaml :
---galaxy_info: author: "Vincent FRICOU" role_name: "monrole" namespace: "local" description: "Description courte de ce que fait le rôle" issue_tracker_url: "<url_pour_ouvrir_des_issues_sur_le_role>" # Optionnel license: "AGPL-3.0-only" min_ansible_version: '2.10' platforms: # Optionnel - name: EL versions: - '8' - '9' - name: Debian version: - 'bookworm' - 'bullseye'
galaxy_tags: # Optionnel - ntp - chronyd
dependencies: [] # OptionnelLes champs surlignés sont obligatoires dans les métadonnées, les autres sont optionnels.
Au plus vous serez exhaustif, plus il sera simple de comprendre ce que fait le rôle et dans quel cadre.
Fichier argument_specs.yaml
Section titled “Fichier argument_specs.yaml”Le fichier argument_specs.yaml est un fichier totalement optionnel.
Il est soumis à un formalisme définit.
Ce fichier est malheureusement bien trop souvent le laissé pour compte. Et le pourquoi se comprend assez aisément.
Malgrès tout, je vous encourage fortement à l’écrire, celà pourra grandement vous aider dans les cas où vous réutilisez
vos rôles dans un futur un peu lointain.
Ceci étant, il a plusieurs avantages non négligeables dans un rôle :
- Permettre la validation des variables d’entrée du rôle (typage, format, contenu)
- Permettre la consultation et la génération automatique de documentation via
ansible-docet/ouantsibull-docs
La rédaction du fichier argument_specs.yaml est fastidieuse, car elle impose une double déclaration des variables,
dans defaults ET dans l’argument spec, mais les bénéfices finaux sont plutôt intéressants.
Pour vous donner un exemple de ceux à quoi ressemble un fichier argument_specs.yaml :
---argument_specs: # On définit le contexte du rôle main: # Les auteurs du rôle author: - 'Vincent FRICOU' # Une description courte short_description: "NFS server management" # Une description un peu plus exhaustive de ce que fait le rôle description: - 'Deploy and manage NFS server' # La liste des variables utilisables avec le rôle (tout ce qui est « modifiable » par l’inventaire. On n’inclu pas les « vars ») options: # Le nom de la variable nfs_server_base_path: # Le type type: str # Une description description: 'Base path to configure NFS exports' # Est-ce que la variable est requise ou non (si l’option est à true, la valeur défaut n’a plus de sens) required: false # La valeur par défaut de la variable default: '/opt/nfs' ... # Un ou des examples d’utilisation du rôle examples: | - name: 'NFS server deployment and configuration' hosts: - nfs_server vars: nfs_server_exports: type: list description: 'List of exports to declare' required: true options: path: type: str description: 'Relative path to configure export behind C(nfs_server_base_path)' required: false host: type: str description: 'Host address allowed to connect to NFS export' required: true comment: type: str description: 'Export comment' required: false opts: type: list description: 'NFS exports options' required: false default: - 'rw' - 'async' - 'no_all_squash' - 'no_root_squash' - 'no_subtree_check' - 'insecure' roles: - role: namespace.collection.nfs_serverJe vous renvoie directement à la documentation Ansible sur le contenu du fichier argument_specs.yaml.