Configurer des filtres Envoy bruts dans Istio avec EnvoyFilter
Pour les fonctionnalités que les API d'Istio n'exposent pas, EnvoyFilter modifie directement la configuration Envoy sous-jacente, avec précaution.
Les ressources de haut niveau d’Istio, VirtualService, DestinationRule, AuthorizationPolicy, couvrent l’essentiel de la gestion quotidienne du trafic sans que personne ait besoin de connaître directement le format de configuration d’Envoy. Mais Envoy dispose de bien plus de filtres et d’options que n’en exposent ces ressources, et pour combler cet écart, Istio fournit EnvoyFilter : une ressource qui modifie directement la configuration Envoy qu’Istio génère. C’est une véritable échappatoire, aussi puissante que facile à mal configurer, et ce guide explique comment elle est structurée, avec un exemple complet.
À quoi sert EnvoyFilter
Si ce dont vous avez besoin dispose d’une ressource Istio dédiée (une règle de routage, une politique de retry, des paramètres de TLS mutuel), utilisez cette ressource à la place. EnvoyFilter existe pour tout le reste : des filtres comme le scripting Lua, le tapping de requêtes, le tagging d’IP, ou toute autre capacité d’Envoy pour laquelle les API de plus haut niveau d’Istio n’ont tout simplement pas de champ. Ne l’utilisez qu’après avoir confirmé que ce dont vous avez besoin n’est vraiment pas exprimable avec les ressources normales, car chaque EnvoyFilter que vous ajoutez est une chose de plus à garder synchronisée avec l’évolution de la configuration générée par Istio au fil des mises à niveau.
Les quatre questions auxquelles répond tout EnvoyFilter
Chaque ressource EnvoyFilter, quoi qu’elle configure, répond aux mêmes quatre questions :
- À quels proxys s’applique-t-elle ? Un
workloadSelectorcible des workloads précis par label ; l’omettre applique le patch à l’ensemble du mesh au sein de son namespace, ou à tout le mesh s’il est placé dans le namespace racine/de configuration d’Istio. - Où, dans la configuration Envoy, le patch s’applique-t-il ? Le champ
applyTodésigne la cible :LISTENER,FILTER_CHAIN,HTTP_FILTER,NETWORK_FILTER,CLUSTER,ROUTE_CONFIGURATION, et quelques autres. - Plus précisément, quelle instance de cet élément ? Un bloc
matchaffine le ciblage, par exemple un port de listener précis, une chaîne de filtres précise, ou le fait que cela s’applique au trafic entrant d’un sidecar, au trafic sortant d’un sidecar ou à une gateway. - Quelle opération effectuer, et avec quel contenu ? Le bloc
patchspécifie à la fois une opération (ADD,REMOVE,MERGE,INSERT_BEFORE,INSERT_AFTERouINSERT_FIRST) et, pour tout ce qui insère ou fusionne de la configuration, la configuration réelle du filtre dans son champvalue.
Les changements sensibles à l’ordre (insérer un filtre HTTP à un endroit précis de la chaîne) utilisent les opérations INSERT_* et désignent un voisin nommé, typiquement le filtre terminal envoy.filters.http.router, pour dire « avant celui-ci » ou « après celui-ci ».
Un exemple complet : taguer les requêtes par IP
Ceci ajoute le filtre HTTP ip_tagging au trafic entrant du sidecar sur le port 80, inséré juste avant le filtre terminal router :
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: ip-tagging
namespace: default
spec:
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
portNumber: 80
filterChain:
filter:
name: envoy.filters.network.http_connection_manager
subFilter:
name: envoy.filters.http.router
patch:
operation: INSERT_BEFORE
value:
name: envoy.filters.http.ip_tagging
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ip_tagging.v3.IPTagging
request_type: BOTH
ip_tags:
- ip_tag_name: hello-envoy-conf
ip_list:
- address_prefix: "0.0.0.0"
prefix_len: 0
Lecture de haut en bas : l’absence de workloadSelector signifie que cela s’applique à chaque workload du namespace default. applyTo: HTTP_FILTER indique qu’on ajoute un filtre HTTP. Le bloc match restreint cela au trafic entrant du sidecar, sur le listener lié au port 80, précisément dans la chaîne de filtres du HTTP Connection Manager, positionné par rapport au filtre router. Le patch demande d’insérer un nouveau filtre avant ce router, et en donne la configuration complète : le nom du filtre, son type URL (@type) et les champs propres au filtre, ici, taguer chaque requête avec X-Envoy-IP-Tags: hello-envoy-conf quelle que soit l’IP source (0.0.0.0/0 correspond à tout).
Appliquez-le et vérifiez :
kubectl apply -f ip-tagging-filter.yaml
kubectl exec deploy/httpbin -c istio-proxy -- curl -s -D - http://localhost:80/get -o /dev/null | grep -i x-envoy-ip-tags
Trouver le nom, le type URL et les champs d’un filtre
Le name, le @type de typed_config et les champs qui se placent dessous sont tous propres à chaque filtre, et c’est la documentation des filtres d’Envoy qui les fournit, même si elle est répartie sur plusieurs pages liées plutôt que présentée en un seul endroit : la page de présentation d’un filtre renvoie généralement vers sa référence protobuf, qui définit à son tour chaque champ, avec souvent d’autres liens pour les types imbriqués. Prévoyez de naviguer pas mal entre les onglets. Quelques astuces permettent d’aller plus vite :
- Cherchez le type URL sur GitHub une fois que vous l’avez. Pour tout filtre assez courant, quelqu’un a probablement déjà publié un
EnvoyFilterou une configuration Envoy brute fonctionnelle qui l’utilise, ce qui est généralement un meilleur point de départ que d’en assembler un à partir de la seule référence des champs. - Tous les filtres Envoy ne sont pas compilés dans le build du proxy d’Istio. Istio livre un build d’Envoy spécifique, et un filtre documenté sur envoyproxy.io n’y est pas forcément inclus. Confirmez qu’un filtre est réellement disponible dans le build d’Istio avant de concevoir une solution autour de lui.
- Utilisez du JSON plutôt que du YAML pour le bloc
valuesi l’indentation du YAML vous paraît source d’erreurs pour une configuration profondément imbriquée ; la configuration d’Envoy accepte les deux, et une indentation mal placée dans un bloc YAML imbriqué est l’une des causes les plus fréquentes d’unEnvoyFilterqui échoue silencieusement à faire ce que vous aviez prévu.
Inspecter ce qui s’exécute réellement
Deux outils aident à confirmer qu’un patch a atterri comme prévu, plutôt que de deviner à partir du seul comportement :
istioctl proxy-config listener POD_NAME -n NAMESPACE
istioctl proxy-config route POD_NAME -n NAMESPACE
istioctl proxy-config cluster POD_NAME -n NAMESPACE
istioctl proxy-config all POD_NAME -n NAMESPACE -o json
istioctl proxy-config, suivi de bootstrap, clusters, routes, listeners ou all, affiche la configuration réelle d’un sidecar telle qu’Istio et Envoy l’ont assemblée, sous forme de tableau par défaut ou en YAML/JSON avec -o. C’est la vérité terrain de ce qui tourne réellement, par opposition à ce que vous aviez l’intention de patcher. Pour comparer visuellement un dump de configuration complet : une configuration Envoy complète est plus longue que ce que la plupart des gens veulent lire directement dans un terminal ; un visualiseur de config dump qui la présente sous forme de structure navigable et avec des liens croisés (la communauté Envoy en maintient quelques-uns) est généralement plus facile à parcourir que du JSON brut qui défile.
La mise en garde essentielle
EnvoyFilter modifie une configuration qu’Istio génère lui-même et régénère à chaque changement, ce qui signifie qu’il est intrinsèquement couplé aux composants internes d’Istio d’une façon que les ressources de plus haut niveau ne sont pas. Un EnvoyFilter écrit pour une version d’Istio peut cesser silencieusement de correspondre à quoi que ce soit, ou correspondre à quelque chose d’inattendu, après qu’une mise à niveau a modifié la façon dont Istio structure ses listeners ou ses chaînes de filtres générés. Traitez-le comme son nom le suggère : un outil précis pour un manque spécifique et vérifié, testé après chaque mise à niveau d’Istio, et non une façon de configurer le trafic par défaut.
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. -
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.