Architecture¶
Ce document explique les choix et leur raison. Pour l'inventaire des ressources
Scaleway, les ports et les couts : docs/infrastructure.md. Pour le cycle de vie
et les pannes connues : docs/operations.md. Pour le filtre de challenge :
docs/proxy.md.
Chaine de trafic¶
Internet
|
| DNS : edge.exemple.fr -> IP publique du worker Elastic Metal
v
+-----------------------------------------------------------+
| Worker Elastic Metal (EM-A116X-SSD, fr-par-1) |
| |
| Cilium en mode NodePort (plage restreinte 80,443) |
| | |
| v |
| Passerelle Istio (Gateway API, GatewayClass "istio") |
| | TLS termine, cert-manager fournit le certificat |
| | |
| | [filtre de challenge, si actif] |
| | 403 + page de preuve de travail, puis clearance |
| v |
| HTTPRoute -> Service -> origines |
+-----------------------------------------------------------+
^ ^
| UDP 51871 (maillage WireGuard) | etcd 2379/2380
| TCP 10250, 6443 | API 6443
| |
+----------------------------------+ |
| 3 x instances Scaleway |--+
| control plane Talos |
| (etcd, kube-apiserver, istiod) |
| pare-feu Scaleway restrictif |
+----------------------------------+
Le trafic du control plane est en mTLS, genere par Talos : etcd, kube-apiserver, kubelet et apid. Ce qui n'est pas chiffre par defaut, c'est le trafic pod-a-pod : c'est le role de l'encryption WireGuard de Cilium.
Pourquoi le filtre de challenge est dans le proxy du bord¶
Le filtre est un module Proxy-WASM charge par le proxy d'Istio, pas un service a part. Trois consequences voulues :
- L'origine ne voit jamais le trafic non qualifie. Le 403 et la page de challenge partent du bord, avant le routage vers l'origine. Un robot qui ne resout pas la preuve consomme du calcul du bord, mais aucune ressource de l'application.
- Pas de saut reseau supplementaire. Le filtre tourne dans le processus du proxy : il n'ajoute ni appel reseau, ni latence de service tiers, ni piece logicielle de plus a surveiller.
- Le filtre suit le sort de la passerelle. Il se pose par une ressource
WasmPlugin, donc il est declare, versionne et detruit avec le reste de la couche de bord.
Deux choix a connaitre. La phase est AUTHN, donc le filtre s'execute avant
l'authentification : un robot qui ne paie pas sa preuve de travail est arrete tot,
et l'application peut poser ses propres controles derriere sans les voir
contournes. Et failStrategy vaut FAIL_OPEN : si le module panique ou ne se
charge pas, le trafic passe. Pour un filtre anti-robot, c'est le bon compromis,
parce qu'une panne du filtre ne doit pas devenir une panne de service. Le prix
est qu'un chargement rate se traduit par une protection absente et non par une
alerte ; la sante du filtre se surveille donc a part.
Composants et versions¶
Tout est pinne, et chaque version est declaree a un seul endroit. C'est ce qui
rend un apply reproductible et une montee de version intentionnelle.
Infrastructure et systeme (tofu/infra, tofu/platform)
- Talos
v1.13.11, blocage explique dansdocs/infrastructure.md. - Kubernetes : la version que Talos embarque,
kubernetes_version = nullpar defaut, donc pas de divergence possible entre l'image et le cluster. - OpenTofu
>= 1.9; providers :scaleway2.87.0,talos0.12.0,alekc/kubectl2.4.1,hashicorp/helm,hashicorp/random,hashicorp/local,hashicorp/null.
Composants du cluster (tofu/platform/variables.tf)
- Cilium
1.20.3, en chart Helm, valeurs dansvalues/cilium.yaml.tftpl. - CRD de l'API Gateway
v1.4.0, bundle versionne dansk8s/crds/gateway-api-v1.4.0.yamlet jamais telecharge a l'apply. - cert-manager
v1.21.2, installe avec le support de l'API Gateway pour que le defi HTTP-01 passe par unHTTPRoute. - Istio
1.30.6, en deux temps :istio/basepuisistiod.
Bord (tofu/edge)
- GatewayClass
istio, declaree a la main : niistio/baseniistiodne la creent, verifie sur 1.30.6. Sans elle, unGatewayest ignore en silence. - ClusterIssuer Let's Encrypt, serveur staging par defaut : c'est volontaire, pour ne pas consommer de quota de production pendant les essais. A basculer en production avant toute mise en service.
- Filtre de challenge Proxy-WASM, facultatif,
pow_enabled = false.
Trois couches, trois states¶
tofu/infra machines Scaleway + cluster Talos (API Scaleway, talosctl)
tofu/platform CNI, CRD Gateway API, cert-manager, Istio (API Kubernetes)
tofu/edge passerelle, routes, exposition (API Kubernetes)
Le decoupage repond a un probleme concret : une ressource dont le CRD est cree
dans le meme cycle ne peut pas etre declaree avec kubernetes_manifest, qui
resout le schema OpenAPI au moment du plan. La couche plateforme installe donc
les CRD avec alekc/kubectl, et la couche edge declare les objets qui s'en
servent, sur un cluster ou ces types existent deja.
Deux consequences utiles : un tofu apply sur les add-ons ne touche jamais aux
serveurs, et la couche edge se rejoue seule quand on itere sur les noms, les
routes ou les certificats. Aucune couche ne lit le state d'une autre : l'infra
ecrit talos/_out/platform-inputs.json, les deux autres le lisent.
Ce qui reste imperatif, et pourquoi¶
Trois operations n'ont pas d'equivalent declaratif :
- le
ddde l'image Talos sur l'Elastic Metal, parce que Scaleway n'accepte qu'unos-idde son catalogue et refuse toute image personnalisee ; - le telechargement de l'image qcow2, plusieurs centaines de Mo, qui n'a rien a faire dans un state ;
- la premiere application de la configuration Talos, parce qu'un noeud en mode
maintenance a un certificat auto-signe et que le provider n'expose pas
--insecure.
Chacune est isolee dans un null_resource dont les declencheurs sont des
hachages, donc rejouable sans effet de bord. Tout le reste est dans le state.
Pourquoi Talos plutot qu'une distribution classique¶
Aucun acces shell, image immuable, configuration declarative par API. Sur un
point de presence exposes a Internet, la surface d'attaque du systeme
d'exploitation est plus faible, et surtout il n'y a rien a configurer a la main
qui puisse diverger du depot. Les patchs dans talos/patches/ sont partages
entre OpenTofu et talosctl : une seule source de verite.
Pourquoi Cilium plutot qu'un CNI plus le kube-proxy¶
Trois fonctions sont demandees au meme endroit :
- remplacement de kube-proxy : le service est resolu dans le datapath eBPF, sans iptables, ce qui tient la charge sur un point de presence ;
- encryption WireGuard : chiffrement transparent du trafic inter-noeuds, avec un cout CPU mesurable mais faible ;
- mode pare-feu : politiques L3/L4/L7 par endpoint, plus un host firewall qui protege les noeuds eux-memes.
Talos documente explicitement que KubeSpan et les configurations Cilium avancees ne cohabitent pas : Cilium attend que le trafic inter-noeuds passe par l'interface primaire, KubeSpan l'intercepte, et le routage devient asymetrique. Ce depot utilise donc Cilium WireGuard et pas KubeSpan.
Pourquoi Istio en API Gateway¶
L'API Gateway de Kubernetes remplace les Ingress. Sur un edge, elle apporte
trois choses que l'Ingress n'a pas : des listeners typés (HTTP, HTTPS, TLS passthrough),
des references de certificats par listener, et un modele de rattachement des
routes explicite par parentRefs et sectionName. Istio fournit
l'implementation, avec un controleur de deploiement qui cree lui-meme le
Deployment et le Service derriere chaque Gateway.
Le choix de sectionName dans les routes est volontaire : plusieurs listeners
partagent le port 443, et sans section explicite une route peut atterrir sur le
mauvais.
Pourquoi cert-manager en HTTP-01 par la passerelle¶
Le defi HTTP-01 ne demande aucun credential DNS, contrairement au DNS-01 : rien a stocker, rien a fuiter. Il exige en revanche que le port 80 standard soit joignable, ce qui impose la plage NodePort restreinte cote Cilium.
Limite a connaitre : HTTP-01 ne delivre pas de certificat wildcard. C'est pourquoi deux listeners HTTPS distincts portent chacun leur nom et leur certificat, au lieu d'un wildcard.
Ce que ce POC ne couvre pas¶
- Absorption volumetrique : l'anti-DDoS de Scaleway est en amont, hors de portee de la machine, et il n'y a ni anycast ni BGP ici. Un seul prefixe, une seule IP par noeud.
- Performance de production : le Xeon E3-1220 de l'A116XSSD saturera avant le
lien de 500 Mbps sur des petites requetes. Les chiffres mesures decrivent
cette machine, pas l'architecture. Pour un chiffre exploitable, une
EM-B130E-NVMe(EPYC 4245P, 3 Gbps) sur une journee suffit. - Haute disponibilite du bord : un seul worker signifie un point unique de defaillance pour le trafic de bord. Le control plane est tolerant aux pannes, pas la passerelle.
- Acceleration XDP : non mesurable avec un seul worker, voir le README.