Voici le sixième article de la formation Ansible. Dans mon précédent article, nous avons vu la gestion des variables de projet dans le shell. L’utilité de cet exposé quelque peu abstrait vous apparaîtra ici, étant donné que nous allons le mettre en application dans la configuration de base d’Ansible.
Organiser un projet Ansible
Placez-vous dans le répertoire du cinquième atelier pratique :
$ cd ~/formation-ansible/atelier-05
Voici les quatre machines virtuelles de cet atelier :
Machine virtuelle | Adresse IP |
---|---|
ansible |
10.23.45.10 |
rocky |
10.23.45.20 |
debian |
10.23.45.30 |
suse |
10.23.45.40 |
Démarrez les VM :
$ vagrant up
Connectez-vous au Control Host :
$ vagrant ssh ansible
L’environnement de cet atelier est préconfiguré et prêt à l’emploi :
- Ansible et
direnv
sont installés sur le Control Host. - Le fichier
/etc/hosts
du Control Host est correctement renseigné. - L’authentification par clé SSH est établie sur les trois Target Hosts.
$ type ansible direnv ansible is /usr/bin/ansible direnv is /usr/local/bin/direnv $ ansible all -i debian,rocky,suse -m ping rocky | SUCCESS => ... debian | SUCCESS => ... suse | SUCCESS => ...
Là encore, vous pouvez sereinement ignorer les avertissements concernant l’interpréteur Python sur l’un ou l’autre Target Host. Nous allons voir tout cela de plus près en temps et en heure.
En principe, Ansible ne nous impose pas vraiment de règles strictes quant à la structure des répertoires et des fichiers. Cela vous laisse pas mal de libertés pour organiser vos projets comme vous l’entendez. Ceci étant dit, voici deux recommandations utiles pour la suite :
- Un projet Ansible se trouve idéalement à l’intérieur d’un seul et même répertoire, ce qui permet de le gérer avec un logiciel de gestion de versions comme Git.
- Le travail au quotidien sur le Control Host se fait en tant qu’utilisateur non privilégié.
La deuxième exigence exclut d’emblée le répertoire /etc/ansible
présent dans certaines distributions, notamment Rocky Linux. S’il est présent sur votre système, oubliez-le tout simplement :
$ ls -l /etc/ansible/ total 8 -rw-r--r--. 1 root root 614 Apr 21 08:02 ansible.cfg -rw-r--r--. 1 root root 1175 Apr 21 08:02 hosts drwxr-xr-x. 2 root root 6 Apr 21 08:02 roles
Un projet Ansible est constitué de plusieurs choses :
- une configuration
- un inventaire (inventory)
- un ou plusieurs playbooks
Commençons par mettre en place une arborescence pour notre projet :
$ mkdir -pv ~/ansible/projets/ema mkdir: created directory '/home/vagrant/ansible' mkdir: created directory '/home/vagrant/ansible/projets' mkdir: created directory '/home/vagrant/ansible/projets/ema' $ cd $_
Vous vous demandez peut-être ce que veut dire le $_
fourni en argument à cd
. Sachez que la variable spéciale $_
contient l’argument fourni à la dernière commande dans le shell Bash.
Configuration de base
Nous allons utiliser Ansible avec une série de paramètres autres que ceux de la configuration fournie par défaut. Il nous faut donc éditer un fichier de configuration, et c’est là où les choses se compliquent un peu. En effet, Ansible va chercher son fichier de configuration à plusieurs endroits du système, par ordre de priorité croissant :
/etc/ansible/ansible.cfg
~/.ansible.cfg
ansible.cfg
dans le répertoire courant- l’emplacement correspondant au contenu de la variable d’environnement
ANSIBLE_CONFIG
Voyons dans la pratique à quoi cela ressemble. La commande ansible --version
nous permet d’afficher le fichier de configuration en vigueur :
$ ansible --version | head -n 2 ansible [core 2.14.14] config file = /etc/ansible/ansible.cfg
Ce fichier fait visiblement partie de l’installation :
$ rpm -qif /etc/ansible/ansible.cfg | head -n 1 Name : ansible-core
À présent, je crée un fichier caché .ansible.cfg
dans mon répertoire utilisateur. Ce fichier peut être vide, peu importe. Ce qui m’intéresse, c’est l’incidence sur l’emplacement du fichier de configuration identifié par Ansible :
$ touch ~/.ansible.cfg $ ansible --version | head -n 2 ansible [core 2.14.14] config file = /home/vagrant/.ansible.cfg
J’en conclus que le fichier ~/.ansible.cfg
aura la priorité sur /etc/ansible/ansible.cfg
lorsque les deux sont présents sur le système.
Continuons cette petite expérience et créons un autre fichier ansible.cfg
dans notre répertoire de projet :
$ cd ~/ansible/projets/ema/ $ touch ansible.cfg $ ansible --version | head -n 2 ansible [core 2.14.14] config file = /home/vagrant/ansible/projets/ema/ansible.cfg
Ici, mon fichier ~/ansible/projets/ema/ansible.cfg
l’emporte visiblement sur les deux autres. Cette solution semble donc adaptée à première vue à notre projet. Tant que nous nous trouvons à la racine du projet, Ansible utilisera le fichier de configuration ansible.cfg
propre au projet.
Le problème, c’est que ce fonctionnement n’est plus valable lorsque vous quittez le répertoire actuel. Dans ce cas, Ansible aura recours à un autre – voire aucun – fichier de configuration, ce qui n’est pas souhaitable :
$ mkdir -v playbooks mkdir: created directory 'playbooks' $ cd playbooks/ $ pwd /home/vagrant/ansible/projets/ema/playbooks $ ansible --version | head -n 2 ansible [core 2.14.14] config file = /home/vagrant/.ansible.cfg
Certes, on aurait toujours la possibilité de rester cantonnés à la racine de notre projet pour invoquer toutes nos commandes, mais ce n’est pas toujours commode. La solution la plus élégante consiste ici à identifier notre fichier de configuration ansible.cfg
grâce à la variable d’environnement ANSIBLE_CONFIG
gérée par direnv
.
Créez un fichier .envrc
à la racine du projet, c’est-à-dire dans ~/ansible/projets/ema
:
export ANSIBLE_CONFIG=$(expand_path ansible.cfg)
Autorisez l’utilisation de la variable d’environnement :
$ direnv allow direnv: loading ~/ansible/projets/ema/.envrc direnv: export +ANSIBLE_CONFIG
Dorénavant, le fichier ansible.cfg
à la racine de votre projet sera correctement identifié même si vous changez de répertoire à l’intérieur de celui-ci :
$ pwd /home/vagrant/ansible/projets/ema $ ansible --version | head -n 2 ansible [core 2.14.14] config file = /home/vagrant/ansible/projets/ema/ansible.cfg $ cd playbooks/ $ pwd /home/vagrant/ansible/projets/ema/playbooks $ ansible --version | head -n 2 ansible [core 2.14.14] config file = /home/vagrant/ansible/projets/ema/ansible.cfg
Maintenant que nous sommes fixés sur l’emplacement du fichier ansible.cfg
, voyons de plus près son contenu. Commençons par une simple directive au format INI qui définit l’emplacement de notre inventaire :
[defaults] inventory = ./inventory
Utiliser les logs
La directive log_path
permet de journaliser toutes les actions d’Ansible. Le fichier journal peut être choisi librement. En revanche, le répertoire censé contenir ce fichier doit exister :
$ mkdir -v ~/logs mkdir: created directory '/home/vagrant/logs'
Partant de là, vous pouvez définir la journalisation dans ansible.cfg
:
[defaults]
inventory = ./inventory
log_path = ~/logs/ansible.log
Faites un test pour vérifier si la journalisation s’effectue comme prévu :
$ ansible all -i rocky,debian,suse -m ping
...
$ cat ~/logs/ansible.log
Un premier inventaire
Un inventaire (inventory) indique à Ansible la liste des Target Hosts qu’il est censé gérer. Notre fichier de configuration ansible.cfg
définit déjà un fichier inventory
comme inventaire. Voici un premier jet de ce fichier, adapté à notre environnement labo :
[testing] rocky debian suse [testing:vars] ansible_python_interpreter=/usr/bin/python3 ansible_user=vagrant
Quelques remarques en vrac :
- La syntaxe utilisée ressemble vaguement à un format INI.
- Les noms entre crochets comme
[testing]
permettent de définir des groupes de cibles. - Rien ne vous oblige à définir des groupes, mais vous verrez que c’est une fonctionnalité pratique.
- Le groupe spécial
[all]
contient toutes les cibles. Il existe toujours, même s’il n’a pas été défini explicitement. - Ici, nous avons paramétré le groupe
[testing]
avec l’ajout:vars
. En l’occurrence, nous avons spécifié l’utilisation de Python 3. - La directive
ansible_user
définit le compte utilisateur avec lequel Ansible est censé se connecter à ses cibles.
Si tout se passe bien, notre ping
ressemblera à ceci :
$ ansible all -m ping
debian | SUCCESS => {
"changed": false,
"ping": "pong"
}
suse | SUCCESS => {
"changed": false,
"ping": "pong"
}
rocky | SUCCESS => {
"changed": false,
"ping": "pong"
}
Au-delà du ping
Le ping
constitue une première étape dans la configuration de nos cibles, mais ce n’est pas tout. Étant donné qu’il ne requiert pas de privilèges particuliers, nous n’en savons pas plus sur les droits d’accès nécessaires pour les tâches administratives diverses et variées. Faisons le test par l’exemple et demandons à Ansible d’exécuter une tâche qui requiert des droits d’accès élevés :
$ ansible all -a "head -n 1 /etc/shadow"
debian | FAILED | rc=1 >>
head: cannot open '/etc/shadow' for reading: Permission denied
rocky | FAILED | rc=1 >>
head: cannot open '/etc/shadow' for reading: Permission denied
suse | FAILED | rc=1 >>
head: cannot open '/etc/shadow' for reading: Permission denied
Dans notre environnement de labo, l’utilisateur vagrant
peut avoir des droits sudo
illimités sans mot de passe. Profitons-en et configurons une élévation des droits avec un seul paramètre supplémentaire :
[testing]
rocky
debian
suse
[testing:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_user=vagrant
ansible_become=yes
Voyons ce que ça donne :
$ ansible all -a "head -n 1 /etc/shadow"
debian | CHANGED | rc=0 >>
root:!$y$j9T$1UCdnxq34BxNVM1P31I2R1$d6AgxFx72UvS6:0:99999:7:::
suse | CHANGED | rc=0 >>
root:!$6$Vkg2x/wlMzXkunYA$aeTVs1qXTe/Dmoo9unCiOxV:19728::::::
rocky | CHANGED | rc=0 >>
root:!!$6$xDTZIRLhFUOzp2Zh$MpRtbsOkz9Qvbxy1C2k9nj:19728:0:99999:7:::
Cette fois-ci, Ansible dispose bien des privilèges nécessaires pour s’acquitter de l’opération avec succès. Nous voilà prêts pour envoyer des vraies pépites de tâches administratives à Ansible.
Quittez le Control Host :
$ exit
Supprimez toutes les VM de l’atelier :
$ vagrant destroy -f
Exercice
Le moment est venu de faire un petit exercice récapitulatif. Placez-vous dans le répertoire du sixième atelier pratique :
$ cd ~/formation-ansible/atelier-06
Voici les quatre machines virtuelles Ubuntu 20.04 de cet atelier :
Machine virtuelle | Adresse IP |
---|---|
control |
10.23.45.10 |
target01 |
10.23.45.20 |
target02 |
10.23.45.30 |
target03 |
10.23.45.40 |
Démarrez les VM :
$ vagrant up
Connectez-vous au Control Host :
$ vagrant ssh control
- Éditez
/etc/hosts
de manière à ce que les Target Hosts soient joignables par leur nom d’hôte simple. - Configurez l’authentification par clé SSH avec les trois Target Hosts.
- Installez Ansible.
- Envoyez un premier
ping
Ansible sans configuration. - Créez un répertoire de projet
~/monprojet
. - Créez un fichier vide
ansible.cfg
dans ce répertoire. - Vérifiez si ce fichier est bien pris en compte par Ansible.
- Spécifiez un inventaire nommé
hosts
. - Activez la journalisation dans
~/journal/ansible.log
. - Testez la journalisation.
- Créez un groupe
[testlab]
avec vos trois Target Hosts. - Définissez explicitement l’utilisateur
vagrant
pour la connexion à vos cibles. - Envoyez un
ping
Ansible vers le groupe de machines[all]
. - Définissez l’élévation des droits pour l’utilisateur
vagrant
sur les Target Hosts. - Affichez la première ligne du fichier
/etc/shadow
sur tous les Target Hosts. - Quittez le Control Host et supprimez toutes les VM de l’atelier.
Lire la suite : Commandes Ad-hoc
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.
2 commentaires
Dav09 · 24 septembre 2024 à 18 h 29 min
Bonjour,
Merci pour le tuto.
Si vous avez un problème pour lancer la VM Ansible de l’atelier 05 avec un message d’erreur pour synced_folder de type SSHFS.
Il faut installer le plugin SSHFS sur l’hôte avec la commande suivante :
vagrant plugin install vagrant-sshfs
kikinovak · 25 septembre 2024 à 7 h 14 min
Alternativement, lisez les articles dans l’ordre en commençant par le premier, et vous n’aurez pas ce problème. :o)