Deux Directions de Traffic, Un Boîtier
Bienvenue
La plupart des diagrammes d'architecture montrent le traffic allant dans une seule direction : le client en haut, le serveur en bas, une flèche pointant vers le bas. La réalité implique que le traffic va dans les deux directions.
Ingress : les clients extérieurs atteignent vos services par ce chemin. Un proxy inverse à l'extrémité de votre réseau termine le TLS, route les demandes et applique la politique d'accès.
Egress : vos services atteignent les services externes par ce chemin. Appel d'un processeur de paiement API, récupération d'un webhook cible, envoi d'une demande vers un partenaire. Souvent via un proxy forward ou un pont NAT avec une liste autorisée.
De nombreuses architectures commencent avec un boîtier gérant les deux. Cela fonctionne, jusqu'au jour où cela ne le fait plus. Le mode de panne est subtil, ne se manifeste que lorsque suffisamment de services internes existent, et enseigne une leçon importante sur la séparation des préoccupations.
Au terme de cette leçon, vous comprendrez :
- Pourquoi l'ingress et l'egress représentent des modèles de traffic fondamentalement différents avec des axes de mise à l'échelle et des modes de panne différents
- L'NAT en boucle et pourquoi un proxy qui tente de se connecter à lui-même échoue
- Le détachement architectural : un boîtier devient deux, et ce que chacun possède ensuite exclusivement
- Les gains d'isolement de sécurité : chaque côté peut verrouiller à ses véritables pairs autorisés
- Comment identifier lorsque votre conception mono-boîtier a franchi le seuil où la division est nécessaire
Pourquoi Les Directions Exigent Des Outils Différents
Deux Charges de Travail Différentes à Un Seul Point de Réseau
Caractéristiques du traffic d'ingress :
- Initié par des parties extérieures (l'Internet en général)
- Volume qui s'accumule avec votre base d'utilisateurs
- Termine TLS, routage des demandes, limitation des débits par source
- Préoccupations de défense en profondeur : DDoS, abus, rassemblement
- L'IP publique doit accepter les connexions de n'importe qui
Caractéristiques du traffic d'egress :
- Initié par vos propres services (un ensemble connu et restreint de clients)
- Volume qui s'accumule avec les modèles d'appel service-à-service et API externe
- Liste d'autorisation des adresses IP source sur les points de terminaison distants (vous avez une IP sortante fixe que les partenaires acceptent)
- Préoccupations concernant la profondeur de la défense : exfiltration de données, services internes compromis appelant à l'extérieur
- Les connexions devraient être refusées provenant de toute autre source que vos propres services
L'asymétrie clé : l'ingress accepte le trafic du monde ; l'egress accepte le trafic uniquement de vos propres services. Mettre les deux sur la même machine signifie que cette machine doit être accessible à la fois du monde entier (pour l'ingress) & uniquement accessible de vos services (pour l'egress). Les règles de pare-feu qui satisfont l'un contrecarrent l'autre.
La voie de croissance : un petit projet peut cacher les deux derrière une IP et une seule boîte outil, car le volume est faible et la liste d'IP des partenaires est courte. À mesure que le projet grandit, la friction entre les deux rôles augmente et un jour un mode de rupture spécifique (NAT en collier) oblige à les séparer.
La faille qui oblige à la séparation
Une histoire de défaillance sanitaire
Imaginez une bifurcation architecturale réelle qui se produit dans les flottes de production. Les noms ci-dessous ont été changés ; la forme est identique à celle que les équipes rencontrent dans la nature.
Une organisation exécute un serveur proxy unique à 203.0.113.5. Il gère l'ingress (port 443 pour les utilisateurs) et l'egress (port 1080 SOCKS5 pour les services internes appelant à l'extérieur). Les services internes vivent dans des sous-réseaux privés et routent tous les flux sortants à travers ce proxy SOCKS5 sur 203.0.113.5:1080.
L'un des services hébergés derrière le même 203.0.113.5 est api.example.com. Le DNS public résout api.example.com vers 203.0.113.5.
Or, un autre service interne doit appeler api.example.com. Son chemin sortant :
1. Le service interne résout api.example.com vers 203.0.113.5
2. Le service interne envoie la requête à travers le proxy SOCKS5 egress à 203.0.113.5:1080
3. Le proxy tente d'ouvrir une connexion à partir de lui-même vers 203.0.113.5:443
4. Refus de connexion. Le paquet devrait sortir et réentrer dans le même NAT, ce que la plupart des stacks de réseaux rejettent. Le proxy ne peut pas se connecter à lui-même via son propre IP public.
Ceci est le NAT en boucle: un paquet qui quitte un NAT et doit réentrer dans le même NAT pour rejoindre son destinataire. Sans un support spécifique du routage en boucle, le paquet est perdu.
Pourquoi Il Apparaît Tardivement
Au début du projet, chaque service interne communiquait soit avec d'autres services internes par l'hostname privé (internal-api.local) ou ne faisait pas appel aux services publics de son propre organisation. La voie en boucle n'existait pas.
Puis une nouvelle fonctionnalité a nécessité que le service A appelle api.example.com (un hostname public). La voie en boucle s'est activée. Refus de la connexion. Panne.
La correction a calmé les symptômes (forcer le résolveur à donner l'IP privée de api.example.com au lieu de l'IP publique). La cause racine : une seule boîte faisait trop de jobs.
La Fourchette Architecturale
Une Boîte Devient Deux
La solution de nettoyage : séparer le proxy en deux machines.
Serveur d'ingress (IP publique 203.0.113.5):
- Caddy / proxy inverse sur les ports 80, 443
- Les enregistrements DNS publics pointent vers ici
- Héberge api.example.com, app.example.com, etc.
Serveur d'egress (une autre IP publique 203.0.113.99):
- SOCKS5 / proxy forward sur le port 1080
- Le pare-feu limite les connexions entrantes aux seules IP du sous-réseau interne
- Les services internes routent toutes les connexions sortantes vers cette adresse
Ce que cela achète:
1. Résolu le chevauchement. Un service interne appelant api.example.com route vers l'extérieur via 203.0.113.99 (egress), qui se connecte ensuite normalement à 203.0.113.5 (ingress, une autre IP). L'ensemble boucle disparaît car les deux IPs vivent sur des machines différentes.
2. Isolement de sécurité. Le serveur egress peut verrouiller le pare-feu sur un petit ensemble d'IP internes. Le serveur d'ingress garde ouvert au monde entier. Deux ensembles de règles, chacun exprimant clairement un rôle.
3. Échelle indépendante. La bande passante d'ingress s'échelle avec les utilisateurs ; la bande passante d'egress s'échelle avec l'activité des services internes. Mettre à niveau l'un sans toucher à l'autre.
4. Isolement des pannes. Un serveur egress mal configuré ne brise plus le site public. Un DDoS contre le site public ne prive plus la bande passante d'egress.
5. Modèle mental plus clair. Chaque machine a un seul job. Les ingénieurs raisonnent sur les préoccupations d'ingress sans penser à l'egress, et vice versa.
Deux axes, deux décisions de dimensionnement
Échelle indépendante
Avant la coupure, la croissance dans n'importe quelle direction mettait sous pression la même machine. Après la coupure, chaque direction a sa propre provisionnement.
Dimensionnement de l'ingress : s'ajuste avec les utilisateurs. Les décisions de capacité se trouvent dans le niveau public (plus de replicas de reverse proxy, VM plus grandes, CDN devant). Budget de bande passante calculé en fonction du trafic utilisateur au pic.
Dimensionnement de l'egress : s'ajuste avec les appels service-externe-API. Souvent dominé par la livraison de webhooks, les appels aux processeurs de paiement ou les récupérations de données tierces. Budget de bande passante calculé en fonction des modèles de appel internes.
Isolement des pannes : un DDoS contre l'ingress public ne mange plus la bande passante egress (ces appels aux processeurs de paiement passent quand même). Une chute de proxy egress ne prend plus en charge le site public (les utilisateurs continuent d'atteindre le site ; seulement les appels externes en sortie échouent).
SLA différents : la disponibilité de l'ingress compte pour les utilisateurs (panne visible du site) ; la disponibilité de l'egress compte pour les opérateurs (échecs de fond qui peuvent prendre plus de temps à détecter). Chaque côté peut avoir son propre SLA.
Plusieurs serveurs egress
Une fois que le rôle egress est sa propre machine, le prochain mouvement évident est de faire tourner plusieurs machines egress derrière un équilibreur de charge pour la HA. Chaque nouveau service interne pointe vers le nom d'hôte egress (qui se résout sur la piscine équilibrée par charge) plutôt qu'à une IP unique.
Même leçon que pour le reste des systèmes distribués : une fois qu'un niveau est sans état et a son propre rôle, il se multiplie facilement.
Une nouvelle intégration de partenaire
Votre organisation met en œuvre la coupure ingress / egress comme conçue. Le serveur egress a une IP publique fixe (203.0.113.99) que vous avez allowlistée avec trois APIs de partenaires existants (un processeur de paiement, une passerelle SMS, un fournisseur d'email).
Un équipe de produit souhaite ajouter une quatrième intégration : un système de livraison de webhooks qui appelle les points de terminaison clients à travers le monde. Prévision de volume : 10 000 appels par minute, avec des pics à 30 000.
Concevez un réseau pour un service en croissance
Synthèse
Vous avez appris pourquoi l'ingress et l'egress nécessitent des outils différents, l'échec de la NAT hairpin qui oblige à séparer réellement les flottes, et comment la mise en place de la séparation apporte une échelle indépendante, un isolement de sécurité et un isolement des pannes.
Appliquez les quatre.
Une PME SaaS de taille moyenne gère trois sous-domaines de produit pour leurs utilisateurs (app, api, admin) ainsi que quatre intégrations de sortie (Stripe, Twilio, SendGrid, un système de webhooks pour les clients). Tous les éléments sont actuellement hébergés derrière une seule machine proxy avec une IP publique. Ils ont commencé à recevoir des rapports de pannes hairpin intermittentes lorsquels services internes tentent d'appeler api.example.com. Ils souhaitent concevoir une solution pérenne.
Où ce cours va à la prochaine
Où ce cours va à la prochaine
Vous avez maintenant vu l'un des refactorages de séparation des préoccupations les plus propres dans les systèmes distribués : une boîte devient deux, chacune avec un rôle clair, et le système hérite de bénéfices d'échelle, de sécurité et d'isolement des pannes au fil du temps.
La prochaine leçon (cs_distsys_failure_modes_and_blast_radius) étend le raisonnement sur l'isolement des pannes. Vous lirez un post-mortem DNS-SERVFAIL sanitarisé, identifierez le modèle de perte cascadiée et écrirez des actions sans faute qui ciblent les systèmes plutôt que les personnes.
Leçon complémentaire: geometry_of_ingress_egress_separation reformule la division en tant qu'ensemble de graphes bipartites et explore les sommets de coupure, les partitions de réseau et ce que la théorie des graphes vous dit sur une frontière de réseau.
Bien fait. En avant.