
Cette page condense en une seule lecture tout ce qu'il faut avoir en tête le jour de l'EX294. Commandes ansible-*, modules essentiels par catégorie, ansible.cfg minimal, syntaxes Vault, FQCN, pièges YAML qui font perdre des points. À lire la veille de l'examen et à garder ouverte pendant les mocks (lab rhce/mock-ex294).
L'EX294 est performance-based : aucun QCM, vous écrivez des playbooks sur un environnement RHEL/AlmaLinux live. Le score se calcule sur des objectifs vérifiés automatiquement. Un playbook qui ne passe pas l'objectif = 0 sur cet objectif. Pas de point partiel.
Tableau "besoin → commande"
Section intitulée « Tableau "besoin → commande" »| Besoin | Commande |
|---|---|
| Tester la connexion Ansible | ansible all -m ansible.builtin.ping |
| Lister inventaire | ansible-inventory --graph |
| Voir variables d'un host | ansible-inventory --host db1.lab |
| Doc d'un module | ansible-doc ansible.builtin.copy |
| Lister tous les modules d'une collection | ansible-doc -l community.general |
| Lancer un playbook | ansible-playbook -i inventory.yml site.yml |
| Mode dry-run | ansible-playbook --check --diff site.yml |
| Limiter à un host | ansible-playbook --limit web1.lab site.yml |
| Filtrer par tags | ansible-playbook --tags config site.yml |
| Vault encrypt fichier | ansible-vault encrypt secret.yml |
| Vault encrypt variable inline | ansible-vault encrypt_string 'value' --name 'key' |
| Vault edit | ansible-vault edit secret.yml |
| Vault rekey | ansible-vault rekey secret.yml |
| Lancer playbook avec vault | ansible-playbook --vault-password-file=.vault_pass site.yml |
| Inspecter config active | ansible-config dump --only-changed |
| Lister tâches sans exécuter | ansible-playbook --list-tasks site.yml |
| Lister hosts ciblés | ansible-playbook --list-hosts site.yml |
| Lint qualité production | ansible-lint --profile production site.yml |
| Installer collection | ansible-galaxy collection install -r requirements.yml |
| Installer rôle Galaxy | ansible-galaxy role install geerlingguy.docker |
ansible.cfg minimal pour l'examen
Section intitulée « ansible.cfg minimal pour l'examen »[defaults]inventory = inventory/hosts.ymlremote_user = ansiblehost_key_checking = Falseroles_path = ./rolescollections_path = ./collectionsforks = 10stdout_callback = yamldeprecation_warnings = False
[privilege_escalation]become = Truebecome_method = sudobecome_user = root
[ssh_connection]pipelining = TrueÀ placer dans le répertoire de travail au début de l'examen, précédence locale > home > /etc.
Modules essentiels par catégorie EX294
Section intitulée « Modules essentiels par catégorie EX294 »Fichiers et templates
Section intitulée « Fichiers et templates »| Module | Usage type |
|---|---|
ansible.builtin.copy | Déposer un fichier (avec content: ou src:) |
ansible.builtin.template | Déposer fichier paramétré Jinja2 (src: file.j2) |
ansible.builtin.file | État d'un fichier/dossier (state: directory|absent|touch) |
ansible.builtin.lineinfile | Une seule ligne dans un fichier (regexp: obligatoire) |
ansible.builtin.blockinfile | Bloc de lignes (marker: configurable) |
ansible.builtin.fetch | Récupérer un fichier de la cible vers le control node |
community.general.archive / ansible.builtin.unarchive | tar.gz, zip |
Paquets et services
Section intitulée « Paquets et services »| Module | Usage |
|---|---|
ansible.builtin.dnf | RHEL/AlmaLinux paquets (name:, state: present|latest|absent) |
ansible.builtin.systemd_service | Activer + démarrer (state: started, enabled: true) |
ansible.builtin.cron | Tâche planifiée |
Utilisateurs et groupes
Section intitulée « Utilisateurs et groupes »| Module | Usage |
|---|---|
ansible.builtin.user | Créer user (name:, uid:, group:, shell:, password:) |
ansible.builtin.group | Créer group (name:, gid:) |
ansible.posix.authorized_key | Déposer clé SSH (user:, key:) |
community.general.sudoers | Règle sudo dédiée |
RHEL spécifique (incontournable EX294)
Section intitulée « RHEL spécifique (incontournable EX294) »| Module | Usage |
|---|---|
ansible.posix.firewalld | permanent: true, immediate: true |
ansible.posix.seboolean | Activer un booléen SELinux (state: true, persistent: true) |
community.general.sefcontext | Contexte SELinux (mapping de contexte de fichier) |
community.general.lvol | Créer un LV |
community.general.filesystem | Formater (xfs, ext4) |
ansible.posix.mount | Monter + fstab |
Diagnostic et contrôle
Section intitulée « Diagnostic et contrôle »| Module | Usage |
|---|---|
ansible.builtin.command / shell | Commandes (changed_when: false pour lecture) |
ansible.builtin.assert | Vérification d'une condition |
ansible.builtin.fail | Échec explicite |
ansible.builtin.debug | Affichage de variables (var: ou msg:) |
ansible.builtin.uri | HTTP request |
ansible.builtin.wait_for | Attendre un port / état |
Syntaxes critiques à connaître
Section intitulée « Syntaxes critiques à connaître »mode: toujours quoté
Section intitulée « mode: toujours quoté »mode: "0644" # ← TOUJOURS quoté (sinon octal interprété en décimal → 420)become: au niveau task ou play
Section intitulée « become: au niveau task ou play »- hosts: db1.lab become: true # ← niveau play : toutes les tâches en sudo tasks: - ansible.builtin.copy: ... become_user: appuser # ← override niveau taskregister: + when:
Section intitulée « register: + when: »- ansible.builtin.command: curl --version register: curl_out changed_when: false # ← lecture seule, pas idempotent
- ansible.builtin.debug: var: curl_out.stdout when: curl_out.rc == 0Boucles loop:
Section intitulée « Boucles loop: »- ansible.builtin.user: name: "{{ item.name }}" uid: "{{ item.uid }}" loop: - { name: alice, uid: 2001 } - { name: bob, uid: 2002 } loop_control: label: "{{ item.name }}" # ← masque le contenu détaillé en sortieConditions when: avec opérateurs
Section intitulée « Conditions when: avec opérateurs »when: - ansible_facts.os_family == "RedHat" - ansible_facts.distribution_major_version | int >= 9 - inventory_hostname in groups['webservers']Vault inline avec encrypt_string
Section intitulée « Vault inline avec encrypt_string »ansible-vault encrypt_string 'SuperSecret' --name 'admin_password'admin_password: !vault | $ANSIBLE_VAULT;1.1;AES256 39373335366336323033666336323535...Multi vault-id par environnement
Section intitulée « Multi vault-id par environnement »ansible-playbook --vault-id dev@.vault_pass_dev --vault-id prod@.vault_pass_prod site.ymlPriorité des variables (de la plus forte à la plus faible)
Section intitulée « Priorité des variables (de la plus forte à la plus faible) »Ordre officiel de la documentation Ansible, de la priorité la plus haute à la plus basse. Ce qui est plus haut dans la liste écrase ce qui est plus bas :
--extra-vars/-e(ligne de commande) : priorité absolue, écrase tout le reste- Paramètres d'
include(vars:d'uninclude_roleouinclude_tasks) - Paramètres de rôle (
roles: [{ role: r, x: val }], ouvars:d'uninclude_role) set_factet variables issues deregister:include_vars- Task vars (
vars:au niveau d'une tâche) - Block vars (
vars:au niveau d'unblock) vars/main.ymld'un rôle (role vars)vars_filesdu play, puisvars_prompt- Play vars (
vars:du play) - Host facts et
set_factmis en cache host_vars/(playbook puis inventaire)group_vars/, du plus spécifique au plus généraldefaults/main.ymld'un rôle : priorité la plus basse
🔍 Le piège de l'examen : le niveau d'une variable bat l'ordre chronologique d'exécution. set_fact l'emporte sur include_vars (juste en dessous) même si l'include_vars s'exécute après dans le playbook. De même, vars_files et le vars/main.yml d'un rôle écrasent les vars: du play. Mesuré sur ansible-core 2.20.1.
Structure d'un rôle conforme
Section intitulée « Structure d'un rôle conforme »roles/myrole/├── defaults/main.yml # variables par défaut (faible précédence)├── vars/main.yml # variables internes (haute précédence)├── tasks/main.yml # tâches principales├── handlers/main.yml # handlers (notifiés par notify:)├── templates/ # *.j2├── files/ # fichiers à copy:├── meta/main.yml # dependencies, supported_platforms└── meta/argument_specs.yml # validation des inputs (Ansible 2.11+)Pièges YAML qui font perdre des points
Section intitulée « Pièges YAML qui font perdre des points »| Erreur | Conséquence |
|---|---|
mode: 0644 (non quoté) | YAML lit octal → décimal 420 → mode 0644 peut devenir 0644 dans certains parseurs ; toujours mode: "0644" |
name: Migration with_* vers loop: (terminé par :) | YAML 1.2 lit comme mapping. Quoter : name: "..." |
dnf: state=present name=httpd (vieux style) | Toujours YAML structuré : dnf: { state: present, name: httpd } ou multi-ligne |
Oublier permanent: true sur firewalld | Règle non persistante après reboot, permanent: true, immediate: true systématique |
Oublier python3-libselinux côté cible | template:/copy: plantent si SELinux=enforcing |
name: Démarrer httpd: finit par : | YAML mapping, quoter |
Confondre import_* (static) et include_* (dynamic) | Tags/conditions ne se propagent pas pareillement, voir Import vs Include |
Stratégie d'examen 4h chrono
Section intitulée « Stratégie d'examen 4h chrono »| Étape | Temps | Action |
|---|---|---|
| Lecture des consignes | 5-10 min | Lire les 12-15 tâches en entier avant d'écrire une ligne |
Setup ansible.cfg + inventaire | 5-10 min | Poser le ansible.cfg minimal + tester ansible all -m ping |
| Tâches faciles | 1h | Faire les 8-9 tâches simples d'abord (validation rapide) |
| Tâches complexes | 1h30 | Rôles, Vault, SELinux, LVM/XFS, les plus longues |
| Vérification | 30 min | Re-lancer chaque playbook, vérifier l'idempotence (changed=0 au 2e run) |
| Buffer | 30 min | Marge pour les pièges de dernière minute |
🔍 Règle d'or : vérifier au fur et à mesure. Ne pas attendre la fin pour relancer tous les playbooks, un bug détecté à la 4e heure coûte 30 min de panique.
Vérification systématique en fin d'examen
Section intitulée « Vérification systématique en fin d'examen »# Pour chaque playbookansible-playbook playbook.yml # 1er runansible-playbook playbook.yml | grep -E 'changed=[1-9]' # 2e run : doit être vide
# Vérifier qu'un service est bien actif après rebootansible <host> -m ansible.builtin.systemd_service -a 'name=httpd' -b# → "ActiveState": "active"# → "UnitFileState": "enabled"
# Vérifier un fichier déposéansible <host> -m ansible.builtin.stat -a 'path=/tmp/file.txt' -b
# Vérifier un useransible <host> -m ansible.builtin.command -a 'id appuser' -bRessources d'urgence pendant l'examen
Section intitulée « Ressources d'urgence pendant l'examen »ansible-doc <module>, la doc complète est embarquée dans l'EE de l'examen.ansible-doc -l | grep <mot>, retrouver le FQCN d'un module par mot-clé.man ansible-playbook, options CLI rapides./usr/share/doc/ansible*/, docs locales sur RHEL.
L'examen vous autorise la documentation locale (ansible-doc, man). Aucun accès internet.
À retenir
Section intitulée « À retenir »- Performance-based : on écrit des playbooks. Pas de QCM.
ansible.cfgprojet en premier, précédence locale > home > /etc.- FQCN systématique :
ansible.builtin.copy, jamaiscopy. mode:toujours quoté ("0644").changed_when: falsesur toute commande de lecture.firewalld:permanent: true, immediate: true.python3-libselinuxcôté cible si SELinux enforcing.- Vérifier l'idempotence : 2e run doit avoir
changed=0. ansible-docest votre meilleur ami pendant l'examen.