Set-OPS-Public/wiki/Multi-instance-et-fédération.md
Daniel Allaire 5ace6bdb95 adressage : le decalage de +10 est retire, l'index se lit dans l'adresse
supernet_de rendait 10.(10+index).0.0/16. Personne ne savait plus pourquoi : ni le
commentaire de la constante, ni le wiki, ni le commit fondateur 36a882b ne le
justifiaient. Trois endroits consultes, zero raison ecrite.

Ses deux effets constates :
  - il reservait 10.0-10.9 sous la plage tenant. Utile tant que l'underlay vivait
    la — mais D-77 l'a fait entrer dans la bande basse de son propre /16, ce qui a
    vide cette reserve de son role la veille ;
  - il eloignait le premier tenant de 10.0.0.0/16, la plage la plus repandue en
    reseau domestique. Ce risque revient donc aux index bas, et c'est ASSUME.

En echange l'index se lit directement dans l'adresse (17 -> 10.17.x.x) et le
plafond passe de 245 a 255 ecosystemes federes.

  Chezlepro (17)   10.27.0.0/16 -> 10.17.0.0/16
  Technolibre (11) 10.21.0.0/16 -> 10.11.0.0/16
  lab (1)          10.11.0.0/16 -> 10.1.0.0/16

Doc alignee : les trois pages du wiki, multi-instances.md (plafond et exemple
devenus faux arithmetiquement), sdn-evpn.md, le libelle de la GUI, la docstring
d'underlay.py, D-77, et le document de preparation d'un site hebergeur. Les
CONSTATS DE TERRAIN dates sont laisses tels quels : ce sont des mesures.

CE COMMIT NE RENUMEROTE RIEN. Il change ce que le plan DERIVE ; l'inventaire
applique porte toujours 10.27.x.x et les quatorze VM tournent dessus. Appliquer
sans reconstruire rendrait la flotte injoignable — le renumerotage est une
operation a part, a mener a froid.

Au passage, retire un debris : une copie de conflit Nextcloud de
serveur_powerdns/defaults/main.yml, IDENTIQUE a l'original, commitee par accident
dans 1295eea et jamais chargee par Ansible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 16:16:08 -04:00

166 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Multi-instance & fédération
> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer.
---
## ① Le concept *(générique)*
Un même **moteur** peut opérer **plusieurs écosystèmes** (organisations, clients, environnements).
Trois questions se posent :
- **Isolation** — chaque écosystème (*tenant*) doit être étanche : ses données, son identité, son
réseau ne touchent pas ceux des autres.
- **Cohabitation sans collision** — si plusieurs tenants partagent une infrastructure physique
(mêmes switches, même hyperviseur), leurs adresses et VLAN doivent être **uniques globalement**,
sinon le réseau se marche dessus.
- **Découverte** — comment le système sait-il *quels* écosystèmes existent ? Par un **registre**
central (qu'il faut tenir à jour) ou par **convention** (ils se reconnaissent d'eux-mêmes) ?
---
## ② Comment Set-OPS le fait
**Un dépôt par écosystème.** L'écosystème actif est celui que pointe le symlink `instance/`. Les
autres sont des **dépôts frères** (`../OPS-Chezlepro`, `../OPS-Technolibre`…).
**Découverte par convention, pas de registre.** Une instance *est* un dossier frère avec un
`plan/nomenclature.yml` portant un `index`. Le code fait `glob('../*/plan/nomenclature.yml')`
rien à inscrire nulle part. Déposer une instance à côté des autres suffit.
**Le seed garantit l'unicité.** Chaque tenant a un `index` distinct → adressage dérivé sans
chevauchement possible : VLAN `1000+index×10+zone` (les VLAN de deux index différents ne peuvent
*mathématiquement* pas se croiser). Plafond : **245** écosystèmes fédérés (borne IPv4).
**Gérer la flotte :**
- `make instances` — la vue d'ensemble : qui existe, l'active (★), index, VLAN, **collision** ;
- `make instance-utiliser NOM=…` ou le bouton **« Activer »** de la GUI (vue Réseau) — basculer ;
- `make instance-creer NOM=… MODELE=…` — créer une instance depuis un modèle ;
- `make model-creer …` — créer/promouvoir un **modèle** (le produit).
**Garde-fous.** `federe: false` exclut un bac à sable local du réseau convergé. La **preuve P21**
échoue si deux instances fédérées partagent un `index`.
**Qui route les tenants : deux mondes.** L'adressage dérive toujours du seed `index`, mais
*qui* l'applique se déclare — `underlay.routage_tenants` :
| | `switch` | `sdn` |
|---|---|---|
| Passerelle d'une zone | **SVI** sur le commutateur L3 | **anycast** sur chaque hyperviseur |
| Isolation inter-tenant | ACL de commutateur | **VRF** (une zone EVPN par tenant) |
| Sur le fil | VLAN étiquetés par zone | **VXLAN** — aucun VLAN de tenant ne circule |
| Inter-tenant | bloqué par ACL | sort du VRF → **passe par la frontière** |
Le `.1` d'une passerelle ne change pas d'adresse d'un monde à l'autre : il **change de
porteur**. C'est la même dérivation, appliquée ailleurs.
**Le devis du commutateur.** `make devis-reseau` dérive la config à coller. En mode `switch` :
VLAN par zone, SVI, ACL d'isolation. En mode `sdn` : rien de tout ça — le commutateur redevient
un **transport IP** qui achemine du VXLAN sans le lire, et le devis dit à sa place pourquoi ces
sections ont disparu.
**Le devis de la frontière.** `make devis-opnsense` dérive la politique de bordure du **même**
registre des flux — les flux `pair: externe`, que le pare-feu d'hôte saute justement parce
qu'ils relèvent de la bordure. Rien n'y est saisi : ni port, ni adresse, ni nom d'hôte.
**Le dialecte de CLI.** Toutes les CLI de commutateur ne se ressemblent pas. Set-OPS génère par
défaut du **Cisco**, mais connaît aussi le **Binardat**, qui diffère sur des détails capables de
faire *passer un VLAN mais fuir un tenant* :
| | Cisco | Binardat |
|---|---|---|
| Masque d'ACL | **inversé** (wildcard `0.0.255.255`) | **normal** (`255.255.0.0`) |
| Commentaire d'ACL | `remark …` | **absent** (omis) |
| Route statique | `ip route <réseau> <masque> <saut>` | **CIDR** : `ip route 0.0.0.0/0 <saut>` |
*(Le SVI `ip address … 255.255.255.0` est en masque normal sur les deux.)* Le dialecte est un
**intrant** — section *Fabric* du panneau — surchargeable par `--dialecte` ou `SETOPS_DIALECTE`.
**Le dépôt public reste générique** (`cisco`).
> **La leçon qui vaut au-delà de Set-OPS.** Trois de ces formes ont été *supposées* avant d'être
> confrontées au matériel ; deux étaient fausses. La pire ne levait aucune erreur :
> `switchport trunk allowed vlan **add** …` *ajoute* à la liste courante, et sur un port neuf
> qui autorise déjà tout, elle ne retranchait rien. La configuration avait l'air d'isoler et
> n'isolait pas. **Une commande acceptée n'est pas une commande qui fait ce qu'on croit.**
**L'underlay — le sous-sol.** Les VLAN tenant (`1000+index×10+zone`) sont les *overlays*. En
dessous vit la **fabric physique** partagée par toute la flotte : management des switches et de
Proxmox/OOB, iSCSI, Ceph (public + cluster). Elle **n'appartient à aucun tenant** et ne dérive
d'aucun `index`. On la décrit dans `underlay.yml`, qui vit dans le dépôt de **l'hébergeur**
(ses switches, ses câbles) et que le moteur monte par symlink à sa racine — comme il monte le
plan par `instance/`. Ce lien ne suit pas `make instance-utiliser` : la fabric reste celle de
l'hébergeur, quel que soit le tenant actif. Gabarit : `underlay.yml.example`.
| Underlay | VLAN | Sous-réseau | Fabric |
|---|---|---|---|
| management (commutateurs, Proxmox, OOB) | 10 | `10.0.0.0/24` | principale |
| **transit** vers la frontière | 40 | `10.0.4.0/29` | principale |
| stockage / iSCSI | 20 | `10.0.1.0/24` | stockage |
| ceph-public | 30 | `10.0.2.0/24` | stockage |
| ceph-cluster | 31 | `10.0.3.0/24` | stockage |
Deux choses à retenir de cette table.
**Les fabrics.** Tous les réseaux ne partagent pas les mêmes câbles. Le stockage jumbo peut
vivre sur ses propres commutateurs ; le devis de l'une ne déclare alors rien de l'autre, et le
dit — `HORS PERIMETRE`. Un devis est une configuration qu'on applique, pas un inventaire.
**Le transit.** C'est le lien entre le routeur et la frontière, et **sans lui la flotte n'a ni
sortie ni chemin de retour**. Il vit dans l'underlay parce qu'il est *partagé* : la frontière
route vers tous les tenants par ce même saut, il ne peut donc dériver d'aucun `index`.
> **Le piège qui a coûté une passe de déploiement.** La route *aller* ne suffit pas. Sans route
> de **retour** vers le réseau d'administration, la réponse d'une VM sort par une autre
> interface que celle où l'état a été créé, et le pare-feu la jette **en silence** — ni réponse,
> ni message d'erreur. Symptôme déroutant : la passerelle répond au ping, aucun hôte derrière
> elle n'est joignable. On cherche une règle de pare-feu ; c'est une route manquante à l'autre
> bout.
En mode `sdn`, ces réseaux transportent du VXLAN : leur **MTU doit atteindre 1550** au minimum,
sinon le ping passe et les transferts échouent. `make underlay` le refuse.
`make underlay` l'affiche et le **valide** : VLAN < 1000 et sous-réseaux hors des supernets
tenant (`10.<index>.0.0/16`) — **aucune collision possible** avec les overlays. `make
devis-reseau` en émet la config (section 0) et l'ajoute au trunk. La **preuve P23** garde la
règle ; elle est *sautée* si aucun `underlay.yml` n'est défini.
---
## ③ Pourquoi c'est transférable
| Set-OPS | Équivalents ailleurs |
|---|---|
| un moteur, N tenants | **multi-tenancy** SaaS, *cloud accounts/projects* |
| isolation par VRF (zone EVPN) | VRF matériel, VPC, *namespaces* Kubernetes |
| découverte par convention | *convention over configuration* (Rails, etc.) |
| tenants NetBox | modèle de source de vérité multi-tenant |
Tu as appris **le multi-tenant, l'isolation réseau, la convention plutôt que la configuration**
pas « le symlink de Set-OPS ».
---
## ④ À toi de jouer
1. **Vois la flotte.** `make instances` : l'active (★), les index, les VLAN, le statut
fédéré/local. Repère qui est en **production**.
2. **Bascule.** GUI, vue **Réseau**, bouton **« Activer »** sur une autre instance (ou
`make instance-utiliser NOM=…`). Toutes les vues suivent — sans redémarrer.
3. **Crée une instance.** `make instance-modeles` (les modèles dispo), puis
`make instance-creer NOM=OPS-Test MODELE=socle INDEX=4`. Un écosystème neuf, en une commande.
4. **Éprouve le garde-fou de collision.** Essaie de créer une instance avec un `index` **déjà
pris** : refus *avant* toute copie. Puis `make prouver`**P21** veille sur la fédération.
5. **Casse & répare.** Donne à deux instances fédérées le **même** index (édite une nomenclature),
`make instances` : la **bannière de collision** s'allume ; `make prouver` : P21 échoue.
Corrige l'index : tout redevient vert.
6. **(Avancé) Promeus un produit.** Une instance qui *tourne et se prouve* peut devenir un modèle
vendable : `make model-creer MODE=instance SOURCE=OPS-… NOM=…` — elle est **généralisée**
(identité → `exemple.*`, secrets retirés) et **validée**.
---
## Pour aller plus loin *(dépôt)*
- Le guide complet : `docs/multi-instances.md`.
- Le seed et la dérivation : unité **[Le plan & l'adressage dérivé](Le-plan-et-l-adressage-dérivé)**.
- L'isolation réseau (VLAN, ACL, OPNsense) : `make devis-reseau` + `scripts/devis_reseau.py`.
- Les garde-fous prouvés : unité **[La preuve](La-preuve)** (P21).