Le HTTP Connection Manager et les chaînes de filtres HTTP
Comment Envoy transforme des octets bruts en requêtes HTTP exploitables, et les moyens d'insérer votre propre logique dans ce pipeline.
L’essentiel de ce que l’on configure au quotidien dans Envoy (manipulation d’en-têtes, journalisation des accès, retries, autorisation externe) se passe à l’intérieur d’un filtre réseau particulier : le HTTP Connection Manager. Ce guide explique ce qu’il fait, comment sa propre chaîne de filtres est structurée, et comment l’étendre avec une logique qui n’est pas intégrée.
HCM : des octets au HTTP
La chaîne de filtres d’un listener commence au niveau réseau, en opérant sur un flux d’octets brut, sans aucune notion de « requête » pour l’instant. Le HTTP Connection Manager (HCM) est le filtre réseau qui change cela : il analyse le flux d’octets pour en faire des requêtes HTTP, des en-têtes, des corps et des trailers, et à partir de là, tout ce qui se trouve après lui dans la chaîne peut travailler avec la sémantique HTTP plutôt qu’avec des octets bruts.
C’est aussi là que vivent les fonctionnalités au niveau de la requête : journalisation des accès, manipulation des requêtes et des réponses et, surtout, la propre chaîne imbriquée de filtres HTTP du HCM, qui est un concept distinct de la chaîne de filtres de niveau réseau dans laquelle elle s’insère.
La chaîne de filtres HTTP
À l’intérieur du HCM, les filtres HTTP s’exécutent dans un ordre défini sur chaque requête HTTP : gestion de CORS, limitation de débit, autorisation externe (un appel vers un autre service pour décider si une requête est autorisée), scripting Lua, modules WebAssembly (Wasm), et plus encore. Le dernier filtre de la chaîne est généralement un filtre terminal, presque toujours le filtre router, dont le rôle est de transmettre la requête à la correspondance de routes puis, de là, à un cluster.
L’ordre compte ici. Un filtre de limitation de débit placé avant un filtre d’authentification ne se comporte pas comme s’il était placé après, et la configuration d’Envoy pour une chaîne de filtres est explicite sur la position de chaque filtre par rapport aux autres, pas seulement sur les filtres présents.
Étendre Envoy : vos options
Quand aucun des filtres intégrés d’Envoy ne fait ce dont vous avez besoin, il existe plusieurs façons d’ajouter une logique personnalisée, chacune avec un coût et une portée différents :
- Les filtres C++ natifs, compilés directement dans un build d’Envoy personnalisé. C’est l’option la plus puissante et la plus lourde : cela implique de maintenir votre propre build d’Envoy plutôt que de consommer une version amont. La distribution d’Envoy d’Istio emprunte cette voie pour une partie de son comportement intégré.
- Le traitement externe (ext_proc), où Envoy appelle un service distinct en cours de requête, ce service effectue le traitement nécessaire puis rend la main à la chaîne de filtres. Cela garde la logique personnalisée entièrement en dehors du processus d’Envoy, au prix d’un saut réseau par requête.
- Le scripting Lua, où un filtre Lua exécute un script embarqué sur la requête et/ou la réponse. Rapide à écrire et à itérer, sans rebuild ni service distinct, au prix d’être limité à ce que Lua et l’API Lua d’Envoy exposent.
- WebAssembly (Wasm), où vous compilez un filtre vers un module
.wasmdans le langage de votre choix, et Envoy le charge et l’exécute dans la chaîne. C’est le mécanisme d’extension le plus orienté vers la distribution et la réutilisation d’un filtre comme artefact portable, plutôt que comme script ou build personnalisé.
Le bon choix dépend du degré de contrôle dont vous avez besoin par rapport à la charge opérationnelle que vous acceptez : un script Lua est généralement le moyen le plus rapide d’essayer quelque chose, un module Wasm est le moyen le plus portable de le livrer une fois que vous savez qu’il fonctionne, et un build C++ personnalisé ou un service externe est ce qui reste quand aucun des deux ne peut faire ce qu’il vous faut.
Ce dont un filtre a réellement besoin pour être configuré
Quel que soit le mécanisme d’extension utilisé, configurer un filtre HTTP se résume toujours à trois choses :
- Le nom du filtre, un identifiant stable.
- Son type URL, qui indique précisément au système de configuration d’Envoy de quel type de filtre il s’agit et quelle forme prend sa configuration.
- La configuration propre au filtre elle-même, les champs que ce filtre précis accepte réellement.
La page de documentation d’Envoy pour chaque filtre indique son type URL et ses champs de configuration, même si la documentation d’un filtre donné est souvent répartie sur plusieurs pages de référence liées plutôt que rassemblée en un seul endroit ; trouver la syntaxe exacte d’un champ précis implique fréquemment de suivre une chaîne de liens plutôt que de lire de haut en bas. Chercher le type URL d’un filtre sur les plateformes d’hébergement de code publiques est un raccourci pratique dès qu’on le connaît : pour tout ce qui est assez courant, quelqu’un a généralement déjà publié une configuration fonctionnelle dont vous pouvez partir plutôt que d’en assembler une à partir de la seule documentation de référence.
Où cela apparaît si vous utilisez un service mesh
Si Envoy s’exécute en sidecar sous Istio ou un mesh similaire, vous écrivez rarement à la main de la configuration brute de filtre HTTP pour les cas courants : les propres API du mesh (règles de routage, politiques de sécurité) la génèrent pour vous. Mais pour tout ce que les API de haut niveau du mesh ne couvrent pas, et il y a toujours quelque chose qu’elles ne couvrent pas, vous finissez par configurer directement un filtre HTTP via l’échappatoire de plus bas niveau que fournit le mesh. Le guide suivant de cette série traite exactement de cela, en prenant la ressource EnvoyFilter d’Istio comme exemple.
Guides populaires
-
Architecture d'Envoy : listeners, clusters et chaînes de filtres Comment une requête circule réellement dans Envoy, du socket où elle arrive jusqu'à l'upstream vers lequel elle est envoyée. -
Où se place Envoy : edge, front proxy et service mesh Le même proxy, déployé de trois façons différentes, et pourquoi « assez léger pour tourner par instance » rend les trois possibles.