Maîtrisez Ansible de zéro à héros : l'automatisation opérationnelle à portée de main

Franchement, mes débuts avec Ansible ont été déroutants. À l'époque, je gérais des dizaines de serveurs, et chaque déploiement ou mise à jour de configuration devait être effectué manuellement, un par un. C'était épuisant et source d'erreurs. Puis j'ai découvert Ansible, qui m'a littéralement libéré les mains.

Qu'est-ce qu'Ansible exactement ?

En termes simples, Ansible est un outil d'automatisation. Vous pouvez le considérer comme une "télécommande" capable de contrôler simultanément plusieurs serveurs. Par exemple, pour installer Nginx sur 100 serveurs, la méthode traditionnelle consisterait à se connecter à chacun d'eux individuellement. Avec Ansible, il suffit d'écrire un script et le tour est joué.

Je me souviens de ma première utilisation d'Ansible pour un déploiement en masse : voir les commandes s'exécuter en cascade dans le terminal était grisant. Un travail qui me prenait une journée entière a été réalisé en 10 minutes.

Relation entre nœud de contrôle et nœuds gérés

Ce concept est très simple : le nœud de contrôle est la machine sur laquelle Ansible est installé, tandis que les nœuds gérés sont les serveurs que vous administrez.

Personnellement, j'installe Ansible sur un serveur bastion pour faciliter la gestion. Le nœud de contrôle doit pouvoir se connecter via SSH à tous les nœuds gérés, c'est le prérequis de base.

# Installation d'Ansible sur le nœud de contrôle
yum install ansible -y

# Ou via pip
pip install ansible

Les nœuds gérés n'ont rien à installer, ils doivent simplement être accessibles via SSH. C'est l'un des avantages d'Ansible : contrairement à d'autres outils, aucun agent n'est nécessaire sur les machines cibles.

Inventaire (Inventory) : le registre des serveurs

Le fichier d'inventaire est comme votre carnet d'adresses des serveurs, contenant les informations de toutes les machines à gérer.

Un inventaire minimal ressemble à ceci :

[webservers]
192.168.1.10
192.168.1.11
192.168.1.12

[databases]
192.168.1.20
192.168.1.21

Mais en production, je le rédige de manière plus détaillée :

[webservers]
web01 ansible_host=192.168.1.10 ansible_user=root ansible_ssh_private_key_file=/root/.ssh/id_rsa
web02 ansible_host=192.168.1.11 ansible_user=root ansible_ssh_private_key_file=/root/.ssh/id_rsa

[databases]
db01 ansible_host=192.168.1.20 ansible_user=mysql ansible_become=yes
db02 ansible_host=192.168.1.21 ansible_user=mysql ansible_become=yes

[production:children]
webservers
databases

Cette approche permet de spécifier des paramètres de connexion différents pour chaque machine, comme l'utilisation de clés SSH, de mots de passe ou l'escalade de privilèges sudo.

Modules : la boîte à outils d'Ansible

Ansible propose des milliers de modules, chacun dédié à une fonction spécifique. Inutile de tous les connaître dès le départ ; maîtrisez d'abord les plus courants.

Modules de gestion de fichiers

Le module copy sert à copier des fichiers :

- name: Copier un fichier de configuration
  copy:
    src: /chemin/local/nginx.conf
    dest: /etc/nginx/nginx.conf
    owner: root
    group: root
    mode: '0644'

Le module file gère les fichiers et répertoires :

- name: Créer un répertoire
  file:
    path: /opt/monapp
    state: directory
    owner: www
    group: www
    mode: '0755'

Gestion des paquets

Le module yum pour CentOS/RHEL :

- name: Installer Nginx
  yum:
    name: nginx
    state: present

Le module apt pour Ubuntu/Debian :

- name: Installer Nginx
  apt:
    name: nginx
    state: present
    update_cache: yes

Gestion des services

Le module systemd gère les services système :

- name: Démarrer le service Nginx
  systemd:
    name: nginx
    state: started
    enabled: yes

En pratique, ces quelques modules couvrent 80 % des tâches quotidiennes d'administration.

Tâches et Playbooks : le scénario d'automatisation

Une tâche est une opération spécifique (installer un logiciel, copier un fichier, etc.). Un playbook organise plusieurs tâches en un flux d'automatisation complet.

Voici un exemple concret pour déployer une application web :

---
- name: Déployer une application web
  hosts: webservers
  become: yes
  vars:
    app_name: monapp
    app_version: 1.2.3

  tasks:
    - name: Installer les paquets requis
      yum:
        name:
          - nginx
          - python3
          - git
        state: present

    - name: Créer le répertoire de l'application
      file:
        path: "/opt/{{ app_name }}"
        state: directory
        owner: nginx
        group: nginx
        mode: '0755'

    - name: Télécharger le code source
      git:
        repo: https://github.com/entreprise/monapp.git
        dest: "/opt/{{ app_name }}"
        version: "{{ app_version }}"
      notify: redemarrer nginx

    - name: Copier la configuration Nginx
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/conf.d/monapp.conf
      notify: redemarrer nginx

    - name: Démarrer le service Nginx
      systemd:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: redemarrer nginx
      systemd:
        name: nginx
        state: restarted

Ce playbook effectue plusieurs actions : installation des paquets, création des répertoires, téléchargement du code, configuration de Nginx et démarrage du service. Si un fichier de configuration change, Nginx est automatiquement redémarré.

Variables et templates : une configuration flexible

En environnement réel, les configurations diffèrent selon l'environnement (production, staging, etc.). C'est là que les variables et templates entrent en jeu.

Je crée généralement des fichiers de variables par environnement :

group_vars/production.yml :

db_host: prod-db.entreprise.com
db_port: 3306
app_env: production
log_level: warn

group_vars/staging.yml :

db_host: staging-db.entreprise.com
db_port: 3306
app_env: staging
log_level: debug

Et j'utilise ces variables dans un template :

templates/app.conf.j2 :

[database]
host = {{ db_host }}
port = {{ db_port }}

[app]
environment = {{ app_env }}
log_level = {{ log_level }}

Ainsi, le même playbook peut s'adapter à différents environnements.

Rôles : l'art de la modularité

Lorsque le projet devient complexe, tout écrire dans un seul playbook devient inapproprié. Les rôles permettent une gestion modulaire.

Structure d'un rôle :

roles/
  nginx/
    tasks/main.yml
    handlers/main.yml
    templates/
    files/
    vars/main.yml
    defaults/main.yml

Exemple d'un rôle nginx :

roles/nginx/tasks/main.yml :

---
- name: Installer Nginx
  yum:
    name: nginx
    state: present

- name: Copier la configuration principale
  template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: redemarrer nginx

- name: Copier les configurations des sites
  template:
    src: "{{ item }}"
    dest: "/etc/nginx/conf.d/{{ item | basename | regex_replace('.j2$', '') }}"
  with_fileglob:
    - "../templates/sites/*.j2"
  notify: redemarrer nginx

- name: Démarrer le service Nginx
  systemd:
    name: nginx
    state: started
    enabled: yes

roles/nginx/handlers/main.yml :

---
- name: redemarrer nginx
  systemd:
    name: nginx
    state: restarted

Utilisation du rôle dans un playbook :

---
- name: Configurer les serveurs web
  hosts: webservers
  roles:
    - nginx
    - php
    - mysql

Handlers : une atuomatisation réactive

Les handlers sont une fonctionnalité puissante d'Ansible. Ils ne s'exécutent que lorsqu'ils sont notifiés, et chaque handler ne s'exécute qu'une seule fois par exécution de playbook, même s'il est notifié plusieurs fois.

Par exemple, après avoir modifié plusieurs fichiers de configuration Nginx, vous ne voulez pas redémarrer le service à chaque modification, mais seulement une fois toutes les modifications effectuées. Les handlers répondent à ce besoin.

tasks:
  - name: Modifier la configuration principale de Nginx
    template:
      src: nginx.conf.j2
      dest: /etc/nginx/nginx.conf
    notify: redemarrer nginx

  - name: Modifier la configuration d'un site
    template:
      src: site.conf.j2
      dest: /etc/nginx/conf.d/site.conf
    notify: redemarrer nginx

  - name: Modifier la configuration SSL
    template:
      src: ssl.conf.j2
      dest: /etc/nginx/conf.d/ssl.conf
    notify: redemarrer nginx

handlers:
  - name: redemarrer nginx
    systemd:
      name: nginx
      state: restarted

Même si les trois tâches notifient le handler, Nginx ne sera redémarré qu'une seule fois.

Astuces pratiques et retours d'expérience

Gestion des clés SSH

Au début, j'ai eu des problèmes de connexion SSH. La meilleure approche est d'utiliser l'authentification par clé et de bien distribuer les clés.

# Génération de la paire de clés
ssh-keygen -t rsa -b 4096 -f ~/.ssh/ansible_rsa

# Distribution de la clé publique vers les nœuds gérés
ssh-copy-id -i ~/.ssh/ansible_rsa.pub user@target_host

Spécification de la clé privée dans l'inventaire :

[servers]
server1 ansible_host=192.168.1.10 ansible_ssh_private_key_file=~/.ssh/ansible_rsa

Importance de l'idempotence

Une caractéristique clé d'Ansible est l'idempotence : l'exécution répétée d'une même opération doit produire le même résultat.

Exemple non idempotent :

- name: Ajouter un utilisateur à sudoers
  shell: echo "myuser ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

Ce code ajoute une ligne supplémentaire à chaque exécution. Il faut plutôt utiliser :

- name: Ajouter un utilisateur à sudoers
  lineinfile:
    path: /etc/sudoers
    line: "myuser ALL=(ALL) NOPASSWD:ALL"
    state: present

Gestion des erreurs et débogage

Voici quelques astuces de débogage :

  1. Augmenter la verbosité avec l'option -v :
ansible-playbook -vvv playbook.yml

  1. Utiliser le module debug pour afficher les variables :
- name: Afficher la variable
  debug:
    var: ansible_facts['os_family']

  1. Ignorer certaines erreurs avec ignore_errors :
- name: Tâche pouvant échouer
  command: some_commande_qui_peut_echouer
  ignore_errors: yes

  1. Définir des conditions d'échec personnalisées avec failed_when :
- name: Vérifier l'état du service
  command: systemctl is-active nginx
  register: nginx_status
  failed_when: nginx_status.rc != 0 and nginx_status.rc != 3

Optimisation des performances

Quand le nombre de machines gérées augmente, les performances deviennent cruciales. Voici quelques optimisations :

  1. Ajuster le nombre de processus en parallèle :
# ansible.cfg
[defaults]
forks = 50

  1. Activer le SSH pipelining :
[ssh_connection]
pipelining = True

  1. Utiliser le plugin de stratégie free :
- name: Playbook d'exécution rapide
  hosts: all
  strategy: free
  tasks:
    - name: Tâche simple
      ping:

Gestion des fichiers de configuration

Le fichier de configuration d'Ansible, ansible.cfg, peut être placé à plusieurs endroits, avec la priorité suivante (de la plus haute à la plus basse) :

  1. Fichier spécifié par la variable d'environnement ANSIBLE_CONFIG
  2. ansible.cfg dans le répertoire courant
  3. .ansible.cfg dans le répertoire personnel
  4. /etc/ansible/ansible.cfg

J'utilise généralement un fichier ansible.cfg dans le répertoire du projet :

[defaults]
inventory = inventory/hosts
host_key_checking = False
timeout = 30
forks = 20
remote_user = root

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

Cas d'usage concrets

Ansible m'a aidé à résoudre de nombreux problèmes en entreprise. Voici quelques scénarios typiques :

Initialisation massive de serveurs

À la mise en service de nouvelles machines, de nombreuses tâches initiales sont nécessaires : création d'utilisateurs, configuration SSH, installation de logiciels de base, réglage du fuseau horaire, etc. Un playbook Ansible permet de tout initialiser en quelques minutes.

Déploiement d'applications

Auparavant, chaque déploiement nécessitait de se connecter à chaque serveur, d'arrêter le service, de sauvegarder, de mettre à jour le code et de redémarrer. Désormais, un seul playbook gère tout, y compris les déploiements sans interruption de service.

Gestion de configuration

Les modifications de configuration système sont monnaie courante. Ansible garantit la cohérence des configurations sur toutes les machines et permet de suivre l'historique des changements.

Maintenance régulière

Pour les tâches périodiques comme le nettoyage des logs, le renouvellement des certificats ou l'application de correctifs de sécurité, un playbook associé à cron simplifie grandement la vie.

Récemment, j'ai dû renouveler les certificats SSL de tous les serveurs de l'entreprise. Manuellement, cela aurait pris plusieurs jours pour des centaines de machines. Avec un playbook Ansible, tout a été fait en une demi-heure, sans aucune erreur.

Bien sûr, Ansible n'est pas une solution universelle. Pour des scénarios d'orchestration complexes, d'autres outils peuvent être nécessaires. Mais pour la majorité des tâches d'administration, Ansible est plus que suffisant.

La meilleure façon d'apprendre Ansible est de pratiquer. Commencez par des tâches simples (exécution de commandes en lot, copie de fichiers) puis explorez progressivement des fonctionnalités plus avancées. Rappelez-vous : tout outil doit résoudre un problème concret ; ne l'utilisez pas pour le plaisir.

J'espère que cet article vous aidera à mieux comprendre et utiliser Ansible. L'automatisation opérationnelle est un long chemin, mais avec Ansible comme allié, votre travail deviendra bien plus léger.

Étiquettes: Ansible automatisation devops playbook role

Publié le 14 juillet à 16h28