Ansible
Changeons de sujet par rapport Ă mes prĂ©cĂ©dents articles. Travaillant dans le domaine de l’intĂ©gration et dĂ©ploiement continu (CICD), j’ai eu envie de faire dĂ©couvrir des outils que j’utilise au quotidien. Le premier est Ansible, un outil de dĂ©ploiement que j’affectionne particuliĂšrement.
Ce premier article sur Ansible vous présentera son histoire, ses concepts, ses principes, et les commandes.
Introduction
Ansible est un outil d’automatisation et de dĂ©ploiement crĂ©Ă© en fĂ©vrier 2012 par Michael DeHaan. Son nom s’inspire d’un dispositif prĂ©sentĂ© dans le roman Le Monde de Rocannon Ă©crit par Urusula K. Le Guin dans lequel l’ansible est un moyen de communication plus rapide que la lumiĂšre. L’entreprise AnsibleWorks Inc. crĂ©Ă©e pour apporter un support commercial Ă l’outil, a Ă©tĂ© rachetĂ©e en 2015 par Red Hat. Depuis, Ansible est intĂ©grĂ© Ă l’offre de l’Ă©diteur spĂ©cialisĂ© dans le logiciel libre.
DĂ©veloppĂ© principalement en Python, il est fourni sous licence GNU General Public Licence 3 et s’installe nativement sur les principales distributions Linux du marchĂ© telles que Fedora, RHEL, CentOS, Debian, Ubuntu, etc.
Ansible travaille majoritairement avec le monde Linux et d’autres Unix-Like tels que les BSD et MacOS, mais aussi avec Microsoft Windows.
Les concepts
L’un des points clĂ©s d’Ansible est que son architecture repose sur l’absence d’agent local sur les cibles. C’est trĂšs simple : une machine avec Python installĂ© dessus et pouvant se connecter en SSH sur les cibles pourra faire office de contrĂŽleur. Et voilĂ !
L’architecture dĂ©centralisĂ©e d’Ansible fait qu’il ne nĂ©cessite aucune machine dĂ©diĂ©e pour faire un dĂ©ploiement. Si le code est versionnĂ© par un gestionnaire de sources tel que Git, celui-ci pourra ĂȘtre exĂ©cutĂ© depuis n’importe quel machine ayant la possibilitĂ© de se connecter en SSH aux noeuds. Ansible dispose de son propre langage dĂ©claratif pour Ă©crire les scripts de dĂ©ploiement.
Un des dĂ©fauts de cette architecture cependant est qu’Ansible ouvre et ferme une connexion SSH Ă chaque action. Par consĂ©quent, il peut devenir assez lent quand on gĂšre un parc consĂ©quent de machines. A ce moment-lĂ , sĂ©parer les exĂ©cutions ou utiliser des plugins d’optimisation peut avoir un intĂ©rĂȘt. Dans la section “plugins” on parlera de Mitogen qui permet d’accĂ©lĂ©rer les perfs de ce dernier.
Les principes clĂ©s d’Ansible sont :
- Conception minimaliste : les systÚmes gérés ne requiÚrent aucun composant supplémentaire. Seul le contrÎleur peut avoir besoin de modules complémentaires selon les besoins. (exemple : modules python-docker pour piloter des containers de ce type)
- Homogénéité : un déploiement Ansible permet de déployer des environnements homogÚnes et cohérents.
- SecuritĂ© : Ansible ne nĂ©cessite pas d’agent sur les noeuds, il n’a besoin que d’une connexion SSH et Python installĂ© dessus.
- FiabilitĂ© : Ansible repose sur le principe d’indempotence et l’Ă©criture des playbooks se doit d’appliquer cette rĂšgle pour garantir que l’exĂ©cution sur un noeud aura systĂ©matiquement le mĂȘme rĂ©sultat.
- Apprentissage rapide : Les playbooks Ansible sont Ă©crits en YAML et en templates Jinja, des syntaxes strictes mais simples Ă maĂźtriser et faciles Ă lire mĂȘme pour un non initiĂ©.
Voyons plus en détails les concepts et mots clés qui ont été balancés comme ça.
Le contrĂŽleur
Le contrĂŽleur est la machine qui lance un dĂ©ploiement Ansible. Il peut s’agir de n’importe quel serveur, PC, etc, sur lequel Ansible est installĂ© et qui invoque les commandes /usr/bin/ansible
ou /usr/bin/ansible-playbook
. On peut avoir plusieurs contrĂŽleurs.
Noeuds managés
Il s’agit des machines qui seront ciblĂ©es par le dĂ©ploiement Ansible, elles sont dĂ©finies dans l’inventaire qu’il utilise. On parle principalement de “hosts”.
L’inventaire
L’inventaire est une liste de hosts, aussi appelĂ© “hostfiles”. Il peut s’agir d’une simple liste d’adresses IP ou de noms de machines, mais aussi d’un fichier plus hiĂ©rarchisĂ© avec des groupes, des dĂ©pendances, ou encore des variables. On le dĂ©taillera plus loin dans la section “Construire son inventaire”.
Les Modules
Les Modules sont le code qu’Ansible exĂ©cute. Un module est un outil dont le but est de remplir une action particuliĂšre en prenant des paramĂštres d’entrĂ©es qui peut ensuite retourner un rĂ©sultat. Les modules d’Ansible vont du simple ping Ă la gestion d’interfaces rĂ©seau, de bases de donnĂ©es, de fichiers, ou encore de commandes systĂšme.
Et comme si cela ne suffisait pas, en plus des modules officiels, il est possible d’Ă©tendre les possibilitĂ©s avec des modules communautaires.
Un module peut ĂȘtre invoquĂ© unitairement via la commande ansible
ou ĂȘtre exploitĂ© dans un ensemble de tĂąches Ă©crites dans un playbook exĂ©cutĂ© par ansible-playbook
.
Les tĂąches
Une tĂąche est une unitĂ© d’action dans Ansible. Elle appelle un module et peut ĂȘtre soit lancĂ©e via un Playbook, soit via la ligne de commande directement.
Les Playbooks
Les Playbooks sont un ensemble de tĂąches ordonnĂ©es qui seront exĂ©cutĂ©es dans l’ordre du script. Ils peuvent Ă©galement contenir des variables en plus des tĂąches. Ils sont Ă©crits en YAML et sont faciles Ă lire, Ă©crire et comprendre. Les playbooks sont lancĂ©s par la commande ansible-playbook
.
Les rĂŽles
Les rĂŽles sont un ensemble de diffĂ©rents fichiers contenant des tĂąches, mais aussi des variables, des templates Ă dĂ©ployer, des fichiers, des dĂ©clencheurs, etc. Un rĂŽle est un moyen d’Ă©crire un code rĂ©utilisable et pouvant ĂȘtre contextualisĂ© selon l’inventaire utilisĂ©.
DĂ©marrage rapide
Nous allons rapidement installer Ansible sur notre contrÎleur et exécuter notre premiÚre commande ad-hoc.
Prérequis
Les prĂ©requis d’Ansible sont simples, mais indispensables.
Sur le contrĂŽleur :
- OS basĂ© sur Linux (REHL, Debian, CentOS, Fedora…) ou Unix-like (BSD, MacOS…)
- A ce jour, Windows n’est pas officiellement supportĂ© comme noeud de contrĂŽle.
- Python 2.7 ou Python 3.5+
- Une certaine proximitĂ© avec les hosts contrĂŽlĂ©s permet d’amĂ©liorer les performances. S’il est parfaitement possible d’attaquer des serveurs Cloud depuis son PC avec Ansible sur sa connexion domestique, un contrĂŽleur dans le mĂȘme rĂ©seau sera plus efficace.
- Certains modules peuvent requĂ©rir un complĂ©ment pour fonctionner. Ceci doit ĂȘtre indiquĂ© dans leur documentation.
Sur les cibles :
- PossibilitĂ© de se connecter dessus en SSH. Ansible utilise par dĂ©faut SFTP pour transfĂ©rer ses scripts, mais il peut ĂȘtre configurĂ© pour SCP si besoin.
- Python 2.6+ ou Python 3.5+
- Si SELinux est activé, le package
libselinux-python
doit ĂȘtre prĂ©sent sur le noeud. Il est parfaitement possible de l’installer via Ansible avant d’utiliser des modules en ayant besoin (comme les modules de copie ou de template notamment). - Par dĂ©faut, Ansible utilise l’interprĂ©teur Python
/usr/bin/python
, mais certains peuvent avoir python3 directement. Il est possible de changer ça dans la config sur le contrÎleur.
Installer Ansible
Pour ma part, étant sous Fedora, Ansible est disponible directement dans les dépÎts de la distribution.
dnf install ansible
Autrement vous pouvez l’installer :
- Par le gestionnaire de paquets de votre distribution
- Via l’utilitaire
pip
de Python - Via les sources
Voir les méthodes possibles sur la documentaire officiel.
Configurer Ansible
La configuration d’Ansible se fait au moyen d’un fichier ansible.cfg
dont le chargement est défini par un ordre de priorité :
- variable d’environnement
ANSIBLE_CONFIG
avec l’emplacement du fichier - ansible.cfg dans le rĂ©pertoire courant oĂč est exĂ©cutĂ© la commande ansible
- ~/.ansible.cfg depuis le répertoire home
- /etc/ansible/ansible.cfg
Le contenu du fichier de configuration peut aussi ĂȘtre surchargĂ© directement en variables d’environnement.
Par exemple l’emplacement par dĂ©faut de l’inventaire /etc/ansible/hosts
peut ĂȘtre changĂ© en modifiant le paramĂštre inventory
dans le fichier ansible.cfg
, mais aussi surchargĂ© via la variable d’environnement ANSIBLE_INVENTORY
sur son profil.
Pour ma part, j’ai pour habitude de mettre un fichier ansible.cfg
avec le code de mes playbooks pour ĂȘtre sĂ»r d’avoir les mĂȘmes pramĂštres selon l’endroit depuis lequel ils sont exĂ©cutĂ©s. J’y mets Ă minima cette valeur pour avoir un rĂ©capitulatif Ă la fin de la durĂ©e des tĂąches :
[defaults]
callback_whitelist = profile_tasks
Ce qui donne à la fin le résultat suivant par exemple :
Tuesday 03 March 2020 18:19:54 +0100 (0:00:01.062) 0:01:00.064 *********
===============================================================================
Install packages-------------------------------------------------------- 37.30s
Gathering Facts --------------------------------------------------------- 9.44s
Lancer une premiĂšre commande
Tout d’abord, on va crĂ©er un inventaire.
Dans un emplacement de votre choix, créez un fichier nommé par exemple inventory
. Mettez dedans des machines distances, IP ou FQDN, peu importe.
Exemple :
192.168.1.20
192.168.1.22
Assurez-vous que vous pouvez bien vous connecter en SSH sur ces machines, de prĂ©fĂ©rence avec un Ă©change de clĂ©s permettant d’Ă©viter la saisie du mot de passe.
Lançons ensuite un simple ping :
ansible -i inventory all -m ping
Explication de la commande :
ansible
est la commande ad hoc permettant de faire une exĂ©cution unitaire d’une tĂąche- L’argument
-i inventory
lui indique de charger le fichier d’inventaire que nous avons prĂ©cĂ©demment crĂ©Ă© all
lui demande de prendre tous les noeuds de l’inventaire-m ping
lui dit de lancer le module “ping”
RĂ©sultat :
192.168.1.20 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.1.22 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Le ping Ansible est trĂšs pratique car avec cette rapide commande vous pouvez valider que :
- Votre inventaire fonctionne
- Votre connexion SSH fonctionne
- L’exĂ©cution d’un script par Ansible fonctionne
Soit … Le nĂ©cessaire :)
Comprendre l’Ă©lĂ©vation de privilĂšge
Allons un peu plus loin pour lui faire exĂ©cuter une commande permettant de comprendre l’Ă©lĂ©vation de privilĂšge.
# je suis connecté sur mon contrÎleur avec user1
[user1@localhost ~]$ ansible -i inventory all -m command -a "whoami"
De la mĂȘme maniĂšre que le ping, je demande Ă exĂ©cuter le module command
en lui donnant l’argument -a
pour qu’il lance la commande whoami
afin de savoir avec quel utilisateur Ansible s’est connectĂ©.
192.168.1.20 | CHANGED | rc=0 >>
user1
192.168.1.22 | CHANGED | rc=0 >>
user1
Le problĂšme, c’est que mon profil user1
est vite limitĂ© car il ne pourra pas faire d’action administrative de lui-mĂȘme… Cependant, il dispose d’un sudoers lui permettant de passer avec le compte root
pour faire des actions spĂ©ciales. Cela se traduit dans Ansible par l’argument become
et become-user
.
[user1@localhost ~]$ ansible -i inventory all -m command -a "whoami" --become
192.168.1.20 | CHANGED | rc=0 >>
root
192.168.1.22 | CHANGED | rc=0 >>
root
Par défaut, --become
fait un sudo root. Mais on peut lui spécifier un utilisateur précis.
[user1@localhost ~]$ ansible -i inventory all -m command -a "whoami" --become --become-user jeanmichel
192.168.1.20 | CHANGED | rc=0 >>
jeanmichel
192.168.1.22 | CHANGED | rc=0 >>
jeanmichel
Les commandes Ansible
Nous avons vu la commande ad hoc ansible
et parlé rapidement de ansible-playbook
, mais ce ne sont pas les seules. Pour les détails sur les arguments, suivez le lien ci aprÚs.
ansible
Commande de base permettant d’exĂ©cuter un module sur un ensemble de noeuds d’un inventaire.
Exemple pour redémarrer le service HTTPD des serveurs de notre inventaire membres du groupe webservers
.
ansible -i inventory webservers -m service -a "name=httpd state=restarted"
ansible-config
La commande ansible-config permet par exemple de consulter le contenu du fichier de configuration actuellement utilisé par Ansible. Elle peut aussi générer un fichier de config en concaténant les différentes disponibles.
ansible-console
Un outil trĂšs pratique pour administrer rapidement un ensemble de noeuds ! A la mĂȘme maniĂšre que la commande ad hoc ansible
, la console permet cependant de rester en mode intéractif et diffuse les appels sur tous les noeuds concernés.
Exemple pour lancer une session interactive sur tous les Webservers :
ansible-console -i inventory webservers
ansible-doc
Permet de retourner la documentation d’un module ou d’un plugin et gĂ©nĂšre directement un code exemple pour l’utiliser.
Exemple pour le module yum
# en mode info sur le module
ansible-doc yum
> YUM (/usr/lib/python3.7/site-packages/ansible/modules/packaging/os/yum.py)
Installs, upgrade, downgrades, removes, and lists packages and groups with the `yum' package manager. This module only works on Python 2. If you require Python 3 support see the
[dnf] module.
* This module is maintained by The Ansible Core Team
* note: This module has a corresponding action plugin.
OPTIONS (= is mandatory):
- allow_downgrade
Specify if the named package and version is allowed to downgrade a maybe already installed higher version of that package. Note that setting allow_downgrade=True can make this module
behave in a non-idempotent way. The task could end up with a set of packages that does not match the complete list of specified packages to install (because dependencies between the
downgraded package and others can cause changes to the packages which were in the earlier transaction).
[Default: no]
type: bool
version_added: 2.4
# en mode générateur de code
ansible-doc yum -s
- name: Manages packages with the `yum' package manager
yum:
allow_downgrade: # Specify if the named package and version is allowed to downgrade a maybe already installed higher version of that package. Note that setting allow_downgrade=True can make this module behave in a non-
idempotent way. The task could end up with a set of packages that does not match the complete list of specified packages to install (because dependencies between the
downgraded package and others can cause changes to the packages which were in the earlier transaction).
autoremove: # If `yes', removes all "leaf" packages from the system that were originally installed as dependencies of user-installed packages but which are no longer required by any such package. Should be used alone or
when state is `absent' NOTE: This feature requires yum >= 3.4.3 (RHEL/CentOS 7+)
ansible-galaxy
Ansible Galaxy est un service complémentaire sur lequel la communauté peut publier du contenu Ansible (playbooks, rÎles, etc).
Cette commande permet donc d’obtenir ou d’y pousser son contenu. Elle est aussi pratique pour gĂ©nĂ©rer en automatique l’arborescence et la structure d’un rĂŽle ansible avec tous les fichiers prĂ© renseignĂ©s. C’est principalement l’utilisation que j’en fais.
Pour initialiser l’arborescence d’un rĂŽle :
ansible-galaxy init mon_nouveau_role --offline
- Role mon_nouveau_role was created successfully
tree mon_nouveau_role/
mon_nouveau_role/
âââ defaults
â  âââ main.yml
âââ files
âââ handlers
â  âââ main.yml
âââ meta
â  âââ main.yml
âââ README.md
âââ tasks
â  âââ main.yml
âââ templates
âââ tests
â  âââ inventory
â  âââ test.yml
âââ vars
âââ main.yml
ansible-inventory
La commande ansible-inventory
permet d’afficher l’inventaire et les variables associĂ©es de la maniĂšre qu’Ansible le voit lors d’une exĂ©cution. Elle peut servir pour contrĂŽler la qualitĂ© d’une config par exemple.
ansible-playbook
L’une des commandes les plus utilisĂ©es, il s’agit lĂ du lanceur d’un playbook Ansible. L’appel ressemble Ă la commande ad hoc ansible
Ă la diffĂ©rence que vous n’avez pas besoin de spĂ©cifier sur quel groupe de hosts faire l’action. En effet, ceci est spĂ©cifiĂ© dans le playbook.
Exemple :
ansible-playbook -i inventory mon_playbook.yml
ansible-pull
Cette commande sert Ă exĂ©cuter des scripts Ansible en les rĂ©cupĂ©rant depuis un gestionnaire de sources. Je ne m’en sers jamais, utilisant directement Git pour ça.
ansible-vault
Ansible Vault est une fonctionnalitĂ© permettant de chiffrer un fichier avec Ansible. Ceci peut ĂȘtre utile par exemple pour vos fichiers de variables qui contiendraient des mots de passe ou des donnĂ©es sensibles. Il est par contre nĂ©cessaire de fournir le mot de passe Vault pour exĂ©cuter le code.
Exemple pour chiffrer l’inventaire :
# on affiche l'inventaire actuel
cat inventory
192.168.1.20
192.168.1.22
# on le chiffre en specifiant un mot de passe
ansible-vault encrypt inventory --ask-vault-pass
# on reaffiche le fichier
cat inventory
$ANSIBLE_VAULT;1.1;AES256
643834373838393832346161393539(...)
Vault peut chiffrer aussi un playbook entier, ou seulement une unique variable dans le contenu. Par contre cela devient vite peu pratique car il faut Ă©diter le fichier avec la commande Vault ou le dĂ©chiffrer/rechiffrer. On peut Ă©galement crĂ©er un fichier Ă charger contenant le mot de passe pour l’exĂ©cution. Bien Ă©videmment, il convient de ne pas pousser ce fichier de mot de passe sur un repository quelquonque, sans quoi l’intĂ©rĂȘt devient nul.
Cette commande dĂ©panne pour un besoin rapide, mais l’utilisation d’un vrai gestionnaire de secrets est recommandĂ©e pour des besoins plus consĂ©quents ou dynamiques (rotation de secrets, etc). Ansible dispose de plugins permettant de s’interfacer avec diffĂ©rents gestionnaires du marchĂ©, comme Hashicorp Vault ou ceux fournis sur les services Cloud d’Azure, AWS et compagnie par exemple.
Attention ! Vault permet seulement de chiffrer les fichiers. Si vous demandez Ă Ansible d’afficher le secret dans une tĂąche debug, il vous l’affichera ! (pensez Ă utiliser l’action “no_log: true” pour censurer une tĂąche qui retournerait du contenu sensible)
Fin premiĂšre partie
Ce premier chapitre vous a prĂ©sentĂ© les principes d’Ansible et les commandes pour l’exploiter. Le prochain article vous prĂ©sentera de maniĂšre plus dĂ©taillĂ©e l’inventaire Ansible.