Deux corrections de propriété, l'une dans le plan, l'autre dans les intrants. 1. Intégrations universelles (D-33/D-34, P26) Le plan portait 57 lignes d'intégration écrites à la main, dont 28 disaient oui à quelque chose de vrai pour tous les hôtes. Elles n'existaient que pour être oubliées — et elles l'avaient été : dans Chezlepro, backup-01 et infra-pki-01 n'étaient ni supervisés, ni journalisés, ni certifiés. Le rôle déclare désormais sa politique une fois, dans meta/integration.yml ; le plan ne garde que les vrais choix et refuse la recopie. Les exemptions se dérivent du service rendu (sauf_role), jamais d'un nom d'hôte : l'AC ne s'enrôle pas auprès d'elle-même, et l'exemption suit step-ca si on le déplace. Une seule fonction de résolution — integrations_de() — lue par l'inventaire, la voûte et le panneau. Sans le passage par la voûte, les secrets des intégrations universelles auraient cessé d'être exigés et P18 serait passé au vert sur une voûte incomplète. Vérifié : diff vide sur Technolibre (la politique reproduit exactement les 41 lignes retirées) ; sur Chezlepro, exactement les groupes manquants, et pas client_pki sur infra-pki-01. 2. Vue Intégrations : la matrice La fiche montrait les intégrations d'UN serveur ; le trou de Chezlepro n'a pas été trouvé par le panneau mais par le devis de pare-feu. Matrice serveurs x intégrations : colonnes de politique en lecture seule, facultatives cochables sur place, ligne de couverture n/N qui rend le motif visible sans le juger. 3. Propriété des intrants (D-35/D-36, P27) Le cluster Proxmox appartient à l'hébergeur, comme sa fabric et sa frontière. Recopié chez chaque tenant, son inventaire avait déjà divergé : deux listes de stockages contradictoires pour le même matériel. API/nœuds/stockages/ponts vont dans proxmox-hebergeur.yml, à côté d'underlay.yml, dont le chemin se dérive — l'hébergeur reste non déclaré (D-17). Restent au tenant son golden template et ses défauts de placement. Le panneau nomme désormais le propriétaire de chaque section : éditer une section « hébergeur » vaut pour tous ses tenants, et l'écran ne le disait pas. 26 preuves OK, 0 échec. --syntax-check des deux playbooks Proxmox. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.5 KiB
Le plan et la génération d'inventaire (méta-classe)
Set-OPS ne s'édite plus comme un inventaire à la main : on décrit un plan, et l'inventaire Ansible en est généré. Le dépôt est la définition ; chaque VM en est une instance. Ce document décrit le modèle, les registres, les commandes et le flux de travail.
Règle d'or :
instance/inventories/production/hosts.ymlest GÉNÉRÉ. Ne jamais l'éditer à la main. On édite le plan puis on régénère (make instancier-appliquer).
1. Le modèle : deux ancres, cinq liens
L'écosystème = des serveurs (VM) et des applications, reliés à leurs bases, leurs domaines et leurs dépendances :
serveur (VM) ──fournit──▶ capacités (= groupes/rôles Ansible)
application ──tourne_sur──▶ serveur (une VM peut porter N applications)
application ──requiert──▶ application(s) (DNS, PKI, BD…)
application ──utilise──▶ base(s) (via le DSN)
application ──expose──▶ domaine(s) public(s) (le FQDN, derrière l'edge)
base ──hébergée_sur──▶ serveur de BD
L'application est l'entité pivot : tout ce qui décrit « ce qui tourne et à quoi c'est connecté » pend d'elle. Le groupe Ansible n'est plus une cible de liaison — seulement une capacité qu'une VM fournit (le rôle appliqué).
2. Les registres (source unique de vérité)
Tous sous docs/, machine-lisibles, validés, consommés par le GUI, le CLI et Ansible.
| Registre | Décrit | Champs clés |
|---|---|---|
nomenclature.yml |
nommage & adressage | fonctions (catégorie/service), categories (VLAN/sous-réseau/passerelle), supernet |
serveurs.yml |
les VM du plan | fonction, etat (actif/planifie), placement Proxmox (noeud/stockage/disque/memoire/coeurs), integrations (les client_* facultatives seulement — les universelles viennent du rôle, voir integrations-vm.md) |
applications.yml |
les applications | groupe (capacité/rôle), hote (VM), port, requiert, expose, (+ bases via consommateur) |
bases-donnees.yml |
serveurs de BD + bases | serveurs_bd ; bases_donnees : serveur/base/proprietaire/secret(Vault), consommateur + portee (application/groupe/hote), usage |
domaines.yml |
zones DNS publiques | domaines_publics : autorite, edge, secondaires, dnssec, mail |
dependances-groupes.yml |
prérequis entre groupes | requiert_groupes_actifs |
Dérivations clés
- Nommage/adressage : tout part de la
fonctionde l'hôte (web-frontal-03).VMID = 9·catégorie·service·NN,VLAN = catégorie.vlan,IP = 10.0.<vlan>.(service×10 + NN). Voirdocs/nomenclature-vm.md. - DSN (lien application↔base) :
<type>://<proprietaire>:<secret>@<hôte>:<port>/<base>. Une application reçoit les bases où(portee=application ET consommateur=elle)OU(portee=groupe ET consommateur=son groupe)OU(portee=hote ET consommateur=son hôte). - Exposition DNS :
application.expose: [fqdn]+ l'edgedu domaine parent →serveur_nginxgénère le vhost (application → hôte → IP:port).
3. La génération (méta-classe)
make instancier produit hosts.yml depuis le plan :
- host vars :
ansible_host/ansible_user+proxmox_*(IP/VMID/VLAN/passerelle dérivés de la nomenclature ; placement/taille depuisserveurs.yml). - groupes d'une VM = socle (
serveur_debian+serveur_durci)- services (les
groupedes applications de l'hôte) - intégrations universelles (politique du rôle :
roles/client_*/meta/integration.yml) - intégrations facultatives (
serveurs.yml: integrations) - état (
hotes_actifs/hotes_planifies).
- services (les
La comparaison est sémantique (via ansible-inventory --list, formatage
ignoré). « Diff vide » = le plan reproduit exactement l'inventaire courant ;
c'est le feu vert pour appliquer.
4. Le flux de travail
éditer le PLAN ──▶ make instancier (revoir le diff) ──▶ make instancier-appliquer ──▶ déployer
(GUI ou CLI) (que va-t-il changer ?) (régénère hosts.yml) (make deployer)
Via le GUI — make inventaire-ui
Cinq vues :
| Vue | Rôle |
|---|---|
| Inventaire | lecture seule (inventaire généré) — vue d'ensemble des hôtes |
| Serveurs | éditer les VM du plan : fonction/état/placement/intégrations (VMID·IP·VLAN dérivés en direct) ; bouton « Appliquer le plan » |
| Chaîne | vue holistique par hôte : groupes → rôles, et par application ses expose / requiert / bases (DSN) |
| Applications | éditer les applications : groupe/hôte/port/requiert/expose |
| Bases | éditer serveurs de BD et bases (portée + consommateur), DSN affiché |
Édition → Sauvegarder (écrit le registre) → Appliquer le plan (régénère
hosts.yml). L'écriture directe de l'inventaire est refusée (409).
Via le CLI / make
Chaque registre a son script miroir et ses cibles make :
| Domaine | Lister | Vérifier | Bootstrap (depuis l'inventaire) |
|---|---|---|---|
| Serveurs | make serveurs |
make serveurs-verifier |
make serveurs-bootstrap |
| Applications | make applications |
make applications-verifier |
make applications-bootstrap |
| Bases | make bases |
make bases-verifier |
— |
| Domaines | make domaines |
make domaines-verifier |
— |
Génération :
make instancier # génère hosts.genere.yml (gitignoré) + diff sémantique
make instancier-appliquer # régénère hosts.yml (refuse si diff non vide ; FORCE=1 pour forcer)
Validation globale : make inventaire-verifier (ansible-inventory + tous les
registres + node --check du JS du GUI).
5. Garde-fous
- Validateurs : chaque registre est validé (références connues, énumérations,
unicité). Un
exposesans domaine parent, unrequiertfantôme, uneporteeinconnue, unefonctionabsente → rejet. - Diff vide :
instancier-appliquerrefuse d'écraser l'inventaire si le plan ne le reproduit pas (saufFORCE=1pour un changement intentionnel). node --check: le JS embarqué du GUI est vérifié (scripts/verifier_gui.py, intégré àmake inventaire-verifier) — une erreur de syntaxe JS casse toute la page.- git :
hosts.ymlest versionné ;git diff/git checkoutest le filet. - Secrets : jamais en clair ;
secret:nomme une variable Ansible Vault.
6. Réutilisation de la règle (Ansible)
La règle de résolution vit une seule fois, en Python (scripts/inventory_rules.py),
et est exposée à Ansible par un filter plugin (filter_plugins/registres.py) :
bases_de_application, applications_de_hote, expositions_des_applications,
chaine_connexion. Les playbooks par application (serveur_web_dorsal/_frontaux)
itèrent ainsi sur les applications de l'hôte et résolvent leurs DSN.
7. Amorçage / reconstruction
Pour (re)construire le plan depuis un inventaire existant :
make serveurs-bootstrap # VM -> instance/plan/serveurs.yml (fonction/état/placement/integrations)
make applications-bootstrap # services serveurs_* (hors socle) -> instance/plan/applications.yml
make instancier # vérifier le diff vide
C'est ainsi que le plan a été initialisé sans perte, avec diff vide vérifié.
8. Moteur et instance : deux dépôts
Le moteur (ce dépôt, Set-OPS) est générique et partageable ; il ne contient
aucune donnée d'instance. Une instance (le plan + l'inventaire d'un loup) vit
dans son propre dépôt (ex. OPS-monatelier).
Le moteur localise l'instance via SETOPS_INSTANCE (défaut : instance). Deux
modèles :
- Modèle A — dépôts frères (en cours) : moteur et instance côte à côte ; un
symlink
instance -> ../OPS-monatelier(gitignoré) fait que le défaut résout l'instance sans configuration. Idéal quand on développe le moteur et l'instance. - Modèle B — moteur en sous-module (futur, pour la meute) : l'instance épingle
une version du moteur ;
SETOPS_INSTANCEpointe la racine de l'instance.
Pour brancher une instance (modèle A) :
cd Set-OPS
ln -s ../OPS-monatelier instance # ou : export SETOPS_INSTANCE=/chemin/instance
make inventaire-verifier # lit l'instance via le symlink
Le moteur écrit hosts.yml (généré) dans le dépôt d'instance, jamais dans le sien.