Automation
AWX en production légère sans usine à gaz
Un cas d’usage concret pour mettre AWX en service sur un petit parc Linux avec inventaires Git, credentials séparés, jobs contrôlés, sauvegarde et vérifications après exécution.
AWX devient intéressant quand il remplace des lancements Ansible faits depuis un poste d’administration, sans journal central, sans contrôle clair des credentials et sans visibilité sur les exécutions. Le cas d’usage retenu ici est volontairement simple. Une équipe exploite une quarantaine de serveurs Linux répartis entre préproduction et production. Les playbooks existent déjà dans Git, mais chacun les lance à sa manière. L’objectif n’est pas de construire une plateforme d’automatisation complète. Il est de centraliser quelques opérations répétées, avec un niveau de contrôle suffisant pour ne pas transformer AWX en console dangereuse.
Le bon périmètre initial tient en trois familles de jobs. Les jobs de lecture vérifient l’état des serveurs. Les jobs de maintenance appliquent des actions bornées, comme redémarrer un service autorisé ou installer un paquet validé. Les jobs de changement appliquent un rôle Ansible déjà testé, sur un inventaire limité. Tout ce qui supprime des données, modifie le réseau, redémarre massivement des machines ou change des secrets reste hors périmètre au démarrage.
Construire le dépôt Ansible avant l’interface
La première erreur consiste à commencer par créer des templates dans AWX sans nettoyer le dépôt Ansible. AWX doit exécuter du code versionné, pas devenir l’endroit où l’on improvise les opérations. Une structure simple suffit, tant qu’elle sépare les playbooks, les rôles et les inventaires.
ansible-operations/
playbooks/
check-linux-baseline.yml
check-disk-usage.yml
restart-approved-service.yml
patch-selected-package.yml
roles/
linux_baseline/
ssh_hardening/
package_management/
inventories/
preprod/hosts.yml
production/hosts.yml
collections/requirements.yml
README.md Dans AWX, le projet pointe vers ce dépôt. La production doit suivre une branche stable. Les tests peuvent utiliser une autre branche ou un autre projet AWX. Cette séparation évite qu’un job de production exécute par erreur un playbook en cours de modification.
Le README du dépôt doit documenter les playbooks réellement exposés dans AWX. Il ne s’agit pas d’écrire une documentation longue, mais d’indiquer le but du job, les groupes autorisés, les variables attendues et les effets possibles. Sans cela, les templates AWX deviennent des boutons dont le comportement dépend de la mémoire de l’équipe.
Créer des inventaires qui empêchent les erreurs évidentes
Un inventaire unique appelé linux est pratique au début, puis dangereux. Il vaut mieux séparer les environnements et les rôles. Un job de maintenance standard ne doit pas pouvoir viser un bastion ou une base de données par accident. Le nom des groupes doit rendre le périmètre évident.
all:
children:
production_web:
hosts:
web01.example.local:
web02.example.local:
production_tools:
hosts:
tools01.example.local:
restricted:
hosts:
bastion01.example.local: Dans AWX, les templates doivent pointer vers l’inventaire adapté. Un template destiné à la préproduction ne doit pas accepter un inventaire de production au lancement. Un template qui redémarre un service doit viser un groupe précis, pas tous les hôtes.
Séparer les credentials par niveau de risque
Un AWX léger devient fragile si tous les jobs utilisent le même compte SSH avec sudo complet. Il faut au minimum trois niveaux. Un compte de lecture pour les contrôles. Un compte de maintenance pour les opérations courantes. Un compte plus privilégié pour quelques changements validés.
Credential read-only
Jobs de contrôle
Pas de sudo
Credential maintenance
Paquets validés
Redémarrage de services autorisés
Sudo limité
Credential restricted-admin
Rôles plus sensibles
Inventaires limités
Usage surveillé La restriction doit exister aussi côté Linux. AWX stocke le credential, mais le vrai garde-fou reste la capacité réelle du compte distant. Donner NOPASSWD: ALL au compte d’automatisation revient à déplacer le risque dans une interface plus jolie.
# Exemple de principe à adapter
%ansible-maintenance ALL=(root) NOPASSWD: /bin/systemctl restart nginx
%ansible-maintenance ALL=(root) NOPASSWD: /usr/bin/apt-get update
%ansible-maintenance ALL=(root) NOPASSWD: /usr/bin/apt-get install *
# À éviter pour un démarrage léger
%ansible-maintenance ALL=(ALL) NOPASSWD: ALL Transformer les jobs en actions bornées
Un template AWX ne doit pas être un lanceur générique. Plus il accepte de variables libres, plus il ressemble à une console distante. Pour un redémarrage de service, il vaut mieux fournir une liste de services autorisés que laisser un champ texte ouvert.
---
- name: Restart an approved service
hosts: "{{ target_group }}"
become: true
vars:
allowed_services:
- nginx
- telegraf
- chronyd
tasks:
- name: Reject unauthorized service
ansible.builtin.fail:
msg: "Service not allowed by this job"
when: service_name not in allowed_services
- name: Restart approved service
ansible.builtin.service:
name: "{{ service_name }}"
state: restarted
- name: Check service after restart
ansible.builtin.service_facts:
- name: Show service state
ansible.builtin.debug:
msg: "{{ service_name }} state: {{ ansible_facts.services[service_name + '.service'].state | default('unknown') }}" Ce type de job est plus utile qu’un simple playbook de redémarrage. Il refuse les services non prévus, exécute l’action, puis affiche un contrôle. Le rapport AWX devient exploitable au lieu de seulement dire que le playbook est terminé.
Ajouter une vérification après chaque changement
Un job qui modifie quelque chose doit prouver le résultat. Installer un paquet sans vérifier la version, appliquer une configuration sans relire le service ou redémarrer sans contrôler l’état laisse une zone grise. AWX doit produire une trace utilisable par l’exploitation.
---
- name: Install and verify a selected package
hosts: "{{ target_group }}"
become: true
tasks:
- name: Install package
ansible.builtin.package:
name: "{{ package_name }}"
state: present
- name: Collect package facts
ansible.builtin.package_facts:
manager: auto
- name: Display installed version
ansible.builtin.debug:
msg: "{{ package_name }} version: {{ ansible_facts.packages[package_name][0].version }}"
when: package_name in ansible_facts.packages Dans AWX, ces sorties deviennent importantes. Elles permettent de relire un changement depuis l’interface, de voir quels hôtes ont été touchés, et de savoir si la vérification post-action a réellement été exécutée.
Sauvegarder ce qui n’est pas dans Git
Les playbooks sont dans Git, mais AWX contient aussi des objets qui ne se reconstruisent pas seuls : projets, inventaires créés dans l’interface, credentials, templates, schedules, historiques et paramètres. Une panne de base sans sauvegarde oblige à reconstruire toute l’organisation AWX manuellement.
Une production légère doit donc avoir un test de restauration minimal. L’objectif n’est pas une procédure complexe. Il faut prouver qu’une instance AWX peut être restaurée, qu’un projet Git se synchronise, qu’un credential fonctionne et qu’un job de lecture peut être lancé.
Test de restauration AWX
Restaurer l'instance ou la base dans un environnement isolé
Vérifier l'accès à l'interface
Synchroniser le projet Git principal
Lancer check-linux-baseline sur une cible de test
Vérifier credentials, inventaires et templates
Noter le temps de reprise Conclusion
Une production légère AWX réussie ne se mesure pas au nombre de fonctionnalités activées. Elle se mesure à la qualité des actions exposées. Un petit nombre de jobs bornés, versionnés, vérifiés et associés à des credentials adaptés vaut mieux qu’une interface large capable de tout lancer partout.
Le bon point de départ est concret : trois inventaires propres, trois niveaux de credentials, cinq templates utiles, une sauvegarde testée et des rapports AWX qui prouvent le résultat de chaque action. Avec cette base, AWX devient un outil d’exploitation maîtrisé, pas une couche d’automatisation supplémentaire difficile à contrôler.