Automation
Difficulte: Intermediate
13 min de lecture

Ansible : Automatisation et gestion de configuration

Découvrez comment utiliser Ansible, l'outil d'automatisation open source, pour gérer vos serveurs et déployer des applications de manière simple et efficace.

Retour aux tutoriels
Qu'est-ce qu'Ansible ?
Ansible est un outil d'automatisation open source maintenu par Red Hat. Il permet de configurer des systèmes, déployer des logiciels et orchestrer des workflows complexes. Son architecture agentless (sans agent) le distingue de Puppet ou Chef : Ansible se connecte aux machines cibles via SSH et exécute les tâches décrites en YAML. Aucune installation n'est requise sur les nœuds gérés, ce qui simplifie considérablement la mise en place et la maintenance.

Prérequis

Avant de commencer avec Ansible, assurez-vous de disposer des éléments suivants :

  • Machine de contrôle : Un poste Linux ou macOS avec Python 3.8+ installé. Windows n'est pas supporté comme contrôleur mais fonctionne comme nœud cible via WinRM.
  • Accès SSH : Connexion SSH configurée vers les machines cibles, idéalement avec des clés SSH (pas de mot de passe).
  • Privilèges : Un utilisateur avec accès sudo sur les machines cibles pour les tâches d'administration.
  • Python sur les cibles : Python 3 installe sur les machines gérées (present par défaut sur la plupart des distributions Linux).
# Vérifier Python sur la machine de controle
python3 --version

# Générer une cle SSH si nécessaire
ssh-keygen -t ed25519 -C "ansible-controller"

# Copier la cle sur les machines cibles
ssh-copy-id user@serveur-cible

Installation multi-OS

Ansible s'installe uniquement sur la machine de contrôle. Voici les méthodes d'installation selon votre système.

Ubuntu / Debian

# Ajouter le PPA officiel Ansible
sudo apt update
sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible

# Vérifier l'installation
ansible --version

CentOS / RHEL

# Activer le depot EPEL
sudo dnf install -y epel-release
sudo dnf install -y ansible

# Sur RHEL 8+ avec subscription
sudo subscription-manager repos --enable ansible-automation-platform
sudo dnf install -y ansible-core

Installation via pip (toutes plateformes)

# Installation dans un virtualenv (recommande)
python3 -m venv ~/ansible-venv
source ~/ansible-venv/bin/activate
pip install ansible

# Ou installation globale
pip3 install ansible

# Installer une version spécifique
pip3 install ansible-core==2.16.0

Configuration de base

La configuration d'Ansible repose sur deux fichiers principaux : le fichier de configuration ansible.cfg et l'inventaire des hôtes.

ansible.cfg

Ansible cherche sa configuration dans cet ordre : variable d'environnement ANSIBLE_CONFIG, ./ansible.cfg (répertoire courant), ~/.ansible.cfg, puis /etc/ansible/ansible.cfg. Placez votre fichier à la racine de votre projet.

# ansible.cfg
[defaults]
inventory = ./inventory/hosts.ini
remote_user = deploy
host_key_checking = False
retry_files_enabled = False
forks = 10
timeout = 30
log_path = ./ansible.log

[privilège_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

Inventaire statique

L'inventaire définit les machines gérées par Ansible. Le format INI est le plus courant :

# inventory/hosts.ini
[webservers]
web1.example.com ansible_host=192.168.1.10
web2.example.com ansible_host=192.168.1.11

[databases]
db1.example.com ansible_host=192.168.1.20
db2.example.com ansible_host=192.168.1.21

[monitoring]
grafana.example.com ansible_host=192.168.1.30

# Groupe de groupes
[production:children]
webservers
databases

# Variables pour tout le groupe
[webservers:vars]
http_port=80
ansible_python_interpreter=/usr/bin/python3

Inventaire en YAML

# inventory/hosts.yml
all:
  children:
    webservers:
      hosts:
        web1.example.com:
          ansible_host: 192.168.1.10
        web2.example.com:
          ansible_host: 192.168.1.11
      vars:
        http_port: 80
    databases:
      hosts:
        db1.example.com:
          ansible_host: 192.168.1.20

Inventaire avancé

Pour les environnements complexes, Ansible offre des fonctionnalités d'inventaire avancées.

Variables de groupe et d'hôte

Organisez les variables dans des fichiers séparés selon la convention suivante :

# Structure des variables d'inventaire
inventory/
  hosts.ini
  group_vars/
    all.yml          # Variables globales
    webservers.yml   # Variables du groupe webservers
    databases.yml    # Variables du groupe databases
  host_vars/
    web1.example.com.yml  # Variables spécifiques a web1
# inventory/group_vars/webservers.yml
---
nginx_worker_processes: auto
nginx_worker_connections: 1024
ssl_certificate_path: /etc/ssl/certs
deploy_user: www-data

Inventaire dynamique

Pour les environnements cloud, utilisez un inventaire dynamique qui interroge l'API du provider :

# inventory/aws_ec2.yml
---
plugin: amazon.aws.aws_ec2
regions:
  - eu-west-1
  - eu-west-3
filters:
  tag:Environment: production
keyed_groups:
  - key: tags.Role
    prefix: role
  - key: placement.availability_zone
    prefix: az
compose:
  ansible_host: private_ip_address
# Tester un inventaire dynamique
ansible-inventory -i inventory/aws_ec2.yml --list
ansible-inventory -i inventory/aws_ec2.yml --graph

Modules essentiels

Ansible dispose de milliers de modules. Voici les plus utilisés au quotidien.

Gestion des paquets : apt et yum

- name: Installer des paquets (Debian/Ubuntu)
  ansible.builtin.apt:
    name:
      - nginx
      - curl
      - htop
    state: present
    update_cache: yes
    cache_valid_time: 3600

- name: Installer des paquets (CentOS/RHEL)
  ansible.builtin.yum:
    name:
      - httpd
      - vim
    state: latest

Gestion des services : service

- name: Demarrer et activer nginx
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: yes

- name: Redémarrer un service
  ansible.builtin.service:
    name: nginx
    state: restarted

Gestion des fichiers : copy, template, file

- name: Copier un fichier de configuration
  ansible.builtin.copy:
    src: files/nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: "0644"
    backup: yes

- name: Déployer un template Jinja2
  ansible.builtin.template:
    src: templates/vhost.conf.j2
    dest: "/etc/nginx/sites-available/{{ domain }}.conf"
    owner: root
    mode: "0644"

- name: Creer un repertoire
  ansible.builtin.file:
    path: /var/www/app
    state: directory
    owner: www-data
    group: www-data
    mode: "0755"
    recurse: yes

Exécution de commandes : shell et command

- name: Executer une commande simple
  ansible.builtin.command:
    cmd: whoami
  register: current_user

- name: Commande shell avec pipe
  ansible.builtin.shell:
    cmd: "df -h | grep /dev/sda1"
  register: disk_usage
  changed_when: false

- name: Afficher le resultat
  ansible.builtin.debug:
    msg: "Espace disque : {{ disk_usage.stdout }}"

Gestion des utilisateurs : user

- name: Creer un utilisateur applicatif
  ansible.builtin.user:
    name: deploy
    shell: /bin/bash
    groups: sudo,docker
    append: yes
    create_home: yes
    generate_ssh_key: yes
    ssh_key_bits: 4096

Playbooks

Les playbooks sont le cœur d'Ansible. Ils décrivent l'état desire de vos systèmes dans des fichiers YAML.

Syntaxe YAML de base

---
# playbook-webserver.yml
- name: Configurer les serveurs web
  hosts: webservers
  become: yes
  vars:
    app_name: monapp
    app_port: 8080

  tasks:
    - name: Mettre à jour le cache apt
      ansible.builtin.apt:
        update_cache: yes
        cache_valid_time: 3600

    - name: Installer les dépendances
      ansible.builtin.apt:
        name: "{{ item }}"
        state: present
      loop:
        - nginx
        - python3-pip
        - supervisor

    - name: Déployer la configuration nginx
      ansible.builtin.template:
        src: templates/nginx-app.conf.j2
        dest: "/etc/nginx/sites-available/{{ app_name }}.conf"
      notify: Recharger nginx

  handlers:
    - name: Recharger nginx
      ansible.builtin.service:
        name: nginx
        state: reloaded

Handlers

Les handlers sont des tâches déclenchées uniquement quand une autre tâche les notifie via notify. Ils s'executent une seule fois à la fin du play, même s'ils sont notifies plusieurs fois :

handlers:
  - name: Redémarrer nginx
    ansible.builtin.service:
      name: nginx
      state: restarted

  - name: Recharger systemd
    ansible.builtin.systemd:
      daemon_reload: yes

Conditions

- name: Installer sur Debian uniquement
  ansible.builtin.apt:
    name: nginx
    state: present
  when: ansible_os_family == "Debian"

- name: Configurer le firewall si actif
  ansible.builtin.ufw:
    rule: allow
    port: "{{ http_port }}"
  when:
    - firewall_enabled | default(false)
    - http_port is defined

Boucles

- name: Creer plusieurs utilisateurs
  ansible.builtin.user:
    name: "{{ item.name }}"
    groups: "{{ item.groups }}"
    shell: /bin/bash
  loop:
    - { name: "alice", groups: "sudo" }
    - { name: "bob", groups: "docker" }
    - { name: "charlie", groups: "sudo,docker" }

- name: Copier plusieurs fichiers
  ansible.builtin.copy:
    src: "files/{{ item }}"
    dest: "/etc/app/{{ item }}"
  loop:
    - app.conf
    - db.conf
    - logging.conf

Tags

Les tags permettent d'exécuter selectivement certaines tâches d'un playbook :

- name: Installer nginx
  ansible.builtin.apt:
    name: nginx
    state: present
  tags:
    - install
    - nginx

- name: Configurer nginx
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  tags:
    - configure
    - nginx
# Executer uniquement les taches taguees "configure"
ansible-playbook site.yml --tags configure

# Exclure les taches taguees "install"
ansible-playbook site.yml --skip-tags install

# Lister les tags disponibles
ansible-playbook site.yml --list-tags

Variables et templates

Types de variables

Ansible propose plusieurs niveaux de variables avec un ordre de precedence precis. Les plus courants :

# Variables dans le playbook
vars:
  app_name: monapp
  app_port: 8080
  db_config:
    host: localhost
    port: 5432
    name: mydb

# Variables depuis un fichier externe
vars_files:
  - vars/common.yml
  - "vars/{{ env }}.yml"

Facts Ansible

Ansible collecte automatiquement des informations (facts) sur les machines cibles. Utilisez-les dans vos playbooks :

- name: Afficher les facts système
  ansible.builtin.debug:
    msg: |
      OS: {{ ansible_distribution }} {{ ansible_distribution_version }}
      IP: {{ ansible_default_ipv4.address }}
      RAM: {{ ansible_memtotal_mb }} MB
      CPU: {{ ansible_processor_cores }} cores
# Consulter tous les facts d'un hote
ansible web1.example.com -m setup

# Filtrer les facts
ansible web1.example.com -m setup -a "filter=ansible_distribution*"

Templates Jinja2

Les templates Jinja2 permettent de générer des fichiers de configuration dynamiques :

# templates/nginx-vhost.conf.j2
server {
    listen {{ http_port | default(80) }};
    server_name {{ domain }};
    root /var/www/{{ app_name }};

    {% if ssl_enabled | default(false) %}
    listen 443 ssl;
    ssl_certificate {{ ssl_cert_path }};
    ssl_certificate_key {{ ssl_key_path }};
    {% endif %}

    {% for location in app_locations | default([]) %}
    location {{ location.path }} {
        proxy_pass http://127.0.0.1:{{ location.port }};
        proxy_set_header Host $host;
    }
    {% endfor %}

    access_log /var/log/nginx/{{ domain }}_access.log;
    error_log /var/log/nginx/{{ domain }}_error.log;
}

Roles

Les rôles structurent votre code Ansible en composants réutilisables et modulaires.

Structure d'un rôle

# Structure standard d'un role
roles/
  nginx/
    tasks/
      main.yml        # Taches principales
    handlers/
      main.yml        # Handlers du role
    templates/
      nginx.conf.j2   # Templates Jinja2
    files/
      index.html      # Fichiers statiques
    vars/
      main.yml        # Variables du role (haute priorite)
    defaults/
      main.yml        # Valeurs par défaut (basse priorite)
    meta/
      main.yml        # Metadonnees et dépendances

Créer un rôle

# Générer la structure avec ansible-galaxy
ansible-galaxy init roles/nginx

# Ou creer manuellement
mkdir -p roles/nginx/{tasks,handlers,templates,files,vars,defaults,meta}
# roles/nginx/tasks/main.yml
---
- name: Installer nginx
  ansible.builtin.apt:
    name: nginx
    state: present

- name: Déployer la configuration
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: Redémarrer nginx

- name: Activer le service
  ansible.builtin.service:
    name: nginx
    state: started
    enabled: yes
# roles/nginx/defaults/main.yml
---
nginx_worker_processes: auto
nginx_worker_connections: 1024
nginx_keepalive_timeout: 65
# Utiliser un role dans un playbook
---
- hosts: webservers
  become: yes
  roles:
    - role: nginx
      vars:
        nginx_worker_connections: 2048
    - role: app
    - role: monitoring

Ansible Galaxy

Galaxy est le dépôt communautaire de rôles Ansible. Utilisez-le pour trouver et partager des rôles :

# Chercher un role
ansible-galaxy search nginx --platforms Ubuntu

# Installer un role depuis Galaxy
ansible-galaxy install geerlingguy.nginx

# Installer des roles depuis un fichier requirements
ansible-galaxy install -r requirements.yml
# requirements.yml
---
roles:
  - name: geerlingguy.nginx
    version: "3.1.0"
  - name: geerlingguy.postgresql
    version: "3.4.0"

collections:
  - name: community.general
    version: ">=5.0.0"

Ansible Vault

Vault permet de chiffrer les données sensibles (mots de passe, clés API, certificats) directement dans vos fichiers Ansible.

# Creer un fichier chiffre
ansible-vault create vars/secrets.yml

# Chiffrer un fichier existant
ansible-vault encrypt vars/production.yml

# Editer un fichier chiffre
ansible-vault edit vars/secrets.yml

# Dechiffrer un fichier
ansible-vault decrypt vars/secrets.yml

# Chiffrer une variable individuelle
ansible-vault encrypt_string "MonMotDePasse123" --name "db_password"
# vars/secrets.yml (contenu avant chiffrement)
---
db_password: "SuperSecret123"
api_key: "ak_live_xxxxxxxxxxxx"
ssl_private_key: |
  -----BEGIN PRIVATE KEY-----
  MIIEvgIBADANBg...
  -----END PRIVATE KEY-----
# Executer un playbook avec Vault
ansible-playbook site.yml --ask-vault-pass

# Utiliser un fichier de mot de passe (recommandé en CI/CD)
ansible-playbook site.yml --vault-password-file ~/.vault_pass

# Plusieurs mots de passe Vault avec des identifiants
ansible-vault encrypt --vault-id prod@prompt vars/prod-secrets.yml
ansible-playbook site.yml --vault-id prod@~/.vault_pass_prod

Bonnes pratiques

Structure de projet

Adoptez une structure standardisee pour vos projets Ansible :

# Structure recommandee
ansible-project/
  ansible.cfg
  site.yml              # Playbook principal
  webservers.yml         # Playbook par groupe
  databases.yml
  inventory/
    production/
      hosts.ini
      group_vars/
        all.yml
        webservers.yml
      host_vars/
        web1.yml
    staging/
      hosts.ini
      group_vars/
  roles/
    common/
    nginx/
    postgresql/
  playbooks/             # Playbooks operationnels
    deploy.yml
    backup.yml
    rollback.yml

Idempotence

Chaque tâche doit être idempotente : l'exécuter plusieurs fois produit le même resultat qu'une seule execution. Evitez les modules shell et command quand un module dédié existe.

# Mauvais : pas idempotent
- name: Creer le repertoire
  ansible.builtin.shell: mkdir -p /var/www/app

# Bon : idempotent
- name: Creer le repertoire
  ansible.builtin.file:
    path: /var/www/app
    state: directory
    mode: "0755"

Conventions de nommage

  • Noms de tâches descriptifs : Installer les dépendances Python plutôt que step 1
  • Variables en snake_case : app_port, db_host
  • Roles nommes par fonction : nginx, postgresql, monitoring
  • Utilisez les FQCN (Fully Qualified Collection Names) : ansible.builtin.apt au lieu de apt

Troubleshooting

Module debug

- name: Afficher une variable
  ansible.builtin.debug:
    var: my_variable

- name: Afficher un message formate
  ansible.builtin.debug:
    msg: "L'utilisateur {{ user }} a ete cree sur {{ inventory_hostname }}"

- name: Capturer et afficher la sortie d'une commande
  ansible.builtin.command: systemctl status nginx
  register: nginx_status
  changed_when: false

- name: Afficher le resultat
  ansible.builtin.debug:
    var: nginx_status.stdout_lines

Mode verbose

# Niveaux de verbosity
ansible-playbook site.yml -v      # Sortie detaillee
ansible-playbook site.yml -vv     # Plus de details
ansible-playbook site.yml -vvv    # Debug connexion SSH
ansible-playbook site.yml -vvvv   # Debug complet avec scripts

# Mode check (dry-run) avec diff
ansible-playbook site.yml --check --diff

# Limiter l'execution a un hote
ansible-playbook site.yml --limit web1.example.com

# Demarrer a une tache spécifique
ansible-playbook site.yml --start-at-task "Déployer la configuration"

# Executer etape par etape
ansible-playbook site.yml --step

Problèmes courants

  • Permission denied : Vérifiez que become: yes est défini et que l'utilisateur a les droits sudo sans mot de passe, ou utilisez --ask-become-pass.
  • Host unreachable : Testez la connectivité avec ansible all -m ping. Vérifiez la configuration SSH et les cles.
  • Module not found : Installez la collection requise avec ansible-galaxy collection install community.general.
  • Variable undefined : Utilisez le filtre default() pour définir des valeurs par défaut : {{ var | default("fallback") }}.
  • Lenteur d'exécution : Activez le pipelining dans ansible.cfg, augmentez les forks, et desactivez la collecte de facts si non nécessaire avec gather_facts: no.

Conclusion

Ansible est un outil puissant qui simplifie l'automatisation de l'infrastructure grâce à son approche agentless et à sa syntaxe YAML accessible. En maîtrisant les concepts présentés dans ce tutoriel (inventaires, modules, playbooks, rôles et Vault), vous disposez des bases solides pour automatiser la gestion de vos serveurs, standardiser vos déploiements et garantir la cohérence de votre infrastructure. Commencez par des playbooks simples, puis structurez progressivement votre code en rôles réutilisables. L'investissement initial est rapidement rentabilisé par le gain de temps et la réduction des erreurs humaines.

Points clés à retenir
- Privilégiez les modules dédiés plutôt que shell/command pour garantir l'idempotence
- Structurez votre code en rôles dès que vous avez plus de 2-3 playbooks
- Chiffrez systematiquement les secrets avec Ansible Vault
- Testez toujours en mode --check --diff avant d'appliquer en production
- Versionnez l'ensemble de votre code Ansible avec Git
Morgann Riu

Écrit par

Morgann Riu

Expert en cybersécurité et administration Linux. Je partage mes connaissances à travers des tutoriels gratuits et des formations pour aider les administrateurs systèmes et développeurs à sécuriser leurs infrastructures.

Partager ce tutoriel

Cet article vous a plu ?

Commentaires

Checklist Sécurité Linux

30 points essentiels pour sécuriser un serveur Linux. Recevez aussi les nouveaux tutoriels par email.

Pas de spam. Désabonnement en 1 clic.