Some checks failed
verifier / verifier (push) Has been cancelled
La revision a commence par un balayage par motifs — chemins morts, cibles make absentes, comptes derives. Il a trouve une trentaine d ecarts et rate presque tout le reste : un motif ne voit que ce qui s exprime en motif. make hote-planifier en est l exemple. La cible EXISTE, donc le controle passait au vert. C est une cible depreciee qui refuse et sort en 2, recommandee par AGENTS.md, et qui contredit la REGLE D OR du meme fichier trois ecrans plus haut. Il fallait lire pour la voir. 74 documents lus un par un. 66 corriges, 8 exacts. CE QUI ETAIT FRANCHEMENT FAUX AGENTS.md, la source d autorite, annoncait la flotte pas encore executee contre des VM reelles. Elle a ete rasee et remontee depuis zero trois fois. ecosysteme-chezlepro.md, le document montre a un client, portait la meme phrase : il se sous-vendait gravement. courriel-conception.md s ouvrait sur aucun role n est encore ecrit, au-dessus de son propre paragraphe 1 qui les nomme. autorisation.md se terminait sur rien n est construit alors qu il rapporte des mesures datees du role en fonctionnement. hebergeur-exploitation.md disait rien n est fait d un depot qui existe. filiation-emancipation.md se contredisait a deux ecrans de distance. DES MODELES DECRITS D APRES UN MONDE ANTERIEUR Le resolveur : cinq documents decrivaient un Unbound par VM en opt-in, trois le donnaient en exemple d integration FACULTATIVE — il est universel depuis le 2026-08-24. L adressage de nomenclature-vm.md : reseau unique, VLAN 11-15, VMID a cinq chiffres. Le nommage SDN de sdn-evpn.md contre le code : c est le wiki qui avait raison. CE QUI CASSE AU PREMIER ESSAI Le nom du gabarit dore etait faux a quatre endroits, dont la procedure qui le FABRIQUE et le critere R2 de l epreuve d operateur independant. preparer-un-site-hebergeur.md avertissait qu une VM faite a la main serait detruite : raser derive du plan, il ne la detruira jamais — le risque est l inverse. Un mot de passe d essai en clair dans un depot public. DEUX PREUVES ETENDUES, ET UNE QUI SE TROMPAIT ELLE-MEME P57 couvre les groupes : elle a signale aussitot 29 groupes annonces au-dessus d un tableau qui en cite 40. P29 confronte le tableau de authentification.md aux declarations reelles : 12 annonces, 21 reels. Et P57 imposait un chiffre faux — 56 preuves alors que le depot en porte 57, la conditionnelle vivant hors de tout comptage. Un garde-fou qui fait respecter une erreur ajoute l assurance a l erreur. CE QUI RESTE, ET QU AUCUNE PREUVE NE TIENT Deux comptes trouves a la main. Et une lacune reelle : rien ne garde les meta/acces.yml — ni qu un service web-sso en porte un, ni que le groupe qu il nomme existe. P29 tient les positions d authentification, personne ne tient les habilitations. make prouver : CONFORME, 56 OK, 0 echec, 1 saute. 0 lien mort. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
223 lines
13 KiB
Markdown
223 lines
13 KiB
Markdown
# SDN EVPN : le routage passe aux hyperviseurs
|
||
|
||
> **Pour qui :** le **mainteneur** du réseau overlay.
|
||
|
||
> **Décision d'architecture du 2026-08-02.** Elle remplace le routage inter-zone sur les
|
||
> commutateurs L3 par des zones EVPN de Proxmox SDN. Complète `docs/frontiere-opnsense.md`
|
||
> (la bordure, inchangée) et `underlay.yml.example` (la fabric, très allégée).
|
||
>
|
||
> **Décidé le 2026-08-03** : une zone EVPN **par tenant** ; le routage **et le filtrage**
|
||
> entre les VLAN d'un même tenant se font à ce niveau ; le trafic **inter-tenant passe
|
||
> obligatoirement par l'OPNsense**.
|
||
|
||
## 1. Ce que la décision résout
|
||
|
||
Les commutateurs Binardat ne savent pas lier une ACL à une interface de routage : l'isolation
|
||
inter-tenant ne pouvait pas vivre sur la fabric. On l'a d'abord assumé — tout sur les nftables
|
||
d'hôte — en notant ce qu'on perdait : **le plan de gestion n'avait plus de protection réseau
|
||
contre les tenants**, une VM émettant vers `10.0.0.x` étant routée localement vers le mgmt des
|
||
commutateurs, celui de Proxmox et l'OOB/IPMI.
|
||
|
||
**Une zone EVPN est un VRF.** Le tenant n'a plus de route vers l'underlay — celui-ci n'est pas
|
||
dans sa table de routage. Son seul chemin vers l'extérieur passe par le nœud de sortie, donc
|
||
par l'OPNsense, qui filtre. Le plan de gestion redevient protégé **par construction**, pas par
|
||
une règle qu'on pourrait oublier.
|
||
|
||
C'est le VRF qu'on regrettait de ne pas avoir dans le matériel, obtenu en logiciel.
|
||
|
||
## 2. La projection du modèle
|
||
|
||
Vérifiée sur chaque tenant fédéré (ils étaient deux au moment de la décision, ils sont
|
||
trois), elle ne demande **aucun changement de dérivation** :
|
||
|
||
| Objet Proxmox SDN | Vient de | Exemple (Chezlepro, zone Services-infra) |
|
||
|---|---|---|
|
||
| **zone** (un VRF) | `zone_de(index)` → `t<index>` | `t17` |
|
||
| **VNet** | `vnet_de(index, libellé)` → `t<index><zone abrégée>` | `t17serv` |
|
||
| **tag** (VNI) | `vlan_de(index, zone)` | `1174` |
|
||
| **subnet** | `sous_reseau_de(index, zone)` | `10.17.19.0/24` |
|
||
| **gateway** | `passerelle_de(index, zone)` | `10.17.19.1` |
|
||
|
||
Les six VNets d'un tenant à l'index 17 : `t17fron`, `t17iden`, `t17donn`, `t17serv`,
|
||
`t17obse`, `t17appl`.
|
||
|
||
> **Rectification du 2026-08-03.** Ce tableau annonçait `chez17-services-infra`, qui
|
||
> aurait été **refusé à l'application** : zones et VNets sont limités à **8 caractères**
|
||
> par Proxmox — l'identifiant sert de base aux noms de bridge, veth et tap. Message
|
||
> amont : *« zone ID … can't be more length than 8 characters »*.
|
||
>
|
||
> **Le nommage a changé une seconde fois, et ce tableau ne l'avait pas suivi.** Il annonçait
|
||
> `CHEZ17` / `chez174`, dérivés de `devis_reseau.prefixe()` — le nom court du *dossier* du
|
||
> tenant. La forme en vigueur est plus simple et ne dépend que du seed :
|
||
> **`t<index>`** pour la zone, **`t<index><zone abrégée>`** pour le VNet
|
||
> (`scripts/devis_sdn.py` : `zone_de`, `vnet_de`). Même préfixe `t` que les IPSets du
|
||
> pare-feu Proxmox, donc un seul vocabulaire d'un bout à l'autre de la fabric ; minuscules,
|
||
> parce que cet identifiant devient une base de nom d'interface.
|
||
>
|
||
> La contrainte qui avait motivé la première rectification tient toujours : zones et VNets
|
||
> sont limités à **8 caractères** par Proxmox — l'identifiant sert de base aux noms de
|
||
> bridge, veth et tap. Message amont : *« zone ID … can't be more length than 8
|
||
> characters »*. Avec `t<index>`, la marge est confortable jusqu'à l'index 255 (`t255` = 4,
|
||
> `t255serv` = 8). **P30** refuse tout dépassement, sur les deux objets.
|
||
>
|
||
> **Les zones créées à la main (`VRF0011`, `VRF0017`) sont remplacées.** Ce nommage ne
|
||
> disait ni de quel tenant il s'agissait, ni rien qu'on puisse relier au plan : il
|
||
> fallait une table de correspondance pour le lire. Le remplacement se fait **pendant
|
||
> que les zones sont vides** — les supprimer ne débranche rien. Avec des VM attachées,
|
||
> ce serait une migration ; le devis émet donc une §0 qui les retire d'abord.
|
||
|
||
**`make devis-sdn`** émet ces objets, tenant par tenant : la zone, ses six VNets, ses six
|
||
sous-réseaux, puis `pvesh set /cluster/sdn` pour pousser. Non destructif, à relire.
|
||
Vérification la plus forte disponible : la dérivation **reproduit à l'identique** les deux
|
||
zones déjà présentes sur le cluster — même nom, même VNI de VRF, même MTU, même
|
||
contrôleur.
|
||
|
||
Le seed `index` reste la source unique. Le `.1` ne change pas d'adresse, il **change de
|
||
porteur** : du SVI d'un commutateur vers la passerelle **anycast** du VNet, présente sur
|
||
chaque hyperviseur — donc plus proche de la VM, et sans point unique de défaillance.
|
||
|
||
Effet de bord favorable : un VNI est codé sur 24 bits là où un VLAN plafonne à 4094. La limite
|
||
du nombre de tenants n'est plus l'espace de VLAN mais le **second octet IPv4** du supernet :
|
||
`valider_index` borne l'index à **0–255**, et 0 est à éviter (les réseaux de service du site
|
||
y vivent). Le plafond reste, sa cause change.
|
||
|
||
## 3. Le partage des responsabilités
|
||
|
||
| Trafic | Où il est routé | Où il est filtré |
|
||
|---|---|---|
|
||
| **entre zones d'un même tenant** | zone EVPN du tenant (VRF, sur les hyperviseurs) | **au même endroit** |
|
||
| **entre tenants** | sort du VRF → nœud de sortie → **OPNsense** | la frontière, et elle seule |
|
||
| **vers l'extérieur** | idem | la frontière |
|
||
| **de service à service, sur un hôte** | — | **deux barrières** : pare-feu Proxmox (`make devis-proxmox-fw`) **puis** nftables d'hôte (`make flux`) |
|
||
|
||
Deux conséquences qui méritent d'être dites.
|
||
|
||
**L'inter-tenant ne peut plus être « oublié ».** Il ne circule pas latéralement : il doit
|
||
sortir du VRF, donc traverser la bordure, qui est en `block` par défaut. Un flux inter-tenant
|
||
légitime doit donc être **déclaré** pour exister — et le registre des flux a désormais le
|
||
mot-clé qui manquait : **`voisins_site`**, « les tenants d'à côté »
|
||
(`scripts/resoudre_flux.py`, `MOTS_PAIR`). Ce paragraphe l'annonçait comme un point ouvert
|
||
jusqu'au 2026-09-06 ; il est fermé.
|
||
|
||
**La défense est en profondeur, sans coût de maintenance.** Le filtrage est-ouest est appliqué
|
||
deux fois : par l'hyperviseur, puis par l'hôte destinataire. Une VM compromise doit franchir
|
||
les deux. Et comme les deux **dérivent du même registre par les mêmes fonctions**, elles ne
|
||
peuvent pas se contredire — la duplication est dans l'application, jamais dans la décision.
|
||
|
||
**Le commutateur ne voit plus rien du trafic tenant.** Il transporte du VXLAN qu'il ne lit
|
||
pas. Y chercher une trace d'un problème applicatif serait perdre son temps : le miroir utile
|
||
est sur l'hyperviseur.
|
||
|
||
## 4. Ce que le devis switch devient
|
||
|
||
C'est fait, et piloté par `underlay.routage_tenants: sdn`. Disparaissent : les VLAN tenants, les SVI de zone, les ACL d'isolation,
|
||
et les VLAN tenants dans les trunks. En EVPN, **aucun VLAN de tenant ne circule sur le fil** —
|
||
seulement du VXLAN encapsulé dans de l'IP.
|
||
|
||
Restent : les VLAN d'underlay, le SVI de management, les trunks qui ne portent plus qu'eux,
|
||
les routes, le spanning-tree. La fabric redevient ce qu'elle aurait dû être — un **transport
|
||
IP**.
|
||
|
||
`underlay.routeur` garde son sens, mais son rôle se réduit : il route l'underlay, plus les
|
||
tenants.
|
||
|
||
## 5. Ce que ça change ailleurs
|
||
|
||
**Le nœud de sortie remplace le prochain saut.** En EVPN, le trafic quitte le VRF par un ou
|
||
plusieurs *exit nodes* désignés. Ce sont eux, et non plus le commutateur, que l'OPNsense voit
|
||
comme voisins.
|
||
|
||
C'est **appliqué** : en mode `sdn`, le devis frontière n'émet plus le SVI du commutateur comme
|
||
prochain saut des routes tenants — il émet le marqueur `<NOEUD-DE-SORTIE-EVPN>` et dit
|
||
pourquoi. Une route pointée vers le SVI arriverait sur un équipement qui n'a aucun chemin vers
|
||
le tenant : c'est le genre de configuration qui s'applique sans erreur et ne fonctionne pas.
|
||
|
||
À noter : `underlay.passerelle_sortie` **garde** son sens — c'est l'adresse du pare-feu sur le
|
||
lien de transit, donc la sortie de l'**underlay**, indépendante du routage tenant. Ce sont
|
||
deux choses distinctes qu'il ne faut pas confondre.
|
||
|
||
**L'overlay est plafonné à 1450** (décision du 2026-08-03) parce que le transport réel — le
|
||
pont `vmbr3` des hyperviseurs — est à **1500** : 1450 + 50 de VXLAN y tient exactement. Conséquence à ne pas manquer : sous 1500, **tout ce qui traverse la frontière dépend de
|
||
la découverte de MTU de chemin**, qui a besoin de l'ICMP « fragmentation nécessaire ».
|
||
|
||
Or le registre des flux ne connaissait que TCP et UDP : ce message ne pouvait pas être
|
||
*déclaré*, et la bordure en `block` l'aurait jeté. Symptôme : la connexion s'établit, les
|
||
petites requêtes passent, les grosses réponses restent suspendues. `protocole: icmp` est
|
||
désormais admis — le champ `port` porte alors le **type** (`frag-needed`) — et le socle déclare
|
||
les deux sens.
|
||
|
||
**Le MTU du transport est un prérequis vérifié, pas un conseil.** VXLAN ajoute 50 octets ; `make underlay`
|
||
**refuse** un réseau de transport sous 1550 dès que `routage_tenants: sdn`. C'est le premier
|
||
mur, et le plus déroutant : il ne casse pas franchement, il casse **partiellement** — le ping
|
||
passe, les transferts échouent.
|
||
|
||
**Ce qui ne change pas** : le plan, le registre des flux, les nftables d'hôte, la frontière
|
||
OPNsense et ses règles dérivées, la voûte, les preuves. La cible d'émission change ; le modèle
|
||
non.
|
||
|
||
## 6. Ce qui reste à éprouver — avant toute génération
|
||
|
||
Le principe du dépôt s'applique : **éprouver l'outil avant d'écrire le rôle.** L'EVPN est la
|
||
partie la plus jeune de Proxmox SDN, et c'est là que vivent les bogues.
|
||
|
||
Un tenant de labo, une zone EVPN, deux VNet, une VM dans chacun — et vérifier dans l'ordre :
|
||
|
||
1. le MTU de bout en bout, avec des paquets pleins et le bit *don't fragment* ;
|
||
2. le routage **entre VNet d'une même zone** (c'est ce qui remplace le SVI du commutateur) ;
|
||
3. l'**absence** de route vers l'underlay depuis le tenant — c'est le gain principal, il se
|
||
vérifie par une tentative qui doit échouer ;
|
||
4. la sortie par le nœud de sortie, jusqu'à la bordure ;
|
||
5. le comportement à la **perte d'un nœud** : la passerelle anycast est censée survivre.
|
||
|
||
Ce n'est qu'après que la question « comment générer cette configuration » se pose.
|
||
|
||
## 7. L'état réel du cluster (reconnaissance du 2026-08-03)
|
||
|
||
Lecture seule par l'API Proxmox. **Le plan de contrôle existe, le plan de données non.**
|
||
|
||
| | |
|
||
|---|---|
|
||
| Proxmox | 8.4.19 — `asgard`, `gandalf`, `vishnu` |
|
||
| Contrôleur | `EVPN0017`, ASN 65000 |
|
||
| Zones | `VRF0011`, `VRF0017` — un VRF par tenant, VNI = index, MTU 1450 |
|
||
| VNets | **aucun** |
|
||
| Nœuds de sortie | **aucun** — un VRF sans sortie n'a aucun chemin vers la frontière |
|
||
|
||
### Deux blocages — levés
|
||
|
||
> **Cette section décrivait l'état du 2026-08-02.** Les deux sont levés ; on la garde parce
|
||
> que le *raisonnement* explique le plan d'adressage actuel, qui paraîtrait arbitraire sans
|
||
> lui.
|
||
|
||
**Les VTEP étaient adressés dans un tenant.** `vmbr3` portait `10.27.19.{41,43,47}` — le
|
||
sous-réseau *Services-infra de Chezlepro*. Le transport du cluster dérivait donc de l'index
|
||
d'un tenant : un changement d'index le cassait, une migration l'emportait. Et une VM de cette
|
||
zone partageait son sous-réseau avec les trois VTEP, ce qui perçait l'isolation à l'endroit
|
||
même que l'EVPN devait fermer.
|
||
|
||
Le modèle **refusait d'ailleurs d'exprimer cet état** : déclarer `10.27.19.0/24` comme réseau
|
||
d'underlay faisait échouer **P23**, qui interdit tout chevauchement accidentel avec un
|
||
supernet tenant. La garde a détecté la faute avant qu'on ne la documente.
|
||
|
||
**Aujourd'hui** : les VTEP vivent sur `underlay-vxlan` — `192.168.50.{41,43,47}`, VLAN 50,
|
||
sur une interface étiquetée dédiée (`bond3.50`). Le transport ne dérive plus d'aucun index.
|
||
*Pourquoi 50 et pas 11 : sous la règle `192.168.<vlan>`, le VLAN 11 aurait produit
|
||
`192.168.11.0/24` — déjà occupé par le contrôle de la grappe. Un plan d'adressage ne doit pas
|
||
dépendre de l'ordre d'une migration.*
|
||
|
||
**Le pont `vmbr3` n'était pas *VLAN-aware***, et l'adresse du VTEP y vivait donc dans le VLAN
|
||
natif du port. C'est ce qui rendait le déplacement plus qu'un changement d'adresse — d'où
|
||
l'interface étiquetée dédiée retenue.
|
||
|
||
## 8. Ce qui reste à trancher
|
||
|
||
- **Où vit la configuration SDN.** Elle est *par cluster*, donc propriété de l'hébergeur —
|
||
comme `underlay.yml`, et par le même raisonnement.
|
||
- **Le contrôleur EVPN** : ASN, voisins, et si l'on fait du BGP avec la bordure ou des routes
|
||
statiques comme aujourd'hui.
|
||
- **Le nombre de nœuds de sortie** et leur redondance.
|
||
- ~~**Le mot-clé d'un flux inter-tenant** dans le registre.~~ **Tranché** : c'est
|
||
`voisins_site` (2026-08-24), né du besoin de chaîner les caches d'artefacts. Cf. §3.
|
||
- **La migration depuis l'existant** : le tenant Chezlepro tourne déjà sur des VLAN. Passer à
|
||
EVPN est un changement de plan de transport pour des VM en service — la recette de
|
||
`docs/migration-tenant.md` s'applique-t-elle, ou faut-il un chemin plus court ?
|