For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.
Staged ExtProc filters
Use the filterStage field in a GatewayExtension resource to control where in the Envoy filter chain an ExtProc filter runs. This way, you can apply multiple ExtProc filters to the same route at different stages.
About ExtProc filter stages
The Envoy filter chain processes each request through a series of ordered stages before forwarding it to the upstream service. By default, the ExtProc filter runs after the AuthZ (authorization) stage. You can use the filterStage field in your GatewayExtension resource to position the ExtProc filter at a different stage in the filter chain, or to run ExtProc at multiple stages for the same route.
The following stages are supported. The stages are listed in the order that a request passes through them. When a response is received from the upstream service, the stages are traversed in reverse order.
filterStage.stage |
Position in the filter chain |
|---|---|
Fault | Earliest stage. ExtProc is executed before fault injection. |
AuthN | External authentication stage. |
AuthZ | Authorization stage. This setting is the default when the filterStage field is not set. |
RateLimit | Rate limiting stage. |
Route | Final processing stage before the request leaves the gateway proxy. |
In addition to the filter stage, you use the filterStage.predicate field to configure when to run ExtProc relative to the stage.
The following predicates are supported:
filterStage.predicate |
Description |
|---|---|
Before | Run the ExtProc filter before the specified stage. |
During | Run the ExtProc filter during the specified stage. This setting is the default when the predicate field is not set. |
After | Run the ExtProc filter after the specified stage. |
Note
When multiple ExtProc filters target the same route at the same stage and predicate, use the filterStage.weight field to control their relative order. A higher weight runs earlier in the chain. Filters with the same weight are sorted alphabetically by GatewayExtension name.
Before you begin
-
Follow the Get started guide to install kgateway.
-
Follow the Sample app guide to create a gateway proxy with an HTTP listener and deploy the httpbin sample app.
-
Get the external address of the gateway and save it in an environment variable.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESS
Set up multiple ExtProc filters at different stages
You can apply multiple ExtProc filters to the same route, each running at a different position in the filter chain. To do that, you create a separate GatewayExtension and TrafficPolicy resource for each stage. Then, you reference both from the same HTTPRoute.
A common use case is to observe how a request changes as it passes through the filter chain. For example, you can run one ExtProc filter before authentication to capture the raw incoming request, and another after the routing decision is made to capture the request before it leaves the gateway proxy.
Note
By default, creating multiple TrafficPolicy resources that all specify the same extProc field results in a policy conflict error. To ensure that you can apply multiple ExtProc stages to the same route, enable deep merging for ExtProc policies by either setting policyMerge.trafficPolicy.extProc=DeepMerge in your Helm installation or using the KGW_POLICY_MERGE={"trafficPolicy":{"extProc":"DeepMerge"}} environment variable.
-
Optional: Get the values of your current Helm installation.
helm get values kgateway -n kgateway-system -o yaml > values.yaml open values.yaml -
Upgrade your Helm installation to enable deep merging for multiple TrafficPolicy resources that all specify the same
extProcfield.helm upgrade kgateway oci://cr.kgateway.dev/kgateway-dev/charts/kgateway \ -n kgateway-system \ --version v2.5.0-main \ -f values.yaml \ --set policyMerge.trafficPolicy.extProc=DeepMerge -
Verify that the control plane pods are up and running.
kubectl get pods -n kgateway-system -
Build the ExtProc server image and load it into your cluster. The image is not published to a public registry and must be built locally from the kgateway repository. Run the following commands from the root of that repository. Replace
<cluster-name>with the name of your kind cluster.make extproc-server-docker EXTPROC_SERVER_VERSION=0.0.2 make cluster-load-extproc-server CLUSTER_NAME=<cluster-name> EXTPROC_SERVER_VERSION=0.0.2 -
Deploy the ExtProc server. This example uses a prebuilt ExtProc server that manipulates request and response headers based on instructions that are sent in an instructions header.
kubectl apply -n kgateway-system -f- <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: ext-proc-grpc spec: selector: matchLabels: app.kubernetes.io/name: ext-proc-grpc replicas: 1 template: metadata: labels: app.kubernetes.io/name: ext-proc-grpc spec: containers: - name: ext-proc-grpc image: ghcr.io/kgateway-dev/extproc-server:0.0.2 imagePullPolicy: IfNotPresent command: ["./server", "--add-header", "x-extproc-processed:true"] ports: - containerPort: 18080 --- apiVersion: v1 kind: Service metadata: name: ext-proc-grpc spec: ports: - port: 4444 targetPort: 18080 protocol: TCP appProtocol: kubernetes.io/h2c selector: app.kubernetes.io/name: ext-proc-grpc EOF -
Verify that the ExtProc server is running.
kubectl get pods -n kgateway-system | grep ext-proc-grpc -
Create two GatewayExtension resources with different
filterStagesettings, one that applies ExtProc before theAuthNstage and one that runs after theRoutestage. You use the same ExtProc server for both stages. However, you can also point to different ExtProc servers for each stage.kubectl apply -n kgateway-system -f- <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: GatewayExtension metadata: name: ext-proc-before-authn spec: extProc: grpcService: backendRef: name: ext-proc-grpc port: 4444 filterStage: stage: AuthN predicate: Before --- apiVersion: gateway.kgateway.dev/v1alpha1 kind: GatewayExtension metadata: name: ext-proc-after-route spec: extProc: grpcService: backendRef: name: ext-proc-grpc port: 4444 filterStage: stage: Route predicate: After EOF -
Create a separate TrafficPolicy resource for each GatewayExtension resource.
kubectl apply -n kgateway-system -f- <<EOF apiVersion: gateway.kgateway.dev/v1alpha1 kind: TrafficPolicy metadata: name: extproc-before-authn spec: extProc: extensionRef: name: ext-proc-before-authn --- apiVersion: gateway.kgateway.dev/v1alpha1 kind: TrafficPolicy metadata: name: extproc-after-route spec: extProc: extensionRef: name: ext-proc-after-route EOF -
Create an HTTPRoute resource that routes traffic along the
extproc.exampledomain to the httpbin app and applies both TrafficPolicy resources to the same route rule.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: extproc-mixed-stages namespace: kgateway-system spec: parentRefs: - name: http namespace: kgateway-system hostnames: - "extproc.example" rules: - matches: - path: type: PathPrefix value: /headers backendRefs: - name: httpbin port: 8000 namespace: httpbin filters: - type: ExtensionRef extensionRef: group: gateway.kgateway.dev kind: TrafficPolicy name: extproc-before-authn - type: ExtensionRef extensionRef: group: gateway.kgateway.dev kind: TrafficPolicy name: extproc-after-route EOF -
Create a ReferenceGrant resource to allow the HTTPRoute to forward traffic to the httpbin app. This resource is required because the HTTPRoute and the httpbin app are in different namespaces.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: allow-httproute-mixed-stages-to-httpbin namespace: httpbin spec: from: - group: gateway.networking.k8s.io kind: HTTPRoute namespace: kgateway-system to: - group: "" kind: Service EOF -
Send a request to the
/headerspath. The ExtProc server is invoked twice. Verify that you see thex-extproc-processed: trueheader in your response.curl -vi http://$INGRESS_GW_ADDRESS:8080/headers -H "host: extproc.example"Example output:
< HTTP/1.1 200 OK HTTP/1.1 200 OK ... < { "headers": { "Accept": [ "*/*" ], "X-Extproc-Processed": [ "true" ], "Host": [ "extproc.example" ], ... -
Check the ExtProc server logs. Verify that you see two
Processlog entries, one for each stage.kubectl logs -n kgateway-system -l app.kubernetes.io/name=ext-proc-grpcExample output:
Process Got RequestHeaders Sending ProcessingResponse Process Got RequestHeaders Sending ProcessingResponse Got ResponseHeaders Sending ProcessingResponse Got ResponseHeaders Sending ProcessingResponse
Cleanup
You can remove the resources that you created in this guide.kubectl delete httproute extproc-mixed-stages -n kgateway-system
kubectl delete TrafficPolicy extproc-before-authn extproc-after-route -n kgateway-system
kubectl delete referencegrant allow-httproute-mixed-stages-to-httpbin -n httpbin
kubectl delete gatewayextension ext-proc-before-authn ext-proc-after-route -n kgateway-system
kubectl delete deployment ext-proc-grpc -n kgateway-system
kubectl delete service ext-proc-grpc -n kgateway-system