Cas d'utilisation simple et rapide pour comprendre Ansible
lun. 31 décembre 2018
On va tenter de comprendre les bases d'Ansible par la pratique en mettant en place un playbook qui nous permettra de créer automatiquement un nouvel utilisateur en lui attribuant des droits sudo.
Principe de base
Ansible utilise 2 types de fichiers:
- Un inventaire dans lequel nous allons décrire nos environnements
- Un playbook pour décrire les actions à réaliser
L'inventaire
Un inventaire est un fichier texte qui contient la liste des machines sur lesquelles on veut travailler. Le format par défaut est le format ini. Les machines peuvent être assemblées dans un groupe. On peut par exemple regrouper les machines dédiées au web:
[webservers]
foo.example.com
bar.example.com
On peut faire bien d'autres choses dans un inventaire comme:
- indiquer un port
- un mot de passe
- créer des variables
Pour en savoir plus rendez-vous sur la documentation ansible.
Le playbook
Un playbook est un fichier qui respecte le format yaml. Il permet de décrire l'exécution d'une liste de tâches sur une machine distante.
Hôtes, utilisateur et Tâches
Pour spécifier ces éléments on utilise des mots-clés:
hosts
permet de spécifier le groupe de l'inventaire sur lesquelle on veut intervenirremote_user
indentifie un utilisateur distanttasks
est une liste (au sens yaml) d'actions à exécuter
Modules
Les actions que l'on décrit dans tasks
utilisent un des nombreux modules fournis par Ansible.
Ces modules sont organisés autour de divers thèmatiques, par exemple:
- Database
- Files
- Network
- Packaging
- System
La liste complète des thèmes est diponible dans l'index des modules
Ansible propose le module user dédié à la gestion des utilisateurs. Il fait partie de la catégorie des modules system.
L'utilisation d'un module est simple est bien documenté.
On commence par un champ name
. Ce champ est optionnel mais il
est affiché lors de l'exécution du playbook ce qui facilite le suivit.
On ajoute ensuite le nom du module et ses paramètres. Par exemple, pour créer l'utilisateur sebastien avec l'uid 1040 on procéde ainsi:
- name: Ajout du user 'sebastien'
become: true
user:
name: sebastien
comment: Sébastien
uid: 1040
become: true
permet d'exécuter une action avec les privilèges root (ansible utilise sudo par defaut).
Exemple complet de playbook
On a maintenant tous les éléments pour créer un utilisateur et lui attribuer les droits sudo
.
Cependant, pour gagner en souplesse on variabilise le nom de l'utilisateur:
vars:
user: seb
Pour exploiter cette variable Ansible utilise la librairie python Jinja2. Jinja est un outil de templating qui s'utilise de la façon suivante:
création de l'utilisateur {{ user }}
Vous pouvez en apprendre plus sur les variables dans la documentation.
La dernière chose à faire pour ajouter des droits sudo est de créer un fichier sudoer dans la machine cible. On va utiliser le module template. L'avantage de ce module par rapport au module copy est qu'on peut utiliser l'outil de templating jinja dans les documents qu'on veut copier.
Le module s'utilise comme ceci:
- template:
src: /mytemplates/foo.j2
dest: /etc/file.conf
owner: bin
group: wheel
mode: 0644
On peut maintenant compléter notre playbook:
---
- name: Création de l'utilisateur
hosts: webservers
remote_user: user1
vars:
user: seb
tasks:
- name: "creation user {{ user }}"
when: user is defined
become: true
user: name={{ user }}
- name: "{{ user }} devient sudoer"
when: user is defined
become: true
template: src=sudoers.j2 dest="/etc/sudoers.d/{{ user }}-sudoer"
...
et le template sudoers.j2
{{ user }} ALL=(ALL:ALL) NOPASSWD: ALL
Exécution du playbook
Pour exécuter ce playbook on lance la commande ansible-playbook avec en paramètre l'inventaire et le playbook:
ansible-playbook -i host-file playbook.yml
Utilisation des Rôles
Voila, le playbook fonctionne mais est ce qu'on peut l'améliorer ?
Pour l'instant il n'y que quelques tâches mais ça pourrait augmenter rapidement. De plus, une liste de tâches mélangées dans un même fichier n'aide pas la réutilisation.
C'est pour répondre à ces problématiques qu'Ansible propose les rôles. Notre playbook est dédié à la création de comptes donc nous allons créer un role user.
Pour ce faire il faut mettre en place la structure de répertoires suivante:
roles/
user/
tasks/
main.yml
templates/
sudoers.j2
Dans main
on déplace toutes les actions:
---
- name: "creation user {{ user }}"
when: user is defined
become: true
user: name={{ user }}
- name: "{{ user }} devient sudoer"
when: user is defined
become: true
template: src=templates/sudoers.j2 dest="/etc/sudoers.d/{{ user }}-sudoer"
On place le fichier sudoers.j2 dans le dossier template. Et pour finir on met à jour le playbook comme ceci:
---
- name: Création de compte
hosts: webservers
remote_user: admin
vars:
user: seb
roles:
- user
...
Voila, le playbook est bien plus lisible ainsi. On peut lui ajouter facilement un rôle. De plus le concept de rôle permet répond bien au souci de réutilisabilité.
Voila !
Documentation
Notes divers
- Le lancement d'un test en local necessite l'ajout de l'option
--connection=local
à la commande ansible-playbook - On peut utiliser également l'une des solutions lister ici ou sur la page Local Playbooks
- L'utilisateur distant (remote_user) doit pouvoir se connecter en ssh aux machines distantes. Plusieurs
solutions sont possibles:
- échange de clé SSH
- ajout du mot de passe dans l'inventaire (ansible_ssh_pass)
- ajout d'une variable dans la ligne de commande avec l'option --extra-vars