Utiliser la notion de role dans Ansible est indispensable pour exploiter toute la puissance de l’outil.
Dans un article précédent, nous avons présenté Ansible et vu son utilisation basique. Cet article portera sur la modularité que peut apporter le rôle Ansible.
Pré-requis
Dans cet article, je suppose que vous savez utiliser Anisble et/ou que vous avez suivi l’article précédent : Ansible : l’outil de déploiement incontournable.
Je rappelle simplement les commandes pour bootstraper le répertoire de travail (CentOS 7).
yum install -y epel-release yum install -y ansible mkdir -p ansible-playbooks/{inventories,roles,{host,group}_vars} cd ansible-playbooks/
Nous allons directement partir au coeur de notre sujet : les rôles Ansible.
Mise en situation
Partons sur la création d’un rôles qui installera le middleware Apache ainsi que des VirtualHost. L’ajout et la suppression des VirtualHost ne devront pas supposer la modification rôle.
Challenge accepted !
L’inventaire de toute une vie
L’inventaire Ansible sur lequel se basera cet article :
vi inventories/reverse_proxy
# Les serveurs centos01 ansible_host=centos01.ineat-conseil.fr # Les groupes [centos] centos01 [linux:children] centos
Le Role Apache
Ecrire un playbook est une chose, mais ce n’est pas pérenne quand on commence à utiliser et réutiliser les taches et les playbooks. C’est ici qu’interviennent les rôles ansible.
Dans l’éco-système Ansible, les rôles sont le pivot qui permettent la modularisation des taches et ainsi faciliter le séquencement des actions sur les serveurs. Ils sont en général constitués des éléments suivants :
- Un répertoire “tasks” qui contient les taches à appliquer sous forme de fichiers .yaml
- Un répertoire “defaults” qui contient les variables par défaut du rôle
- Un répertorie “files” qui contient les fichiers à copier sur le serveur cible
- Un répertoire “templates” qui contient les fichiers variabilisés à copier sur le serveur cible
- Un répertoire “handlers” qui contient les actions à déclencher
A minima, un rôle doit contenir la structure suivante pour fonctionner :
ansible-playbooks/ └── roles/ └── tasks/ └── main.yaml
Le rôle se base sur le fichier tasks/main.yaml
pour exécuter les taches. Libre à vous de créer d’autres fichiers de taches et de les importer dans le main.yaml
.
Documentation officielle sur le role
Ecrivons la structure de notre premier rôle appelé “httpd” :
mkdir -p roles/httpd/{defaults,tasks,files,templates,handlers} touch roles/httpd/{defaults,tasks,handlers}/main.yaml
ansible-playbooks/ └── roles/ └── httpd/ ├── defaults/ │ └── main.yaml ├── tasks/ │ └── main.yaml ├── files/ ├── templates/ └── handlers/ └─── main.yaml
Parcourons ensemble les différents répertoires. Chacun d’entre-eux nous apportent leurs lots de fonctionnalités.
Définir les déclencheurs du rôle
Commençons par les handlers
, particularité de Ansible, ce sont des taches qui seront déclenchées par les taches principales.
Partons pour notre première tache déclenchable sur le redémarrage du service Apache. On utilise le module systemd pour réaliser le redémarage d’Apache.
vi roles/httpd/handlers/main.yaml
--- - name: Reload apache service systemd: name: httpd state: restarted
L’attribut name
est très important, car c’est lui qui va définir l’identifiant du déclencheur.
Les taches du rôle
Définissons les taches du rôles dans le fichier tasks/main.yaml
. Rendons notre rôle simple à lire.
Le fichiers de taches principal ordonnance les groupes de taches rangés par fichiers :
vi roles/httpd/tasks/main.yaml
--- - include_tasks: install.yaml
Et le fichier d’installation apache :
vi roles/httpd/tasks/install.yaml
--- - name: Install package httpd yum: name: httpd state: installed
Les variables du rôle
Les variables du rôle ont pour portée… le rôle ! =D
Rien de plus simple que de limiter des variables à un rôle et qu’elles soient surchargées par les group_vars du playbook. On peut ainsi rendre le rôle non bloquant (sur le plan des variables) tout en le laissant modulable.
Documentation officielle sur les variables
Définissons une variable contenant une liste de VirtualHost pour configurer le middleware Apache.
vi roles/httpd/defaults/main.yaml
--- apache_virtualhosts: - servername: website.ineat-conseil.fr documentroot: /var/www/html
On pourra ainsi rendre la configuration des VirtualHost Apache facile à modifier et à surcharger. Cette pratique permet de conserver un rôle dans un état figé, et uniquement modifier ses paramètres : vive la modularité !
Copier les fichiers du rôle
Créons notre superbe site internet à base de “Hello World” :
vi roles/httpd/files/index.html
Hello World !
On peut maintenant faire appel à ce fichier et le copier sur le serveur distant dans le répertoire /var/www/html
.
C’est le module copy
qui se charge de copier des fichiers d’un serveur à l’autre. Il prend en paramètre le fichier source (celui à copier) et le fichier cible (le chemin complet du fichier à copier sur le serveur distant).
Documentation officielle sur le module copy
Le paramètre src
peut être référencé avec un nom de fichier, le chemin relatif du fichier ou le chemin absolu du fichier sur le serveur.
En utilisant le chemin absolu, pas de mystère le fichier se trouve pile à cet endroit sur le serveur.
En utilisant le nom du fichier (ou le chemin relatif), la recherche se fait nativement à plusieurs niveaux :
- Dans le répertoire
files
du rôle, - Le répertoire courant du fichier de tâches du rôle,
- Le répertoire courant du playbook qui lance le rôle.
vi roles/httpd/tasks/website.yaml
- name: Copy website index become: true copy: src: index.html dest: /var/www/html/index.html owner: apache group: apache
Le paramètre src
fait ici référence au fichier créé à l’étape précédente dans le répertoire roles/httpd/files/virtualhost.conf
.
Vous l’aurez remarqué, l’instruction become
s’est ajouté au sein de la tâche, elle permet d’élever les droits sur les instructions demandées. Remarque : il est nécessaire d’être root pour attribuer des droits (utilisateur et permissions) au travers des tâches Ansible.
N’oublions pas de mettre à jour le fichier de taches principal :
vi roles/httpd/tasks/main.yaml
--- - include_tasks: install.yaml - include_tasks: website.yaml
Utiliser les templates du rôle
Il nous fat maintenant un VirtualHost à copier sur le serveur distant.
Copier un fichier statique est une bonne chose, mais nous souhaitons aller un cran plus loin avec notre configuration Apache. C’est ici qu’est introduit la notion de Template avec Ansible.
Un Template Ansible est un fichier qui utilise les variables contextualisées.
Variables contextualisées…?? Un bien grand mot qui fait référence à l’ensemble des variables collectées, assemblées, agrégées au lancement du playbook et du rôle.
Le template s’utilise comme le fichier statique, on manipule un fichier du rôle qui se trouve cette fois dans le répertoire templates
du rôle. L’import des variables se fait à l’aide de la syntaxe Jinja2. On peut aller très loin dans la récupération des variables Jinja en leur appliquant des transformation, des filtres, des pipelines d’agrégation, …
Documentation officielle sur le module template
Commençons simple avec l’import du fichier 🙂
Créons un VirtualHost qui va récupérer le dictionnaire apache_virtualhosts
.
Les exemples qui vont suivre suivent un cheminement pour permettre de mieux comprendre la manipulation des variables Jinja2 dans les templates.
Approche 1 : Itération dans le template
Première approche : itérer sur le dictionnaire directement dans le template du virtualhost.
vi roles/httpd/tasks/virtualhosts.yaml
- name: Copy the Apache VirtualHost template become: true template: src: virtualhost.conf.j2 dest: /etc/httpd/conf.d/virtualhost.conf onwer: root group: root
Créons le template :
vi roles/httpd/templates/virtualhost.conf.j2
{% for vhost in apache_virtualhosts.items() %} <VirtualHost *:80> Servername {{ vhost.servername }} DocumentRoot {{ vhost.documentroot }} </VirtualHost> {% endfor %}
Lançons la tache pour tester et s’assurer du rendu final. Le résultat semble correct, le templating se fait correctement. Première approche pas trop mal, mais qui apporte beaucoup de complexité au sein même du template.
Approche 2 : Itération sur la tâche
Seconde approche : itérer sur la tache qui applique le template du virtualhost.
vi roles/httpd/tasks/virtualhosts.yaml
- name: Copy the Apache VirtualHost template become: true template: src: virtualhost.conf.j2 dest: "/etc/httpd/conf.d/{{ item.servername }}.conf" owner: root group: root loop: "{{ apache_virtualhosts }}"
Créons le template :
vi roles/httpd/templates/virtualhost.conf.j2
<VirtualHost *:80> Servername {{ item.servername }} DocumentRoot {{ item.documentroot }} /VirtualHost>
Lançons la tache pour tester et s’assurer du rendu final. Le résultat semble correct, le templating se fait correctement.
Approche totalement différente de la précédente, ici on démultiplie les VirtualHost par fichier, c’est l’application de la boucle avec loop:
qui change la nature du fichier final.
Cette seconde approche apporte beaucoup de clarté dans le template Ansible et séquence la résultante de la tache par une multitude de fichiers. Dans notre cas, c’est l’approche que je conseille pour Apache notamment.
N’oublions pas de mettre à jour le fichier de taches principal
vi roles/httpd/tasks/main.yaml
--- - include_tasks: install.yaml - include_tasks: website.yaml - include_tasks: virtualhosts.yaml
Appliquer les déclencheurs du rôle
Vous vous souvenez des handlers
déclarés précédemment, nous allons maintenant les appeler pour agrémenter notre rôle.
Sauf que les handlers
se déclenchent sur la résultante [changed]
d’une tache. Il faut donc appliquer un changement à toute tache qui apporte des modifications nécessitant un redémarrage d’Apache :
- Les fichiers de configuration
Modifions donc notre module template précédemment créé.
vi roles/httpd/tasks/virtualhosts.yaml
- name: Copy the Apache VirtualHost template become: true template: src: virtualhost.conf.j2 dest: "/etc/httpd/conf.d/{{ item.servername }}.conf" onwer: root group: root loop: "{{ apache_virtualhosts }}" notify: - Reload apache service
L’appel au déclencheur se fait sur base du paramètre notify
et prend en valeur le nom du ou des actions à déclencher, ici Reload apache service
.
Construction du playbook
Maintenant que tous les ingrédients sont réunis, nous pouvons construire le playbook qui va appeler toute cette magie !
Documentation officielle sur la construction d’un playbook role
Oulalah !! Ca va être compliqué d’appeler un rôle… je laisse juger par vous-même.
vi install_httpd.yaml
--- - hosts: [centos] roles: - httpd
Et c’est tout !!! Rapide, n’est-ce pas ?!
A présent, il ne reste plus qu’à lancer le tout et attendre que la magie opère…
ansible-playbook -i inventories/reverse_proxy install_httpd.yaml
Conclusion
Dans ce “rapide” tutoriel, nous avons vu les points suivants :
- Création d’un Role
- Notification avec les Handlers
- Utilisation des Variables
- Utilisation des Templates
- Séquencement avec les Modules
- Gestion des paquets avec
yum
- Services systèmes avec
systemd
- Transfère des fichiers avec
copy
- Variabilisation des fichiers avec
template
- Gestion des paquets avec
- Création d’un playbook de rôles
Nous avons vu les différentes applications des Templates dans Ansible et du niveau de boucle associé.
J’apporterai très prochainement des sources GitHub qui compileront les exercices réalisés dans ce tutoriel.
Vous avez maintenant les armes nécessaire pour bien aborder Ansible, ses modules, ses rôles et ses playbooks sereinement avec quelques bonnes pratiques d’emblée.
Dans un très prochain article, nous passerons en revue les filtres Jinja2 applicables dans les Template Ansible.