Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
gfaivre committed Jan 11, 2024
1 parent 5f920c3 commit 4a3f80f
Showing 1 changed file with 247 additions and 3 deletions.
250 changes: 247 additions & 3 deletions content/blog/cours/ansible/ansible-les-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,42 @@ Il s'agit bien évidemment de supports à vocation pédagogique qui **ne sont pa

Avoir suivi/lu les cours concernant les [inventaires](/blog/cours/ansible/ansible-les-inventaires-statiques) et les [playbooks](/blog/cours/ansible/ansible-les-playbooks) !

Et donc disposer d'un inventaire s'approchant de celui-ci:

```yaml
all:
hosts:
vm-web-prod-01:
ansible_host: XXX.XXX.XXX.XXX
ansible_user: debian
vm-db-prod-01:
ansible_host: XXX.XXX.XXX.XXX
ansible_user: debian
vm-web-staging-01:
ansible_host: XXX.XXX.XXX.XXX
ansible_user: debian
vm-db-staging-01:
ansible_host: XXX.XXX.XXX.XXX
ansible_user: debian
children:
webservers:
hosts:
vm-web-prod-01: ~
vm-web-staging-01: ~
dbservers:
hosts:
vm-db-prod-01: ~
vm-db-staging-01: ~
staging:
hosts:
vm-web-staging-01: ~
vm-db-staging-01: ~
production:
hosts:
vm-web-prod-01: ~
vm-db-prod-01: ~
```
## Introduction
Nous avons vu précemment comment débuter avec Ansible avec les notions fondamentales d'inventaire et de playbooks. Dans l'idée d'apporter un peu plus d'outils à cet ensemble Ansible est également capable de gérer et interpréter des variables qui peuvent venir de différentes sources.
Expand All @@ -31,15 +67,223 @@ Pour commencer attaquons nous aux variables qu'Ansible lui même manipule pour s
## Les variables
Ansible introduit énormément de souplesse en terme « d'endroit » ou peuvent être déclarées des variables ce qui laisse énormémement de liberté sur la façon dont on souhaite organiser notre projet mais qui a pour contrepartie de demander énormément de rigueur afin de respecter les standards établis pour le projet, sous peine que cela devienne très rapidement un vrai foutoir.
### Les variables d'hôte
hostname: web-staging-01
Pour commencer nous aborderons le principe des variables d'hôtes qui en toute logique, permettent de définir des variables au niveau d'une machine bien précise. Vous verrez avec le temps que sur des infrastructures d'exploitation conséquentes ces variables sont souvent peu utilisées car il est rare de n'avoir qu'une seule machine derrière un service.
Commençons par créer un nouveau répertoire `host_vars` à la racine de notre répertoire de travail qui contiendra des fichiers reprenant les nom d'hôtes définis dans notre inventaire, nous commencerons par les membres du groupe `webservers` et crérons donc 2 fichiers `vm-web-prod-01.yml` et `vm-web-staging-01.yml`.

Chaque fichier contiendra pour l'instant une définition de variable selon l'exemple suivant:

```yaml
hostname: web-production-01
```
On fera bien évidemment de même avec le second fichier et les instances du groupe `dbservers` en ajoutant les fichiers `vm-db-prod-01.yml` et `vm-db-staging-01.yml` contenant respectivement:

```yaml
hostname: db-production-01
```

et

```yaml
hostname: db-staging-01
```
Il est possible de faire afficher à Ansible les différentes variables définies `ansible-inventory --graph -i inventories --vars` qui devrait vous renvoyer pour l'instant:

```yaml
@all:
|--@ungrouped:
|--@webservers:
| |--vm-web-prod-01
| | |--{ansible_host = 162.19.93.111}
| | |--{ansible_user = debian}
| | |--{hostname = web-production-01}
| |--vm-web-staging-01
| | |--{ansible_host = 162.19.93.190}
| | |--{ansible_user = debian}
| | |--{hostname = web-staging-01}
|--@dbservers:
| |--vm-db-prod-01
| | |--{ansible_host = 162.19.92.208}
| | |--{ansible_user = debian}
| | |--{hostname = db-prod-01}
| |--vm-db-staging-01
| | |--{ansible_host = 162.19.92.175}
| | |--{ansible_user = debian}
| | |--{hostname = db-staging-01}
|--@staging:
| |--vm-web-staging-01
| | |--{ansible_host = 162.19.93.190}
| | |--{ansible_user = debian}
| | |--{hostname = web-staging-01}
| |--vm-db-staging-01
| | |--{ansible_host = 162.19.92.175}
| | |--{ansible_user = debian}
| | |--{hostname = db-staging-01}
|--@production:
| |--vm-web-prod-01
| | |--{ansible_host = 162.19.93.111}
| | |--{ansible_user = debian}
| | |--{hostname = web-production-01}
| |--vm-db-prod-01
| | |--{ansible_host = 162.19.92.208}
| | |--{ansible_user = debian}
| | |--{hostname = db-prod-01}
```

Où l'on peut constater la présence de nos variables au niveau de chacun des hôtes !

### Les variables de groupe

hostname: web-staging-01
Passons à présent aux variables de groupes, vous l'aurez compris celles-ci s'appliqueront à un groupe de machine tel que nous l'aurons défini dans notre inventaire.
Leur fonctionnement repose sur le même principe que les variables d'hôtes, nous crérons donc cette fois un répertoire appelé `group_vars` contenant un fichier pour chacun des groupes que nous aurons défini.

Nous allons donc créer les fichiers `production.yml` et `staging.yml` contenant respectivement pour l'instant:

```yaml
stage: production
```
et
```yaml
stage: staging
```

En rejouant la commande ansible précédente vous pourrez constater qu'une nouvelle variables `stage` apparait bien comme définie lors de l'affichage de votre inventaire.

!!! info "L'héritage des variables"
Il est bien évidemment possible d'appliquer une définition de variable aux groupes parent comme aux groupes enfant, dans ce cas on prendra bien soin de faire attention à l'héritage des variables !

On oubliera pas au passage que même s'il n'apparait pas de manière explicite dans notre inventaire, le groupe `all` est systématiquement définit par Ansible comme « super parent » et qu'il est donc de manière possible de déclarer des variables pour ce groupe en créant un fichier `all.yml` dans `group_vars` contenant par exemple:

```yaml
workshop: ansible
### Les « facts »
```

### Définir des variables dans un inventaire

Il est possible (je vous l'ai dit Ansible est très souple) de définir des variables directement dans votre fichier d'inventaire, on l'a déjà plus ou moins vu d'ailleurs avec la définition de clés spécifiques à Ansible comme `ansible_host` ou `ansible_user` au niveau d'un hôte, l'ajout de variable sur un hôte fonctionne donc de la même façon en ajoutant des clés à la suite.

Au niveau d'un groupe il faudra passer par la clé `vars` on pourrait imaginer par exemple indiquer un serveur de temps bien précis pour une zone géographique avec quelque chose comme:

```yaml
france:
hosts:
host-01:
host-02:
vars:
ntp_server: ntp.univ-lyon1.fr
```

### Comment les variables sont elles fusionnées ?

Ansible fusionne les variables pour les appliquer de manière spécifique à chacun de nos hôte, cela signifie que sortie de notre définition d'inventaire et de correspondance hôte/groupe la notion de groupe ne perdure pas, en effet Ansible va écraser les variables préalablement définies en suivant cet ordre (de poids le plus faible au plus important):

- groupe `all` (n'oubliez pas c'est le parent « racine »)
- groupe parent
- groupe enfant
- hôte

Pour résumer de la variable la moins précise (en terme de périmètre de définition) à la plus précise.

**Quelques points d'attention toutefois:**

Pour les groupes de même niveau hiérarchique les variables du dernier groupe considéré écraseront les autres, sauf si une pondération est appliqué au niveau du groupe en utilisant la variable `ansible_group_priority` comme suit:

```yaml
france:
hosts:
host-01:
host-02:
vars:
ntp_server: ntp.sophia.mines-paristech.fr
lyon:
hosts:
host-01:
host-02:
vars:
ntp_server: ntp.univ-lyon1.fr
ansible_group_priority: 10
```

!!! info "Prioriser un groupe"
`ansible_group_priority` peut uniquement être défini au niveau de l'inventaire, il n'est pas possible de l'utiliser dans `group_vars`.

### Last but not least, les facts

Les facts sont au coeur du fonctionnement des variables dans Ansible dans le sens où ce sont des variables spécifiques récupérées directement depuis l'hôte concerné par un déploiement.
Elles permettent de récupérer pas mal d'information parmi lesquelles notamment la ou les interfaces réseaux des machines, le type d'OS et sa version ou encore des informations concernant le matériel de la cible.

On peut les consulter en utilisant par exemple le module `setup` directement en ligne de commande: `ansible -i inventories vm-web-prod-01 -m setup`.
Il est possible de filtrer la sortie affichée par Ansible en utilisant l'option `filter`: `ansible -i inventories vm-web-prod-01 -m setup -a "filter=ansible_default_ipv4"`

Ces « facts » se reveleront fort utiles au fur et à mesure de votre prise en main d'Ansible.

## Utiliser les variables dans nos playbooks

Nous avons vu comment définir des variables, c'est bien beau mais comment les utilisées ?

Reprenons par exemple nos fichiers d'hôte ou nous définissons la clé `hostname`, on peut constater que celle-ci dispose d'une partie qui reprend le contenu de la clé `stage` définie au niveau du groupe.
On peut donc modifier nos fichiers d'hôte de la manière suivante pour exploiter cette définition:

```
hostname: "web-{{ stage }}-01"
```

Et allons modifier notre playbook (`example.yml`) pour utiliser ces variables de la manière suivante:

```yaml
---
- hosts: webservers
pre_tasks:
- name: Updating APT cache index
ansible.builtin.apt:
update_cache: yes
tasks:
# NGINX
- name: Install Nginx web server
ansible.builtin.apt:
name: nginx
state: present
- name: Nginx status configuration file
ansible.builtin.copy:
src: nginx/status.conf
dest: /etc/nginx/conf.d/status.conf
notify:
- restart_nginx
# CONFIG
- name: Set a hostname
ansible.builtin.hostname:
name: "{{ hostname }}"
handlers:
- name: restart_nginx
ansible.builtin.service:
name: nginx
state: restarted
```

## Les templates

Sujet étroitement lié à l'utilisation des variables, les templates au sens d'Ansible sont des fichiers un peu particulier dont le contenu peut-être défini dynamiquement (par opposition notamment à l'utilisation de fichiers de configuration « statiques ») comme nous avons pu le voir dans la partie [playbook](http://localhost:8000/blog/cours/ansible/ansible-les-playbooks#les-handlers).

Il faut également savoir qu'Ansible s'appuie sur le moteur de template [Jinja2](https://jinja.palletsprojects.com/en/3.1.x/) issu du monde Python qui pourrait être comparé à Twif pour PHP, Pebble pour Java, Liquid pour RoR ou encore DotLiquid pour .Net.

Nous l'avons vu les variables peuvent être définies à divers endroits et peuvent ensuite être accessibles avec les doubles parenthèses `{{ ... }}`.

Imaginons que nous souhaitions personnaliser nos [motd](https://fr.wikipedia.org/wiki/Message_of_the_Day) par exemple en fonction de l'environnement que nous allons accéder.

### Définir et utiliser un nouveau template





- https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html#assigning-a-variable-to-one-machine-host-variables
- https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html#assigning-a-variable-to-many-machines-group-variables

0 comments on commit 4a3f80f

Please sign in to comment.