Cas d'utilisation simple et rapide pour comprendre Ansible

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:

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:

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:

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:

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