Guide de conception des listeners Envoy Gateway : patterns multi-port, multi-hostname et multi-ingress
Beaucoup de gens qui apprennent Gateway API traitent Listener comme "ah oui, c'est juste le champ port: 80."
Mais dans les déploiements réels, Listener est loin d'être un figurant : c'est plutôt le centre de contrôle du trafic pour toute votre couche d'entrée.
Un listener ne se contente pas d'ouvrir un port. Il définit :
- Quel protocole accepter
- Quel hostname accepter
- S'il faut effectuer TLS
- Quels types de routes sont autorisés à s'attacher
Autrement dit, un listener est un contrat d'entrée. Écrivez des contrats propres, et les routes en aval, la répartition des responsabilités d'équipe et la complexité du débogage deviennent plus propres elles aussi.
Construire le bon modèle mental : un listener = un slot d'entrée
Prenez ce Gateway :
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: eg
spec:
gatewayClassName: eg
listeners:
- name: http
protocol: HTTP
port: 80
- name: https
protocol: HTTPS
port: 443
hostname: app.example.com
tls:
mode: Terminate
certificateRefs:
- name: app-cert
- name: grpc
protocol: HTTPS
port: 8443
hostname: grpc.example.com
tls:
mode: Terminate
certificateRefs:
- name: grpc-certCe n'est pas juste "un Gateway avec trois trous". Voyez-le plutôt comme :
- Le listener
http: pour le HTTP en clair - Le listener
https: pourapp.example.com - Le listener
grpc: un point d'entrée dédié aux services gRPC
Une fois que vous pensez ainsi, beaucoup de décisions de conception deviennent immédiatement claires. Vous n'assemblez pas seulement du YAML, vous dessinez des frontières d'entrée.
Trois patterns de découpage courants
Pattern 1 : découper par protocole
L'approche la plus intuitive :
- HTTP sur un listener
- HTTPS sur un listener
- gRPC sur un listener
- TCP/TLS passthrough séparés à part
Cela donne des responsabilités claires. Même si gRPC et les API web générales peuvent tous deux tourner sur HTTP/2, leurs modèles de service diffèrent. Les garder séparés évite que les routes interfèrent les unes avec les autres.
Pattern 2 : découper par hostname
Si vous avez plusieurs domaines, un pattern courant consiste à mettre un listener par hostname principal :
listeners:
- name: app
hostname: app.example.com
protocol: HTTPS
port: 443
- name: admin
hostname: admin.example.com
protocol: HTTPS
port: 443Cela fonctionne bien pour :
- Séparer la gouvernance publique et la gouvernance d'administration
- Des hostnames différents nécessitant des certificats différents
- Garder des frontières d'attachement de routes bien nettes
Pattern 3 : découper par responsabilité d'équipe ou d'environnement
Dans les setups multi-équipes, les listeners peuvent servir de frontières de gouvernance :
public-apipour le trafic produit externeinternal-apipour les systèmes internespartner-apipour les intégrations partenaires
Ici, la valeur du listener dépasse la simple configuration technique : il devient une frontière de permissions et de responsabilités. Ce pattern change réellement la donne dans les équipes moyennes à grandes, car il réduit la catastrophe du "même point d'entrée où tout le monde peut attacher n'importe quoi".
sectionName et allowedRoutes : deux champs critiques
Une route s'attache à un listener précis via parentRefs.sectionName :
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
spec:
parentRefs:
- name: eg
sectionName: https
hostnames:
- "app.example.com"
rules:
- backendRefs:
- name: app-service
port: 8080Cette route ne cherchera que le listener https.
Sans préciser sectionName, le système applique des règles pour trouver des listeners compatibles, mais dans les configurations multi-listeners, être explicite est presque toujours plus sûr.
L'autre champ critique est allowedRoutes :
listeners:
- name: public
protocol: HTTPS
port: 443
allowedRoutes:
namespaces:
from: SameCela signifie que seules les routes présentes dans le même namespace que le Gateway peuvent s'attacher.
Valeurs courantes :
Same: uniquement le même namespaceAll: n'importe quel namespaceSelector: uniquement les namespaces correspondant à un sélecteur de labels
Si vous voulez construire délibérément des frontières de plateforme, ce champ est très puissant. Il décide lui-même, au niveau du listener, de "qui peut s'attacher à cette entrée".
Conseil pratique : comment structurer les listeners sans le regretter plus tard
Un principe très utile :
Chaque listener porte une responsabilité clairement définie.
Par exemple :
- Un listener sert un groupe principal de hostnames
- Un listener gère un type de protocole principal
- Un listener est ouvert à un type de route ou à un ensemble fixe de namespaces
Ne concentrez pas tout le trafic dans un listener universel en espérant que les routes s'organiseront ensuite toutes seules. Ce pattern a l'air efficace au début, mais trois mois plus tard il ressemble au tiroir à câbles mystérieux qu'on finit tous par avoir chez soi : tout est dedans, rien n'est retrouvable.
Suggestions concrètes :
- Les noms de listeners doivent être sémantiques :
https-public,grpc-internal - Dans les setups multi-listeners, utilisez toujours
sectionName - Ne mélangez pas des hostnames importants dans un même listener
- Commencez par restreindre
allowedRoutespar défaut, ne démarrez pas avecfrom: All
Résumé en une ligne
Traitez Listener comme un contrat d'entrée, pas comme un simple réglage de port.
Des frontières propres côté listener signifient que les routes s'attachent correctement, que les équipes possèdent naturellement leur périmètre et que le débogage ressemble moins à la poursuite d'un chat dans un labyrinthe.
Étape suivante
Une fois la conception des listeners réglée, la question suivante revient souvent : Entre différents namespaces et différentes équipes, qui peut attacher des routes, et qui peut référencer quoi ?
L'article suivant couvre les patterns inter-namespace et la répartition de responsabilité : 👉 Multi-namespace et responsabilité d'équipe