Introduction
Ansible est un logiciel destiné à la configuration et la gestion de parc informatique.
Il est disponible sur la plupart des distributions Linux.
Il permet de déployer des logiciels, de gérer des configurations et de lancer des tâches sur une ou plusieurs cibles.
Ansible est codé en python et fonctionne avec des fichiers de configuration au format YAML qui décrivent les tâches à accomplir.
L'avantage des fichiers au format YAML est qu'ils sont humainement lisibles et plus faciles à gérer que certains autres formats de fichiers comme par exemple le XML.
Nous présentons dans cet article une utilisation légèrement détournée de l'usage initial de ce logicel.
L'objectif va être d'utiliser Ansible pour installer un environnement Yocto avec ses différentes sources et ses configurations.
Les principes de base d'Ansible
Ansible permet d'effectuer une ou plusieurs actions sur une ou plusieurs machines.
Pour décrire son fonctionnement, nous présentons une utilisation simple comme un ping. Donc une seule action sur une ou plusieurs machines.
Puis nous introduisons le principe de playbook qui permet de lancer plusieurs actions sur une ou plusieurs machines.
Utilisation simple - une seule action
L'objectif de ce cas d'usage est d'effectuer un ping
depuis plusieurs machines en une seule action. Nous allons nous connecter sur plusieurs machines simultanément et chacune de ces machines lancera un ping.
Définition des hôtes
Nous commençons par configurer l'environnement Ansible en décrivant les machines visées par l'application, nous construisons une liste de ces machines dans le fichier suivant:
/etc/ansible/hosts
On y inscrit les machines avec leur nom ou leur adresse ip comme ceci:
192.0.2.50 linuxembedded.exemple.fr
Il est possible de lister les hôtes sous forme individuelle ou par groupement d'hôtes.
Ansible va tenter de se connecter aux différents hôtes en utilisant ssh, par conséquent il est nécessaire d'avoir mis votre clé publique dans le fichier authorized_keys
de vos hôtes.
Action à distance
Il est maintenant possible de lancer une commande à distance avec le programme ansible
.
Ces commandes (qui ne sont pas nécessairement des commandes shell) peuvent être ciblées pour un ou plusieurs hôtes. Par exemple voici une commande permettant de lancer un ping sur tous les hôtes connus puis un ping sur un hôte particulier :
$ ansible all -a "/bin/ping 8.8.8.8 -c1"
$ ansible linuxembedded.exemple.fr -a "/bin/ping 8.8.8.8 -c1"
Ansible fournit un ensemble de modules. Ces modules permettent de lancer des actions avec un comportement prédéfini (une liste non exhaustive sera présentée un peu plus bas). Par exemple, le module ping
a pour action de se connecter à un hôte, de tester l'utilisabilité de python puis de renvoyer le résultat pong
en cas de succès (donc attention aux "faux-amis", le module ping
n'est pas identique à la commande ping
shell).
Voici ce qu'ansible affichera pour chacune des machines :
$ ansible all -m ping
<address_ip> | SUCCESS => {
"changed": false,
"ping": "pong"
}
Introduction aux actions multiples - le principe de playbook
Pour effectuer plusieurs actions en une seule commande on peut utiliser ce que l'on appelle un playbook (ou playbook YAML), il permet de lister un ensemble d'actions à effectuer. Comme présenté au dessus, les actions peuvent utiliser les modules prédéfinis d'Ansible. La liste des actions est décrite dans un fichier de type YAML.
La syntaxe YAML va être présentée un peu plus bas. Tout d'abord, regardons comment utiliser un playbook simplement.
Pour lancer un playbook on n'utilise plus la commande simple ansible
, mais ansible-playbook
avec en paramètre le fichier YAML décrivant vos actions à effectuer.
$ ansible-playbook mon-fichier.yml
Le fichier contient à la fois la liste des hôtes et les actions à executer. Ansible effectuera donc toutes les actions listées sur tous les hôtes listés dans le fichier.
Manipuler son playbook Ansible pour aller plus loin
La syntaxe YAML
Le format YAML est utilisé dans divers projets que l'on peut retrouver sur yaml.org. Le standard YAML a été créé en 2001.
Un fichier YAML est formé de variables, de dictionnaires (des paires clé/valeur), et de listes. Par ailleurs, Ansible dispose d'un système de modules (plugins) utilisables dans les playbook.
Les variables
Les variables sont déclarées de la façon suivante :
vars: base_path: /mon/path
Pour accéder à la valeur il faut utiliser des doubles accolades :
{{ base_path }}
Attention, il faut entourer les variables de guillemets pour la gestion de chemin si ce dernier commence par la variable:
app_path: "{{ base_path }}/app"
Il est également possible de passer des variables en ligne de commande lors de l'exécution d'Ansible. Ainsi la variable peut être définie au moment de l'appel et non dans le fichier YAML :
--extra-vars "base_path=/mon/path/"
Les dictionnaires
Les dictionnaires sont définis sous la forme clé: valeur
.
# Information sur une personne martin: nom: Martin Dévloper travail: Developer niveau: Expérimenté
Les listes
Les listes sont définies avec -␣
, un tiret suivi d'un espace.
# Une liste de fruits - Pomme - Orange - Framboise - Mangue
D'autres choses plus complexes sont possibles en mélangeant les différentes syntaxes:
# Liste de plusieurs employés - martin: nom: Martin D'vloper travail: Developer compétences: - python - perl - pascal - tabitha: nom: Tabitha Bitumen travail: Developer compétences: - lisp - fortran - erlang
Il existe d'autres façon de représenter des listes que nous ne détaillerons pas ici. Pour ça, je vous invite à lire la documentation: http://docs.ansible.com/ansible/latest/YAMLSyntax.html
Les modules
Les modules YAML lus par ansible contiennent des actions à exécuter sous forme de liste de paires clé/valeur. La clé est le nom d'un module à utiliser, la valeur est un ensemble de paramètres qui décrivent plus précisément ce que doit faire le module.
Voici une liste non exhaustive de types de modules disponibles :
- git,
- patch,
- get_url,
- shell,
- copy,
- service,
- apt,
- yum,
- lxc_container,
- make.
La liste complète est disponible sur le site Ansible:
Si nous voulons télécharger un dépôt git et l'installer à un endroit précis, nous pouvons ajouter l'extrait suivant à notre playbook :
# Exemple d'un téléchargement de source git - git: repo: 'https://git.yoctoproject.org/git/poky' version: krogoth dest: /home/user/poky
Pour l'exemple de git, des options utiles sont:
- Pour mettre à jour le repo à chaque exécution
update: yes
.
(attention si le dépôt n'est pas propre, Ansible refusera la mise à jour) - Pour créer directement un "git archive" utilisez
archive: /path/to/archive.zip
Il est aussi possible de créer soi-même des modules.
Vous trouverez plus d'informations sur la page git_module.
Un module particulier : le module "hosts"
Ce module est obligatoire et doit être instancié en début de fichier YAML, il fait référence aux hôtes configurés précédemment dans le fichier :
/etc/ansible/hosts
Il permet de définir les différents hôtes (nommés Hosts
dans le fichier YAML) pour lesquels certaines instructions vont être exécutées.
- hosts: all remote_user: root
Notre cas d'usage - Ansible et Yocto
Nous avons choisi de détourner l'usage habituel de Ansible pour créer un environnement pour un projet Yocto.
Lorsque l'on utilise Yocto on a souvent plusieurs layers à télécharger, que ce soit sous forme de dépot git ou bien d'archives. Il peut être parfois nécessaire d'appliquer des patchs sur des repos communautaires qui ne sont plus maintenus activement, oui bien d'ajouter des fichiers de configuration; dans ce cas, Ansible peut nous faciliter la vie.
L'hôte
Ansible étant fait pour gérer un parc informatique, il va falloir modifier le contenu de Hosts
afin que les actions soient faites localement.
Pour ça il suffit de mettre en début de fichier YAML:
- hosts: 127.0.0.1 connection: local
Le répertoire de travail
Afin d'avoir le projet construit avec toutes les sources au même endroit, nous allons utiliser une variable externe appelée "TOP_SRCDIR".
Ainsi avec l'option --extra-vars "TOP_SRCDIR=<path_to_top_srcdir>
vous pouvez spécifier le répertoire où installer votre projet Yocto :
- name: "Get poky" git: repo: https://git.yoctoproject.org/git/poky version: krogoth dest: "{{TOP_SRCDIR}}"
En cas de besoin, il est possible d'appliquer un patch après le clonage du dépôt :
- name: "Patch poky krogoth" patch: src: /path/to/patch/0001-qemu-Add-space-to-fix-concatenated-SRC_URI.patch basedir: "{{TOP_SRCDIR}}" strip: 1
Pour les personnes qui souhaitent mettre des règles de commit, il est tout à fait possible d'ajouter un hook local après installation d'un repo git:
- name: "Copy hooks into layer" copy: src: /path/to/hooks/commit-msg dest: "{{TOP_SRCDIR}}/meta-projet/.git/hooks/commit-msg" mode: 755
Un exemple complet
Voici un exemple d'un fichier YAML plus complet (nommé mon-fichier.yml
) :
- name: "Mon Projet" hosts: 127.0.0.1 connection: local tasks: - name: "Get poky" git: repo: https://git.yoctoproject.org/git/poky version: krogoth dest: "{{TOP_SRCDIR}}" update: no - name: "Patch poky krogoth" patch: src: ../0001-qemu-Add-space-to-fix-concatenated-SRC_URI.patch basedir: "{{TOP_SRCDIR}}" strip: 1 - name: "Copy hooks into poky" copy: src: /path/to/hooks/commit-msg dest: "{{TOP_SRCDIR}}/.git/hooks/commit-msg" mode: 755 - name: "Get meta-openembedded" git: repo: http://git.openembedded.org/meta-openembedded version: krogoth dest: "{{TOP_SRCDIR}}/meta-openembedded" update: yes - name: "Get meta-linaro" git: repo: http://git.linaro.org/openembedded/meta-linaro.git version: krogoth dest: "{{TOP_SRCDIR}}/meta-linaro" update: yes - name: "Get toolchain" get_url: url: http://192.168.2.200/src/toolchain/toolchain-M2.1.tgz checksum: md5:31a70bd7f7b74724af915a88fbe64f3d dest: "{{TOP_SRCDIR}}" - name: "Untar toolchain" shell: tar xzf {{TOP_SRCDIR}}/toolchain-M2.1.tgz -C {{TOP_SRCDIR}}/sdk/prebuilts/gcc/
Il suffit ensuite de lancer la commande :
$ ansible-playbook mon-fichier.yml --extra-vars "TOP_SRCDIR=/home/user/mon-projet/"
À l'issue de la procédure vous aurez une arborescence du type:
$ tree poky poky/ ├── bitbake ├── build ├── documentation ├── LICENSE ├── meta ├── meta-linaro ├── meta-openembedded ├── meta-poky ├── meta-selftest ├── meta-skeleton ├── meta-yocto ├── meta-yocto-bsp ├── oe-init-build-env ├── oe-init-build-env-memres ├── README ├── README.hardware ├── sdk ├── scripts └── toolchain-M2.1.tgz
Votre environnement de travail est maintenant prêt à l'utilisation !
Conclusion
Ansible est un logiciel qui peut être détourné pour différentes tâches grâce à ses nombreux modules.
Ceci permet donc de paramétrer la mise en place d'un environnement de build Yocto qui serait décrit dans un seul fichier YAML.
Ainsi, il suffit d'une machine avec Ansible et de partager le fichier de description YAML pour permettre l'initialisation d'un environnement de travail sans intervention manuelle des utilisateurs.
Les liens utiles
Dépôt git:
https://github.com/ansible/ansible
La documentation Ansible est très complète:
http://docs.ansible.com/ansible/latest/index.html
Des exemples de fichier YAML sont disponibles sur le github d'Ansible:
https://github.com/ansible/ansible-examples
Vous pouvez tester la syntaxe vos fichiers YAML sur www.yamllint.com
Il est possible de discuter via IRC sur le chanel #ansible de Freenode.