f-50: lab: résultats d'E5, contrôle DHCP de s1 sur les couples MAC/IP, perte du route reflector #50

Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
GnomeZworc 2026-10-04 21:17:48 +02:00
commit 909b4110c2
Signed by: nicolas.boufideline
GPG key ID: 4406BBBF8845D632
4 changed files with 47 additions and 13 deletions

View file

@ -94,9 +94,21 @@ l'adresse du lien en secondaire et la loopback sur ``lo1`` :
- up des deux côtés - up des deux côtés
* - sessions des deux hyperviseurs vers ``10.255.255.1`` * - sessions des deux hyperviseurs vers ``10.255.255.1``
- Established, voisins dynamiques, iBGP AS 64600, famille L2VPN EVPN négociée - Established, voisins dynamiques, iBGP AS 64600, famille L2VPN EVPN négociée
* - routes EVPN échangées * - routes EVPN échangées, VM ↔ VM entre deux hyperviseurs
- aucune : rien à annoncer tant que two n'a pas créé de VXLAN — voir - routes de type 3 échangées, ping et MTU 1500 de bout en bout — à partir de la release
:doc:`premier-hyperviseur` ``0.2.0rc003``, qui pose l'adresse VTEP locale des VXLAN
(`#51 <https://git.g3e.fr/syonad/two/issues/51>`_)
.. warning::
**Les tunnels ne survivent pas à la perte du route reflector.** Mesuré dans le lab
(2026-10-04, FRR 10.7.1, un seul route reflector, sans ``graceful-restart``) : à l'arrêt de
FRR sur le route reflector, la session EVPN des hyperviseurs tombe aussitôt, FRR retire les
routes apprises et, avec elles, le VTEP distant et l'entrée d'inondation du VXLAN — **plus
aucun paquet ne passe** entre hyperviseurs, à 30 s comme à 90 s. Au redémarrage de FRR sur le
route reflector, VTEP distant et trafic reviennent **31 s** plus tard. Le trafic entre VM d'un
même hyperviseur n'est pas concerné. La redondance (deux route reflectors) ou
``graceful-restart`` sont les deux leviers ; ni l'un ni l'autre n'est encore qualifié.
Le routeur du lab n'est qu'une configuration minimale écrite pour l'essai, pas celle des routeurs Le routeur du lab n'est qu'une configuration minimale écrite pour l'essai, pas celle des routeurs
de cluster (:doc:`routeurs`). de cluster (:doc:`routeurs`).
@ -109,9 +121,8 @@ de cluster (:doc:`routeurs`).
lancer sur n'importe quel hyperviseur), et s'il s'agit d'une VM créée par l'agent comme les lancer sur n'importe quel hyperviseur), et s'il s'agit d'une VM créée par l'agent comme les
autres ou d'un cas particulier — l'image, elle, est l'image golden de :doc:`image-qcow2` ; autres ou d'un cas particulier — l'image, elle, est l'image golden de :doc:`image-qcow2` ;
* la redondance : une seule VM route reflector, ou deux, et sur quels hyperviseurs ; * la redondance : une seule VM route reflector, ou deux, et sur quels hyperviseurs ;
* la procédure de reconstruction, et l'état du cluster pendant que le route reflector est * la procédure de reconstruction — l'état du cluster pendant l'absence du route reflector est
absent — les tunnels déjà établis continuent-ils de fonctionner, et pendant combien de mesuré ci-dessus : plus de trafic entre hyperviseurs ;
temps ;
* la procédure d'amorçage : ce qui fonctionne, et dans quel ordre, quand on démarre un cluster * la procédure d'amorçage : ce qui fonctionne, et dans quel ordre, quand on démarre un cluster
entier depuis zéro — le premier hyperviseur n'a pas de session FRR établie tant que cette VM entier depuis zéro — le premier hyperviseur n'a pas de session FRR établie tant que cette VM
n'existe pas, cf. :doc:`premier-hyperviseur`. n'existe pas, cf. :doc:`premier-hyperviseur`.

View file

@ -725,6 +725,29 @@ scénario envoie des blocs de shell aux nœuds par ``on <nœud> [VAR=valeur…]
elle n'est réussie que si le SSH vers la VM a fonctionné **et** que la commande y a échoué — un elle n'est réussie que si le SSH vers la VM a fonctionné **et** que la commande y a échoué — un
SSH en panne ne passe jamais pour une isolation. SSH en panne ne passe jamais pour une isolation.
Résultats du 2026-10-04 sur le serveur de lab, release ``0.2.0rc003``, hv1 sur le DHCP intégré et
hv2 sur dnsmasq — toute la série en 8 minutes :
.. code-block:: text
$ scripts/lab/scenario.sh all | grep -E '^(=== s[0-9].* : |INFO)'
INFO: MAC de sn-s1a : 00:22:33:00:00:0a 00:22:33:00:00:0b ; de sn-s1b : 00:22:33:00:00:0a 00:22:33:00:00:0b
=== s1-dhcp-two : 37 réussi(s), 0 échoué(s)
=== s2-gateway : 22 réussi(s), 0 échoué(s)
=== s3-isolation-local : 12 réussi(s), 0 échoué(s)
=== s4-evpn : 14 réussi(s), 0 échoué(s)
=== s5-isolation-evpn : 13 réussi(s), 0 échoué(s)
INFO: 30 s après l'arrêt du route reflector : 0 réponses dans les 10 dernières secondes (50 si le trafic passe intégralement)
INFO: VTEP distant encore connu : 0 ; entrée d'inondation : 0
INFO: 90 s après l'arrêt : 0 réponses dans les 10 dernières secondes
INFO: retour du VTEP distant et du trafic 31 s après le redémarrage de FRR
=== s6-rr-loss : 8 réussi(s), 0 échoué(s)
Dans ce run, le contrôle « uniquement les MAC de son subnet » de ``s1`` ne prouvait rien : two
dérive la MAC du rang de l'IP, et les VM ``.10``/``.11`` des deux subnets avaient les mêmes MAC.
Vérifié à la main sur le lab, chaque serveur DHCP ne connaissait que les couples MAC/IP de son
subnet ; le scénario compare désormais ces couples.
Les VM sont accessibles depuis le netns de leur VPC, sur l'hyperviseur, avec l'utilisateur Les VM sont accessibles depuis le netns de leur VPC, sur l'hyperviseur, avec l'utilisateur
``syonad`` créé par les métadonnées de two : ``syonad`` créé par les métadonnées de two :

View file

@ -146,6 +146,6 @@ while not buf.endswith(b"\n"):
break break
buf += c buf += c
state = json.loads(buf).get("state") or {} state = json.loads(buf).get("state") or {}
print(" ".join(sorted(h["mac"].lower() for h in state.get("hosts") or []))) print(" ".join(sorted(h["mac"].lower() + "=" + h["ip"] for h in state.get("hosts") or [])))
PY PY
} }

View file

@ -25,10 +25,10 @@ for vm in 10.210.1.10:10.210.1.1 10.210.1.11:10.210.1.1 10.210.2.10:10.210.2.1 1
check "${ip} : route vers la VPC via ${gw}" route_via vp-s1 "${ip}" 10.210.0.0/16 "${gw}" check "${ip} : route vers la VPC via ${gw}" route_via vp-s1 "${ip}" 10.210.0.0/16 "${gw}"
check "${ip} : route /32 vers les métadonnées via ${gw}" route_via vp-s1 "${ip}" 169.254.169.254 "${gw}" check "${ip} : route /32 vers les métadonnées via ${gw}" route_via vp-s1 "${ip}" 169.254.169.254 "${gw}"
done done
mac () { vm_ssh vp-s1 "${1}" 'cat /sys/class/net/ens3/address'; } vm_host () { echo "$(vm_ssh vp-s1 "${1}" 'cat /sys/class/net/ens3/address')=${1}"; }
A_MACS=$(printf '%s\n' "$(mac 10.210.1.10)" "$(mac 10.210.1.11)" | sort | tr '\n' ' ' | sed 's/ $//') A_HOSTS=$(printf '%s\n' "$(vm_host 10.210.1.10)" "$(vm_host 10.210.1.11)" | sort | tr '\n' ' ' | sed 's/ $//')
B_MACS=$(printf '%s\n' "$(mac 10.210.2.10)" "$(mac 10.210.2.11)" | sort | tr '\n' ' ' | sed 's/ $//') B_HOSTS=$(printf '%s\n' "$(vm_host 10.210.2.10)" "$(vm_host 10.210.2.11)" | sort | tr '\n' ' ' | sed 's/ $//')
info "MAC de sn-s1a : ${A_MACS} ; de sn-s1b : ${B_MACS}" info "sn-s1a : ${A_HOSTS} ; sn-s1b : ${B_HOSTS}"
check "probe sn-s1a : uniquement les MAC de sn-s1a" test "$(dhcp_hosts vp-s1_br-s1a)" = "${A_MACS}" check "probe sn-s1a : uniquement les couples MAC/IP de sn-s1a" test "$(dhcp_hosts vp-s1_br-s1a)" = "${A_HOSTS}"
check "probe sn-s1b : uniquement les MAC de sn-s1b" test "$(dhcp_hosts vp-s1_br-s1b)" = "${B_MACS}" check "probe sn-s1b : uniquement les couples MAC/IP de sn-s1b" test "$(dhcp_hosts vp-s1_br-s1b)" = "${B_HOSTS}"
NODE NODE