TODO: 修改引用

通过使用 EnvoyFilter 自定义资源定义(CRD),你可以自定义请求头和响应头。EnvoyFilter CRD 允许你直接修改 Istio 代理(Envoy)的配置,从而在请求或响应流经代理时添加、删除或修改其头信息。

前提条件

步骤 1:定义 EnvoyFilter 模板

Istio 允许你使用模板创建 EnvoyFilter。这个模板可以用于创建多个 EnvoyFilter,并应用于不同的工作负载和命名空间,提高配置的可重用性和管理效率。

以下是一个 EnvoyFilter 模板的示例。有关更多信息,请参见 EnvoyFilter 参考

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: custom-header-filter-template
  namespace: istio-system
spec:
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: ANY
        listener:
          filterChain:
            filter:
              name: envoy.filters.network.http_connection_manager
              subFilter:
                name: envoy.filters.http.router
        proxy:
          proxyVersion: '^1\.20.*'
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.lua
          typed_config:
            '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
            inlineCode: |
              function envoy_on_request(request_handle)
                -- 从请求头中获取指定的键和值
                local header_key = "x-custom-request-header" -- 你要获取的请求头的键
                local header_value = request_handle:headers():get(header_key)
                if header_value then
                  -- 将数据写入 OpenTelemetry Baggage
                  local baggage = header_key .. "=" .. header_value
                  request_handle:headers():add("baggage", baggage)
                  request_handle:streamInfo():dynamicMetadata():set("envoy.filters.http.lua", "otel.baggage", baggage)
                end
              end

              function envoy_on_response(response_handle)
                -- 从动态元数据中获取 OpenTelemetry Baggage
                local metadata = response_handle:streamInfo():dynamicMetadata():get("envoy.filters.http.lua") or {}
                local baggage = metadata["otel.baggage"]
                if baggage then
                  -- 将 OpenTelemetry Baggage 写入新的响应头
                  local new_header_key = "x-custom-response-header" -- 新的响应头的键
                  response_handle:headers():add(new_header_key, baggage)
                end
              end              

注意:

  • proxyVersion 字段的值替换为你的 Istio 代理版本(例如,Istio 1.18.x 对应 ^1\.18.*)。
  • Lua 过滤器中的代码通过添加自定义头信息,基于现有的头和动态元数据来修改请求和响应头。

步骤 2:使用模板创建 EnvoyFilter

定义 EnvoyFilter 模板后,你可以创建一个 EnvoyFilter,将模板应用于特定的工作负载或命名空间。这样,基于该模板创建的 EnvoyFilter 只会影响指定的工作负载或命名空间。

以下示例创建了一个名为 custom-header-filter 的 EnvoyFilter,将 Lua 过滤器应用于 default 命名空间中带有标签 app: httpbinversion: v1 的工作负载。

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: custom-header-filter
  namespace: default
spec:
  workloadSelector:
    labels:
      app: httpbin
      version: v1
  configPatches:
    - applyTo: HTTP_FILTER
      match:
        context: SIDECAR_INBOUND
        listener:
          filterChain:
            filter:
              name: envoy.filters.network.http_connection_manager
              subFilter:
                name: envoy.filters.http.router
        proxy:
          proxyVersion: '^1\.20.*'
      patch:
        operation: INSERT_BEFORE
        value:
          name: envoy.lua
          typed_config:
            '@type': type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
            inlineCode: |
              function envoy_on_request(request_handle)
                -- 从请求头中获取指定的键和值
                local header_key = "x-custom-request-header" -- 你要获取的请求头的键
                local header_value = request_handle:headers():get(header_key)
                if header_value then
                  -- 将数据写入 OpenTelemetry Baggage
                  local baggage = header_key .. "=" .. header_value
                  request_handle:headers():add("baggage", baggage)
                  request_handle:streamInfo():dynamicMetadata():set("envoy.filters.http.lua", "otel.baggage", baggage)
                end
              end

              function envoy_on_response(response_handle)
                -- 从动态元数据中获取 OpenTelemetry Baggage
                local metadata = response_handle:streamInfo():dynamicMetadata():get("envoy.filters.http.lua") or {}
                local baggage = metadata["otel.baggage"]
                if baggage then
                  -- 将 OpenTelemetry Baggage 写入新的响应头
                  local new_header_key = "x-custom-response-header" -- 新的响应头的键
                  response_handle:headers():add(new_header_key, baggage)
                end
              end              

解释:

  • workloadSelector 指定了 EnvoyFilter 适用的工作负载,这些工作负载具有标签 app: httpbinversion: v1
  • configPatches 部分将模板中定义的 Lua 过滤器应用于指定的工作负载。
  • 确保元数据中的 namespace 字段与你的工作负载所在的命名空间一致。

重要提示:

EnvoyFilter 是一种强大但复杂的配置方法,它直接修改底层的 Envoy 配置。在使用 EnvoyFilter 时,建议你熟悉 Envoy 的配置模型,并谨慎修改以避免潜在错误。此外,随着 Istio 版本的升级,配置结构可能会发生变化,请注意兼容性问题。

步骤 3:在访问日志中查看自定义的请求头和响应头

Istio 允许你自定义日志格式。你可以在访问日志中获取请求头、响应头和 Envoy 内置变量的值。有关更多信息,请参见自定义访问日志的格式

以下表格列出了在访问日志中显示内容的自定义字段:

字段 类型 日志格式表达式
my-x-custom-request-header 请求属性 %REQ(x-custom-request-header)%
baggage-from-request 请求属性 %REQ(baggage)%
my-x-custom-response-header 响应属性 %RESP(x-custom-response-header)%

你可以使用以下命令查看 httpbin Pod 的访问日志:

kubectl logs -l app=httpbin -c istio-proxy

你将看到类似以下内容的日志:

{
    "bytes_received": "0",
    "bytes_sent": "490",
    "duration": "1",
    "method": "GET",
    "path": "/headers",
    "protocol": "HTTP/1.1",
    "response_code": "200",
    "response_flags": "-",
    "my-x-custom-request-header": "xxx",
    "baggage-from-request": "x-custom-request-header=xxx",
    "my-x-custom-response-header": "x-custom-request-header=xxx"
}

在这个日志条目中:

  • my-x-custom-request-header 显示了自定义请求头 x-custom-request-header 的值。
  • baggage-from-request 显示了 Lua 过滤器添加的行李(Baggage)信息。
  • my-x-custom-response-header 显示了自定义响应头 x-custom-response-header 的值。

参考

https://www.alibabacloud.com/help/en/asm/user-guide/customize-the-request-header-and-response-header-by-using-the-envoy-filter-resource

最后更新于 2024/11/27