Rohe Envoy-Filter in Istio mit EnvoyFilter konfigurieren
Für Funktionen, die Istios eigene APIs nicht anbieten, patcht EnvoyFilter die zugrunde liegende Envoy-Konfiguration direkt – mit Vorsicht.
Istios übergeordnete Ressourcen – VirtualService, DestinationRule, AuthorizationPolicy – decken das tägliche Traffic-Management ab, ohne dass jemand Envoys Konfigurationsformat direkt kennen muss. Envoy hat aber weit mehr Filter und Optionen, als jede dieser Ressourcen bereitstellt. Für diese Lücke bietet Istio EnvoyFilter: eine Ressource, die die von Istio erzeugte Envoy-Konfiguration direkt patcht. Sie ist ein echter Notausgang, mächtig und ebenso leicht falsch zu konfigurieren. Diese Anleitung behandelt ihren Aufbau mit einem vollständigen Beispiel.
Wofür EnvoyFilter gedacht ist
Wenn das, was du brauchst, eine eigene Istio-Ressource hat – eine Routing-Regel, eine Retry-Policy, Einstellungen für Mutual TLS –, nimm diese Ressource. EnvoyFilter gibt es für alles andere: Filter wie Lua-Skripting, Request-Tapping, IP-Tagging oder jede andere Envoy-Fähigkeit, für die Istios übergeordnete APIs schlicht kein Feld haben. Greife erst dazu, wenn du bestätigt hast, dass das Gewünschte wirklich nicht über die normalen Ressourcen ausdrückbar ist, denn jeder EnvoyFilter, den du hinzufügst, ist eine weitere Sache, die du synchron halten musst, während sich Istios eigene generierte Konfiguration über Upgrades hinweg weiterentwickelt.
Die vier Fragen, die jeder EnvoyFilter beantwortet
Jede EnvoyFilter-Ressource beantwortet, unabhängig davon, was sie konfiguriert, dieselben vier Fragen:
- Auf welche Proxies gilt das? Ein
workloadSelectorzielt per Label auf bestimmte Workloads. Ohne ihn gilt der Patch namespace-weit, oder mesh-weit, wenn er im Root-/Config-Namespace von Istio liegt. - Wo in der Envoy-Konfiguration gilt der Patch? Das Feld
applyTobenennt das Ziel:LISTENER,FILTER_CHAIN,HTTP_FILTER,NETWORK_FILTER,CLUSTER,ROUTE_CONFIGURATIONund einige weitere. - Genauer: welche Instanz davon? Ein
match-Block grenzt weiter ein, zum Beispiel auf einen bestimmten Listener-Port, eine bestimmte Filter-Kette oder darauf, ob das für Sidecar-Inbound-Traffic, Sidecar-Outbound-Traffic oder ein Gateway gilt. - Welche Operation soll mit welchem Inhalt ausgeführt werden? Der
patch-Block gibt eine Operation an –ADD,REMOVE,MERGE,INSERT_BEFORE,INSERT_AFTERoderINSERT_FIRST– und für alles, was Konfiguration einfügt oder zusammenführt, die eigentliche Filterkonfiguration alsvalue.
Reihenfolgeabhängige Änderungen (das Einfügen eines HTTP-Filters an einer bestimmten Stelle der Kette) nutzen die INSERT_*-Operationen und verweisen auf einen benannten Nachbarn, typischerweise den abschließenden Filter envoy.filters.http.router, um „vor diesem“ oder „nach diesem“ zu sagen.
Ein vollständiges Beispiel: Requests nach IP taggen
Das fügt den HTTP-Filter ip_tagging zu Sidecar-Inbound-Traffic auf Port 80 hinzu, direkt vor dem abschließenden Router-Filter:
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
Von oben nach unten gelesen: Kein workloadSelector bedeutet, dass das für jeden Workload im Namespace default gilt. applyTo: HTTP_FILTER sagt, dass wir einen HTTP-Filter hinzufügen. Der match-Block grenzt das auf Sidecar-Inbound-Traffic auf dem an Port 80 gebundenen Listener ein, genauer innerhalb der Filter-Kette des HTTP Connection Managers, positioniert relativ zum Router-Filter. Der patch sagt, einen neuen Filter vor diesem Router einzufügen, und gibt seine vollständige Konfiguration an: den Namen des Filters, seine Typ-URL (@type) und die filterspezifischen Felder – hier wird jede Anfrage unabhängig von der Quell-IP mit X-Envoy-IP-Tags: hello-envoy-conf getaggt (0.0.0.0/0 passt auf alles).
Wende ihn an und bestätige:
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
Name, Typ-URL und Felder eines Filters finden
Der name, das @type in typed_config und die Felder darunter sind jeweils spezifisch für jeden Filter, und sie stammen aus Envoys eigener Filter-Dokumentation – die allerdings über mehrere verlinkte Seiten verteilt ist, statt an einem Ort zu stehen: Die Übersichtsseite eines Filters verlinkt meist auf seine Protobuf-Referenz, die wiederum jedes Feld definiert, oft mit weiteren Links für verschachtelte Typen. Plane einiges an Tab-Wechseln ein. Ein paar Dinge machen es schneller:
- Suche die Typ-URL auf GitHub, sobald du sie hast. Für jeden halbwegs gängigen Filter hat vermutlich schon jemand einen funktionierenden
EnvoyFilteroder eine rohe Envoy-Konfiguration damit veröffentlicht, was meist ein schnellerer Ausgangspunkt ist, als einen allein aus der Feldreferenz zusammenzubauen. - Nicht jeder Envoy-Filter ist in Istios Proxy-Build einkompiliert. Istio liefert einen bestimmten Envoy-Build aus, und ein auf envoyproxy.io dokumentierter Filter ist nicht garantiert darin enthalten. Bestätige, dass ein Filter tatsächlich in Istios Build verfügbar ist, bevor du eine Lösung darum herum entwirfst.
- Nutze JSON statt YAML für den
value-Block, wenn dir die Einrückung von YAML bei tief verschachtelter Konfiguration fehleranfällig erscheint. Envoys Konfiguration akzeptiert beides, und eine falsch gesetzte Einrückung in einem verschachtelten YAML-Block ist eine der häufigsten Ursachen, warum einEnvoyFilterstillschweigend nicht das tut, was du wolltest.
Prüfen, was tatsächlich läuft
Zwei Werkzeuge helfen zu bestätigen, dass ein Patch so gelandet ist, wie du es erwartest, statt aus dem Verhalten zu raten:
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, gefolgt von bootstrap, clusters, routes, listeners oder all, gibt die tatsächliche Konfiguration eines Sidecars aus, wie Istio und Envoy sie zusammengesetzt haben – standardmäßig als Tabelle oder mit -o als YAML/JSON. Das ist die Ground Truth dafür, was wirklich läuft, im Gegensatz dazu, was du patchen wolltest. Zum visuellen Vergleich eines vollständigen Config-Dumps: Eine vollständige Envoy-Konfiguration ist mehr, als die meisten direkt im Terminal lesen wollen. Ein Config-Dump-Viewer, der sie als durchsuchbare, querverlinkte Struktur darstellt (die Envoy-Community pflegt einige), ist meist leichter durchzuarbeiten als rohes JSON zu scrollen.
Die zentrale Warnung
EnvoyFilter patcht Konfiguration, die Istio selbst bei jeder Änderung erzeugt und neu erzeugt, was bedeutet, dass er auf eine Weise an Istios Interna gekoppelt ist, wie es die übergeordneten Ressourcen nicht sind. Ein für eine Istio-Version geschriebener EnvoyFilter kann nach einem Upgrade, das ändert, wie Istio seine generierten Listener oder Filter-Ketten strukturiert, stillschweigend nichts mehr treffen oder etwas Unbeabsichtigtes treffen. Behandle ihn so, wie der Name es nahelegt: ein präzises Werkzeug für eine spezifische, verifizierte Lücke, nach jedem Istio-Upgrade getestet – nicht ein Standardweg, Traffic zu konfigurieren.
Beliebte Anleitungen
-
Envoy-Architektur: Listener, Cluster und Filter-Ketten Wie eine Anfrage tatsächlich durch Envoy läuft – vom Socket, an dem sie ankommt, bis zum Upstream, an den sie gesendet wird. -
Wo Envoy hineinpasst: Edge-, Front-Proxy- und Service-Mesh-Muster Derselbe Proxy, auf drei Arten betrieben – und warum „leicht genug, um pro Instanz zu laufen“ alle drei möglich macht. -
Der HTTP Connection Manager und HTTP-Filter-Ketten Wie Envoy rohe Bytes in HTTP-Anfragen verwandelt, auf die er reagieren kann – und die Wege, eigene Logik in diese Pipeline einzubinden.