Passer au contenu principal

Fondamentaux (Ansible)

Les modules essentiels

Ansible dispose de plusieurs milliers de modules. En pratique, une dizaine de modules couvrent 80 % des cas d'usage en gestion de configuration Linux. Les maîtriser en profondeur, avec leurs options et leurs subtilités, est plus utile que de connaître superficiellement l'ensemble du catalogue.

apt : gestion des paquets Debian

# Installer un paquet
- ansible.builtin.apt:
    name: nginx
    state: present
    update_cache: true   # équivalent apt-get update avant l'installation

# Installer plusieurs paquets
- ansible.builtin.apt:
    name:
      - nginx
      - curl
      - htop
    state: present

# Supprimer avec purge
- ansible.builtin.apt:
    name: apache2
    state: absent
    purge: true

# Mettre à jour tous les paquets
- ansible.builtin.apt:
    upgrade: dist
    update_cache: true

Pour une gestion multi-distributions, le module ansible.builtin.package utilise le gestionnaire natif de l'OS, mais expose moins d'options que apt.

service / systemd : gestion des services

# Démarrer et activer un service
- ansible.builtin.systemd:
    name: nginx
    state: started
    enabled: true
    daemon_reload: true   # si des fichiers unit ont changé

state: restarted redémarre toujours. state: reloaded envoie SIGHUP (rechargement de config sans coupure). Préférer reloaded pour nginx et autres services qui le supportent.

copy vs template

C'est la distinction la plus importante à comprendre :

  • copy : transfère un fichier statique tel quel
  • template : traite le fichier source comme un template Jinja2, substitue les variables, puis transfère le résultat
# copy : fichier statique
- ansible.builtin.copy:
    src: files/nginx.conf          # relatif au rôle/playbook
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: "0644"
    backup: true                   # garde une copie .bak en cas de changement

# template : fichier avec variables
- ansible.builtin.template:
    src: templates/nginx.conf.j2   # le .j2 est une convention
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: "0644"

file : gérer les fichiers et répertoires

# Créer un répertoire
- ansible.builtin.file:
    path: /var/www/myapp
    state: directory
    owner: www-data
    group: www-data
    mode: "0755"

# Créer un lien symbolique
- ansible.builtin.file:
    src: /etc/nginx/sites-available/myapp
    dest: /etc/nginx/sites-enabled/myapp
    state: link

# Supprimer un fichier ou répertoire
- ansible.builtin.file:
    path: /tmp/obsolete
    state: absent

user : gestion des utilisateurs

- ansible.builtin.user:
    name: appuser
    uid: 1500
    group: appgroup
    groups:
      - sudo
      - docker
    append: true           # ajoute aux groupes existants, ne remplace pas
    shell: /bin/bash
    home: /home/appuser
    create_home: true
    system: false          # true pour un compte système (pas de home, pas de shell)
    state: present

command vs shell

Les deux modules exécutent des commandes sur la cible, mais avec une différence fondamentale :

  • command : exécute directement le binaire, sans passer par un shell. Pas d'interprétation de |, >, $VAR, etc. Plus sûr.
  • shell : exécute via /bin/sh. Supporte les pipes, redirections, variables d'environnement.
# command : préférable par défaut
- ansible.builtin.command:
    cmd: /usr/local/bin/myapp --init
    creates: /var/lib/myapp/.initialized   # idempotence manuelle

# shell : quand les features du shell sont nécessaires
- ansible.builtin.shell:
    cmd: "ps aux | grep nginx | grep -v grep"
  register: nginx_process
  changed_when: false   # cette commande ne modifie rien

Règle : utiliser command par défaut, shell uniquement quand les features shell sont indispensables. Dans les deux cas, préférer un module dédié quand il existe.

stat : inspecter l'état d'un fichier

- ansible.builtin.stat:
    path: /etc/myapp/initialized
  register: init_flag

- name: Initialiser l'application si pas déjà fait
  ansible.builtin.command:
    cmd: /usr/local/bin/myapp --init
  when: not init_flag.stat.exists