全部產品
Search
文件中心

Alibaba Cloud Service Mesh:通過EnvoyFilter資源自訂要求標頭和回應標頭

更新時間:Jun 30, 2024

您可以使用EnvoyFilter資源來自訂要求標頭和回應標頭。EnvoyFilter資源允許您直接修改Istio代理(Envoy)的配置,從而可以在請求或響應流經代理時添加、刪除或修改頭資訊。

前提條件

部署httpbin應用

步驟一:定義Envoy過濾器模板

ASM支援通過Envoy過濾器模板建立Envoy過濾器。同一個Envoy過濾器模板可以被用來建立多個Envoy過濾器,應用於不同的工作負載和命名空間,從而提高配置的複用性和管理效率。

Envoy過濾器模板YAML樣本如下。更多資訊,請參見Envoy Filter

展開查看EnvoyFilter YAML

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: custom-header-filter
  namespace: my-namespace
spec:
  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)
                -- 從要求標頭中擷取一個header key和value。
                local header_key = "x-custom-request-header" -- 您想擷取的要求標頭的key。
                local header_value = request_handle:headers():get(header_key)
                if header_value then
                  -- 寫入到Otel 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)
                -- 從動態中繼資料中擷取Otel Baggage。
                local metadata = response_handle:streamInfo():dynamicMetadata():get("envoy.filters.http.lua") or {}
                local baggage = metadata["otel.baggage"]
                if baggage then
                  -- 把Otel Baggage寫入到另一個header中。
                  local new_header_key = "x-custom-response-header" -- 新的回應標頭的key。
                  response_handle:headers():add(new_header_key, baggage)
                end
              end
  workloadSelector:
    labels:
      app: httpbin
      version: v1

  • 如果您使用的Istio1.9及以上版本,請根據版本替換proxyVersion欄位。

  • 如果您使用的Istio為1.8及以下版本,請根據版本替換proxyVersion欄位,並且替換上述EnvoyFilter中的envoy.filters.network.http_connection_managerenvoy.http_connection_managerenvoy.filters.http.routerenvoy.routertype.googleapis.com/envoy.extensions.filters.http.lua.v3.Luatype.googleapis.com/envoy.config.filter.http.lua.v2.Lua

步驟二:使用Envoy過濾器模板建立EnvoyFilter資源

Envoy過濾器模板建立成功後,您需要將Envoy過濾器模板綁定至指定的工作負載或命名空間,從而使Envoy過濾器僅在指定工作負載或命名空間上生效。綁定工作負載或命名空間後,將自動建立Envoy過濾器。

建立出來的EnvoyFilter資源定義內容類別似如下,它表示向進入工作負載的請求添加一個自訂要求標頭,並向發出的響應添加一個自訂回應標頭。以下樣本將建立一個名為custom-header-filter的EnvoyFilter資源,並配置了Lua過濾器來添加請求和回應標頭。它會對所有帶有app: my-app標籤的工作負載生效。

展開查看EnvoyFilter YAML

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: custom-header-filter
  namespace: my-namespace
spec:
  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)
                -- 從要求標頭中擷取一個header key和value
                local header_key = "x-custom-request-header" -- 你想擷取的要求標頭的key。
                local header_value = request_handle:headers():get(header_key)
                if header_value then
                  -- 寫入到Otel 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)
                -- 從動態中繼資料中擷取Otel Baggage。
                local metadata = response_handle:streamInfo():dynamicMetadata():get("envoy.filters.http.lua") or {}
                local baggage = metadata["otel.baggage"]
                if baggage then
                  -- 把Otel Baggage寫入到另一個header中。
                  local new_header_key = "x-custom-response-header" -- 新的回應標頭的key。
                  response_handle:headers():add(new_header_key, baggage)
                end
              end
  workloadSelector:
    labels:
      app: httpbin
      version: v1

重要

EnvoyFilter是一種強大但複雜的配置方式,它直接修改了底層Envoy配置。因此,在使用EnvoyFilter時,建議您熟悉Envoy的配置模型,謹慎地修改以避免潛在的副作用。同時,EnvoyFilter的配置可能會隨著Istio版本的升級而變動,請注意相容性問題。

步驟三:通過日誌查看自訂請求和響應內容

ASM提供自訂日誌格式的功能,支援從請求Header、響應Header、Envoy內建值中取值。具體操作,請參見可觀測配置

如下所示,新增3個欄位用於在日誌中顯示內容,具體設定如下:

變數名稱

類型

變數值

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的日誌內容,可以看到類似如下內容:

{
    "bytes_received": "0",
    "bytes_sent": "490",
    "duration": "1",
    "istio_policy_status": "-",
    "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",
}