本文使用istio版本为v1.9.2。
1. Istio与Envoy
Envoy 是专为大型现代 SOA(面向服务架构)架构设计的 L7 代理和通信总线。Envoy支持同时在L3\L4\L7层来对数据进行处理操作。
Istio默认使用Envoy作为其智能代理工作在数据平面。
Pilot是istio中的一个组件,pilot-agent进程根据K8S API Server中的配置信息生成Envoy的配置文件,并负责启动Envoy进程。Pilot在启动Envoy时会为其bootstrap静态配置,配置文件在/etc/istio/proxy/envoy-rev0.json
。
此外,通过istio对业务容器进行的流量管理都是动态配置并实时生效的。Envoy通过数据面标准API的xDS接口从pilot获取动态配置信息,包括路由(route),监听器(listener),服务集群(cluster)和服务端点(endpoint)。
因此Envoy的配置主要包括以下四部分:
- bootstrap:Envoy proxy 启动时候加载的静态配置。
- listeners:监听器配置,使用 LDS 下发。
- clusters:集群配置,静态配置中包括 xds-grpc 和 zipkin 地址,动态配置使用 CDS 下发。
- routes:路由配置,静态配置中包括了本地监听的服务的集群信息,其中引用了 cluster,动态配置使用 RDS 下发。
通过Envoy的管理端口15000,我们可以通过其api导出所有配置:
# kubectl -n bookinfo exec reviews-v3-7b65d86dc8-rh24p -c istio-proxy -- curl http://localhost:15000/config_dump > dump-reviews-v3-envoy-full-config.json
这个文件中的内容,是被istio所管理的所有envoy配置,而非被导出服务自身的全量配置。
2. Istio超时与自动重试
超时
与重试
是istio对HTTP流量管理中重要的功能。通过在virtual service
(vs, 虚拟服务)中添加HTTPRoute.timeout
与HTTPRoute.retries
可以自定义配置超时与重试。
1) Istio添加的默认配置
在istio默认注入sidecar时,默认在创建了动态路由重试策略(参见istio中源码),即在满足retry_on
中指定条件情况下,自动重试2次(猜测官方为了处理连接超时中断问题,见后面章节)。测试服务的envoy配置导出如下:
"route": {
"cluster": "outbound|5000||helloworld.hello.svc.cluster.local",
"timeout": "0s",
"retry_policy": {
"retry_on": "connect-failure,refused-stream,unavailable,cancelled,retriable-status-codes",
"num_retries": 2,
"retry_host_predicate": [
{
"name": "envoy.retry_host_predicates.previous_hosts"
}
],
"host_selection_retry_max_attempts": "5",
"retriable_status_codes": [
503
]
}
其中各个字段详细含义参见官网:
-
cluster: 请求将被路由到的上游集群目标;
-
timeout: 上游路由超时时间,默认15秒。时间跨度上从下游请求到上游响应时间全都被考虑在内。设为0则禁用路由超时。
-
retry_policy:路由重试策略。优先级高于虚拟主机级别的路由重试策略。
经测试,通过istio的VirtualService仅修改`spec.http.retries.attempts=0`**无法关闭**默认的重试功能,该字段只能设置为**大于0**的数值,此问题参见[github](https://github.com/istio/istio/issues/14900)。
2) 重试触发条件
Istio默认添加的重试只在特定条件下才会触发,通过vs中的spec.http.retries.retryOn
来指定,对应到envoy配置中的字段retry_on
。
Envoy默认支持的触发条件可参见envoy官方。Istio默认创建的触发条件为:
-
connect-failure: 上游服务器对请求的失败响应,包括连接超时、5xx等,注意请求失败指的是TCP级而非请求级别(如通过路由配置重试策略或x-envoy-upstream-rq-timeout-ms消息头等);
-
refused-stream: 上游服务器重置了一个
REFUSED_STREAM
流(stream)状态码,该类型一般暗示可以安全的重试; -
retriable-status-codes: 根据路由策略中的
route.retriable_status_codes
配置或x-envoy-retriable-status-codes消息头; -
cancelled:GRPC响应头中返回了“cancelled” (1)状态码;
-
unavailable:GRPC响应头中返回了“unavailable” (14)状态码;
除了上述在重试策略中配置的方式,还可以通过在请求头中添加特定的header进行配置:
-
x-envoy-retriable-status-codes:该消息头用于告知envoy在什么条件下结合重试策略进行重试。当在配置重试策略情况下,该消息头列表中的状态码将被认为是重试策略的一个补充。
多个状态码通过','来连接,是一种'或'的关系,如"504,409"。
该消息头只有通过内部客户端发出的请求才能生效。
-
x-envoy-retriable-header-names:该消息头用于告知envoy在什么条件下结合重试策略进行重试。当在配置重试策略情况下,该消息头列表中的消息头值将被认为是重试策略的一个补充。
多个消息头通过','来连接,是一种'或'的关系,如"X-Upstream-Retry,X-Try-Again"。消息头是大小写敏感的,并且只有在重试策略中使能
retriable-headers
(路由策略的retry_on配置下)下生效。该消息头只有通过内部客户端发出的请求才能生效。
3) 最大重试次数
若创建了一个路由重试策略 或 虚拟主机重试策略 ,未显示指定情况下envoy默认进行一次重试;若路由重试策略未设置并且x-envoy-retry-on
或 x-envoy-retry-grpc-on
消息头未指定,envoy并不会进行失败重试;