séparation des plans réseau + où vont les services de l'hébergeur (D-46 à D-48)
Le port du commutateur vers la frontière était figé sur le seul VLAN de transit. Depuis que les bifrost ont une patte sur le VLAN de sortie tenant, ce port serait resté muet : le devis aurait eu l'air juste et le trafic ne serait jamais arrivé. Il dérive maintenant des rattachements déclarés des hôtes `role: frontiere`. Contexte, côté underlay (dépôt de l'hébergeur) : le VTEP vivait sur le VLAN 10, donc le transport tenant partageait son domaine de diffusion avec l'administration des équipements. Plus grave, un nœud de sortie décapsule le trafic tenant et le remet dans sa table principale — dont la route par défaut sort par vmbr0, l'interface de gestion des nœuds. D'où deux VLAN dédiés, 11 (transport VXLAN) et 41 (trafic décapsulé). Le second n'a volontairement pas de passerelle : le commutateur le transporte sans le router, et le devis n'émet donc pas d'interface Vlan41. Services de l'hébergeur — décision consignée, rien n'est construit : Aucun équipement de l'hébergeur n'est dans un inventaire Ansible, et rien ne sauvegarde leurs configurations. Ni hyperviseurs, ni commutateurs, ni frontière. D-46 : un hébergeur porte trois catégories — son tenant (un client comme les autres), ses opérations (supervision de la fabric, journaux, sauvegarde des configs, DNS d'underlay), et le plan de contrôle (déjà dehors). D-47 : les opérations vivent dans le dépôt de l'hébergeur, et leurs VM se rattachent à un pont VLAN, jamais un VNet. Un service qui observe la fabric ne peut pas dépendre d'elle : l'EVPN tombe, et la supervision tombe avec la raison de la panne. D-48 : les hyperviseurs sont gérables par Ansible ; « hors flotte » ne vaut que pour les commutateurs (aucun agent) et la frontière (API seulement). Question laissée ouverte : l'index 0 réservé au tenant propre de l'hébergeur. Il produit les VNI 1001-1006, que le parc hérité utilise déjà (1001 TechnoLibre historique, 1003 KBR), et P21 déclencherait une fausse collision entre deux dépôts d'hébergeurs. Construction parallèle vérifiée : aucune collision entre les 38 VM héritées et les VNI/VLAN projetés. 30 preuves OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
3b1d9b6660
commit
d645532c88
6 changed files with 258 additions and 10 deletions
69
CHANGELOG.md
69
CHANGELOG.md
|
|
@ -1,5 +1,74 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-08-04 — séparation des plans, et où vont les services de l'hébergeur
|
||||
|
||||
### Deux VLAN pour séparer ce qui était mêlé
|
||||
|
||||
Le VTEP vivait sur le VLAN 10, donc le transport tenant partageait son domaine de
|
||||
diffusion avec l'administration des **équipements** (SVI du commutateur, OPNsense).
|
||||
Plus grave : un nœud de sortie décapsule le trafic tenant et le remet dans sa table
|
||||
principale — dont la route par défaut sort par `vmbr0`, **l'interface de gestion des
|
||||
nœuds**. Le trafic des VM aurait emprunté le lien physique de l'interface web, de SSH
|
||||
et du cluster.
|
||||
|
||||
Ça défaisait ce que l'EVPN devait obtenir. `underlay.yml` déclare donc :
|
||||
|
||||
```
|
||||
vlan 11 underlay-vxlan 10.0.5.0/24 SVI 10.0.5.1 transport VXLAN
|
||||
vlan 41 sortie-tenant 10.0.6.0/24 aucun SVI trafic décapsulé
|
||||
```
|
||||
|
||||
`sortie-tenant` n'a **volontairement pas de passerelle** : le commutateur le transporte
|
||||
sans le router, donc le trafic tenant en clair ne traverse aucun SVI de gestion. Le
|
||||
devis n'émet d'ailleurs pas d'`interface Vlan41` — le modèle a exprimé l'intention sans
|
||||
qu'on ait à la commenter.
|
||||
|
||||
Support prévu : `bond3` une fois doublé — `enp7s0` est libre sur les trois nœuds, et le
|
||||
bond est déjà en `active-backup`, le mode qui convient sans MLAG. Aujourd'hui `bond3`
|
||||
n'a **qu'une carte** : tout le trafic tenant, intra-zone compris, repose sur `enp8s0`.
|
||||
|
||||
### Un défaut que ce changement a créé, et corrigé
|
||||
|
||||
Le port du commutateur vers la frontière était figé sur le **seul** VLAN de transit. Les
|
||||
`bifrost` ayant désormais une patte sur le 41, ce port serait resté muet : le devis
|
||||
aurait eu l'air juste et le trafic ne serait jamais arrivé. Il **dérive maintenant des
|
||||
rattachements déclarés** des hôtes `role: frontiere` → `allowed vlan 40,41`.
|
||||
|
||||
### Vérification de la construction parallèle
|
||||
|
||||
Le cluster actuel ne correspond pas à ce qui est planifié, et c'est voulu : on construit
|
||||
à côté. Encore faut-il qu'il n'y ait pas de collision. Mesuré sur les 38 VM héritées :
|
||||
étiquettes `7, 8, 9, 10, 12, 13, 14, 15, 1001, 1003` — aucune ne croise les VNI projetés
|
||||
(`1111‑1116`, `1171‑1176`) ni les VLAN d'underlay.
|
||||
|
||||
Deux points relevés : le VLAN 10 porte 4 VM héritées (il n'est donc pas purement de la
|
||||
gestion), et `infra-pki-01` est encore branchée **à l'ancienne** — `vmbr3` + étiquette
|
||||
`1174` — pas sur le VNet `t17serv`. À rebrancher à la bascule.
|
||||
|
||||
### Où vont les services de l'hébergeur (D-46 à D-48)
|
||||
|
||||
Constat : **aucun équipement de l'hébergeur n'est dans un inventaire Ansible**, et rien
|
||||
ne sauvegarde leurs configurations. Ni les hyperviseurs, ni les commutateurs, ni la
|
||||
frontière.
|
||||
|
||||
Un hébergeur porte **trois** catégories : son **tenant** (son courriel, sa forge — un
|
||||
client comme les autres), ses **opérations** (supervision de la fabric, journaux,
|
||||
sauvegarde des configs, DNS d'underlay), et le **plan de contrôle** (déjà dehors).
|
||||
|
||||
Les opérations vivent dans **le dépôt de l'hébergeur**, et leurs VM se rattachent à un
|
||||
**pont VLAN, jamais un VNet** : un service qui observe la fabric ne peut pas dépendre
|
||||
d'elle. Et la doctrine « hors flotte » ne vaut que pour les commutateurs et la
|
||||
frontière — les hyperviseurs sont des Debian joignables en SSH.
|
||||
|
||||
**Décision consignée, rien n'est construit.** `docs/hebergeur-exploitation.md`.
|
||||
|
||||
### Question laissée ouverte
|
||||
|
||||
L'index `0` réservé au tenant propre de chaque hébergeur — local par construction, donc
|
||||
jamais à coordonner. Deux obstacles mesurés : il produit les VNI `1001`–`1006`, que le
|
||||
parc hérité utilise déjà (`1001` TechnoLibre historique, `1003` KBR) ; et P21
|
||||
déclencherait une fausse collision entre deux dépôts d'hébergeurs. En attente.
|
||||
|
||||
## 2026-08-03 (suite 17) — le plan de données existe (`make devis-sdn`)
|
||||
|
||||
Ajouter un tenant n'ajoute pas qu'un plan : cela implique **1 zone EVPN + 6 VNets +
|
||||
|
|
|
|||
66
docs/audit/preuve-2026-08-04.md
Normal file
66
docs/audit/preuve-2026-08-04.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# Preuve de conformite — Set-OPS — 2026-08-04
|
||||
|
||||
> Genere par `make prouver` (`scripts/prouver.py`). **Rejouable** : relancer
|
||||
> reproduit ce rapport. Chaque preuve rejoue l'outillage existant du depot ;
|
||||
> aucune validation n'est reimplementee ici. Voir le mode d'emploi :
|
||||
> [`docs/audit/README.md`](README.md), et le registre trace :
|
||||
> [`docs/audit/affirmations.md`](affirmations.md).
|
||||
|
||||
- **Instance** : `instance` — inventaire `instance/inventories/principal/hosts.yml`
|
||||
- **Verdict** : ✅ CONFORME (30 OK · 0 echec · 0 saute)
|
||||
|
||||
## Preuves
|
||||
|
||||
| # | Preuve | Affirmations | Statut | Detail |
|
||||
|---|---|---|---|---|
|
||||
| P01 | Lint (ansible-lint) | AFF-006 | ✅ OK | |
|
||||
| P02 | Tests unitaires (inventory_host) | — | ✅ OK | 4 tests passes. |
|
||||
| P03 | Diff-vide du plan (inventaire genere) | AFF-001, AFF-004, AFF-030, AFF-031, AFF-032 | ✅ OK | DIFF VIDE : le plan reproduit exactement l'inventaire actuel. Bascule possible. |
|
||||
| P04 | Groupes <-> playbooks homonymes | AFF-008 | ✅ OK | |
|
||||
| P05 | Dependances causales de groupes | AFF-009, AFF-084 | ✅ OK | |
|
||||
| P06 | Validateurs de registres (serveurs/apps/bases/domaines) | AFF-003 | ✅ OK | Registre des domaines valide. |
|
||||
| P07 | GUI (node --check) | AFF-033 | ✅ OK | JS du GUI : syntaxe valide (node --check). |
|
||||
| P08 | Orchestration (couches + graphe) | AFF-070 | ✅ OK | Orchestration coherente : 30 groupes classes, aucun cycle, aucune arete en arriere. |
|
||||
| P09 | Flux reseau (schema + matrice) | AFF-071 | ✅ OK | Flux coherents : 29 rôles, 70 flux, schéma + matrice OK. |
|
||||
| P10 | Handlers <-> notify | AFF-034, AFF-035 | ✅ OK | Tout notify pointe vers un handler du meme role (49 roles). |
|
||||
| P11 | Syntaxe des playbooks (--syntax-check) | AFF-083 | ✅ OK | playbook: playbooks/proxmox/cloner_vm_debian.yml |
|
||||
| P12 | Existence des runbooks cites | AFF-010, AFF-011, AFF-012, AFF-083 | ✅ OK | 17/17 runbooks/registres cites presents. |
|
||||
| P13 | Invariants structurels/doctrinaux | AFF-015, AFF-022, AFF-037, AFF-038, AFF-062 | ✅ OK | LICENSE, socle dossier, pas de couches paralleles, SSH clef-only, nftables off : OK. |
|
||||
| P14 | Pas de chemin lab/ code en dur | AFF-097 | ✅ OK | Aucun chemin instance/inventories/lab/group_vars code en dur. |
|
||||
| P15 | Modele public socle valide | AFF-022, AFF-099 | ✅ OK | Modele public socle : domaines/serveurs/applications/bases valides. |
|
||||
| P16 | Inventaire Ansible complet (--list) | AFF-030 | ✅ OK | 14 hotes, 29 groupes (inventaire dechiffre et parse). |
|
||||
| P17 | Tous les modeles valident (registres + underlay) | AFF-022, AFF-099 | ✅ OK | Les 1 modele(s) decouvert(s) valident. |
|
||||
| P18 | Gabarit de voute complet | AFF-026 | ✅ OK | Gabarit de voute complet : 21 secret(s) exige(s), tous presents. Voute reelle : 24 cle(s), aucun manque. |
|
||||
| P19 | Le GUI couvre le schema du plan | AFF-002, AFF-095 | ✅ OK | GUI : les 27 champ(s) des plans reels sont editables (2 plan(s) inspecte(s)), registres toleres : nomenclature. |
|
||||
| P20 | Adressage 100% derive du seed (aucun stocke) | AFF-001, AFF-003 | ✅ OK | 2 nomenclature(s) : adressage 100% derive du seed index. |
|
||||
| P21 | Federation : aucun index en collision | AFF-102 | ✅ OK | Federation coherente : 2 instance(s) federee(s), aucun index en collision. |
|
||||
| P22 | Plan de recette a jour (genere du wiki) | AFF-002 | ✅ OK | Plan de recette à jour (19 sections). |
|
||||
| P23 | Underlay sans collision avec la plage tenant | AFF-103 | ✅ OK | Underlay conforme : 7 reseau(x), aucune collision avec la plage tenant. |
|
||||
| P24 | Frontiere nord/sud : acces d'administration declare | AFF-104 | ✅ OK | CONFORME : frontiere nord/sud, 26 regles, 2 routes, admin=192.168.254.2/32,192.168.255.0/24,192.168.255.2/32. |
|
||||
| P25 | Pare-feu Proxmox : est-ouest intra-tenant derive | AFF-107 | ✅ OK | CONFORME : pare-feu Proxmox, 2 tenant(s), 36 groupe(s), 56 regle(s). |
|
||||
| P26 | Integrations universelles : aucun hote laisse de cote | AFF-108 | ✅ OK | 14 hote(s) x 3 integration(s) universelle(s) : aucune lacune, aucune recopie (1 exemption(s) derivee(s) du service rendu). |
|
||||
| P27 | Propriete des intrants : hebergeur et tenant separes | AFF-109 | ✅ OK | 8 cle(s) de cluster chez l'hebergeur, aucune recopiee dans les group_vars du tenant. |
|
||||
| P28 | Pools Proxmox : un par tenant, sans collision | AFF-110 | ✅ OK | CONFORME : 2 pool(s) Proxmox, 28 VM placee(s), aucun nom ni VMID en collision. |
|
||||
| P29 | Authentification : chaque role declare sa position | AFF-111 | ✅ OK | 23 role(s) serveur declares (interne-sans-auth 2, ldap-direct 2, sans-auth-humaine 12, socle-identite 2, web-sso 5) ; 2 lacune(s) nommee(s) : serveur_loki, serv |
|
||||
| P30 | SDN EVPN : zones, VNets et sous-reseaux derives | AFF-112 | ✅ OK | CONFORME : SDN EVPN, 2 zone(s), 12 VNet(s), 12 sous-reseau(x), aucune collision ; /!\ aucun noeud de sortie declare (VRF sans chemin vers l'exterieur). |
|
||||
|
||||
## Couverture des affirmations ✅ du registre
|
||||
|
||||
Chaque affirmation ✅ automatisable est couverte par la preuve indiquee ci-dessus.
|
||||
Les ✅ **structurelles/doctrinales** non rejouables par une commande (ex. AFF-005
|
||||
`make`=aide, AFF-014 ciblage groupe, AFF-024 `instancier-appliquer`, AFF-051 autorite
|
||||
d'AGENTS.md, AFF-073/075 gardes `make`, AFF-090 wiki) ont ete verifiees a l'audit ;
|
||||
elles restent hors du harnais recurrent (rien d'executable a rejouer).
|
||||
|
||||
## Declarations d'intention (⚪ invérifiables localement — assumees)
|
||||
|
||||
Ces affirmations ne sont pas rejouables hors production ; elles sont **assumees**
|
||||
comme declarations d'intention, non comme preuves :
|
||||
|
||||
- **AFF-036** — « testables avec `--check` autant que possible » : verifiable seulement
|
||||
contre une flotte vivante.
|
||||
- **AFF-091** — contenu pedagogique du wiki : affirmations conceptuelles.
|
||||
- **AFF-096** — « GUI 100 % francais » : revue exhaustive des libelles rendus, non automatisee.
|
||||
- **AFF-007** — hote d'exemple `web-frontal-01` : placeholder assume.
|
||||
|
||||
_Rapport genere le 2026-08-04._
|
||||
|
|
@ -48,6 +48,7 @@ Ce que je re-découvre sinon. **Consulter avant de concevoir un nouveau mécanis
|
|||
| Voûte au déploiement | secret jamais en clair | `ANSIBLE_VAULT_PASSWORD_FILE` / `~/.config/setops-vault-pass` ; déréférencé par `lookup('vars', <nom>)` | — |
|
||||
| Multi-instance | un dépôt par écosystème ; l'active = symlink `instance/`, les autres **découvertes par convention** (dossiers frères, aucun registre) | active : symlink `instance/` ; découverte : `scripts/instances.py` / `devis_reseau.py` (glob `../*/plan/nomenclature.yml` avec `index`) ; garde-fou collision : preuve **P21** | `multi-instances.md` |
|
||||
| Exposition → edge | app expose un FQDN public servi par un edge | `plan/domaines.yml` + `expose` (applications) | `bindings-conception.md` §4 |
|
||||
| Exploitation de l'hébergeur | ses **opérations** (supervision de la fabric, sauvegarde des configs, DNS d'underlay) n'appartiennent à aucun tenant et restent **hors overlay** | décidé, **non construit** : aucun équipement d'hébergeur n'est encore dans un inventaire | `hebergeur-exploitation.md` |
|
||||
| Authentification | web → Keycloak ; LDAP source unique ; secours par `sudo`, formulaire local non annoncé | `<rôle>_connexion_locale: false` (grafana, forgejo, nextcloud) ; garde de version Forgejo ≥ 10 | `authentification.md` |
|
||||
| SDN EVPN | ajouter un tenant implique **1 zone + 6 VNets + 6 sous-réseaux**, tous dérivés du seed | `scripts/devis_sdn.py` (`make devis-sdn`) ; nommage dérivé du tenant (`CHEZ17`, `chez174`), ≤ 8 caractères ; garde **P30** | `sdn-evpn.md` §2 |
|
||||
| Pools Proxmox | un pool par tenant : les noms courts de VM sont **volontairement identiques** d'un tenant à l'autre (même fonction, même nom), et seule la console Proxmox en souffrait | `scripts/devis_proxmox_pools.py` (`make devis-proxmox-pools`) ; nom dérivé de l'`index` ; garde de collision = preuve **P28** | `decisions-architecture.md` D-37 |
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ sont les seules vérifiables.
|
|||
| **D-36** | Le panneau **nomme le propriétaire** de chaque section d'intrants | éditer une section « hébergeur » vaut pour tous ses tenants ; l'écran ne le disait pas | `scripts/inventory_gui.py` (`INTRANTS_SCHEMA`) | — |
|
||||
| **D-37** | Chaque tenant a son **pool Proxmox** ; les noms courts de VM restent **identiques** d'un tenant à l'autre | 11 serveurs sur 14 sont homonymes — c'est la preuve que la nomenclature est un gabarit ; le coût est humain (la console affiche le nom), et le pool le corrige sans rien renommer | `devis_proxmox_pools.py` | P28 |
|
||||
| **D-45** | L'**affinité de VM** (garder un groupe sur le même hyperviseur) attend **Proxmox 9** ; tenue à la main d'ici là | les *resource affinity rules* n'existent qu'en 9 ; en 8.4 seuls les groupes HA épinglent à des **nœuds**, pas des VM entre elles. Sans ressource HA déclarée, rien ne déplace ni ne sépare les VM — le sujet ne devient réel qu'en activant la HA | `sdn-evpn.md` | — |
|
||||
| **D-46** | Un hébergeur porte **trois** catégories, pas deux : son **tenant**, ses **opérations**, le **plan de contrôle** | Chezlepro est hébergeur ET tenant, ce qui masquait des besoins n'appartenant à aucun tenant | `hebergeur-exploitation.md` §2 | — |
|
||||
| **D-47** | Les **services d'exploitation** de l'hébergeur vivent dans **son dépôt**, et leurs VM se rattachent à un **pont VLAN, jamais un VNet** | un service qui observe la fabric ne peut pas dépendre d'elle : l'EVPN tombe, et la supervision tombe avec la raison de la panne | `hebergeur-exploitation.md` §1, §4 | — |
|
||||
| **D-48** | Les **hyperviseurs** sont gérables par Ansible ; « hors flotte » ne vaut que pour les **commutateurs** et la **frontière** | ce sont des Debian joignables en SSH ; c'est la seule façon d'y poser un exportateur de métriques | `hebergeur-exploitation.md` §5 | — |
|
||||
| **D-18** | Chaque tenant a un **responsable désigné** | sans lui, « qui peut décider de déménager cette organisation ? » se pose au pire moment | `migration-tenant.md` §3 | — |
|
||||
|
||||
| **D-38** | Toute authentification **web** passe par Keycloak ; LDAP est la **source unique** des comptes | une identité, un mot de passe ; aucun service ne tient son propre répertoire d'humains | `authentification.md` §1-2 | — |
|
||||
|
|
|
|||
86
docs/hebergeur-exploitation.md
Normal file
86
docs/hebergeur-exploitation.md
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# Les services d'exploitation de l'hébergeur
|
||||
|
||||
> **Décision du 2026-08-04.** Tout ce qu'un hébergeur fait tourner n'appartient pas à un
|
||||
> tenant. Ce document dit où va quoi, et pourquoi certains services ne peuvent pas vivre
|
||||
> dans l'overlay qu'ils observent. **Rien n'est construit** : la décision est consignée,
|
||||
> le chantier reste devant.
|
||||
|
||||
## 1. Le test qui tranche
|
||||
|
||||
Pour chaque service, une seule question : **de quoi doit-il survivre ?**
|
||||
|
||||
Un service qui observe ou répare la fabric ne peut pas dépendre de la fabric. Mettez
|
||||
Prometheus dans une zone EVPN pour surveiller les hyperviseurs, et le jour où le VXLAN
|
||||
tombe vous perdez la supervision **et** la raison de la panne en même temps. Pire pour les
|
||||
sauvegardes : on veut restaurer la configuration d'un commutateur précisément quand le
|
||||
réseau est cassé.
|
||||
|
||||
C'est le motif *in-band / out-of-band*, et il ne se contourne pas.
|
||||
|
||||
## 2. Trois catégories, pas deux
|
||||
|
||||
**Le tenant de l'hébergeur** — son courriel, sa forge, son nuage, son site. L'hébergeur
|
||||
*comme entreprise*. Aucune différence avec un client : même plan, même machinerie, mêmes
|
||||
preuves, même EVPN. Chezlepro est ici hébergeur **et** tenant, ce qui a longtemps masqué
|
||||
la distinction (D-13).
|
||||
|
||||
**Les opérations de l'hébergeur** — ce qui fait tenir la fabric. Doit rester **hors
|
||||
overlay**.
|
||||
|
||||
**Le plan de contrôle** — Set-OPS lui-même, les dépôts, la voûte. Déjà dehors, sur le
|
||||
poste de l'opérateur et sa forge. Rien à changer.
|
||||
|
||||
## 3. Ce qui n'a pas de maison aujourd'hui
|
||||
|
||||
Constaté le 2026-08-04 : **aucun équipement de l'hébergeur n'est dans un inventaire
|
||||
Ansible**, et rien ne sauvegarde leurs configurations.
|
||||
|
||||
| Besoin | État |
|
||||
|---|---|
|
||||
| Supervision des hyperviseurs, commutateurs, frontière | personne |
|
||||
| Journaux de ces équipements | personne |
|
||||
| Sauvegarde de leurs configs (`running-config`, `config.xml`, `/etc/pve`) | personne |
|
||||
| Résolution des noms d'underlay (`asgard`, `sleipnir-01`, `bifrost-1`) | personne |
|
||||
| Certificats pour leurs interfaces web | personne |
|
||||
|
||||
Ce n'est pas un oubli de conception : ces besoins tombaient entre les chaises. Ils ne sont
|
||||
d'aucun tenant, et `underlay.yml` ne décrit que du matériel, sans service.
|
||||
|
||||
## 4. Où ça va
|
||||
|
||||
**Dans le dépôt de l'hébergeur** — celui qui porte déjà `underlay.yml` et
|
||||
`proxmox-hebergeur.yml`. Ses services d'exploitation lui appartiennent au même titre que
|
||||
sa fabric ; les loger ailleurs recréerait la confusion qu'on vient de défaire.
|
||||
|
||||
Ce dépôt n'a pas d'inventaire Ansible aujourd'hui : c'est ce que le chantier ajoutera.
|
||||
|
||||
**Rattachement réseau : un pont VLAN ordinaire, jamais un VNet du SDN.** C'est la
|
||||
contrainte qui découle du §1, et la seule qui distingue ces VM de celles d'un tenant.
|
||||
|
||||
## 5. Ce que ça ne change pas
|
||||
|
||||
Les **commutateurs** et la **frontière** restent hors flotte : le premier n'a pas d'agent,
|
||||
la seconde se pilote par API. Ils reçoivent des devis, pas des rôles (D-23).
|
||||
|
||||
Les **hyperviseurs** sont un cas différent, et la doctrine « hors flotte » les englobait à
|
||||
tort : ce sont des machines Debian, joignables en SSH. Rien n'empêche de les gérer par
|
||||
Ansible depuis l'inventaire de l'hébergeur — c'est même la seule façon d'y poser un
|
||||
`node_exporter` et un expéditeur de journaux.
|
||||
|
||||
## 6. Question ouverte, non tranchée
|
||||
|
||||
**L'index du tenant propre de l'hébergeur.** L'idée d'un `0` réservé — local par
|
||||
construction, donc jamais à coordonner entre hébergeurs, et jamais porté par un tenant qui
|
||||
déménage — est séduisante et reste **en attente**.
|
||||
|
||||
Deux obstacles mesurés le 2026-08-04, à lever avant :
|
||||
|
||||
- l'index 0 produit les VNI `1001`–`1006`, et le parc hérité utilise déjà `1001`
|
||||
(TechnoLibre historique, 8 VM) et `1003` (KBR). C'est une condition de **séquence** :
|
||||
la place se libère quand l'ancien monde s'éteint ;
|
||||
- **P21** vérifie l'unicité des index entre dépôts frères. Si tout hébergeur a un tenant
|
||||
`0`, poser deux dépôts d'hébergeurs côte à côte déclencherait une fausse collision — il
|
||||
faudrait exempter `0`, donc inscrire dans la garde que cette valeur est locale.
|
||||
|
||||
À noter au passage : la convention héritée était déjà `1000 + numéro de tenant`. La formule
|
||||
de Set-OPS (`1000 + index×10 + zone`) en est un raffinement, pas une invention.
|
||||
|
|
@ -302,25 +302,47 @@ def partie_acces(underlay: dict | None, tenants: list, vlans: str,
|
|||
return out
|
||||
|
||||
|
||||
def section_frontiere(transit: dict | None, bord: bool = False,
|
||||
ports: list[str] | None = None) -> list[str]:
|
||||
"""Port du switch vers le pare-feu de bordure. Porte le VLAN de transit, et lui seul.
|
||||
def vlans_de_la_frontiere(underlay: dict | None, transit: dict | None) -> list[dict]:
|
||||
"""Reseaux que le port de la frontiere doit porter — DERIVES de ses rattachements.
|
||||
|
||||
Distinct du trunk vers Proxmox : les hyperviseurs n'ont aucune interface sur le
|
||||
transit, et le pare-feu n'a rien a faire des VLAN tenants — il route vers eux, il
|
||||
ne les etiquette pas.
|
||||
Le transit ne suffit plus. Depuis la separation des plans (2026-08-04), la
|
||||
frontiere a aussi une patte sur le VLAN de sortie tenant : c'est par la que le
|
||||
trafic DECAPSULE lui parvient, sans traverser ni la gestion des noeuds ni celle
|
||||
des equipements. Une liste figee sur le seul transit aurait produit un port muet
|
||||
sur ce VLAN — le devis aurait eu l'air juste et le trafic ne serait jamais arrive.
|
||||
"""
|
||||
noms = {h.get("reseau") for h in underlay_mod.hotes(underlay)
|
||||
if h.get("role") == "frontiere" and h.get("reseau")}
|
||||
fab = underlay_mod.fabric_du_routeur(underlay)
|
||||
reseaux = [r for r in underlay_mod.reseaux_de_fabric(underlay, fab)
|
||||
if r.get("nom") in noms and r.get("vlan") is not None]
|
||||
if not reseaux and transit:
|
||||
reseaux = [transit]
|
||||
return sorted(reseaux, key=lambda r: int(r["vlan"]))
|
||||
|
||||
|
||||
def section_frontiere(transit: dict | None, bord: bool = False,
|
||||
ports: list[str] | None = None,
|
||||
underlay: dict | None = None) -> list[str]:
|
||||
"""Port du switch vers le pare-feu de bordure.
|
||||
|
||||
Distinct du trunk vers Proxmox : le pare-feu n'a rien a faire des VLAN tenants —
|
||||
il route vers eux, il ne les etiquette pas.
|
||||
"""
|
||||
if not transit:
|
||||
return ["! ----- 4b. Port vers la frontiere -----",
|
||||
"! Aucun reseau de transit declare dans underlay.yml (cle 'passerelle_sortie')."]
|
||||
reseaux = vlans_de_la_frontiere(underlay, transit)
|
||||
liste = ",".join(str(r["vlan"]) for r in reseaux)
|
||||
detail = ", ".join(f"{r['vlan']} ({r['nom']})" for r in reseaux)
|
||||
return [
|
||||
"! ----- 4b. Port vers la frontiere nord/sud -----",
|
||||
f"! Porte le seul VLAN {transit['vlan']} ({transit['nom']}). En lien dedie,",
|
||||
f"! remplacer par : switchport access vlan {transit['vlan']}.",
|
||||
f"! Porte {detail}.",
|
||||
"! Derive des rattachements declares des hotes `role: frontiere`.",
|
||||
"! Port terminal : rien derriere lui ne participe au spanning-tree.",
|
||||
] + [ligne
|
||||
for port in (ports or ["<PORT-VERS-FRONTIERE>"])
|
||||
for ligne in bloc_trunk(port, str(transit["vlan"]), bord=bord)]
|
||||
for ligne in bloc_trunk(port, liste, bord=bord)]
|
||||
|
||||
|
||||
def inventaire_de(nom_instance: str) -> Path | None:
|
||||
|
|
@ -573,7 +595,8 @@ def generer(tenants: list[tuple[str, str, dict]], dialecte: str | None = None) -
|
|||
out += ["!"] + section_frontiere(
|
||||
transit, bord=bool(underlay_mod.stp(underlay)),
|
||||
ports=ports_ou_marqueur(hote_nomme(underlay, underlay_mod.routeur(underlay)),
|
||||
"frontiere", "<PORT-VERS-FRONTIERE>"))
|
||||
"frontiere", "<PORT-VERS-FRONTIERE>"),
|
||||
underlay=underlay)
|
||||
out += ["!"] + section_rayons(underlay, ",".join(vlans_underlay + vlans_tenants))
|
||||
out += ["!"] + section_routes(underlay, dialecte)
|
||||
out += section_stp(underlay, dialecte)
|
||||
|
|
|
|||
Loading…
Reference in a new issue