ℹ️ À savoir · En bref

Ansible est un outil open source (Red Hat) qui automatise la configuration de serveurs et d'applications. On décrit l'état voulu en YAML ; Ansible se connecte en SSH (Linux) ou WinRM/SSH (Windows), applique ce qui manque, et ne touche à rien si tout est déjà conforme.

Trois mots à retenir : agentless (rien à installer sur les cibles), push (c'est le nœud de contrôle qui pousse), idempotent (rejouer = même résultat).

Objectifs de la fiche

  • Comprendre l'architecture et le vocabulaire Ansible.
  • Écrire un inventaire et un playbook idempotent.
  • Utiliser variables, templates, handlers et rôles.
  • Exécuter sans risque (--check --diff, --limit) et éviter les pièges classiques.

Le vocabulaire en 1 tableau

TermeCe que c'estExemple
Nœud de contrôleLa machine où Ansible est installé et d'où partent les exécutions.Poste admin Linux, WSL, conteneur
Nœud géréUne cible configurée par Ansible. Aucun agent permanent.vda-ubuntu01, srv-sf01
InventaireLa liste des cibles, rangées en groupes, avec leurs variables.inventory/hosts.yml
ModuleL'unité de travail : une action idempotente avec des paramètres.ansible.builtin.apt
TaskUn appel de module, avec un nom lisible.« Installer sssd »
PlayAssocie un groupe d'hôtes à une liste de tâches.hosts: vda_linux
PlaybookFichier YAML contenant un ou plusieurs plays.site.yml
HandlerTâche déclenchée seulement si une autre tâche a changé quelque chose.Redémarrer un service
RôlePaquet réutilisable de tâches, templates, variables, handlers.rôle linux_vda
CollectionDistribution de modules/rôles/plugins par éditeur (FQCN).ansible.windows, microsoft.ad
FactsInfos collectées automatiquement sur la cible au début du play.ansible_distribution

Architecture : comment ça s’exécute

Le nœud de contrôle pousse les modules vers les cibles via SSH ou WinRM
Le nœud de contrôle pousse les modules vers les cibles via SSH ou WinRM

À chaque tâche, Ansible copie un petit module sur la cible, l'exécute, récupère un résultat JSON puis nettoie. Le statut retourné est l'un de :

StatutSignificationCouleur console
okL'état était déjà conforme, rien n'a été modifié.vert
changedAnsible a modifié la cible pour la rendre conforme.jaune
failedLa tâche a échoué : l'hôte sort du play.rouge
skippedTâche ignorée (condition when fausse, mode check…).cyan
unreachableConnexion impossible (SSH, DNS, identifiants).rouge

L’inventaire

Il décrit qui est géré. Format YAML (ou INI), statique ou dynamique (plugins Azure, vSphere, etc. qui interrogent l'API à chaque exécution).

inventory/hosts.yml

all:
  children:
    vda_linux:
      hosts:
        vda-ubuntu01:
        vda-ubuntu02:
      vars:
        ansible_user: ansible
    storefront:
      hosts:
        srv-sf01:
          ansible_host: 10.0.10.21
      vars:
        ansible_connection: winrm
        ansible_winrm_transport: kerberos
        ansible_port: 5986

💡 Astuce

Sors les variables de l'inventaire : un dossier group_vars/vda_linux.yml et host_vars/srv-sf01.yml à côté de l'inventaire sont chargés automatiquement. Vérifie le résultat avec ansible-inventory -i inventory --graph --vars.

Anatomie d’un playbook

Playbook → plays → (rôles) → tasks → modules ; les handlers sont notifiés
Playbook → plays → (rôles) → tasks → modules ; les handlers sont notifiés

playbooks/vda_linux.yml

---
- name: Configurer les VDA Linux
  hosts: vda_linux
  become: true                      # sudo
  vars:
    ad_domain: corp.local
  tasks:
    - name: Installer sssd, realmd et Kerberos
      ansible.builtin.apt:
        name: [sssd, realmd, krb5-user]
        state: present              # état voulu, pas une action
        update_cache: true

    - name: Déployer sssd.conf depuis un template Jinja2
      ansible.builtin.template:
        src: sssd.conf.j2
        dest: /etc/sssd/sssd.conf
        owner: root
        mode: "0600"
      notify: Redémarrer sssd       # seulement si le fichier change

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

ℹ️ À savoir · Le concept clé

Idempotence : state: present décrit un résultat, pas une commande. 1re exécution → changed, 2e exécution → ok partout, changed=0.

C'est le test de qualité n°1 d'un playbook : le rejouer deux fois de suite et vérifier qu'il n'y a plus de changement.

Variables, templates et précédence

Les variables s'écrivent {{ ma_variable }} (moteur Jinja2), dans les tâches comme dans les templates .j2. Quand la même variable est définie à plusieurs endroits, la plus « proche » de l'exécution gagne :

PrioritéSource (version simplifiée)Usage recommandé
1 — la plus faibleRôle : defaults/main.ymlValeurs par défaut, faites pour être surchargées
2Inventaire : group_vars/all, puis group_vars/<groupe>Paramètres d'environnement / de groupe
3Inventaire : host_vars/<hôte>Exceptions propres à une machine
4Facts collectésLecture seule : OS, IP, mémoire…
5Play : vars:, vars_files:Constantes du playbook
6Rôle : vars/main.ymlConstantes internes du rôle (rarement surchargées)
7set_fact / registerValeurs calculées pendant l'exécution
8 — la plus forteLigne de commande : -e var=valeurForçage ponctuel ; gagne toujours

⚠️ Piège

Une valeur YAML qui commence par {{ doit être entre guillemets : dest: "{{ base_dir }}/app.conf". Sans guillemets, YAML l'interprète comme un dictionnaire et le playbook ne se charge pas.

Rôles et collections

Un rôle est une arborescence normalisée que l'on réutilise d'un projet à l'autre ; on le crée avec ansible-galaxy role init linux_vda.

structure d'un rôle

roles/linux_vda/
├── defaults/main.yml     # variables par défaut (priorité basse)
├── vars/main.yml         # constantes du rôle
├── tasks/main.yml        # point d'entrée des tâches
├── handlers/main.yml     # handlers
├── templates/sssd.conf.j2
├── files/                # fichiers copiés tels quels
└── meta/main.yml         # dépendances, plateformes

Les collections apportent les modules hors cœur. On les déclare dans collections/requirements.yml puis ansible-galaxy collection install -r collections/requirements.yml. Toujours appeler un module par son FQCN (ansible.windows.win_feature plutôt que win_feature).

Cibles Windows : les différences

SujetLinuxWindows
TransportSSH (port 22)WinRM HTTPS 5986 (ou HTTP 5985), ou OpenSSH
Prérequis ciblePython 3PowerShell 5.1+ / .NET
AuthentificationClé SSHKerberos (recommandé en domaine), NTLM, CredSSP, certificat
Élévationbecome_method: sudobecome_method: runas
Modulesansible.builtin.*ansible.windows.*, community.windows.*, microsoft.ad.*

Commandes essentielles

CommandeÀ quoi ça sert
ansible all -m ansible.builtin.pingTester la connexion + Python sur les Linux
ansible storefront -m ansible.windows.win_pingIdem côté Windows
ansible-inventory -i inventory --graphVisualiser groupes et hôtes
ansible-playbook site.yml --syntax-checkValider la syntaxe sans rien exécuter
ansible-playbook site.yml --check --diffSimulation : montre ce qui changerait (dry run)
ansible-playbook site.yml --limit vda-ubuntu01Restreindre à un hôte / groupe
ansible-playbook site.yml --tags sssdN'exécuter que les tâches étiquetées
ansible-playbook site.yml -e env=prdPasser une variable (priorité maximale)
ansible-vault encrypt_string 'S3cret' --name pwdChiffrer un secret à coller dans un fichier de vars
ansible-doc ansible.builtin.templateDocumentation hors-ligne d'un module
ansible-lintVérifier les bonnes pratiques

Pièges classiques

SymptômeCauseParade
La tâche est « changed » à chaque exécutioncommand / shell n'ont aucune notion d'étatModule dédié ; sinon creates:, changed_when:
Mot de passe visible dans Git ou les logsSecret en clair dans les varsansible-vault + no_log: true sur la tâche
« conflicting action statements » / erreur YAMLIndentation ou {{ }} non quotéGuillemets, éditeur YAML, ansible-lint
Le handler ne s'est pas exécutéUne tâche a échoué avant la fin du play--force-handlers ou meta: flush_handlers
--check « rate » des tâchesLes modules command/shell sont ignorés en checkcheck_mode: false si la commande est sans effet
Module introuvableCollection non installée ou nom court ambiguFQCN + requirements.yml

🔷 En contexte Citrix

Gold image Linux VDA : paquets, jonction AD via sssd/realmd, variables de ctxsetup.sh, puis MCS clone l'image : Ansible rend la préparation reproductible.

Gold image Windows : rôles et fonctionnalités, clés de registre, optimisations, installation silencieuse du VDA.

Infra : configuration homogène des StoreFront, Cloud Connectors (prérequis OS), sauvegardes de config.

Combo classique : Terraform crée les VM / le catalogue, Ansible configure l'intérieur (voir fiche TF-01).

À retenir

  • Agentless, push, SSH/WinRM : seul le nœud de contrôle a Ansible.
  • On décrit un état ; un bon playbook rejoué donne changed=0.
  • Inventaire = qui · Playbook = quoi · Rôle = comment le réutiliser.
  • --check --diff et --limit avant toute exécution en production.
  • Secrets dans ansible-vault, modules appelés par leur FQCN.

Auto-évaluation

Q1. Pourquoi dit-on qu'Ansible est « agentless » ?

→ Il n'y a aucun service permanent sur les cibles : le module est copié et exécuté via SSH/WinRM, puis supprimé.

Q2. Quelle est la différence entre une task et un handler ?

→ Une task s'exécute toujours (sauf condition) ; un handler ne s'exécute qu'une fois, en fin de play, et seulement s'il a été notifié par une task « changed ».

Q3. Une variable port vaut 80 dans defaults/ du rôle, 8080 dans group_vars/web, et on lance -e port=9000. Quelle valeur ?

→ 9000 : les extra vars (-e) ont toujours la priorité la plus haute.

Q4. Comment vérifier ce qu'un playbook va modifier sans rien changer ?

→ ansible-playbook site.yml --check --diff (en gardant en tête que command/shell sont ignorés).

Pour aller plus loin