Envoy Filter用于自定義控制面生成的Envoy配置。您可以使用Envoy Filter修改配置中某些字段的值、添加特定的過濾器、添加全新的監聽器、Cluster(Envoy中Cluster指一組接受來自Envoy的流量的上游主機)等。與其他Istio網絡對象不同,Envoy Filters是疊加應用。對于特定命名空間中的給定工作負載,可以存在任意數量的Envoy Filters。本文介紹Envoy Filter的注意事項、配置示例和字段說明。
注意事項
使用此功能需謹慎操作,不正確的配置可能會破壞整個網格的穩定性。
此API的某些方面與Istio網絡子系統的內部實現以及Envoy的XDS API緊密相連。雖然Envoy Filter API本身將保持向后兼容性,但在服務網格版本升級過程中,通過此機制提供的任何Envoy配置都應仔細檢查,以確保已刪除和適當替換已棄用字段。
當多個Envoy Filters綁定到給定命名空間中的同一工作負載時,所有補丁將按創建時間的順序依次處理。如果多個Envoy Filters配置之間存在沖突,將會導致未定義的行為。
若要將Envoy Filter資源應用于系統中的所有工作負載(Sidecar和Gateway),請在istio-system命名空間中定義資源,資源中不要添加workloadSelector字段。
配置示例
示例一:為所有Sidecar的出站端口9307添加自定義協議過濾器
在名為istio-config的istio-system命名空間中聲明一個全局默認EnvoyFilter資源,為系統中所有Sidecar的出站端口9307添加自定義協議過濾器。該過濾器聲明在tcp_proxy
過濾器執行之前生效。同時,它還為網關和Sidecar中的所有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命名空間中的reviews服務8080端口的所有入站HTTP調用開啟Envoy的Lua過濾器
以下示例為發往bookinfo命名空間中的reviews服務8080端口的所有入站HTTP調用開啟Envoy的Lua過濾器。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:
# 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"
inlineCode: |
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命名空間下的入口網關監聽器中的過濾器
以下示例針對SNI主機名app.example.com,覆寫位于istio-system命名空間下的入口網關監聽器中的過濾器http_connection_manager
中的部分字段(HTTP idle timeout和X-Forward-For trusted hops)。
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
示例四:在myns命名空間中插入一個attributegen過濾器
以下示例插入了一個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.
字段說明
EnvoyFilter
EnvoyFilter提供一種機制來自定義控制面生成的Envoy配置。EnvoyFilters按照生效優先級從高到低依次為:istio-system命名空間中的所有EnvoyFilters、工作負載命名空間中所有匹配的EnvoyFilters。
字段 | 類型 | 是否必選 | 說明 |
workloadSelector | 否 | 用于選擇Pod的條件,被選中的Pod將應用此補丁配置。如果省略,則該配置中的補丁集將應用于同一命名空間中的所有工作負載實例。如果EnvoyFilter存在于istio-system命名空間中,則它將應用于任何命名空間中的所有適用工作負載。 | |
configPatches | 是 | 具有匹配條件的一個或多個補丁。 | |
priority | int32 | 否 | 優先級定義在上下文中應用補丁集的順序。當一個補丁依賴于另一個補丁時,補丁應用的順序較為重要。 API提供以下兩種主要的補丁排序原則:
priority的默認值為0,取值范圍為[min-int32,max-int32]。具有負優先級的補丁集在默認補丁集之前處理。具有正優先級的補丁集在默認補丁集之后處理。建議從10的倍數優先級值開始,以留有進一步插入的空間。 |
EnvoyFilter.ProxyMatch
要匹配的代理屬性。
字段 | 類型 | 是否必選 | 說明 |
proxyVersion | string | 否 | Golang RE2格式的正則表達式,可以用它來選擇使用特定版本的Istio代理。一個代理的Istio版本是從節點元數據字段ISTIO_VERSION中讀取,該字段的值是Sidecar代理連接到控制面時,由Sidecar代理提供。該值作為環境變量(ISTIO_META_ISTIO_VERSION)嵌入到Istio代理Docker鏡像中。自定義代理實現應提供此元數據變量以利用Istio版本檢查選項。 |
metadata | map<string, string> | 否 | 該選項用于匹配代理連接到控制面時提供的節點元數據。雖然Envoy的節點元數據類型為Struct,但Pilot只處理字符串鍵值對。元數據中指定的所有鍵必須與確切的值匹配。如果任何指定的鍵不存在或值不能匹配,則將匹配失敗。 |
EnvoyFilter.ClusterMatch
必須滿足ClusterMatch中指定的條件才能將補丁應用到集群。
字段 | 類型 | 是否必選 | 說明 |
portNumber | uint32 | 否 | Cluster的服務端口。如果省略,則適用于任何端口的Cluster。 說明 對于入站Cluster,此字段應是服務的目標端口。 |
service | string | 否 | 此集群的完全限定服務名稱。如果省略,則適用于任何服務的Cluster。對于通過集群外服務(Service Entry)定義的服務,服務名稱與集群外服務中定義的主機相同。 說明 對于入站Cluster,此字段將被忽略。 |
subset | string | 否 | 與服務關聯的子集。如果省略,則適用于服務的任何子集的Cluster。 |
name | string | 否 | 要匹配的Cluster的確切名稱。要按名稱匹配特定Cluster,例如內部生成的Passthrough集群,請將clusterMatch中除name外的所有字段留空。 |
EnvoyFilter.RouteConfigurationMatch
必須滿足RouteConfigurationMatch中指定的條件,才能將補丁應用于路由配置對象或路由配置中的特定虛擬主機。
字段 | 類型 | 是否必選 | 說明 |
portNumber | uint32 | 否 | 生成此路由配置的服務端口號或網關服務器端口號。如果省略,則適用于所有端口的路由配置。 |
portName | string | 否 | 僅適用于GATEWAY上下文。生成此路由配置的網關服務器端口名稱。 |
gateway | string | 否 | 生成此路由配置的Istio網關配置的命名空間/名稱。僅適用于上下文為GATEWAY的情況。應采用命名空間/名稱格式。結合portNumber和portName使用此字段,可以準確地為網關配置對象中特定HTTPS服務器選擇Envoy路由配置。 |
vhost | 否 | 匹配路由配置中的特定虛擬主機并將補丁應用到虛擬主機。 | |
name | string | 否 | 要匹配的路由配置名稱。可用于按名稱匹配特定的路由配置,例如內部http_proxy為所有Sidecar生成的路由配置。 |
EnvoyFilter.ListenerMatch
必須滿足ListenerMatch中指定的條件,才能將補丁應用到所有過濾器鏈中的特定監聽器,或監聽器內的特定過濾器鏈。
字段 | 類型 | 是否必選 | 說明 |
portNumber | uint32 | 否 | 向Pod發送或接收流量的服務端口或網關端口。如果未指定,則匹配所有監聽器。即使是為Pod生成的入站監聽器,也應該只使用服務端口(而不是Pod端口)來匹配監聽器。 |
filterChain | 否 | 匹配監聽器中的特定過濾器鏈。如果指定,補丁將應用于過濾器鏈(以及指定的特定過濾器)而不是監聽器中的其他過濾器鏈。 | |
listenerFilter | string | 否 | 匹配特定的監聽器過濾器。如果指定,補丁將應用于指定的監聽器過濾器。 |
name | string | 否 | 按名稱匹配特定的監聽器。Pilot生成的監聽器通常命名為 |
EnvoyFilter.Patch
Patch指定應如何修改所選對象。
字段 | 類型 | 是否必選 | 說明 |
operation | 否 | 指定應如何應用補丁。 | |
value | Struct | 否 | 正在修補的對象的JSON配置。這將使用Proto合并語義與路徑中的現有Proto合并。 |
filterClass | 否 | 確定過濾器插入順序。 |
EnvoyFilter.EnvoyConfigObjectMatch
將補丁應用于給定代理的生成配置之前需滿足的匹配條件。
字段 | 類型 | 是否必選 | 說明 |
context | 否 | 要匹配的特定配置生成上下文。控制面會在網關、流量進入Sidecar和流量離開Sidecar的上下文中生成Envoy配置。 | |
proxy | 否 | 匹配與代理關聯的屬性。 | |
listener | 否 | 匹配Envoy的監聽器屬性。 | |
routeConfiguration | 否 | 匹配Envoy HTTP路由配置屬性。 | |
cluster | 否 | 匹配Envoy Cluster屬性。 |
EnvoyFilter.EnvoyConfigObjectPatch
對Envoy配置對象進行的更改。
字段 | 類型 | 是否必選 | 說明 |
applyTo | 否 | 指定應在Envoy配置中的哪個位置應用補丁。match應該基于applyTo去選擇適當的對象。
| |
match | 否 | 匹配監聽器、路由配置或Cluster。 | |
patch | 否 | 操作應用的補丁。 |
EnvoyFilter.RouteConfigurationMatch.RouteMatch
在路由配置中匹配虛擬主機內的特定路由。
字段 | 類型 | 是否必選 | 說明 |
name | string | 否 | 默認生成的Route對象被命名為default。虛擬服務生成的路由對象將具有虛擬服務的HTTP路由中使用的名稱。 |
action | 否 | 匹配具有特定操作類型的路由。 |
EnvoyFilter.RouteConfigurationMatch.VirtualHostMatch
匹配路由配置中的特定虛擬主機。
字段 | 類型 | 是否必選 | 說明 |
name | string | 否 | Istio生成的VirtualHosts對象命名為 |
route | 否 | 匹配虛擬主機中的特定路由。 |
EnvoyFilter.ListenerMatch.FilterChainMatch
對于具有多個過濾器鏈的偵聽器(例如具有Permissive mTLS的Sidecar上的入站監聽器、具有多個SNI匹配的網關監聽器),可以使用過濾器鏈匹配來選擇要修改的特定過濾器鏈。
字段 | 類型 | 是否必選 | 說明 |
name | string | 否 | 分配給過濾器鏈的名稱。 |
sni | string | 否 | 過濾器鏈的匹配條件使用的SNI值。如果過濾器鏈沒有sni匹配,則此條件將為false。 |
transportProtocol | string | 否 | 僅適用于SIDECAR_INBOUND上下文。如果非空,則在確定過濾器鏈匹配時要考慮傳輸協議。當
|
applicationProtocols | string | 否 | 僅適用于Sidecar。如果非空,則設置為一組由英文半角逗號(,)分隔的應用協議,用于確定過濾器鏈匹配。當由類似http_inspector的監聽器過濾器檢測到新連接時,將比較此值和新連接的應用協議。取值包括h2、http/1.1和http/1.0。 |
filter | 否 | 要應用補丁的特定過濾器的名稱。將此字段設置為 | |
destinationPort | uint32 | 否 | 過濾器鏈的匹配使用的destinationPort值。如果過濾器鏈沒有destinationPort匹配,則此條件將為false。 |
EnvoyFilter.ListenerMatch.FilterMatch
匹配過濾器鏈中特定過濾器的條件。
字段 | 類型 | 是否必選 | 說明 |
name | string | 否 | 要匹配的過濾器名稱。對于標準的Envoy過濾器,應使用規范過濾器名稱。更多信息,請參見規范過濾器。 |
subFilter | 否 | 此過濾器中要匹配的下一級過濾器。通常用于HTTP Connection Manager和Thrift過濾器。 |
EnvoyFilter.ListenerMatch.SubFilterMatch
在過濾器中匹配特定子過濾器的條件。該字段通常用于匹配envoy.filters.network.http_connection_manager
網絡過濾器內的HTTP過濾器,也適用于Thrift過濾器。
字段 | 類型 | 是否必選 | 說明 |
name | string | 否 | 要匹配的過濾器名稱。 |
EnvoyFilter.RouteConfigurationMatch.RouteMatch.Action
Action指定Envoy在HTTP路由匹配時采取的路由動作。
字段 | 說明 |
ANY | 以下三個動作全部執行。 |
ROUTE | 將流量路由到Cluster或加權Cluster。 |
REDIRECT | 重定向請求。 |
DIRECT_RESPONSE | 直接返回包含特定負載的響應。 |
EnvoyFilter.Patch.Operation
Operation指定應如何將補丁應用于選中的配置。
字段 | 說明 |
MERGE | 使用Proto合并語義將提供的配置與生成的配置合并。如果您要完整指定配置,請改用REPLACE。 |
ADD | 將提供的配置添加到現有列表(監聽器、Cluster、虛擬主機、網絡過濾器或HTTP過濾器)。當applyTo設置為ROUTE_CONFIGURATION或HTTP_ROUTE時,將忽略此操作。 |
REMOVE | 從列表(監聽器、Cluster、虛擬主機、網絡過濾器、路由或HTTP過濾器)中刪除所選對象,不需要指定值。當applyTo設置為ROUTE_CONFIGURATION或HTTP_ROUTE時,將忽略此操作。 |
INSERT_BEFORE | 對命名對象數組執行插入操作。此操作通常僅在過濾器或路由的上下文中有用,其中元素的順序很重要。因為選擇的是第一個匹配的元素,路由應基于最具體到最一般的匹配條件進行排序。對于Cluster和虛擬主機,數組中元素的順序無關緊要。此操作將會在選定的過濾器或子過濾器之前插入。如果沒有選擇過濾器,指定的過濾器將被插入到列表的前面。 |
INSERT_AFTER | 對命名對象數組上執行插入操作。此操作通常僅在過濾器或路由的上下文中有用,其中元素的順序很重要。因為選擇的是第一個匹配的元素,路由應基于最具體到最一般的匹配條件進行排序。對于Cluster和虛擬主機,數組中元素的順序無關緊要。此操作將會在選定的過濾器或子過濾器之后插入。如果未選定過濾器,則指定的過濾器將插入到列表的最后面。 |
INSERT_FIRST | 對命名對象數組上執行插入操作。此操作通常僅在過濾器或路由的上下文中有用,其中元素的順序很重要。因為選擇的是第一個匹配的元素,路由應基于最具體到最一般的匹配條件進行排序。對于Cluster和虛擬主機,數組中元素的順序無關緊要。根據所選過濾器的存在與否在列表的首部插入。當您希望過濾器基于Match子句中指定的匹配條件在列表中排在第一位時,可以使用本字段。 |
REPLACE | 用新內容替換命名過濾器的內容。REPLACE操作僅適用于HTTP_FILTER和NETWORK_FILTER。如果未找到命名過濾器,則此操作無效。 |
EnvoyFilter.Patch.FilterClass
FilterClass用于確定過濾器鏈中過濾器的插入點,插入點相對于控制平面隱式插入的過濾器而言。此項應與ADD操作一起使用。這是添加過濾器的首選插入機制,而不是使用INSERT_*操作,因為那些操作依賴于潛在不穩定的過濾器名稱。如果您的過濾器依賴于或影響過濾器鏈中的另一個過濾器的功能,則過濾器排序較為重要。在過濾器類中,過濾器按處理順序插入。
字段 | 說明 |
UNSPECIFIED | 控制平面決定在何處插入過濾器。如果過濾器是獨立于其他過濾器,則不要指定FilterClass。 |
AUTHN | 在Istio身份驗證過濾器之后插入過濾器。 |
AUTHZ | 在Istio授權過濾器之后插入過濾器。 |
STATS | 在Istio統計過濾器之前插入過濾器。 |
EnvoyFilter.ApplyTo
ApplyTo指定應在Envoy配置中的哪個位置應用給定的補丁。
字段 | 說明 |
LISTENER | 將補丁應用于監聽器。 |
FILTER_CHAIN | 將補丁應用于過濾器鏈。 |
NETWORK_FILTER | 將補丁應用于網絡過濾器鏈,以修改現有過濾器或添加新過濾器。 |
HTTP_FILTER | 將補丁應用于HTTP連接管理器中的HTTP過濾器鏈,以修改現有過濾器或添加新過濾器。 |
ROUTE_CONFIGURATION | 將補丁應用于HTTP Connection Manager內的路由配置(DRS輸出)。該字段不適用于虛擬主機。路由配置對象上僅允許使用MERGE操作。 |
VIRTUAL_HOST | 將補丁應用于路由配置內的虛擬主機。 |
HTTP_ROUTE | 將補丁應用于路由配置中匹配的虛擬主機內的路由對象。 |
CLUSTER | 將補丁應用于CDS輸出中的Cluster,也可用于添加新Cluster。 |
EXTENSION_CONFIG | 在ECDS輸出中應用補丁或添加擴展配置。僅HTTP過濾器支持ECDS。 |
BOOTSTRAP | 將補丁應用于引導程序配置。 |
LISTENER_FILTER | 將補丁應用于監聽器過濾器。 |
EnvoyFilter.PatchContext
PatchContext根據流量方向和工作負載類型選擇一類配置。
字段 | 說明 |
ANY | Sidecar和網關中的所有監聽器、路由或Cluster。 |
SIDECAR_INBOUND | Sidecar中的入站所有監聽器、路由或Cluster。 |
SIDECAR_OUTBOUND | Sidecar中的出站監聽器、路由或Cluster。 |
GATEWAY | 網關監聽器、路由或Cluster。 |