Tout le monde sait à quel point le Continuous Integration et le Continuous Delivery sont primordiaux dans une équipe Agile. Nous allons parler ici de Continuous Delivery, et faire un focus sur le déploiement et sur la gestion de la configuration, à travers Ansible. Cerise sur le gâteau : Ansible permet aussi de gérer la configuration des PC Windows et des Mac.


La gestion de la configuration (Configuration Management), qu'est-ce que c'est ? C'est un process de contrôle des changements de configuration de manière à ce que le système maintienne son intégrité dans le temps. On parle donc ici de la configuration des machines, des environnements de build, d'exécution, des postes de travail, ...

L'outils que je présente ici est Ansible. Il existe d'autres solutions : Puppet et Chef par exemple. Mais Ansible présente un certain nombre d'avantage par rapport à ses concurrents. Il utilise un format facilement lisible pour un être humain, le format YAML. Cela présente un intérêt pour la documentation : ces fichiers constituent directement de la documentation. Le code est votre documentation ! C'est un gain de temps notable. Il est très simple à déployer. La seule chose dont il a besoin sur les machines distantes, c'est de Python et d'un accès SSH. Pas besoin d'installer un agent sur ces machines. Il a également une caractéristiques intéressantes : l'idempotence. Quésaco ? Cela signifie qu'exécuter un script plusieurs fois donne le même résultat. Cela a l'air de rien, mais ça simplifie nettement le travail. Avant de faire une action sur la machine distante, vous n'avez pas besoin de vérifier si elle a déjà été faite.

Installation

OSX

La mise en place d'Ansible est simple. Sur OSX, vous pouvez utiliser le gestionnaire de package Homebrew ou le gestionnaire de package Python pip si vous préférez. Il suffit ensuite de configurer SSH en générant une clé publique et une clé privée avec ssh-keygen.

Etape 1 : Gérer les hôtes

La première chose que vous avez à faire est d'identifier et de lister les hôtes que vous voulez gérer. Ceci va être fait dans un fichier inventory. Pour simplifier la gestion des hôtes, il est possible de créer des groupes logiques. Un hôte peut alors être répété dans plusieurs groupes. Les commandes Ansible pourront être exécutées soit sur la globalité des hôtes spécifiés dans ce fichier inventory, soit sur un hôte particulier. C'est bien pratique.

Voici un exemple de fichier inventory :

[webservers]
web1.company.com
web2.company.com

[dbservers]
db1.company.com
db2.company.com

[servers:children]
webservers
dbservers

Le second fichier qui nous intéresse, c'est le fichier de configuration ansible.cfg. Encore une fois, la lisibilité se trouve au centre d'Ansible. Vous pourrez donc utiliser des entêtes de section pour gagner en lisibilité. Voici un exemple de fichier ansible.cfg :

[defaults]
inventory = /etc/ansible/hosts
remote_user = ansible
host_key_checking = False

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

Exécuter des commandes ad-hoc

Vous avez déclaré les hôtes gérés. C'est bien. Mais pour quoi faire concrètement ? Et bien pour exécuter des commandes. Les commandes ad-hoc permettent d'effectuer facilement des tâches sur les hôtes gérés comme des changements de configuration ou des diagnostiques.

Pour cela, elles utilisent les modules. Pour exécuter un module, utilisez l'option -m et spécifiez ses arguments avec l'option -a.  Les principaux modules comptent command, shell et copy.

  • Le module command permet d'exécuter une commande sur un hôte managé.
  • Le module shell permet d'exécuter une commande sur l'hôte managé via le shell local.
  • Le module copy permet de copier un fichier vers un hôte managé.

Pour exécuter le module command avec argument comme argument sur tous les hôtes managés [all], utilisez cette commande: 

ansible all -m command -a argument

Prenons un exemple. Si nous voulons créer un fichier README.md avec un contenu particulier, on peut utiliser cette commande :

ansible my_host -m copy -a 'content="<p>This is a README.</p>" dest=/tmp/README.md'

Pour obtenir la liste des modules installés, entrez cette commande:

ansible-doc -l

Pour afficher la documentation d'un module spécifique :

ansible-doc module

Et pour obtenir un exemple de code prêt à être intégré dans un playbook :

ansible-doc -s module

Mais pour utiliser un module, vous pouvez aussi l'inclure dans un Playbook au sein d'une tâche :

  tasks:
  - name: Install vsftpd
    yum:
      name: vsftpd

Etape 3 : Ecrire un Playbook

Voici un exemple de Playbook my_playbook.yml :

---
- hosts: webserver1
  tasks:
  - name: Ensure apache is at the latest version
    apt: name=apache2 state=latest
  - name: Ensure apache is running
    service: name=apache2 state=started enabled=yes

Etape 4 : Exécuter un Playbook

Maintenant que vous avez créé l'inventory et le playbook, vous pouvez exécuter les commandes se trouvant dans le playbook avec cette ligne de commande :

ansible-playbook my_playbook.yml --inventory my_inventory

L'option --inventory (ou -i) permet de spécifier le nom du fichier inventory.

Vous pouvez aussi n'exécuter que les commandes liées aux hôtes webserver1 et webserver2.

ansible-playbook my_playbook.yml --inventory my_inventory --limit "webserver1,webserver2"

Les variables

Il y a un moment où vous allez avoir des tâches répétitives sur les hôtes. Pour éviter ces répétitions, vous pouvez utiliser les variables.

Une variable peut avoir différents scopes :

  • global : ce sont les variables définies dans les lignes de commande ou dans le fichier de configuration Ansible;
  • play : ce sont les variables liées au Playbook;
  • host : ce sont les variables définies sur les hôtes de groupe ou individuels.

Les variables peuvent être définies :

  • dans un Playbook :

- hosts: all
  vars:
    user: john
    home: /home/john

  • dans un inventory pour un hôte individuel ou pour un groupe d'hôtes (c'est la méthode recommandée)

[webservers]
web1.example.com
web2.example.com

[webservers:vars]
documentroot=/web

  • dans un fichier externe YAML, référencé dans le Playbook dans la section vars_files :

- hosts: all
  vars_files:
  - vars/users.yml

Le fichier vars/users.yml a alors un contenu du type:

user: john
home: /home/john
user: paul
home: /home/paul

Mais vous pouvez aussi définir des variables dans un répertoire :

  • le répertoire group_vars pour les groupes d'hôtes,
  • le répertoire host_vars pour un hôte particulier.

Sachez qu'il est déconseillé de définir les variables dans l'Inventory.

Pour utiliser les variables dans le Playbook, il suffit de placer la variable entre {{ et }}.

Voici un exemple :

tasks:
  - name: Creates the user {{ user }}
    user:
      name: "{{ user }}"

Les Facts

Les faits (Facts) contiennent les informations qu'Ansible a récupéré sur un hôte. Vous pouvez filtrer les informations dans les Facts grâce aux filtres (Filters). Vous pouvez créer vos propres Facts pour stocker des propriétés spécifiques à certains hôtes. On parle alors de Custom Facts.

Pour utiliser les Facts, c'est simple : vous les utilisez comme les variables dans les Playbooks.

Par défaut, les commandes Ansible récupère les Facts. C'est très pratique mais la contre-partie est que ça ralentit les commandes. Vous pouvez donc désactiver la récupération des Facts en ajoutant cette ligne dans le Playbook :

gather_facts: no

Les handlers et les notifications

Les Handlers sont des sortes de tâches déclenchées lors de certaines notifications. Ces notifications sont spécifiées comme arguments aux tâches :

tasks:
- name: copy configuration
  copy:
    src: mywebsite.conf
    dest: /etc/mywebsite.conf
  notify:
  - restart apache
handlers:
- name: restart apache
  service:
    name: apache2
    state: restarted

Les handlers sont par exemple utilisés pour redémarrer un service. Les notifications sont exécutées dans l'ordre d'apparition dans le Playbook et une fois les tâches exécutées. Attention, il existe cependant une restriction : les handlers dans un include ne peuvent pas être notifiés.

Les items

Vous pourrez parfois avoir besoin de répéter des actions plusieurs fois.

Pour cela, procédez en deux temps :

  • définissez la liste des items avec with_items,
  • traitez chaque item avec "{{ with_items }}"

Exemple :

tasks:
- name: Remove services
  yum:
    name: "{{ item }}"
    state: absent
  with_items:
    - httpd
    - vsftpf

Eviter de réinventer la roue avec les rôles

Un rôle est un ensemble de tâches et de variables qui effectuent une tâche complexe. Un rôle correspond donc à une portion de Playbook réutilisable, que l'on souhaite pouvoir partager entre plusieurs Playbook.

Les rôles comprennent des unités séparées selon la structure arborescente suivante:

templates/
tasks/
handlers/
vars/
defaults/
meta/

Dans chaque répertoire, nous définissons le fichier main.yml, qui contient les parties de playbook qui peuvent être incluses dans le fichier playbook.yml.

Pour utiliser le rôle nginx par exemple, on ajouterait simplement deux lignes dans le playbook :

- hosts: my_server
  roles:
    - nginx

Ansible Galaxy est le repository officiel de rôles Ansible partagés entre les utilisateurs d'Ansible. Il se trouve à l'adresse https://galaxy.ansible.com/.

Pour installer un rôle depuis Ansible Galaxy, c'est simple:

ansible-galaxy install username.role_name

Voici un example:

ansible-galaxy install geerlingguy.mysql

Si vous avez besoin d'installer de nombreux rôles en même temps, vous pouvez les définir dans le fichier requirements.yml et utiliser cette commande:

ansible-galaxy install -r requirements.yml

Crypter les informations sensibles avec Ansible Vault

Il est réquent d'avoir à stocker des informations confidentielles comme des mots de passe ou des clés d'API.

Le moyen le plus simple de les stocker en clair dans des variables. Cette méthode est bien sûr très fortement déconseillée.

Ces informations doivent être cryptées. Pour les crypter et les décrypter, vous devez donc utiliser un outils :

  • Ansible intègre Ansible Vault pour crypter et décrypter des données.
  • Vous pouvez aussi utiliser une autre outils externe, de votre choix.

Pour crypter un fichier, utilisez la commande ansible-vault.

Pour référencer un fichier crypté depuis un Playbook, ajoutez lors de l'exécution du Playbook l'option --aks-vault-pass pour pouvoir saisir le mot de passe utilisé pour décrypter le fichier.

ansible-playbook --ask-vault-pass webservers.yaml

Optimisation

Par convention, on utilise souvent l'arborescence suivante :

my_ansible_project
|--ansible.cfg
|--group_vars
| |--webservers
| |--db
|--host_vars
| |--mycompany.com
| | ...
|--inventory
|--playbook.yaml

Parfois vous aurez besoin de capturer la sortie d'une commande dans une variable. Pour cela, utiliser l'ordre register.

- name: Example for register
  hosts: my_host
  tasks:
  - name: Show users
    command: who
    register: the_users

D'autres fois, vous aurez besoin d'afficher la valeur d'une variable afin de déboguer un script.

- name: Example for debug
  hosts: my_host
  tasks:
    - debug: var=the_variable_to_debug

Si votre Playbook deviennent trop gros ou si vous voulez structurer votre Playbook en modules, vous pouvez utiliser l'inclusion de fichier dans le Playbook :

  • include pour inclure les fichiers de tâches,
  • include_vars pour inclure les fichiers de variables.

 

Ansible présente deux avantages particulièrement importants : le code constitue lui-même la documentation. Le second est son repository de rôles, qui vous fera gagner un temps précieux. Il devient alors facile de déployer de nouveaux environnements (dev, test, pre-prod, prod, ...) en fonction des besoins de l'équipe. L'exécution automatique des tests (unitaires et autres) est primordiale dans une équipe Agile. Mais le déploiement des environnements est également une tâche très importante qui doit être automatisée.


Pensées pour mieux produire

Soyez prévenu dès que mon livre "Pensées pour mieux produire" sera disponible à la vente !

DevOps, Agile, Scrum, Kanban, XP, SAFe, LeSS, Lean Startup, Lean UX, Design Thinking, Craftmanship, Management 3.0, ...

 

Bruno Delb

Agile Coach and DevOps, with an experience in the Medical Device software domain, Management 3.0, Agile games and development (especially on mobile) are my passion.

Search

Ads