-
Notifications
You must be signed in to change notification settings - Fork 250
A103: xDS Composite Filter #511
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
59cc515
4412a75
32c8b04
b8987fb
c932213
94c4bfb
4d4f41a
13868f6
c6bbc1e
27fd0ad
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| A103: xDS Composite Filter | ||
| ---- | ||
| * Author(s): markdroth | ||
| * Approver: ejona86, dfawley | ||
| * Status: {Draft, In Review, Ready for Implementation, Implemented} | ||
| * Implemented in: <language, ...> | ||
| * Last updated: 2025-12-01 | ||
| * Discussion at: https://groups.google.com/g/grpc-io/c/es5taH0OZS8 | ||
|
|
||
| ## Abstract | ||
|
|
||
| gRPC will support the [xDS Composite filter][composite], which is a | ||
| "wrapper" filter that dynamically determines which filter to use based | ||
| on request attributes. | ||
|
|
||
| [composite]: https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/composite_filter | ||
|
|
||
| ## Background | ||
|
|
||
| xDS support in the gRPC client and server are described in [A27] and | ||
| [A36], respectively. xDS HTTP filter support is described in [A39]. | ||
|
|
||
| The composite filter will make use of the Unified Matching API and CEL | ||
| support described in [A77]. | ||
|
|
||
| ### Related Proposals: | ||
| * [A27: xDS-Based Global Load Balancing][A27] | ||
| * [A39: xDS HTTP Filter Support][A39] | ||
| * [A36: xDS-Enabled Servers][A36] | ||
| * [A77: xDS Server-Side Rate Limiting][A77] (pending) | ||
| * [A83: xDS GCP Authentication Filter][A83] | ||
|
|
||
| [A27]: A27-xds-global-load-balancing.md | ||
| [A36]: A36-xds-for-servers.md | ||
| [A39]: A39-xds-http-filters.md | ||
| [A77]: https://github.com/grpc/proposal/pull/414 | ||
| [A83]: A83-xds-gcp-authn-filter.md | ||
|
|
||
| ## Proposal | ||
|
|
||
| We will support the composite filter in both the gRPC client and gRPC | ||
| server. | ||
|
|
||
| ### xDS Resource Validation | ||
|
|
||
| Today, the composite filter supports configuring only one filter as a | ||
| result of the matching tree. However, we have use-cases where we need | ||
| to select a chain of more than one filter based on the matching tree. | ||
| As a result, we are proposing a change to the composite filter's config | ||
| to allow selecting a chain of filters | ||
| (https://github.com/envoyproxy/envoy/pull/40885). | ||
|
|
||
| The composite filter is configured via the | ||
| [`envoy.extensions.common.matching.v3.ExtensionWithMatcher` | ||
| proto](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/common/matching/v3/extension_matcher.proto#L25). | ||
| Within it, gRPC will look at the following fields: | ||
| - [extension_config](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/common/matching/v3/extension_matcher.proto#L34C39-L34C55): | ||
| This must contain a | ||
| [`envoy.extensions.filters.http.composite.v3.Composite` | ||
| proto](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/filters/http/composite/v3/composite.proto#L33), | ||
| which has no fields. | ||
| - [xds_matcher](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/common/matching/v3/extension_matcher.proto#L31): | ||
| Specifies a unified matcher tree indicating the config of the filter | ||
| to use. The actions in this tree must be one of two types: | ||
| - [`envoy.extensions.filters.common.matcher.action.v3.SkipFilter`](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/filters/common/matcher/action/v3/skip_action.proto#L24): | ||
| This indicates that no filter will be executed. | ||
| - [`envoy.extensions.filters.http.composite.v3.ExecuteFilterAction`](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/filters/http/composite/v3/composite.proto#L49): | ||
| This indicates which filter should be executed. Within it: | ||
| - [typed_config](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/filters/http/composite/v3/composite.proto#L54C39-L54C51): | ||
| The filter to configure. It will be validated using the xDS HTTP filter | ||
| registry, just as the top-level filters in the HTTP connection manager | ||
| config are. This field is ignored if `filter_chain` is set. It | ||
| is an error if neither `typed_config` nor `filter_chain` are set. | ||
| - [dynamic_config](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/filters/http/composite/v3/composite.proto#L59): | ||
| This field will be ignored for now, since gRPC does not currently | ||
| support ECDS. Support for ECDS will be added in a subsequent gRFC. | ||
| - filter_chain (new field added in | ||
| https://github.com/envoyproxy/envoy/pull/40885): This specifies a | ||
| chain of filters to call, in order. Each filter in the chain will | ||
| be validated using the xDS HTTP filter registry, just as the | ||
| top-level filters in the HTTP connection manager config are. | ||
| If set, the `typed_config` field is ignored. It is an error if | ||
| neither `typed_config` nor `filter_chain` are set. | ||
| - [sample_percent](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/filters/http/composite/v3/composite.proto#L69C43-L69C57): | ||
| - Optional; if unset, the specified filter(s) are always executed. | ||
| If set, for each RPC, a random number will be generated between | ||
| 0 and 100, and if that number is less than the specified | ||
| threshold, the specified filter(s) will be executed. | ||
| Within this field: | ||
| - [default_value](https://github.com/envoyproxy/envoy/blob/cdd19052348f7f6d85910605d957ba4fe0538aec/api/envoy/config/core/v3/base.proto#L648): | ||
| This field must be present. The configured value will be capped at | ||
| 100%. | ||
| - runtime_key: This field will be ignored, since gRPC does not | ||
| have a runtime system. | ||
| - matcher: gRPC will not support this deprecated field. | ||
|
|
||
| We will also support per-route overrides via the | ||
| [`envoy.extensions.common.matching.v3.ExtensionWithMatcherPerRoute` | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this means we can have filters defined wholly in the RouteConfiguration? The Listener would no longer enumerate all the filters being used.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's correct. In the future, we'll also add ECDS support, which would be another way for the Listener to not enumerate all of the filters being used, even if there is no per-route override. |
||
| proto](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/common/matching/v3/extension_matcher.proto#L39C9-L39C37). | ||
| In this proto, the | ||
| [xds_matcher](https://github.com/envoyproxy/envoy/blob/0685d7bf568485eb112df2a9c73248cb8bfc1c37/api/envoy/extensions/common/matching/v3/extension_matcher.proto#L41) | ||
| must be validated the same way as the corresponding field in the | ||
| top-level config. The value of this field will replace the value of the | ||
| field in the top-level config. | ||
|
|
||
| The parsed representation of the composite filter's config will be a | ||
| matcher tree, using the same unified matcher API implemented for [A77]. | ||
| The actions in the matcher tree will be one of two possible values: a | ||
| parsed filter config, or an indication that the filter should be skipped | ||
| (in the case of a `SkipFilter` proto). | ||
|
|
||
| Note that in order to avoid potential stack overflows, we will impose | ||
| a maximum recursion depth of 8 when parsing HTTP filter configs. | ||
|
|
||
| ### CEL Attributes | ||
|
|
||
| In addition to the CEL request attributes described in [A77], we will | ||
| also add support for some additional [CEL | ||
| attributes](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/advanced/attributes.html) | ||
| that we expect to be useful for the composite filter. | ||
|
|
||
| On both the gRPC client and server sides, we will add support for the | ||
| `xds.route_metadata.filter_metadata` attribute. To support this, we will | ||
| add support for parsing the [`Route.metadata` | ||
| field](https://github.com/envoyproxy/envoy/blob/f384ab2b3e3aa0564ef25f57dc2ed8ad61eaf0cb/api/envoy/config/route/v3/route_components.proto#L319) | ||
| in the xDS RouteConfiguration. This field will be validated the same | ||
| way as cluster metadata, as described in [A83]. The parsed metadata map | ||
| will be added to the route in the parsed RouteConfiguration resource, | ||
| and that map will be accessed by this CEL attribute. Note that we will | ||
| support only `filter_metadata`, not `typed_filter_metadata`, so that we | ||
| do not have to handle protobuf descriptor functionality; to that end, we | ||
| will use only those entries in the parsed metadata map that correspond | ||
| to `google.protobuf.Struct` type. | ||
|
|
||
| We will also add support for the following attributes on the gRPC server | ||
| side only (these attributes are not relevant on the client side): | ||
| - `source.address` | ||
| - `source.port` | ||
| - `connection.requested_server_name` | ||
| - `connection.tls_version` | ||
| - `connection.sha256_peer_certificate_digest` | ||
|
|
||
| ### Filter Behavior | ||
|
|
||
| Because all of the CEL attributes that we are exposing are available | ||
ejona86 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| when we see the client's initial metadata, that is the point at which | ||
| the filter will evaluate the matcher tree and decide which filter chain | ||
| to use. After that point, all other filter hooks will be delegated to | ||
| the chosen filter chain. | ||
|
|
||
| If we ever in the future need to support other attributes that are not | ||
| yet available at this point, we will need to make changes here. | ||
|
|
||
| ### Temporary environment variable protection | ||
|
|
||
| Support for the composite filter will be guarded by the | ||
| `GRPC_EXPERIMENTAL_XDS_COMPOSITE_FILTER` environment variable. This | ||
| guard will be removed once the feature passes interop tests. | ||
|
|
||
| ## Rationale | ||
|
|
||
| The composite filter API seems a little unusual. One would naively | ||
| have expected it to be structured by having the matcher tree live | ||
| in the config for the composite filter directly, rather than using | ||
| `ExtensionWithMatcher`. Unfortunately, that's not the way the API evolved | ||
| in Envoy, so we'll stick with what already exists for compatibility | ||
| reasons. | ||
|
|
||
| ## Implementation | ||
|
|
||
| Will be implemented in C-core, Java, Go, and Node. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The links seem to be broken...