Envoy 过滤器
EnvoyFilter
提供了一种机制,用于自定义 Istio Pilot 生成的 Envoy 配置。使用 EnvoyFilter 可以修改某些字段的值,添加特定的过滤器,甚至添加全新的监听器、集群等。此功能必须谨慎使用,因为错误的配置可能会导致整个服务网格不稳定。与其他 Istio 网络对象不同,EnvoyFilter 是累加应用的。任何数量的 EnvoyFilter 都可以存在于特定命名空间中给定工作负载的范围内。这些 EnvoyFilter 的应用顺序如下:首先应用配置根命名空间 中的所有 EnvoyFilter,然后应用工作负载命名空间中所有匹配的 EnvoyFilter。
注意 1:此 API 的某些方面与 Istio 网络子系统以及 Envoy 的 XDS API 的内部实现紧密相关。虽然 EnvoyFilter API 本身将保持向后兼容性,但应仔细监控通过此机制提供的任何 envoy 配置在 Istio 代理版本升级期间的变化,以确保已弃用的字段被适当地移除和替换。
注意 2:当多个 EnvoyFilter 绑定到给定命名空间中的同一工作负载时,所有补丁都将按创建时间的顺序依次处理。如果多个 EnvoyFilter 配置相互冲突,则行为未定义。
注意 3:要将 EnvoyFilter 资源应用于系统中的所有工作负载(边车和网关),请在配置根命名空间 中定义该资源,且不带工作负载选择器。
以下示例在根命名空间中声明了一个名为 istio-config
的全局默认 EnvoyFilter 资源,该资源在系统中的所有边车上添加了一个自定义协议过滤器,用于出站端口 9307。过滤器应在终止 tcp_proxy 过滤器之前添加才能生效。此外,它还为网关和边车中的所有 HTTP 连接设置了 30 秒的空闲超时。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: custom-protocol
namespace: istio-config # as defined in meshConfig resource.
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
context: SIDECAR_OUTBOUND # will match outbound listeners in all sidecars
listener:
portNumber: 9307
filterChain:
filter:
name: "envoy.filters.network.tcp_proxy"
patch:
operation: INSERT_BEFORE
value:
# This is the full filter config including the name and typed_config section.
name: "envoy.extensions.filters.network.mongo_proxy"
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy"
...
- applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
match:
# context omitted so that this applies to both sidecars and gateways
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
patch:
operation: MERGE
value:
name: "envoy.filters.network.http_connection_manager"
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
common_http_protocol_options:
idle_timeout: 30s
以下示例为到达 bookinfo 命名空间中带有标签“app: reviews”的 reviews 服务 pod 的服务端口 8080 的所有入站 HTTP 调用启用 Envoy 的 Lua 过滤器。lua 过滤器会调用外部服务 internal.org.net:8888,该服务需要在 envoy 中进行特殊的集群定义。集群也作为此配置的一部分添加到边车中。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: reviews-lua
namespace: bookinfo
spec:
workloadSelector:
labels:
app: reviews
configPatches:
# The first patch adds the lua filter to the listener/http connection manager
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
listener:
portNumber: 8080
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
subFilter:
name: "envoy.filters.http.router"
patch:
operation: INSERT_BEFORE
value: # lua filter specification
name: envoy.filters.http.lua
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
defaultSourceCode:
inlineString: |
function envoy_on_request(request_handle)
-- Make an HTTP call to an upstream host with the following headers, body, and timeout.
local headers, body = request_handle:httpCall(
"lua_cluster",
{
[":method"] = "POST",
[":path"] = "/acl",
[":authority"] = "internal.org.net"
},
"authorize call",
5000)
end
# The second patch adds the cluster that is referenced by the lua code
# cds match is omitted as a new cluster is being added
- applyTo: CLUSTER
match:
context: SIDECAR_OUTBOUND
patch:
operation: ADD
value: # cluster specification
name: "lua_cluster"
type: STRICT_DNS
connect_timeout: 0.5s
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: lua_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
protocol: TCP
address: "internal.org.net"
port_value: 8888
以下示例覆盖了 istio-system 命名空间中入口网关上的监听器中 HTTP 连接管理器中的某些字段(HTTP 空闲超时和 X-Forward-For 可信跃点),用于 SNI 主机 app.example.com。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: hcm-tweaks
namespace: istio-system
spec:
workloadSelector:
labels:
istio: ingressgateway
configPatches:
- applyTo: NETWORK_FILTER # http connection manager is a filter in Envoy
match:
context: GATEWAY
listener:
filterChain:
sni: app.example.com
filter:
name: "envoy.filters.network.http_connection_manager"
patch:
operation: MERGE
value:
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
xff_num_trusted_hops: 5
common_http_protocol_options:
idle_timeout: 30s
以下示例插入一个 attributegen 过滤器,该过滤器生成 istio_operationId
属性,该属性由 istio.stats 过滤器使用。filterClass: STATS
编码了这种依赖关系。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: reviews-request-operation
namespace: myns
spec:
workloadSelector:
labels:
app: reviews
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
patch:
operation: ADD
filterClass: STATS # This filter will run *before* the Istio stats filter.
value:
name: istio.request_operation
typed_config:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
value:
config:
configuration: |
{
"attributes": [
{
"output_attribute": "istio_operationId",
"match": [
{
"value": "ListReviews",
"condition": "request.url_path == '/reviews' && request.method == 'GET'"
}]
}]
}
vm_config:
runtime: envoy.wasm.runtime.null
code:
local: { inline_string: "envoy.wasm.attributegen" }
以下示例在 myns
命名空间中插入一个 http ext_authz 过滤器。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: myns-ext-authz
namespace: myns
spec:
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
patch:
operation: ADD
filterClass: AUTHZ # This filter will run *after* the Istio authz filter.
value:
name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
grpc_service:
envoy_grpc:
cluster_name: acme-ext-authz
initial_metadata:
- key: foo
value: myauth.acme # required by local ext auth server.
myns
命名空间中的工作负载需要访问一个不同的 ext_auth 服务器,该服务器不接受初始元数据。由于 proto 合并无法删除字段,因此以下配置使用 REPLACE
操作。如果您不需要继承字段,则 REPLACE 比 MERGE 更可取。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: mysvc-ext-authz
namespace: myns
spec:
workloadSelector:
labels:
app: mysvc
configPatches:
- applyTo: HTTP_FILTER
match:
context: SIDECAR_INBOUND
patch:
operation: REPLACE
value:
name: envoy.filters.http.ext_authz
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz
grpc_service:
envoy_grpc:
cluster_name: acme-ext-authz-alt
以下示例为所有入站边车 HTTP 请求部署了一个 Wasm 扩展。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: wasm-example
namespace: myns
spec:
configPatches:
# The first patch defines a named Wasm extension and provides a URL to fetch Wasm binary from,
# and the binary configuration. It should come before the next patch that applies it.
# This resource is visible to all proxies in the namespace "myns". It is possible to provide
# multiple definitions for the same name "my-wasm-extension" in multiple namespaces. We recommend that:
# - if overriding is desired, then the root level definition can be overridden per namespace with REPLACE.
# - if overriding is not desired, then the name should be qualified with the namespace "myns/my-wasm-extension",
# to avoid accidental name collisions.
- applyTo: EXTENSION_CONFIG
patch:
operation: ADD
value:
name: my-wasm-extension
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
config:
root_id: my-wasm-root-id
vm_config:
vm_id: my-wasm-vm-id
runtime: envoy.wasm.runtime.v8
code:
remote:
http_uri:
uri: http://my-wasm-binary-uri
configuration:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{}
# The second patch instructs to apply the above Wasm filter to the listener/http connection manager.
- applyTo: HTTP_FILTER
match:
listener:
filterChain:
filter:
name: envoy.filters.network.http_connection_manager
subFilter:
name: envoy.filters.http.router
patch:
operation: INSERT_BEFORE
value:
name: my-wasm-extension # This must match the name above
config_discovery:
config_source:
ads: {}
type_urls: ["type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm"]
以下示例在 envoy.filters.listener.tls_inspector
之前插入一个 envoy.filters.listener.proxy_protocol
监听器过滤器。
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: listener-filter-example
namespace: myns
spec:
configPatches:
- applyTo: LISTENER_FILTER
match:
context: SIDECAR_INBOUND # will match inbound listeners in all sidecars
listener:
portNumber: 15006
listenerFilter: "envoy.filters.listener.tls_inspector"
patch:
operation: INSERT_BEFORE
value:
# This is the full filter config including the name and typed_config section.
name: "envoy.filters.listener.proxy_protocol"
typed_config:
"@type": "type.googleapis.com/envoy.extensions.filters.listener.proxy_protocol.v3.ProxyProtocol"
EnvoyFilter
EnvoyFilter 提供了一种机制,用于自定义 Istio Pilot 生成的 Envoy 配置。
EnvoyFilter.ProxyMatch
代理的一个或多个要匹配的属性。
EnvoyFilter.ClusterMatch
必须满足 ClusterMatch
中指定的条件才能将补丁应用于集群。
EnvoyFilter.RouteConfigurationMatch
必须满足 RouteConfigurationMatch 中指定的条件才能将补丁应用于路由配置对象或路由配置中的特定虚拟主机。
EnvoyFilter.ListenerMatch
必须满足监听器匹配中指定的条件才能将补丁应用于所有过滤器链中的特定监听器,或监听器内的特定过滤器链。
EnvoyFilter.Patch
Patch 指定应如何修改所选对象。
EnvoyFilter.EnvoyConfigObjectMatch
在将修补程序应用于给定代理的生成配置之前,需要满足的一个或多个匹配条件。
EnvoyFilter.EnvoyConfigObjectPatch
要对各种 envoy 配置对象进行的更改。
EnvoyFilter.RouteConfigurationMatch.RouteMatch
匹配路由配置中虚拟主机内的特定路由。
EnvoyFilter.RouteConfigurationMatch.VirtualHostMatch
匹配路由配置中的特定虚拟主机。
EnvoyFilter.ListenerMatch.FilterChainMatch
对于具有多个过滤器链的监听器(例如,具有宽松 mTLS 的 sidecar 上的入站监听器、具有多个 SNI 匹配的网关监听器),过滤器链匹配可用于选择要修补的特定过滤器链。
EnvoyFilter.ListenerMatch.FilterMatch
匹配过滤器链内特定过滤器的条件。
EnvoyFilter.ListenerMatch.SubFilterMatch
匹配另一个过滤器内特定过滤器的条件。此字段通常用于匹配 envoy.filters.network.http_connection_manager
网络过滤器内的 HTTP 过滤器。这也可能适用于 thrift 过滤器。
EnvoyFilter.RouteConfigurationMatch.RouteMatch.Action
Action 指的是当 http 路由匹配时 Envoy 执行的路由操作。
Name | 描述 |
---|---|
ANY | 所有三种路由操作 |
ROUTE | 将流量路由到集群/加权集群。 |
REDIRECT | 重定向请求。 |
DIRECT_RESPONSE | 直接使用特定有效负载响应请求。 |
EnvoyFilter.Patch.Operation
Operation 表示应如何将修补程序应用于选定的配置。
Name | 描述 |
---|---|
INVALID | |
MERGE | 使用 proto 合并语义将提供的配置与生成的配置合并。如果您正在完整地指定配置,请改用 |
ADD | 将提供的配置添加到现有列表(监听器、集群、虚拟主机、网络过滤器或 http 过滤器)。当 |
REMOVE | 从列表(监听器、集群、虚拟主机、网络过滤器、路由或 http 过滤器)中删除选定的对象。不需要指定值。当 |
INSERT_BEFORE | 命名对象的数组上的插入操作。此操作通常仅在过滤器或路由的上下文中才有用,其中元素的顺序很重要。路由应根据最具体到最不具体的匹配条件进行排序,因为选择第一个匹配的元素。对于集群和虚拟主机,数组中元素的顺序无关紧要。在选定的过滤器或子过滤器之前插入。如果没有选择过滤器,则指定的过滤器将插入列表的开头。 |
INSERT_AFTER | 命名对象的数组上的插入操作。此操作通常仅在过滤器或路由的上下文中才有用,其中元素的顺序很重要。路由应根据最具体到最不具体的匹配条件进行排序,因为选择第一个匹配的元素。对于集群和虚拟主机,数组中元素的顺序无关紧要。在选定的过滤器或子过滤器之后插入。如果没有选择过滤器,则指定的过滤器将插入列表的末尾。 |
INSERT_FIRST | 命名对象的数组上的插入操作。此操作通常仅在过滤器或路由的上下文中才有用,其中元素的顺序很重要。路由应根据最具体到最不具体的匹配条件进行排序,因为选择第一个匹配的元素。对于集群和虚拟主机,数组中元素的顺序无关紧要。根据选定过滤器是否存在在列表中插入第一个。当您希望您的过滤器根据 Match 子句中指定的匹配条件在列表中排在第一位时,这特别有用。 |
REPLACE | 用新内容替换命名过滤器的内容。 |
EnvoyFilter.Patch.FilterClass
FilterClass 确定过滤器链中相对于控制平面隐式插入的过滤器的过滤器插入点。它与 ADD
操作结合使用。这是添加过滤器的首选插入机制,而不是 INSERT_*
操作,因为这些操作依赖于可能不稳定的过滤器名称。如果您的过滤器依赖于或影响过滤器链中另一个过滤器的功能,则过滤器排序很重要。在过滤器类中,过滤器按处理顺序插入。
Name | 描述 |
---|---|
UNSPECIFIED | 控制平面决定在哪里插入过滤器。如果过滤器与其他过滤器无关,请不要指定 |
AUTHN | 在 Istio 身份验证过滤器之后插入过滤器。 |
AUTHZ | 在 Istio 授权过滤器之后插入过滤器。 |
STATS | 在 Istio 统计过滤器之前插入过滤器。 |
EnvoyFilter.ApplyTo
ApplyTo
指定应在 Envoy 配置的何处应用给定的修补程序。
Name | 描述 |
---|---|
INVALID | |
LISTENER | 将修补程序应用于监听器。 |
FILTER_CHAIN | 将修补程序应用于过滤器链。 |
NETWORK_FILTER | 将修补程序应用于网络过滤器链,以修改现有过滤器或添加新过滤器。 |
HTTP_FILTER | 将修补程序应用于 http 连接管理器中的 HTTP 过滤器链,以修改现有过滤器或添加新过滤器。 |
ROUTE_CONFIGURATION | 将修补程序应用于 HTTP 连接管理器内的路由配置(rds 输出)。这并不适用于虚拟主机。目前,仅允许对路由配置对象执行 |
VIRTUAL_HOST | 将修补程序应用于路由配置中的虚拟主机。 |
HTTP_ROUTE | 将修补程序应用于路由配置中匹配的虚拟主机内的路由对象。 |
CLUSTER | 将修补程序应用于 CDS 输出中的集群。还用于添加新集群。 |
EXTENSION_CONFIG | 将修补程序应用于 ECDS 输出中的扩展配置或添加扩展配置。请注意,ECDS 仅受 HTTP 过滤器支持。 |
BOOTSTRAP | 已弃用。将修补程序应用于引导配置。 |
LISTENER_FILTER | 将修补程序应用于监听器过滤器。 |
EnvoyFilter.PatchContext
PatchContext 根据流量流方向和工作负载类型选择一类配置。
Name | 描述 |
---|---|
ANY | sidecar 和网关中所有监听器/路由/集群。 |
SIDECAR_INBOUND | sidecar 中的入站监听器/路由/集群。 |
SIDECAR_OUTBOUND | sidecar 中的出站监听器/路由/集群。 |
GATEWAY | 网关监听器/路由/集群。 |