feat(ingress) : le tier en conteneur, servant sous son propre nom #24

Merged
thystips merged 2 commits from feat/ingress-container into main 2026-08-09 00:24:26 +02:00
Owner

Le proxy descend en conteneur sur les quatre nœuds. La VIP ne bouge pas : elle reste sur les nœuds, annoncée par leur Bird. Le conteneur sert sous son adresse propre, donc il est vérifiable de bout en bout pendant que rien n'en dépend.

La mesure qui a défait la décision précédente

Le plan tenait Caddy et OpenBao pour indissociables : un Caddy en conteneur ne joindrait pas un coffre resté sur le plan de management. Vrai par DN42, faux par le pont NATé — mesuré depuis un conteneur de Bordeaux :

OK    10.1.70.20:8200    ca1, à Roubaix     ← déjà autorisé par la PR #23
FAIL  10.1.242.201:8200  coffre fr-rbx1     ← notre seule règle
FAIL  10.2.242.202:8200  coffre fr-bod1

Le témoin ca1 emprunte le même chemin : même NAT, même plan privé, même site distant. Le coffre ne bouge donc pas, et le descendre redevient un sujet à part — qui coûterait un nouveau raft et un quorum dépendant de l'overlay.

Ce que le conteneur fait disparaître

Mesuré avant d'écrire une ligne : l'AC de burble répond en v6 (fd42:4242:2601:ac83::1:443), et le Knot de la zone de challenge répond en TCP/53 depuis l'autre site. Les quatre mécanismes de franchissement de VRF n'ont donc plus lieu d'être — relais 127.0.0.42, route de traversée, /etc/hosts privé, BindToDevice=. Ils sont regroupés dans tasks/vrf-crossing.yml, importé derrière un when, pour partir ensemble à la bascule.

Une propriété change avec eux : aujourd'hui un seul nœud sait résoudre le challenge dns-01, depuis un conteneur les quatre le peuvent. Le magasin partagé reste, mais pour le verrou — quatre émissions concurrentes sur un seul RRset _acme-challenge — et non plus parce que trois nœuds sur quatre n'auraient aucun certificat.

Trois conséquences

  • openbao_binary, un rôle pour le seul binaire : bao server et bao agent sont le même exécutable et ne tournent plus sur la même machine. Une version, une somme, un contrôle.
  • L'AppRole caddy-storage gagne 10.42.0.0/24 dans ses deux liaisons CIDR. Un conteneur qui interroge le coffre de son nœud présente 10.42.0.x, le trafic vers la machine elle-même n'étant pas NATé — sans cette ligne, un 403 à l'amorçage, plusieurs couches sous sa cause.
  • Les deux ancres de confiance passent dans ansible/files/ : le conteneur a besoin des deux, et aucun des rôles qui les posaient sur les nœuds n'y tourne.

Pare-feu et matrice dans le même commit : ligne 19a et ses jumelles de forward. Deux règles par service, la leçon de ca1 qui se répète.

Le sync NetBox était cassé, et depuis la PR #21

build() itérait sur les conteneurs comme sur des nœuds et s'arrêtait sur un KeyError. Vérifié sur main avant de conclure. --check n'étant pas dans le lint — délibérément — rien ne l'a dit : huit adresses DN42 vivaient hors de l'IPAM et le rôle incus manquait aux descriptions depuis la PR #20.

Les conteneurs sont modélisés plutôt que filtrés : une VM par conteneur, eth0 dans la VRF avec son adresse, eth1 décrite sans adresse — son bail vient du dnsmasq du nœud, et un IPAM qui inventerait une adresse DHCP serait faux au premier renouvellement.

Vérifié

Résultat
HTTP, nœud tiers → conteneur 302, X-Ingress-Node: fr-rbx1 — le backend LG est atteint par le NAT
HTTPS inter-site, rbx1 → conteneur de bod1 302, ssl_verify_result=0 contre la racine DN42
Empreinte du certificat, conteneur vs VIP identiques — lu dans le magasin, aucune émission
Témoin négatif : SSH d'un autre nœud depuis un conteneur toujours fermé
Second passage changed=0 sur les quatre conteneurs
Nœuds Caddy actif, VIP en place, sessions BGP établies
NetBox 32 créés, 4 mis à jour, --check à zéro

Ce qui reste, et qui n'est pas dans cette PR

La bascule elle-même : Bird dans le conteneur, la VIP, le filtre d'import — un conteneur qui parle iBGP peut injecter — l'ouverture de 80/443 vers le conteneur, et le retrait de l'ingress des hôtes. Le montage a été mesuré, routes temporaires posées puis retirées : une VIP v4 sur lo d'un conteneur v6 seul, jointe en TCP par un next-hop v6, retour compris. C'est l'extended_next_hop que l'AS impose déjà partout, appliqué au dernier saut.

⚠ Les journaux de Caddy cesseront de remonter à la bascule : un conteneur a son propre journald, et monitoring_journal_units lit celui de l'hôte.

Le proxy descend en conteneur sur les quatre nœuds. **La VIP ne bouge pas** : elle reste sur les nœuds, annoncée par leur Bird. Le conteneur sert sous son adresse propre, donc il est vérifiable de bout en bout pendant que rien n'en dépend. ## La mesure qui a défait la décision précédente Le plan tenait Caddy et OpenBao pour indissociables : un Caddy en conteneur ne joindrait pas un coffre resté sur le plan de management. Vrai **par DN42**, faux **par le pont NATé** — mesuré depuis un conteneur de Bordeaux : ``` OK 10.1.70.20:8200 ca1, à Roubaix ← déjà autorisé par la PR #23 FAIL 10.1.242.201:8200 coffre fr-rbx1 ← notre seule règle FAIL 10.2.242.202:8200 coffre fr-bod1 ``` Le témoin `ca1` emprunte le **même** chemin : même NAT, même plan privé, même site distant. Le coffre ne bouge donc pas, et le descendre redevient un sujet à part — qui coûterait un nouveau raft et un quorum dépendant de l'overlay. ## Ce que le conteneur fait disparaître Mesuré avant d'écrire une ligne : l'AC de burble répond en v6 (`fd42:4242:2601:ac83::1:443`), et le Knot de la zone de challenge répond en TCP/53 **depuis l'autre site**. Les quatre mécanismes de franchissement de VRF n'ont donc plus lieu d'être — relais `127.0.0.42`, route de traversée, `/etc/hosts` privé, `BindToDevice=`. Ils sont regroupés dans `tasks/vrf-crossing.yml`, importé derrière un `when`, pour partir ensemble à la bascule. Une **propriété** change avec eux : aujourd'hui un seul nœud sait résoudre le challenge `dns-01`, depuis un conteneur les quatre le peuvent. Le magasin partagé reste, mais pour le **verrou** — quatre émissions concurrentes sur un seul RRset `_acme-challenge` — et non plus parce que trois nœuds sur quatre n'auraient aucun certificat. ## Trois conséquences - **`openbao_binary`**, un rôle pour le seul binaire : `bao server` et `bao agent` sont le même exécutable et ne tournent plus sur la même machine. Une version, une somme, un contrôle. - **L'AppRole `caddy-storage` gagne `10.42.0.0/24`** dans ses deux liaisons CIDR. Un conteneur qui interroge le coffre de *son* nœud présente `10.42.0.x`, le trafic vers la machine elle-même n'étant pas NATé — sans cette ligne, un 403 à l'amorçage, plusieurs couches sous sa cause. - **Les deux ancres de confiance passent dans `ansible/files/`** : le conteneur a besoin des deux, et aucun des rôles qui les posaient sur les nœuds n'y tourne. Pare-feu et matrice dans le même commit : ligne 19a et ses jumelles de `forward`. **Deux règles par service**, la leçon de `ca1` qui se répète. ## Le sync NetBox était cassé, et depuis la PR #21 `build()` itérait sur les conteneurs comme sur des nœuds et s'arrêtait sur un `KeyError`. Vérifié sur `main` avant de conclure. `--check` n'étant pas dans le lint — délibérément — rien ne l'a dit : huit adresses DN42 vivaient hors de l'IPAM et le rôle `incus` manquait aux descriptions depuis la PR #20. Les conteneurs sont **modélisés** plutôt que filtrés : une VM par conteneur, `eth0` dans la VRF avec son adresse, `eth1` décrite **sans adresse** — son bail vient du dnsmasq du nœud, et un IPAM qui inventerait une adresse DHCP serait faux au premier renouvellement. ## Vérifié | | Résultat | |---|---| | HTTP, nœud tiers → conteneur | `302`, `X-Ingress-Node: fr-rbx1` — le backend LG est atteint par le NAT | | HTTPS inter-site, rbx1 → conteneur de bod1 | `302`, `ssl_verify_result=0` contre la racine DN42 | | Empreinte du certificat, conteneur vs VIP | **identiques** — lu dans le magasin, aucune émission | | Témoin négatif : SSH d'un autre nœud depuis un conteneur | toujours fermé | | Second passage | `changed=0` sur les quatre conteneurs | | Nœuds | Caddy actif, VIP en place, sessions BGP établies | | NetBox | 32 créés, 4 mis à jour, `--check` à zéro | ## Ce qui reste, et qui n'est pas dans cette PR La bascule elle-même : Bird dans le conteneur, la VIP, le filtre d'import — un conteneur qui parle iBGP peut injecter — l'ouverture de 80/443 vers le conteneur, et le retrait de l'ingress des hôtes. Le montage a été mesuré, routes temporaires posées puis retirées : une VIP **v4** sur `lo` d'un conteneur **v6 seul**, jointe en TCP par un next-hop v6, retour compris. C'est l'`extended_next_hop` que l'AS impose déjà partout, appliqué au dernier saut. ⚠ Les journaux de Caddy cesseront de remonter à la bascule : un conteneur a son propre `journald`, et `monitoring_journal_units` lit celui de l'hôte.
Le proxy descend en conteneur. Ce commit l'y installe et l'y fait servir ; il ne
touche PAS à la VIP anycast, qui reste sur les nœuds — la descendre est un
changement de routage, avec un Bird dans le conteneur et un filtre d'import, et
ça vaut son propre changement.

CE QUI A DÉFAIT LA DÉCISION PRÉCÉDENTE. Le plan tenait Caddy et OpenBao pour
indissociables : un Caddy en conteneur ne joindrait pas un coffre resté sur le
plan de management. C'était vrai par DN42 et faux par le pont NATé, mesuré depuis
un conteneur de Bordeaux —

    OK    10.1.70.20:8200    ca1, à Roubaix        ← déjà autorisé (PR #23)
    FAIL  10.1.242.201:8200  coffre fr-rbx1        ← notre seule règle
    FAIL  10.2.242.202:8200  coffre fr-bod1

— le témoin `ca1` empruntant le MÊME chemin. Le coffre ne bouge donc pas, et
descendre OpenBao redevient un sujet à part.

CE QUE LE CONTENEUR FAIT DISPARAÎTRE, mesuré avant d'écrire quoi que ce soit :
l'AC de burble répond en v6 (`fd42:4242:2601:ac83::1:443`), et le Knot de la zone
de challenge répond en TCP/53 depuis l'AUTRE site. Les quatre mécanismes de
franchissement de VRF n'ont donc plus lieu d'être dans un conteneur — relais
`127.0.0.42`, route de traversée, `/etc/hosts` privé, `BindToDevice=`. Ils sont
regroupés dans `tasks/vrf-crossing.yml`, importé derrière un `when`, pour partir
ensemble.

Et une propriété change avec eux : aujourd'hui un seul nœud sait résoudre le
challenge `dns-01`, depuis un conteneur les QUATRE le peuvent. Le magasin partagé
reste, mais pour le VERROU — quatre émissions concurrentes sur un seul RRset
`_acme-challenge` — et non plus parce que trois nœuds sur quatre n'auraient aucun
certificat.

Le conteneur écoute sur SON adresse (`<services /64>:🅱️<id>`) et non sur la VIP :
il est ainsi vérifiable de bout en bout pendant que rien n'en dépend. C'est aussi
ce que fait Knot en écoutant sur sa loopback à côté de l'anycast.

Trois choses en découlent :

- `openbao_binary`, un rôle pour le seul binaire. `bao server` et `bao agent` sont
  le même exécutable et ne tournent plus sur la même machine : l'agent part avec
  Caddy. Une version, une somme, un contrôle.
- L'AppRole `caddy-storage` gagne `10.42.0.0/24` dans ses deux liaisons CIDR. Un
  conteneur qui interroge le coffre de SON nœud présente `10.42.0.x`, le trafic
  vers la machine elle-même n'étant pas NATé — sans cette ligne, un 403 à
  l'amorçage, plusieurs couches sous sa cause.
- Les deux ancres de confiance passent dans `ansible/files/` : le conteneur a
  besoin des deux, et aucun des rôles qui les posaient sur les nœuds n'y tourne.

Pare-feu et matrice dans le même commit : lignes 19a (coffre et frontal LG du nœud
lui-même) et leurs jumelles de `forward` pour les trois autres. Deux règles par
service, la leçon de `ca1` qui se répète. Vérifié sur les quatre nœuds, avec le
SSH d'un autre nœud comme témoin négatif — toujours fermé.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FGwvXLVXJ2PrRFwJTB3Xp9
Depuis que les conteneurs sont des hôtes d'inventaire (PR #21), `build()` itérait
dessus comme sur des nœuds et s'arrêtait sur un `KeyError: 'dn42_site'`. Le sync
était donc CASSÉ depuis hier, et rien ne l'a dit : `--check` n'est pas dans
`./.ci/lint.sh`, délibérément, parce qu'il demande le réseau et un token.

C'est exactement le mode de panne contre lequel le README du dépôt met en garde.
Pendant ce temps huit adresses DN42 étaient attribuées sans figurer dans l'IPAM,
et le rôle `incus` manquait à la description des quatre nœuds depuis la PR #20.

Les conteneurs sont donc modélisés plutôt que filtrés : une VM par conteneur dans
le cluster de son site, `eth0` dans la VRF avec son adresse, et `eth1` DÉCRITE
SANS ADRESSE — son bail vient du dnsmasq du nœud, et un IPAM qui inventerait une
adresse DHCP serait faux au premier renouvellement.

Le rôle NetBox `dn42` est réutilisé plutôt qu'un rôle inventé : le sync n'a pas le
droit d'en créer un, et la description dit ce que la machine est.

Après application : 32 objets créés, 4 mis à jour, `--check` à zéro.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FGwvXLVXJ2PrRFwJTB3Xp9
thystips deleted branch feat/ingress-container 2026-08-09 00:24:26 +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!24
No description provided.