RousselTMLEARNING

Automatisation

Ansible : aller plus loin (tests, qualité, CI/CD et performance)

Industrialiser Ansible : ansible-lint, yamllint, Molecule, intégration continue, collections, execution environments, mitogen et optimisation des performances.

1. Garantir la qualité du code #

Linters et tests.

yamllint et ansible-lint #

pip install ansible-lint yamllint molecule molecule-plugins[docker]

yamllint .
ansible-lint                              # analyse tout le projet
ansible-lint --profile production site.yml
ansible-lint --fix                        # corrige automatiquement ce qui peut l'être

# .ansible-lint
profile: production
skip_list:
  - yaml[line-length]

ansible-lint signale par exemple les modules sans FQCN (apt au lieu de ansible.builtin.apt), les tâches sans name, l'usage de shell à la place d'un module ou les permissions de fichiers manquantes.

Tester un rôle avec Molecule #

Pipeline de qualité
Chaque étape bloque la suivante en cas d'échec.
cd roles/nginx
molecule init scenario default --driver-name docker

# molecule/default/molecule.yml
driver: { name: docker }
platforms:
  - name: instance
    image: geerlingguy/docker-debian12-ansible:latest
    pre_build_image: true
provisioner: { name: ansible }
verifier: { name: ansible }

molecule test           # create -> converge -> idempotence -> verify -> destroy
molecule converge       # appliquer seulement
molecule login          # se connecter dans le conteneur pour déboguer
# molecule/default/verify.yml
- name: Vérifier
  hosts: all
  tasks:
    - name: nginx répond
      ansible.builtin.uri: { url: http://localhost, status_code: 200 }
    - name: Le service est activé
      ansible.builtin.service_facts:
    - ansible.builtin.assert:
        that: ansible_facts.services['nginx.service'].state == 'running'
À savoir : Molecule exécute deux fois le rôle et échoue si la seconde passe contient des changements : c'est le test d'idempotence.

2. Intégration et livraison continues #

Un pipeline complet.

Exemple GitLab CI #

# .gitlab-ci.yml
stages: [lint, test, deploy-preprod, deploy-prod]

lint:
  stage: lint
  image: python:3.12
  script:
    - pip install ansible ansible-lint yamllint
    - yamllint . && ansible-lint

molecule:
  stage: test
  image: docker:27
  services: [docker:27-dind]
  script:
    - pip install molecule molecule-plugins[docker] ansible
    - cd roles/nginx && molecule test

deploy-preprod:
  stage: deploy-preprod
  script:
    - ansible-galaxy install -r requirements.yml
    - ansible-playbook site.yml -i inventories/preprod --check --diff
    - ansible-playbook site.yml -i inventories/preprod

deploy-prod:
  stage: deploy-prod
  when: manual
  only: [main]
  script:
    - ansible-playbook site.yml -i inventories/prod --vault-password-file <(echo "$VAULT_PASSWORD")

3. Reproductibilité : collections et execution environments #

Figer les dépendances.

Collections et requirements #

ansible-galaxy collection list
ansible-galaxy collection install -r requirements.yml -p ./collections
ansible-galaxy collection build                 # packager sa propre collection
ansible-galaxy collection init mon_ns.ma_collection

Execution Environments #

Un Execution Environment (EE) est une image de conteneur contenant Ansible, ses collections et les dépendances Python/système. Le même EE tourne sur le poste du développeur et dans AWX : fini les « ça marche chez moi ».

pip install ansible-builder ansible-navigator
cat > execution-environment.yml <<'EOF'
version: 3
images:
  base_image:
    name: quay.io/fedora/fedora:40
dependencies:
  ansible_core: { package_pip: ansible-core }
  ansible_runner: { package_pip: ansible-runner }
  galaxy: requirements.yml
  python: requirements.txt
EOF
ansible-builder build -t registry.lab/ee-infra:1.0
ansible-navigator run site.yml -i inventories/lab --eei registry.lab/ee-infra:1.0 --mode stdout

4. Performances #

Accélérer des milliers d'hôtes.

Réglages ansible.cfg #

[defaults]
forks = 50
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400
callbacks_enabled = profile_tasks, timer

[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=120s
retries = 3
ansible-playbook site.yml          # avec profile_tasks, affiche les tâches les plus lentes
# TASKS RECAP *****************************
# Installer les paquets ................. 41.20s
# Déployer le template .................. 3.12s

Stratégies d'exécution #

- hosts: all
  strategy: free         # chaque hôte avance à son rythme (sans attendre les plus lents)
  gather_facts: false
  tasks:
    - ansible.builtin.package: { name: htop, state: present }
      async: 300         # lancer en tâche de fond
      poll: 0
Erreur Courante : strategy: free n'est pas adaptée aux déploiements ordonnés : une tâche peut s'exécuter sur certains hôtes avant d'être terminée ailleurs.
Bonne Pratique : Mesurez avant d'optimiser : activez profile_tasks et attaquez-vous aux 3 tâches les plus longues (souvent la collecte de facts et les installations de paquets).

Articles liés

Ansible : l'inventaire (statique, dynamique, groupes et variables)

Comprendre et maîtriser l'inventaire Ansible : fichiers INI et YAML, groupes, variables d'hôte et de groupe, …

Ansible : les commandes Ad-Hoc

Exécuter des actions immédiates sur un parc de serveurs avec ansible : modules ping, command, shell, copy, ap…

Ansible : structurer son code avec les rôles

Créer, organiser et réutiliser des rôles Ansible : arborescence, defaults, tasks, handlers, templates, dépend…

Pour aller plus loin

Soutenir

♥ SOUTENIR

Soutenez RousselTM Learning

Les formations, articles, TP et attestations restent gratuits et sans publicité intrusive. Une contribution libre, du montant de votre choix, finance l’hébergement, les environnements de TP et l’écriture de nouveaux contenus.

Contribuer avec PayPal Montant libre · carte bancaire ou compte PayPalEn savoir plus
QR code PayPal
Ou scannez ce QR code avec votre téléphone

Merci, chaque contribution compte !