Aller au contenu

Ansible : inventaire dynamique et playbooks types

Day 2 · ExploiterNiveau 3 · MaîtriserProcédureRédigé · à valider en lab

Objectif : construire automatiquement l'inventaire Ansible à partir du cluster Proxmox VE (VM, pools, tags), puis lancer des playbooks types : snapshot avant mise à jour, démarrage et arrêt de VM, mise à jour des systèmes invités.

Ce qu'il faut savoir

Élément Détail
Collection community.proxmox (communautaire, non éditée par Proxmox). Les anciens modules community.general.proxmox* sont dépréciés et redirigés vers elle.
Dépendances (sur le poste Ansible, pas sur les nœuds) ansible-core 2.17 ou plus, Python proxmoxer et requests
Inventaire dynamique Plugin community.proxmox.proxmox, fichier nommé *.proxmox.yml
Modules utiles proxmox_kvm (VM), proxmox (conteneurs), proxmox_snap, proxmox_vm_info, proxmox_disk, proxmox_nic, proxmox_backup, proxmox_pool_member
Authentification api_user + api_token_id (nom court du jeton) + api_token_secret

Ansible pilote l'API Proxmox pour les VM, et se connecte en SSH aux systèmes invités pour les configurer. La gestion des hyperviseurs eux-mêmes (paquets, réseau, Corosync) par Ansible reste du ressort du MSP.

Avant de toucher la prod

  • Compte svc-ansible@pve, jeton svc-ansible@pve!ci en privsep 1, rôle PVEVMAdmin sur /pool/ansible et PVEDatastoreUser sur le stockage : voir Jetons API.
  • Pour l'inventaire seul, un jeton PVEAuditor suffit.
  • Secret dans Ansible Vault ou variable d'environnement PROXMOX_TOKEN_SECRET, jamais en clair dans Git.
  • Playbooks testés sur le pool de test avec --check puis sur une VM de recette.
  • Sauvegarde PBS récente des VM ciblées (vzdump ou job planifié).

Étapes

1. Préparer le poste de contrôle

python3 -m venv ~/venv-ansible && . ~/venv-ansible/bin/activate
pip install ansible-core proxmoxer requests
ansible-galaxy collection install community.proxmox
ansible-galaxy collection list | grep proxmox

2. Déclarer l'inventaire dynamique

inventory/pve.proxmox.yml :

plugin: community.proxmox.proxmox
url: https://pve01.corp.local:8006
user: svc-ansible@pve
token_id: ci
# token_secret lu dans la variable d'environnement PROXMOX_TOKEN_SECRET
validate_certs: true
want_facts: true
keyed_groups:
  - key: proxmox_tags_parsed
    separator: ""
    prefix: tag_
compose:
  ansible_host: proxmox_ipconfig0.ip | default(proxmox_net0.ip) | ansible.utils.ipaddr('address')

Le filtre ipaddr nécessite la collection ansible.utils et la bibliothèque Python netaddr.

export PROXMOX_TOKEN_SECRET='xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
ansible-inventory -i inventory/pve.proxmox.yml --graph

Le plugin crée des groupes préfixés proxmox_ (par nœud, par type, par état, par pool) et les groupes de tags définis dans keyed_groups. Vérifiez leurs noms exacts avec --graph avant de les utiliser dans hosts:.

3. Playbook type : snapshot puis mise à jour des invités

group_vars/all/vault.yml (chiffré avec ansible-vault encrypt) :

vault_pve_token_secret: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

maj-invites.yml :

- name: Snapshot puis mise à jour des VM taguées "web"
  hosts: tag_web
  serial: 1
  gather_facts: false
  tasks:
    - name: Snapshot avant mise à jour
      community.proxmox.proxmox_snap:
        api_host: pve01.corp.local
        api_user: svc-ansible@pve
        api_token_id: ci
        api_token_secret: "{{ vault_pve_token_secret }}"
        vmid: "{{ proxmox_vmid }}"
        snapname: avant-maj
        state: present
      delegate_to: localhost

    - name: Mise à jour des paquets
      ansible.builtin.apt:
        update_cache: true
        upgrade: dist
      become: true

4. Playbook type : démarrer une VM et attendre l'agent

- name: Démarrer la VM 101
  hosts: localhost
  gather_facts: false
  tasks:
    - community.proxmox.proxmox_kvm:
        api_host: pve01.corp.local
        api_user: svc-ansible@pve
        api_token_id: ci
        api_token_secret: "{{ vault_pve_token_secret }}"
        node: pve01
        vmid: 101
        state: started

Lancement : ansible-playbook -i inventory/pve.proxmox.yml maj-invites.yml --check --diff, puis sans --check.

Vérifications

  • ansible-inventory --graph liste les VM attendues, et seulement celles-là si le jeton est limité au pool.
  • ansible -i inventory/pve.proxmox.yml tag_web -m ansible.builtin.ping : pong pour chaque VM.
  • qm listsnapshot 101 sur le nœud : le snapshot avant-maj est présent.
  • Le playbook se termine avec failed=0 dans le récapitulatif.

Rollback

Revenir au snapshot : qm rollback 101 avant-maj (ou module proxmox_snap avec state: rollback), puis supprimer le snapshot une fois l'application validée. Un snapshot conservé longtemps consomme de l'espace et ralentit certains stockages : le supprimer sous 48 heures.

Pièges vus en support

  • api_token_id renseigné avec l'identifiant complet svc-ansible@pve!ci au lieu du nom court ci : erreur d'authentification.
  • Inventaire vide : jeton en privsep 1 sans ACL propre, ou VM sans IP déclarée (pas de ipconfig0, agent absent).
  • validate_certs: false laissé en production après un test : attaque de l'homme du milieu possible sur le secret.
  • Playbook lancé sans serial sur toutes les VM d'une application : tous les nœuds web redémarrent en même temps.
  • Snapshot sur une VM avec disque sur un stockage qui ne les supporte pas (LVM épais sur SAN) : la tâche échoue.

Quand ouvrir un ticket iTop

Mise à jour invitée qui rend une VM injoignable et rollback impossible : P2, restauration selon RB-12. Automatisation des hyperviseurs eux-mêmes, conception de rôles Ansible : demande P4 au MSP.

Ouvrir un ticket iTop

Pour aller plus loin