EnvoyFilter

EnvoyFilter 提供了一种机制来定制 Istio Pilot 生成的 Envoy 配置。使用 EnvoyFilter 来修改某些字段的值,添加特定的过滤器,甚至添加全新的 listener、cluster 等。这个功能必须谨慎使用,因为不正确的配置可能破坏整个网格的稳定性。与其他 Istio 网络对象不同,EnvoyFilter 是累加应用。对于特定命名空间中的特定工作负载,可以存在任意数量的 EnvoyFilter。这些 EnvoyFilter 的应用顺序如下:配置根命名空间中的所有 EnvoyFilter,其次是工作负载命名空间中的所有匹配 EnvoyFilter。

注意一

该 API 的某些方面与 Istio 网络子系统的内部实现以及 Envoy 的 xDS API 有很深的关系。虽然 EnvoyFilter API 本身将保持向后兼容,但通过该机制提供的任何 Envoy 配置应在 Istio 代理版本升级时仔细审查,以确保废弃的字段被适当地删除和替换。

注意二

当多个 EnvoyFilter 被绑定到特定命名空间的同一个工作负载时,所有补丁将按照创建顺序处理。如果多个 EnvoyFilter 的配置相互冲突,则其行为将无法确定。

注意三

要将 EnvoyFilter 资源应用于系统中的所有工作负载(sidecar 和 gateway)上,请在 config 根命名空间中定义该资源,不要使用 workloadSelector。

示例

下面的例子在名为 istio-config 的根命名空间中声明了一个全局默认的 EnvoyFilter 资源,在系统中的所有 sidecar 上添加了一个自定义的协议过滤器,用于 outbound 端口 9307。该过滤器应在终止 tcp_proxy 过滤器之前添加,以便生效。此外,它为 gateway 和 sidecar 的所有 HTTP 连接设置了 30 秒的空闲超时。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: custom-protocol
  namespace: istio-config # 如在 meshConfig 资源中定义的。
spec:
  configPatches:
  - applyTo: NETWORK_FILTER
    match:
      context: SIDECAR_OUTBOUND # 将会匹配所有 sidecar 中的所有 outbound listener
      listener:
        portNumber: 9307
        filterChain:
          filter:
            name: "envoy.filters.network.tcp_proxy"
    patch:
      operation: INSERT_BEFORE
      value:
        # 这是完整的过滤器配置,包括名称和 typed_config 部分。
        name: "envoy.config.filter.network.custom_protocol"
        typed_config:
         ...
  - applyTo: NETWORK_FILTER # HTTP 连接管理器是 Envoy 的一个过滤器。
    match:
      # 省略了上下文,因此这同时适用于 sidecar 和 gateway。
      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

下面的例子启用了 Envoy 的 Lua 过滤器,用于处理所有到达 bookinfo 命名空间中的对 reviews 服务 pod 的 8080 端口的 HTTP 调用,标签为 app: reviews。Lua 过滤器调用外部服务internal.org.net:8888,这需要在 Envoy 中定义一个特殊的 cluster。该 cluster 也被添加到 sidecar 中,作为该配置的一部分。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: reviews-lua
  namespace: bookinfo
spec:
  workloadSelector:
    labels:
      app: reviews
  configPatches:
    # 第一个补丁将 lua过 滤器添加到监听器/http 连接管理器。
  - 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 过滤器配置
       name: envoy.lua
       typed_config:
          "@type": "type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua"
          inlineCode: |
            function envoy_on_request(request_handle)
              -- 向上游主机进行 HTTP 调用,header、body 和 time欧特 如下。
              local headers, body = request_handle:httpCall(
               "lua_cluster",
               {
                [":method"] = "POST",
                [":path"] = "/acl",
                [":authority"] = "internal.org.net"
               },
              "authorize call",
              5000)
            end
  # 第二个补丁添加了被 lua 代码引用的 cluster,cds 匹配被省略,因为正在添加一个新的 cluster。
  - applyTo: CLUSTER
    match:
      context: SIDECAR_OUTBOUND
    patch:
      operation: ADD
      value: # cluster 配置
        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

下面的例子覆盖了 SNI 主机 app.example.comistio-system 命名空间的 ingress gateway 的监听器中的 HTTP 连接管理器的某些字段(HTTP 空闲超时和X-Forward-For信任跳数)。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: hcm-tweaks
  namespace: istio-system
spec:
  workloadSelector:
    labels:
      istio: ingressgateway
  configPatches:
  - applyTo: NETWORK_FILTER # HTTP 连接管理器是 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

下面的例子插入了一个产生 istio_operationId 属性的 attributegen 过滤器,该属性被 istio.stats fiter 消费。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 # 这个过滤器将在 Istio 统计过滤器之前运行。
      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 # 该过滤器将在 Istio authz 过滤器之后运行。
      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 # 本地 ext auth 服务器要求的。

myns 命名空间中的一个工作负载需要访问一个不接受初始元数据的不同 ext_auth服务器。由于 proto merge 不能删除字段,下面的配置使用 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

下面的例子为所有 inbound 的 sidecar HTTP 请求部署了一个 Wasm 扩展。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: wasm-example
  namespace: myns
spec:
  configPatches:
# 第一个补丁定义了一个 Wasm 扩展,并提供了一个 URL 来获取 Wasm 二进制文件,以及二进制配置。它应该出现在应用它的下一个补丁之前。这个资源对命名空间 "myns" 中的所有代理是可见的。有可能在多个命名空间为同一名称 "my-wasm-extension" 提供多个定义。我们建议,如果需要覆盖,那么可以用 REPLACE 覆盖每个命名空间的根级定义;如果不需要覆盖,那么这个名字应该用命名空间 "myns/my-wasm-extension" 来限定,以避免意外的名字冲突。
  - applyTo: EXTENSION_CONFIG
    patch:
      operation: ADD # REPLACE is also supported, and would override a cluster level resource with the same name.
      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: |
                {}
  # 第二个补丁指示将上述 Wasm 过滤器应用于 listener/http 连接管理器。
  - applyTo: HTTP_FILTER
    match:
      context: SIDECAR_INBOUND
    patch:
      operation: ADD
      filterClass: AUTHZ # 这个过滤器将在 Istio authz 过滤器之后运行。
      value:
        name: my-wasm-extension # 这个必须匹配上面的名字。
        config_discovery:
          config_source:
            api_config_source:
              api_type: GRPC
              transport_api_version: V3
              grpc_services:
              - envoy_grpc:
                  cluster_name: xds-grpc
          type_urls: ["envoy.extensions.filters.http.wasm.v3.Wasm"]

关于 EnvoyFilter 配置的详细用法请参考 Istio 官方文档

参考

最后更新于