chore(ingress) : la moitié « nœud » du rôle s'en va, et avec elle la dernière exception d'output #34

Merged
thystips merged 1 commit from chore/ingress-node-half-removal into main 2026-08-11 23:46:41 +02:00
Owner

Le tier d'ingress est en conteneur depuis la PR #25. Le rôle avait gardé de quoi tourner sur un nœud et de quoi s'en retirer ; les quatre nœuds étant basculés, les deux n'ont plus d'objet.

C'était un reliquat « en attente », c'est devenu un prérequis : tasks/vrf-crossing.yml s'accroche à la traversée xvrf-glb que l'étape suivante — le résolveur en conteneur — vient supprimer.

Ce qui part

Quatre mécanismes qui n'existaient que parce qu'un proxy en table globale n'a pas de pied dans la VRF :

  • le relais systemd-socket-proxyd vers l'AC ACME, sur 127.0.0.42:443, sous ip vrf exec ;
  • le /etc/hosts privé monté dans la seule unité caddy, qui y détournait le nom de l'AC ;
  • la route de traversée xvrf-glb vers le Knot de la zone de challenge ;
  • BindToDevice= sur la socket d'écoute.

Plus ingress_on_node, tasks/teardown.yml, l'entrée ingress: caddy de network_anycast_owners, et le rôle ingress du play des nœuds.

⚠ Ce qui n'était pas prévu : une ouverture de pare-feu vivante pour un usage mort

L'exception ACME d'outputla seule exception au garde-fou anti-fuite de tout le jeu de règles — avait sa garde écrite sur dn42_roles.ingress. Ce drapeau a changé de sens à la PR #25 : il voulait dire « ce nœud fait tourner le proxy », il veut dire « ce nœud héberge le conteneur du proxy ». La condition, elle, n'a pas suivi, et la règle a continué de se rendre quatre jours sur les quatre nœuds pour un Caddy absent.

La chaîne output est maintenant réduite à ses deux garde-fous, sans une seule exception.

⚠ Et un défaut latent dans network, de la même famille

Le handler « Put back the anycast addresses that the reconfigure stripped » bouclait sur dn42_anycast, qui liste ce que le nœud annonce — y compris les services qu'un conteneur sert. Retirer ingress: caddy de la map l'aurait fait échouer sur un KeyError ; le garder laissait une entrée désignant une unité absente de la machine.

Le vrai risque est au-delà : rien n'empêchait ce handler de créer la VIP sur lo-dn42 d'un nœud où plus rien n'écoute, que Bird aurait aussitôt annoncée. Un trou noir anycast né d'un handler censé réparer.

L'assert qui contrôle et le handler qui agit lisent désormais la même liste filtrée, network_anycast_local — un fait et non deux expressions écrites deux fois.

La preuve du rendu

git worktree sur main, le même script de rendu des deux côtés, diff -ru :

  • nftables, les 4 nœuds : le seul changement est le bloc de l'exception ACME. Rien d'autre ne bouge d'une ligne.
  • les 3 fichiers du conteneur d'ingress : identiques hors commentaires.

Ce second point a une conséquence de déploiement : caddy.socket change quand même (commentaires), donc socket puis service redémarrent, donc la VIP bat. D'où un conteneur à la fois.

Le déroulé

Fait sur les 12 machines. Sur les quatre nœuds : ACME=0, la VIP d'ingress absente de lo-dn42, output sans exception, résolveur et proxy qui répondent. Sur les quatre conteneurs : Caddy actif, VIP sur lo, route préférée cnt_ingress (préférence 200) en v4 et en v6, HTTP et HTTPS à 302.

X-Ingress-Node a montré fr-bod1 depuis fr-bod2 juste après son déroulé — pas un défaut, la bascule anycast en train de faire son travail le temps que la session iBGP du conteneur revienne.

Au passage

Le README du rôle portait encore deux sections décrivant caddy.storage.swytch, remplacé le 07/08 — dont ses trois modes de panne, présentés comme ceux du module actuel. Regroupés et datés plutôt que supprimés : la leçon (« un magasin de certificats se juge sur ce qu'il fait quand un pair manque ») survit au module.

Ce qui part est le code, pas la mémoire de ce qu'il a coûté : les quatre mécanismes gardent leur explication dans les defaults du rôle, dans son README et dans flow-matrix.md.

Le tier d'ingress est en conteneur depuis la PR #25. Le rôle avait gardé de quoi tourner sur un nœud et de quoi s'en retirer ; les quatre nœuds étant basculés, les deux n'ont plus d'objet. C'était un reliquat « en attente », c'est devenu un **prérequis** : `tasks/vrf-crossing.yml` s'accroche à la traversée `xvrf-glb` que l'étape suivante — le résolveur en conteneur — vient supprimer. ## Ce qui part Quatre mécanismes qui n'existaient que parce qu'un proxy en table globale n'a pas de pied dans la VRF : - le relais `systemd-socket-proxyd` vers l'AC ACME, sur `127.0.0.42:443`, sous `ip vrf exec` ; - le `/etc/hosts` privé monté dans la seule unité `caddy`, qui y détournait le nom de l'AC ; - la route de traversée `xvrf-glb` vers le Knot de la zone de challenge ; - `BindToDevice=` sur la socket d'écoute. Plus `ingress_on_node`, `tasks/teardown.yml`, l'entrée `ingress: caddy` de `network_anycast_owners`, et le rôle `ingress` du play des nœuds. ## ⚠ Ce qui n'était pas prévu : une ouverture de pare-feu vivante pour un usage mort L'exception ACME d'`output` — **la seule exception au garde-fou anti-fuite de tout le jeu de règles** — avait sa garde écrite sur `dn42_roles.ingress`. Ce drapeau a **changé de sens** à la PR #25 : il voulait dire « ce nœud fait tourner le proxy », il veut dire « ce nœud héberge le conteneur du proxy ». La condition, elle, n'a pas suivi, et la règle a continué de se rendre quatre jours sur les quatre nœuds pour un Caddy absent. La chaîne `output` est maintenant réduite à ses deux garde-fous, **sans une seule exception**. ## ⚠ Et un défaut latent dans `network`, de la même famille Le handler « Put back the anycast addresses that the reconfigure stripped » bouclait sur `dn42_anycast`, qui liste ce que le nœud **annonce** — y compris les services qu'un **conteneur** sert. Retirer `ingress: caddy` de la map l'aurait fait échouer sur un `KeyError` ; le garder laissait une entrée désignant une unité absente de la machine. Le vrai risque est au-delà : rien n'empêchait ce handler de **créer** la VIP sur `lo-dn42` d'un nœud où plus rien n'écoute, que Bird aurait aussitôt annoncée. **Un trou noir anycast né d'un handler censé réparer.** L'assert qui **contrôle** et le handler qui **agit** lisent désormais la même liste filtrée, `network_anycast_local` — un fait et non deux expressions écrites deux fois. ## La preuve du rendu `git worktree` sur `main`, le même script de rendu des deux côtés, `diff -ru` : - **nftables, les 4 nœuds** : le seul changement est le bloc de l'exception ACME. Rien d'autre ne bouge d'une ligne. - **les 3 fichiers du conteneur d'ingress** : identiques **hors commentaires**. Ce second point a une conséquence de déploiement : `caddy.socket` change quand même (commentaires), donc socket puis service redémarrent, donc la VIP bat. D'où un conteneur à la fois. ## Le déroulé Fait sur les 12 machines. Sur les quatre nœuds : `ACME=0`, la VIP d'ingress absente de `lo-dn42`, `output` sans exception, résolveur et proxy qui répondent. Sur les quatre conteneurs : Caddy actif, VIP sur `lo`, route préférée `cnt_ingress` (préférence 200) en v4 **et** en v6, HTTP et HTTPS à 302. ⚠ `X-Ingress-Node` a montré `fr-bod1` depuis `fr-bod2` juste après son déroulé — **pas un défaut**, la bascule anycast en train de faire son travail le temps que la session iBGP du conteneur revienne. ## Au passage Le README du rôle portait encore **deux sections décrivant `caddy.storage.swytch`**, remplacé le 07/08 — dont ses trois modes de panne, présentés comme ceux du module actuel. Regroupés et datés plutôt que supprimés : la leçon (« un magasin de certificats se juge sur ce qu'il fait quand un pair manque ») survit au module. Ce qui part est le **code**, pas la mémoire de ce qu'il a coûté : les quatre mécanismes gardent leur explication dans les defaults du rôle, dans son README et dans `flow-matrix.md`.
Le tier d'ingress est en conteneur depuis la PR #25. Le rôle avait gardé de quoi
tourner sur un nœud et de quoi s'en retirer : les quatre nœuds étant basculés, les
deux n'ont plus d'objet.

Ce qui part avec — quatre mécanismes qui n'existaient que parce qu'un proxy en table
globale n'a pas de pied dans la VRF :

  - le relais `systemd-socket-proxyd` vers l'AC ACME sur 127.0.0.42:443 ;
  - le /etc/hosts privé monté dans la seule unité caddy, qui y détournait le nom ;
  - la route de traversée `xvrf-glb` vers le Knot de la zone de challenge ;
  - `BindToDevice=` sur la socket d'écoute.

⚠ ET UNE OUVERTURE DE PARE-FEU VIVANTE POUR UN USAGE MORT. L'exception ACME
d'`output` — la SEULE exception au garde-fou anti-fuite de tout le jeu de règles —
avait sa garde écrite sur `dn42_roles.ingress`, un drapeau qui a CHANGÉ DE SENS : il
dit maintenant « ce nœud héberge le conteneur du proxy ». Une condition écrite avec un
drapeau ne suit pas le drapeau quand celui-ci se met à parler d'autre chose, et la
règle a continué de se rendre sur les quatre nœuds pour un Caddy absent.

⚠ ET UN DÉFAUT LATENT DANS `network`. Le handler qui repose les adresses anycast après
un `networkctl reconfigure` bouclait sur `dn42_anycast`, qui inclut les services
qu'un conteneur sert. Retirer `ingress: caddy` de `network_anycast_owners` l'aurait
fait échouer ; le garder aurait laissé une entrée désignant une unité absente. Les
deux — l'assert qui CONTRÔLE et le handler qui AGIT — lisent désormais la même liste
filtrée, `network_anycast_local`. Sans ce filtre, le handler aurait pu CRÉER la VIP
sur un nœud où rien ne l'écoute, et Bird l'aurait annoncée : un trou noir anycast né
d'un handler censé réparer.

Le rendu prouvé plutôt que supposé, sur les quatre nœuds : le jeu de règles nftables
ne perd QUE le bloc de l'exception ACME, et les trois fichiers du conteneur d'ingress
sont identiques hors commentaires.

Le README du rôle garde ce que ces mécanismes ont coûté — c'est le code qui part, pas
la mémoire. Deux sections y décrivaient encore `caddy.storage.swytch`, remplacé le
07/08 : ses trois modes de panne sont regroupés et datés au lieu de flotter sous un
titre qui parle du module actuel.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FGwvXLVXJ2PrRFwJTB3Xp9
thystips deleted branch chore/ingress-node-half-removal 2026-08-11 23:46:41 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ThysTips_dn42/infra-dn42!34
No description provided.