Envoy Envoy

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.

14 min Avancé

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 :

  1. À quels proxys s’applique-t-elle ? Un workloadSelector cible 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.
  2. Où, dans la configuration Envoy, le patch s’applique-t-il ? Le champ applyTo désigne la cible : LISTENER, FILTER_CHAIN, HTTP_FILTER, NETWORK_FILTER, CLUSTER, ROUTE_CONFIGURATION, et quelques autres.
  3. Plus précisément, quelle instance de cet élément ? Un bloc match affine 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.
  4. Quelle opération effectuer, et avec quel contenu ? Le bloc patch spécifie à la fois une opération (ADD, REMOVE, MERGE, INSERT_BEFORE, INSERT_AFTER ou INSERT_FIRST) et, pour tout ce qui insère ou fusionne de la configuration, la configuration réelle du filtre dans son champ value.

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 EnvoyFilter ou 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 value si 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’un EnvoyFilter qui é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