Set-OPS-Public/docs/plan-et-generation.md
Daniel Allaire b0e56cbfc0 intégrations : le rôle déclare sa politique ; le cluster passe à l'hébergeur
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>
2026-08-03 14:09:22 -04:00

8.5 KiB
Raw Blame History

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.yml est 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 fonction de l'hôte (web-frontal-03). VMID = 9·catégorie·service·NN, VLAN = catégorie.vlan, IP = 10.0.<vlan>.(service×10 + NN). Voir docs/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'edge du domaine parent → serveur_nginx gé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 depuis serveurs.yml).
  • groupes d'une VM = socle (serveur_debian + serveur_durci)
    • services (les groupe des 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).

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 expose sans domaine parent, un requiert fantôme, une portee inconnue, une fonction absente → rejet.
  • Diff vide : instancier-appliquer refuse d'écraser l'inventaire si le plan ne le reproduit pas (sauf FORCE=1 pour 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.yml est versionné ; git diff / git checkout est 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_INSTANCE pointe 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.