三、Istio流量治理(二)
因语雀与csdn markdown 格式有区别,请查看原文:
https://www.yuque.com/dycloud/pss8ys
一、流量治理重要配置详解
1.1 Pilot 配置分发机制
Pilot 负责网格中数据平面相关配置信息的获取、生成及分发,它通过用户配置及服务注册表获取网格配置信息并将其转换成 xDS 接口的标准数据格式,然后经 gRPC 分发至相关的 Envoy。
**<font style="color:#DF2A3F;">Service Registry</font>**
:服务注册表中存储有相关平台上注册的各 Service 相关信息,例如 Kubernetes 的 Service 等。
**<font style="color:#DF2A3F;">Config Storage</font>**
:配置存储,例如 K8S 中的 APIServer,配置信息通常是由用户提供,对于 k8s 来说,他们以 k8s crd 格式提供并存储在 APIServer 中。
1.2 Pilot 流量管理的相关组件
Pilot工作架构的相关组件包括:<font style="color:#DF2A3F;">pilot-discovery</font>
、<font style="color:#DF2A3F;">k8s apiserver</font>
、<font style="color:#DF2A3F;">Envoy(istio-proxy)</font>
、<font style="color:#DF2A3F;">pilot-agent</font>
,以及命令工具<font style="color:#DF2A3F;">istioctl</font>
和<font style="color:#DF2A3F;">kubectl</font>
;
Pilot项目自身的组件也是由工作于控制平面的<font style="color:#DF2A3F;">polit-discovery</font>
和工作于数据平面的<font style="color:#DF2A3F;">pilot-agent</font>
共同组成;
控制平面相关组件
**<font style="color:#DF2A3F;">pilot-discovery</font>**
:它主要完成以下功能- 从
<font style="color:#DF2A3F;">Service Registry(Service)</font>
中获取服务信息; - 从
<font style="color:#DF2A3F;">API Server</font>
中获取配置信息; - 将服务信息和配置信息转化为
<font style="color:#DF2A3F;">Envoy</font>
的配置格式,并通过<font style="color:#DF2A3F;">xDS API</font>
完成分发;
- 从
**<font style="color:#DF2A3F;">Kubernetes API Server </font>**
- 配置存储系统,负责存储用户以kubernetes crd格式(例如
**<font style="color:#DF2A3F;">VirtualService</font>**
和**<font style="color:#DF2A3F;">DestinationRule</font>**
等)提供的配置信息;
- 配置存储系统,负责存储用户以kubernetes crd格式(例如
数据平面相关组件:
**<font style="color:#DF2A3F;">Istio proxyv2</font>**
镜像启动的容器中会运行<font style="color:#DF2A3F;">pilot-agent</font>
和<font style="color:#DF2A3F;">envoy</font>
两个进程;
istio-proxy@client-f98d4768d-c6m7b:/$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
istio-p+ 1 0.5 0.1 1253196 36924 ? Ssl 06:04 0:00 /usr/local/bin/pilot-agent proxy sidecar --domain app.svc.cluster.local --proxyLogLevel=warning --proxyComponentLogLevel=misc:error --log_output_leve
istio-p+ 11 0.7 0.2 3328592 85900 ? Sl 06:04 0:00 /usr/local/bin/envoy -c etc/istio/proxy/envoy-rev.json --drain-time-s 45 --drain-strategy immediate --local-address-ip-version v4 --file-flush-interv
istio-p+ 25 0.0 0.0 4584 3904 pts/0 Ss 06:05 0:00 bash
istio-p+ 32 0.0 0.0 7884 3968 pts/0 R+ 06:05 0:00 ps aux
**<font style="color:#DF2A3F;">pilot-agent </font>**
- 基于k8s api server为envoy初始化出可用的
<font style="color:#DF2A3F;">boostrap</font>
配置文件并启动envoy; - 监控并管理envoy的运行状态,包括envoy出错时重启envoy,以及envoy配置变更后将其重载等;
- 基于k8s api server为envoy初始化出可用的
**<font style="color:#DF2A3F;">envoy</font>****<font style="color:rgb(0,0,0);"> </font>**
- envoy由
<font style="color:#DF2A3F;">pilot-agent</font>
进程基于生成bootstrap配置进行启动,而后根据配置中指定的pilot地址,通过<font style="color:#DF2A3F;">xDS API</font>
获取动态配置信息; - Sidecar形式的Envoy通过流量拦截机制为应用程序实现入站和出站代理功能;
- envoy由
1.3 流量治理
- Istio的流量路由规则使运维人员可以轻松控制服务之间的流量和API调用
- Istio简化了诸如断路器,超时和重试之类的服务级别属性的配置,并使其易于设置重要任务(如A/B测试, canary部署和基于百分比的流量拆分的分段部署)
- 它还提供了开箱即用的故障恢复功能,有助于使应用程序更强大,以防止相关服务或网络的故障
- 使用Istio进行流量管理从本质上是将流量与底层基础架构的伸缩机制相解耦,从而让运维工程师能够通过
<font style="color:#DF2A3F;">Pilot</font>
指定他们希望流量自身需要遵循哪些规则,而非仅仅只能定义由哪些特定的pod/VM接收流量,并在这些pod/VM之间以受限于数量比例的方式分配流量;<font style="color:#DF2A3F;">Pilot</font>
和<font style="color:#DF2A3F;">Envoy proxy</font>
负责实现流量规则中定义的流量传输机制- 例如,可以通过Pilot指定希望特定服务的5%流量转到Canary版本,而与Canary部署的大小无关,或者根据请求的内容将流量发送到特定版本
- Istio的所有路由规则和控制策略都基于Kubernetes CRD实现,这包括网络功能相关的
**<font style="color:#DF2A3F;">VirtualService</font>**
、**<font style="color:#DF2A3F;">DestinationRule</font>**
、**<font style="color:#DF2A3F;">Gateway</font>**
、**<font style="color:#DF2A3F;">ServiceEntry</font>**
和**<font style="color:#DF2A3F;">EnvoyFilter</font>**
等;
1.4 VirtualService 配置详解
前面其实已经学习了 Istio 中南北、东西向流量的部署服务的方式以及路由规则等,现在来学习一下 virtualService 到底是什么,有哪些配置。
VirtualService(虚拟服务) 是Istio流量管理的核心API,用于定义如何将请求路由到服务网格内的服务。它允许配置:
- 请求路由规则(基于HTTP/HTTPS/TCP等协议)
- 流量拆分和镜像
- 重试、超时和故障注入策略
1.4.1 关键术语
术语 | 说明 |
---|---|
Host | 目标服务标识(K8s Service 名称或 FQDN) |
Subset | 服务子集(由 DestinationRule 定义的服务版本) |
Gateway | 流量入口点(网格入口/出口网关) |
Route | 具体的路由规则(HTTP/TCP/TLS) |
Destination | 路由目标(服务+子集+端口) |
Match Condition | 流量匹配条件(URI/Header/端口等) |
<font style="color:#DF2A3F;">hosts</font>
: 必选字段,用于指定流量请求的目标,可以是一个DNS名称或IP地址;- DNS名称可以使用通配符,也可以使用短格式的Service名称;
<font style="color:#DF2A3F;">gateways</font>
:指定应用流量规则的Gateway资源,在<font style="color:#DF2A3F;">VirtualService</font>
上使用<font style="color:#DF2A3F;">gateways</font>
字段时遵循如下规则- 仅应用于网格内的东西流量时,应省略
**<font style="color:#DF2A3F;">gateways</font>**
字段; - 仅用于引入网格外的流量,为
<font style="color:#DF2A3F;">gateways</font>
字段赋予合适的值(Gateway名称列表)即可- 客户端源自网格外部
<font style="color:#DF2A3F;">Gateway</font>
负责接入这部分流量,<font style="color:#DF2A3F;">VirtualService</font>
负责将这部分流量完成在网格内的路由
- 同时用于网格内和网格外的流量时,需要将
<font style="color:#DF2A3F;">gateways</font>
字段的列表值的其中一项指定为“<font style="color:#DF2A3F;">mesh</font>
”- 客户端既可源自网格外部,也可以是网格内部的流量
- 仅应用于网格内的东西流量时,应省略
<font style="color:#DF2A3F;">http</font>
: 配置http协议的流量管理机制的有序列表,其配置框架称为<font style="color:#DF2A3F;">HTTPRoute</font>
<font style="color:#DF2A3F;">tls</font>
:用于处理非终结的TLS和HTTPS流量的有序列表,其配置框架称为<font style="color:#DF2A3F;">TLSRoute</font>
<font style="color:#DF2A3F;">tcp</font>
:管理四层的TCP流量的有序列表,其配置框架称为<font style="color:#DF2A3F;">TCPRoute</font>
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:name: product-service-route
spec:# 1. 目标服务(必填)hosts:- "product-service.svc.cluster.local" # K8s服务名- "store.example.com" # 外部域名# 2. 应用网关(默认应用网格内流量)gateways:- istio-ingressgateway # 入口网关- mesh # 网格内部流量# 3. HTTP路由规则(核心配置)http:- name: v1-route # 规则名称# 匹配条件match:- uri:prefix: "/v1" # URI前缀匹配headers: # Header匹配x-user-type: exact: "vip"# 路由目标route:- destination:host: product-servicesubset: v1 # 服务子集port: number: 8080weight: 80 # 流量权重# 高级策略timeout: 2s # 超时设置retries: # 重试策略attempts: 3perTryTimeout: 1sfault: # 故障注入delay:percentage: value: 10fixedDelay: 5s# 4. 默认路由(无匹配条件时生效)- route:- destination:host: product-servicesubset: v2
1.4.2 HTTPRoute
HTTPRoute 是 VirtualService 的核心组成部分,用于定义 HTTP/HTTPS 流量的路由规则:
- 与 VirtualService 的关系:
- VirtualService 是顶层对象
<font style="color:#DF2A3F;">HTTPRoute</font>
是其<font style="color:#DF2A3F;">spec.http</font>
字段下的路由规则定义- **一个
**<font style="color:#DF2A3F;">VirtualService</font>**
可包含多个 ****<font style="color:#DF2A3F;">HTTPRoute</font>**
- 核心结构:
http:
- name: "路由规则名称"match: [...] # 匹配条件route: [...] # 路由目标redirect: [...] # 重定向rewrite: [...] # URI重写timeout: ... # 超时retries: ... # 重试fault: ... # 故障注入
匹配条件(match)类型:
<font style="color:rgb(251, 71, 135);">uri</font>
:路径匹配(<font style="color:#DF2A3F;">prefix</font>
/<font style="color:#DF2A3F;">exact</font>
/<font style="color:#DF2A3F;">reg</font><font style="color:rgb(51, 54, 57);">ex</font>
)<font style="color:rgb(251, 71, 135);">headers</font>
:请求头匹配<font style="color:rgb(251, 71, 135);">method</font>
:HTTP方法(GET/POST等)<font style="color:rgb(251, 71, 135);">authority</font>
:Host头匹配<font style="color:rgb(251, 71, 135);">queryParams</font>
:查询参数匹配
<font style="color:#DF2A3F;">virtualservice.http</font>
配置如何处理http流量
- 服务的端口协议是HTTP、HTTP2和GRPC,即在服务的端口名中包含http-、http2-和grpc-等;
- Gateway的端口协议是HTTP、HTTP2和GRPC,或者Gateway终结了TLS;
- ServiceEntry的端口协议是HTTP、HTTP2和GRPC;
路由机制及服务韧性等相关的配置,即满足<font style="color:#DF2A3F;">HTTPMatchRequest</font>
条件的流量可以做如下处理
- 路由到指定目标(HTTPRouteDestination)
- 执行重定向(HTTPRedirect)
- URL重写(HTTPRewrite)
- 请求重试(HTTPRetry)
- 故障注入(HTTPFaultInjection)
- 跨站资源引用(CorsPolicy)
- …
Envoy 中的路由配置可以查看这里:https://www.yuque.com/dycloud/pss8ys/og9o5a4y3o26xzu6
而 Istio 简化了 Envoy 中的路由配置:
1.4.3 HTTPRoute 配置示例
# VirtualService:为 productpage 服务定义路由,将流量全部发往 v1 版本
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: productpage # VirtualService 的名称
spec:hosts:- productpage # 作用的服务名称(Service 名)http:- route:- destination:host: productpage # 后台服务名subset: v1 # 指定发往 v1 版本的 Pod(需有对应 DestinationRule)
---
# VirtualService:为 ratings 服务定义路由,将流量全部发往 v2 版本
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: ratings
spec:hosts:- ratings # 作用的服务名称http:- route:- destination:host: ratings # 后台服务名subset: v2 # 指定发往 v2 版本的 Pod---# VirtualService:为 reviews 服务(FQDN)定义路由及路径重写
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: reviews-route # VirtualService 的名称
spec:hosts:- reviews.prod.svc.cluster.local # 完整域名,K8s 内部 DNS 名http:# 路由1:当路径匹配 /wpcatalog 或 /consumercatalog 时- name: "reviews-v2-routes" # 路由规则名称match:- uri:prefix: "/wpcatalog" # 匹配以 /wpcatalog 前缀的请求- uri:prefix: "/consumercatalog" # 匹配以 /consumercatalog 前缀的请求rewrite:uri: "/newcatalog" # 将请求路径重写为 /newcatalogroute:- destination:host: reviews.prod.svc.cluster.local # 服务的域名subset: v2 # v2 版本# 路由2:其余所有流量默认发往 v1- name: "reviews-v1-route"route:- destination:host: reviews.prod.svc.cluster.local # 服务的域名subset: v1 # v1 版本---
# VirtualService:为 details 服务注入故障,百分百中止并返回555
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: details
spec:hosts:- details # 作用的服务名称http:- fault: # 故障注入配置abort:httpStatus: 555 # 返回 555 状态码percent: 100 # 百分之百请求被中止route:- destination:host: details # 路由目标服务subset: v1 # v1 版本
1.5 DestinationRule 配置详解
<font style="color:rgb(251, 71, 135);">DestinationRule</font>
是 Istio Service Mesh 流量管理的核心资源对象之一,作用是针对服务流量的“下游路由”指定详细细粒度的策略。
部署到 Mesh 的控制面后,Envoy Proxy 会根据规则执行相应的流量调度策略,保障微服务间通信的安全、稳定与弹性。它可以实现:
- 指定服务的负载均衡算法
决定同一目标服务不同 Pod 实例间如何分配请求 - 细化服务子集(subset)
通常配合<font style="color:rgb(251, 71, 135);">VirtualService</font>
做灰度、金丝雀、多版本流量分配,例如 product-v1, product-v2 - 连接池控制
限制上游连接数量/保持/超时等,有效防止雪崩、探活问题放大 - 异常实例剔除(Outlier Detection)
实时检测/剔除故障实例,提升可用性 - 跨命名空间可见性
通过<font style="color:rgb(251, 71, 135);">exportTo</font>
控制规则应用范围 - TLS/加密通讯策略
可为服务间通讯设置自定义的TLS相关配置
1.5.1 资源结构与字段详解
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: productpage-destination # 规则对象名称
spec:host: productpage # 适用的服务名,支持svc短名或FQDNtrafficPolicy: # 整体服务级别的流量控制策略loadBalancer: # 负载均衡策略simple: ROUND_ROBIN # 常见类型还有 LEAST_CONN、RANDOM、PASSTHROUGHoutlierDetection: # 异常实例剔除consecutiveErrors: 3interval: 5sbaseEjectionTime: 15smaxEjectionPercent: 50connectionPool: # 连接池配置(HTTP和TCP)tcp:maxConnections: 500connectTimeout: 30mshttp:http1MaxPendingRequests: 1000http2MaxRequests: 1000maxRequestsPerConnection: 100maxRetries: 3subsets: # 定义服务的多个子集(一般对应服务版本等标签组合)- name: v1labels:version: v1trafficPolicy: # 可为各个子集单独配置流量策略(如自定义v1的负载均衡)loadBalancer:simple: LEAST_CONN- name: v2labels:version: v2
字段名 | 作用及典型用法 |
---|---|
<font style="color:rgb(251, 71, 135);">host</font> | 必填项。规则应用的目标服务名称。可用短名、全名、ServiceEntry等 |
<font style="color:rgb(251, 71, 135);">subsets</font> | 定义服务的“子集”——常以 labels 区分(如版本、区域、多活等) |
<font style="color:rgb(251, 71, 135);">trafficPolicy</font> | 全局流量策略,包括负载均衡、连接池、驱逐、TLS、端口级策略 |
<font style="color:rgb(251, 71, 135);">exportTo</font> | 控制当前规则在哪些命名空间下 Sidecar 可见 (<font style="color:rgb(251, 71, 135);">.</font> 当前,<font style="color:rgb(251, 71, 135);">*</font> 全局) |
子集 subset
<font style="color:#DF2A3F;">name</font>
: 子集名称,与<font style="color:#DF2A3F;">VirtualService</font>
使用的<font style="color:#DF2A3F;">subset</font>
保持一致<font style="color:#DF2A3F;">labels</font>
: 服务实例上需匹配的<font style="color:#DF2A3F;">label</font>
(用于分组/区分版本)<font style="color:#DF2A3F;">trafficPolicy</font>
: 子集专有的流量策略
1.5.2 TrafficPolicy 内部主要子配置
1、<font style="color:#DF2A3F;">loadBalancer</font>
- 常用策略
<font style="color:rgb(251, 71, 135);">ROUND_ROBIN</font>
(轮询,默认参数)<font style="color:rgb(251, 71, 135);">LEAST_CONN</font>
(最少连接)<font style="color:rgb(251, 71, 135);">RANDOM</font>
(随机)<font style="color:rgb(251, 71, 135);">PASSTHROUGH</font>
(跳过流量管理)
- 一致性哈希
loadBalancer:consistentHash:httpHeaderName: "X-User"minimumRingSize: 1024
2、<font style="color:#DF2A3F;">outlierDetection</font>
(异常驱逐)
- 实现健康探测/容错/自动剔除异常实例
<font style="color:rgb(251, 71, 135);">consecutiveErrors</font>
:触发剔除的连续错误阈值<font style="color:rgb(251, 71, 135);">interval</font>
:错误采样时间窗<font style="color:rgb(251, 71, 135);">baseEjectionTime</font>
:单实例被摘除的基准时间<font style="color:rgb(251, 71, 135);">maxEjectionPercent</font>
:最多剔除比例<font style="color:rgb(251, 71, 135);">minHealthPercent</font>
:剔除后剩余健康实例的最小比例
3、<font style="color:#DF2A3F;">connectionPoll</font>
- TCP 连接池
<font style="color:rgb(251, 71, 135);">maxConnections</font>
:为上游服务的所有实例简历的最大连接数,默认 1024<font style="color:rgb(251, 71, 135);">connectTimeout</font>
:TCP 连接超时时长<font style="color:rgb(251, 71, 135);">tcpKeepalive</font>
:TCP 存活配置,定期给发送一个 keepalived 探测报文来判断连接是否可用。
- HTTP 连接池
<font style="color:rgb(251, 71, 135);">http1MaxPendingRequests</font>
:HTTP1.1最大挂起请求数,默认 1024<font style="color:rgb(251, 71, 135);">http2MaxRequests</font>
:HTTP2最大请求数,默认 1024<font style="color:rgb(251, 71, 135);">maxRequestsPerConnection</font>
:每连接的最大请求数,默认无限制,1 表示禁用 keepalive<font style="color:rgb(251, 71, 135);">maxRetries</font>
:最大自动重试次数,默认为 3<font style="color:rgb(251, 71, 135);">idleTimeout</font>
:空闲连接自动回收时间
4、<font style="color:#DF2A3F;">tls</font>
- 配置 mTLS/TLS 上下游通讯
trafficPolicy:tls:mode: ISTIO_MUTUAL
1.5.3 DestinationRule 配置示例
# 1. reviews 服务的 DestinationRule,定义了三个子集(版本v1、v2、v3)
# 用于 VirtualService 按不同子集路由流量
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: reviews # 规则名称(推荐唯一,便于管理)
spec:host: reviews # 目标服务(短名,K8s Service名)subsets:- name: v1 # 子集名称,与 VirtualService 中 subset 字段对应labels:version: v1 # 匹配带有 version=v1 标签的 Pod- name: v2labels:version: v2- name: v3labels:version: v3---# 2. ratings 服务的 DestinationRule,设置了全局负载均衡与版本子集专属策略
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: bookinfo-ratings # 规则名称
spec:host: ratings.prod.svc.cluster.local # 完整域名(推荐用 FQDN,防止多namespace歧义)trafficPolicy: # 全局流量策略loadBalancer:simple: LEAST_CONN # 全局默认最少连接数优先subsets:- name: testversion # 定义一个子集,名为 testversionlabels:version: v3 # 匹配 version=v3 的 PodtrafficPolicy: # 子集专属流量策略loadBalancer:simple: ROUND_ROBIN # testversion 子集单独用轮询分流---# 3. reviews 服务的 DestinationRule(含全局随机负载均衡)
# 注意:如需多个 DestinationRule 操作同一个 host,只能在不同 namespace 下!
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: reviews-random
spec:host: reviewstrafficPolicy:loadBalancer:simple: RANDOM # 全局负载均衡使用随机分发subsets:- name: v1labels:version: v1- name: v2labels:version: v2- name: v3labels:version: v3# 提示:
# 如果在同一个 namespace 下有多个 DestinationRule,host 必须不同,否则配置会冲突。
# 如果 reviews 服务下需要多份流量策略和不同名字的 DR,请合理区分 namespace。
1.6 Gateway
Gateway(网关)是 Istio 网络流量管理体系中的入口资源,用于声明和配置网格边界的流量接入/转发规则。它定义在边缘(如 Ingress Gateway Pod 所在位置),负责允许外部用户或系统通过HTTP/HTTPS/TCP 协议安全、灵活地接入 Service Mesh。
- 直观地说:
Gateway ≈ “Kubernetes Ingress” 的升级版,但更灵活、可配合 Istio 强大流量管理功能(如灰度、TLS、观测等)。 - 重要补充:
Gateway 只负责暴露端口和协议,不决定流量路由,内部实际路由还靠 VirtualService。
1.6.1 Gateway 资源的核心字段
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:name: my-gatewaynamespace: istio-system # 推荐部署和ingressgateway pod同一个namespace
spec:selector: # Pod 选择器,绑定到特定的 Ingress Gateway 组件(通常由 Istio 自动部署,标签名如 istio=ingressgateway)istio: ingressgatewayservers: # 可以配置多个 server,分别定义监听的端口和协议- port:number: 80 # 接收请求的端口号name: http # 端口名称protocol: HTTP # 协议类型,如 HTTP/HTTPS/TCP/TLShosts:- "*.example.com" # 支持 * 通配符,必须为FQDN格式- "www.example.com"- port:number: 443name: httpsprotocol: HTTPShosts:- "secure.example.com"tls: # 若发布为HTTPS,需要配置TLSmode: SIMPLE # 支持 SIMPLE(单向TLS)、MUTUAL(双向TLS)、PASSTHROUGH 等credentialName: example-credential # 证书密钥,需预先创建 SecretminProtocolVersion: TLSV1_2maxProtocolVersion: TLSV1_3
<font style="color:rgb(251, 71, 135);">selector</font>
:Pod标签选择器
绑定到某个具体的 Istio Ingress Gateway Deployment(默认<font style="color:#DF2A3F;"> istio: ingressgateway</font>
);只有标签匹配的 Pod 会被此 gateway 控制<font style="color:rgb(251, 71, 135);">servers</font>
:服务监听组,可以有多个<font style="color:rgb(251, 71, 135);">port</font>
:服务开放的监听端口,外部流量的入口<font style="color:rgb(251, 71, 135);">hosts</font>
:绑定的 FQDN 域名(或 *),决定哪些 Host 头才会被此 gateway 接收入站流量<font style="color:rgb(251, 71, 135);">tls</font>
:如果监听 HTTPS,还可声明 TLS 一系列加密配置
<font style="color:rgb(251, 71, 135);">tls.credentialName</font>
:引用 Kubernetes Secret,实现 TLS 证书热更新<font style="color:rgb(251, 71, 135);">tls.mode: MUTUAL</font>
:实现双向 TLS(客户端/服务端双方证书验证)- 支持多端口、多协议同一 Gateway
- SNI 路由、通配符域名、大规模多租户支持
1.6.2 Gateway 与 VirtualService 的关系
- Gateway 只是暴露入口端口和协议,真正的 HTTP 路由、流量分配和各类规则需要
**<font style="color:#DF2A3F;">VirtualService</font>**
绑定**<font style="color:#DF2A3F;">Gateway</font>**
共同实现
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: my-vs
spec:hosts:- "www.example.com"gateways:- my-gateway # 绑定上面定义的Gatewayhttp:- match:- uri:prefix: /apiroute:- destination:host: backend-service.default.svc.cluster.localport:number: 8080
- 如果 VirtualService 的
<font style="color:rgb(251, 71, 135);">gateways</font>
设置为<font style="color:rgb(251, 71, 135);">mesh</font>
,则作用于网格内部流量,否则会作用在指定的 Gateway 上,实现真实外网<->内部服务的流量路由。
- Gateway 与
**<font style="color:#DF2A3F;">Ingress Gateway Pod</font>**
必须同 namespace否则无法正确调度- hosts 必须为 FQDN(支持 * 通配),不接受非域名字符串
- tls 相关配置需要提前准备好 Kubernetes Secret
- selector 控制配置应用到哪些 Ingress Gateway Pod,支持一套 Mesh 多套边界网关并行
- Ingress Gateway Controller (istio-ingressgateway) 通常是一个 Deployment,默认在
<font style="color:#DF2A3F;"> istio-system</font>
命名空间- Gateway 实际“只监听端口”,不做流量分配。需要配合 VirtualService,使用
<font style="color:rgb(251, 71, 135);">hosts</font>
、<font style="color:rgb(251, 71, 135);">uri</font>
等精准转发路径规则
1.6.3 Gateway 配置示例
# 1. my-gateway
# 用于暴露 uk.bookinfo.com 和 eu.bookinfo.com 两个域名的流量入口
# 支持 HTTP(自动跳转到 HTTPS)和 HTTPS(443 端口证书配置)
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:name: my-gateway # Gateway 对象的名称namespace: some-config-namespace # 需保证与目标 IngressGateway Pod 在同命名空间
spec:selector:app: my-gateway-controller # 该 Gateway 规则只会应用到带此标签的 ingressgateway Podservers:- port:number: 80name: httpprotocol: HTTPhosts:- uk.bookinfo.com- eu.bookinfo.comtls:httpsRedirect: true # 自动将 HTTP 301 跳转至 HTTPS- port:number: 443name: https-443protocol: HTTPShosts:- uk.bookinfo.com- eu.bookinfo.comtls:mode: SIMPLE # SIMPLE 表示单向 TLS(HTTPS 服务)serverCertificate: /etc/certs/servercert.pem # 服务端证书路径privateKey: /etc/certs/privatekey.pem # 私钥路径---# 2. grafana-gateway
# 用于暴露 Grafana 面板,监听 15031 端口,支持所有域名流量进入
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:name: grafana-gatewaynamespace: istio-system
spec:selector:istio: ingressgateway # 绑定到 istio 默认部署的 ingressgateway Podservers:- port:number: 15031name: http-grafanaprotocol: HTTPhosts:- "*" # 支持所有主机头(Host)---# 3. kiali-gateway
# 用于暴露 Kiali 面板,监听 15029 端口,支持所有域名流量进入
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:name: kiali-gatewaynamespace: istio-system
spec:selector:istio: ingressgateway # 绑定到 istio 默认部署的 ingressgateway Podservers:- port:number: 15029name: http-kialiprotocol: HTTPhosts:- "*" # 支持所有主机头(Host)
二、流量治理高级案例
https://istio.io/latest/docs/reference/config/networking/virtual-service/
2.1 URL 重定向
2.1.1 Istio URL重定向配置
Istio 的 URL 重定向一般是在 VirtualService 资源中实现的。当请求进入服务网格后,基于 <font style="color:#DF2A3F;">VirtualService</font>
规则,Istio 可以把请求重定向到新的 URL,实现路径、主机、端口、协议等的改变。
这种功能通常用于:
- HTTP → HTTPS 安全升级
- 统一入口(如 /v1/xxx → /v2/xxx)
- 域名跳转
- 更换后端服务端口
- 其他自定义 URL 路径变换
Istio中的<font style="color:#DF2A3F;">HTTP Redirect</font>
操作,通过向客户端返回<font style="color:#DF2A3F;">301</font>
响应码,指示其向新的<font style="color:#DF2A3F;">uri</font>
和<font style="color:#DF2A3F;">authority</font>
指向的新目标进行重新请求
字段名 | 用法/含义 |
---|---|
**<font style="color:#DF2A3F;">uri</font>** | 重定向时覆盖原 URL 的 Path 部分。配置后,请求的路径会被完全替换,无论原路径是什么。 |
**<font style="color:#DF2A3F;">authority</font>** | 覆盖原 URL 的 Host(域名/authority)部分,可以实现主机名切换跳转。 |
**<font style="color:#DF2A3F;">port</font>** | 覆盖 URL 的端口部分。指定目标端口号。 |
**<font style="color:#DF2A3F;">derivePort</font>** | 动态设置端口:可选 FROM_PROTOCOL_DEFAULT(HTTP用80,HTTPS用443),或 FROM_REQUEST_PORT(使用原始请求端口)。 |
**<font style="color:#DF2A3F;">scheme</font>** | 覆盖 URL 的协议部分(如 http/https)。未设置时用原协议。如配合 derivePort 为 FROM_PROTOCOL_DEFAULT,可以自动影响端口。 |
**<font style="color:#DF2A3F;">redirectCode</font>** | 设置 HTTP 重定向的返回码。默认是 301(永久重定向)。可自定义为 302/303 等。 |
2.1.2 URL 重定向案例
还是基于之前的 frontend 和 demoapp 案例来做案例:
- 访问 frontend 服务的"
<font style="color:#DF2A3F;">/backend</font>
“路径,将会被自动重定向到”<font style="color:#DF2A3F;">http://dycloud.fun</font>
" - 访问 demoapp 服务的"
<font style="color:#DF2A3F;">/frontend</font>
“路径,将会被自动重定向到”<font style="color:#DF2A3F;">http://frontend</font>
"
**配置 frontend 的 ****<font style="color:#DF2A3F;">virtualService</font>**
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: frontend
spec:hosts:- "fe.dujie.com"- "frontend.dujie.com"gateways:- frontend-gateway#- meshhttp:- name: redirectmatch:- uri:prefix: "/backend"redirect:uri: /authority: dycloud.funport: 80- name: defaultmatch:- uri: prefix: /route:- destination:host: frontendport:number: 80
配置 demoapp 的 <font style="color:#DF2A3F;">virtualService</font>
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: demoapp
spec:hosts:- demoapphttp:- name: redirectmatch:- uri:prefix: "/frontend"redirect:uri: /authority: frontendport: 80- name: canarymatch:- uri:prefix: /canary # 访问/canary 路由给v2-canary子集rewrite:uri: /route:- destination:host: demoappsubset: v2-canary- name: default # 其他路径,路由给v2子集route:- destination:host: demoappsubset: v2
2.1.3 验证前端应用
可以访问frontend.dujie.com/backend 验证是否会自动重定向到 <font style="color:#DF2A3F;">dycloud.fun</font>
[root@k8s-master01 /usr/local/src]# curl -I frontend.dujie.com/backend
HTTP/1.1 301 Moved Permanently
location: http://dycloud.fun/
date: Mon, 04 Aug 2025 08:03:07 GMT
server: istio-envoy
connection: close
transfer-encoding: chunked
2.1.4 验证 demoapp
验证访问 demoapp:8080/frontend 时是否会自动重定向到/frontend
[root@k8s-master01 /usr/local/src]# kubectl exec -it -n app client-f98d4768d-c6m7b bash
root@client-f98d4768d-c6m7b /# curl -I demoapp:8080/frontend
HTTP/1.1 301 Moved Permanently
location: http://frontend/
date: Mon, 04 Aug 2025 08:07:08 GMT
server: envoy
transfer-encoding: chunked
验证/canary 路径是否路由到 v2-canary 子集
root@client-f98d4768d-c6m7b /# while true; do curl demoapp:8080/canary; sleep 0.$RANDOM; done
2.2 操作报文标头示例
Headers为Istio提供了操作HTTP Header的途径,用于操作HTTP 请求报文中Request或者Response标头
- headers字段支持
<font style="color:#DF2A3F;">request</font>
和<font style="color:#DF2A3F;">response</font>
两个内嵌字段<font style="color:#DF2A3F;">request</font>
:操纵发送给Destination的请求报文中的标头<font style="color:#DF2A3F;">response</font>
:操纵发送给客户端的响应报文中的标头
- ◼ 以上两个对应的类型都是
<font style="color:#DF2A3F;">HeaderOperations</font>
类型,都支持使用<font style="color:rgb(0,0,0);">set</font>
、<font style="color:rgb(0,0,0);">add</font>
、<font style="color:rgb(0,0,0);">remove</font>
字段操纵指定的标头<font style="color:#DF2A3F;">set</font>
:使用map上的Key和Value覆盖Request或者Response中对应的Header<font style="color:#DF2A3F;">add</font>
:追加map上的Key和Value到原有 Header<font style="color:#DF2A3F;">remove</font>
:删除在列表中指定的Header
2.2.1 修改 demoapp 的 virtualService
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: demoapp
spec:hosts:- demoapphttp:- name: canarymatch:- headers: # 匹配请求头中带有x-canary并且值为true的x-canary: exact: "true"route: # 将上面的匹配请求都发送到v2-canary子集- destination:host: demoappsubset: v2-canaryheaders: # 并且在请求头中配置User-Agent 的值为wgetrequest:set:User-Agent: wgetresponse: # 在响应头中添加x-canary等于true 字段add:x-canary: "true"- name: default # 其余的请求在响应头中添加X-Envoy等于test字段headers:response:add:X-Envoy: testroute:- destination: # 将其余请求都发往v2子集host: demoappsubset: v2
2.2.2 测试
在 client pod 中测试,在 curl 命令中添加请求头参数,可以看到请求到达的子集是 <font style="color:#DF2A3F;">v2-canary</font>
,并且在响应报文中添加了<font style="color:#DF2A3F;"> x-canary: true </font>
字段
root@client-f98d4768d-c6m7b /# curl -I -H "x-canary: true" frontend
HTTP/1.1 200 OK
server: envoy
date: Mon, 04 Aug 2025 08:16:36 GMT
content-type: text/html; charset=utf-8
content-length: 145
x-envoy-upstream-service-time: 6
x-canary: true
root@client-f98d4768d-c6m7b /# curl -H "x-canary: true" frontend
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-4lkfz, Server IP: 172.16.54.222 ~
还可以循环访问
root@client-f98d4768d-c6m7b /# while true; do curl -H "x-canary: true" frontend; sleep 0.$RANDOM; done
然后查看 canary 的日志,可以看到 user agent 信息已经被替换成 wget 了
04/Aug/2025:08:23:59 +0000 127.0.0.6 - - [None] "GET /? HTTP/1.1" - "wget" "127.0.0.6"
04/Aug/2025:08:24:00 +0000 127.0.0.6 - - [None] "GET /? HTTP/1.1" - "wget" "127.0.0.6"
04/Aug/2025:08:24:00 +0000 127.0.0.6 - - [None] "GET /? HTTP/1.1" - "wget" "127.0.0.6"
2.3 故障注入
故障注入(Fault Injection)是Istio流量管理能力的一部分,允许开发者和运维人员在服务通信过程中“模拟”异常,如强制延迟请求返回、注入错误响应等。
其作用主要有:
- 验证应用的容错和降级能力(如服务超时、重试、熔断等逻辑是否生效)
- 帮助定位在下游服务不稳定、网络有抖动时,系统整体的弹性表现问题
- 测试微服务环境下的稳健性
Istio 支持两种类型的故障注入:
- 延迟注入(Delay Injection)
- 人为让响应耗时增加
字段 | 含义说明 |
---|---|
fixedDelay | 固定延迟时长,即 Istio 在请求转发前人为增加的延迟(如 1h/1m/1s/1ms),最小为 1ms。 |
percentage | 指定被延迟的流量百分比(建议用这个)。如设为 50,表示50%的请求会被加延迟。 |
percent | 被延迟的流量百分比(0~100),已过时,推荐用 <font style="color:rgb(251, 71, 135);">percentage</font> 字段替代。 |
- 中断注入(Abort Injection)
- 人为返回异常状态码而非正常接口响应
字段 | 含义说明 |
---|---|
httpStatus | 终止 HTTP 请求时返回给客户端的状态码(如 500、503 等),模拟 HTTP 服务端异常。 |
grpcStatus | 终止 gRPC 请求时返回的错误码,必须为 gRPC文档里的字符串全写形式,如 <font style="color:rgb(251, 71, 135);">UNAVAILABLE</font> 。 |
percentage | 指定被中断(即被返回错误码)的流量百分比。如设置为 50,表示有50%的请求会被强制返回 <font style="color:rgb(51, 54, 57);">httpStatus</font> 或 <font style="color:rgb(51, 54, 57);">grpcStatus</font> 。 |
2.3.1 修改 demoapp 的 virtualService
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: demoapp
spec:hosts:- demoapphttp:- name: canarymatch:- headers:x-canary: # 匹配请求头中带有x-canary等于true的exact: "true"route:- destination:host: demoapp # 路由到v2-canarysubset: v2-canaryheaders:request: # 并在请求头中设置User-Agent的值为wgetset:User-Agent: wgetresponse: # 在响应头中添加x-canary等于trueadd:x-canary: "true"fault: # 配置故障注入,20%的流量返回555错误abort:percentage:value: 20httpStatus: 555- name: default # 其余流量路由到v2子集route:- destination:host: demoappsubset: v2fault: # 配置故障注入,20%的流量延时5秒delay:percentage:value: 20fixedDelay: 5s
2.3.2 测试故障注入
进行请求测试,可于集群上的客户端Pod中直接请求<font style="color:#DF2A3F;">frontend.default.svc</font>
主机, 或者于集群外请求<font style="color:#DF2A3F;">frontend.dujie.com</font>
主机
MacBook-Pro:~ root# while true; do curl frontend.dujie.com/services; sleep 0.$RANDOM; done
frontend (frontend-7c55c868cf-6mpj7) successfully connects to demoapp-v2.1 (demoapp-59598585bf-ddw4b) in 5.55 ms.
frontend (frontend-7c55c868cf-6mpj7) successfully connects to demoapp-v2.1 (demoapp-59598585bf-h5z7b) in 4.16 ms.
frontend (frontend-7c55c868cf-srjmj) successfully connects to demoapp-v2.1 (demoapp-59598585bf-ddw4b) in 5009.27 ms.
frontend (frontend-7c55c868cf-6mpj7) successfully connects to demoapp-v2.1 (demoapp-59598585bf-h5z7b) in 4.89 ms.
frontend (frontend-7c55c868cf-srjmj) successfully connects to demoapp-v2.1 (demoapp-59598585bf-ddw4b) in 3.87 ms.
frontend (frontend-7c55c868cf-6mpj7) successfully connects to demoapp-v2.1 (demoapp-59598585bf-h5z7b) in 3.59 ms.
frontend (frontend-7c55c868cf-srjmj) successfully connects to demoapp-v2.1 (demoapp-59598585bf-h5z7b) in 4.15 ms.
frontend (frontend-7c55c868cf-srjmj) successfully connects to demoapp-v2.1 (demoapp-59598585bf-ddw4b) in 3.60 ms.
frontend (frontend-7c55c868cf-srjmj) successfully connects to demoapp-v2.1 (demoapp-59598585bf-dlc6r) in 3.88 ms.
frontend (frontend-7c55c868cf-6mpj7) successfully connects to demoapp-v2.1 (demoapp-59598585bf-dlc6r) in 5007.23 ms.
...
(base) dujie@MacBook-Pro ~ % while true; do CONTENT=$(curl -s -H "x-canary: true" frontend.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-szdbw, Server IP: 172.16.85.217 ~
fault filter abort
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-fhxzq, Server IP: 172.16.58.240 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-4lkfz, Server IP: 172.16.54.222 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-4lkfz, Server IP: 172.16.54.222 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-szdbw, Server IP: 172.16.85.217 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-szdbw, Server IP: 172.16.85.217 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-fhxzq, Server IP: 172.16.58.240 ~
fault filter abort
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-4lkfz, Server IP: 172.16.54.222 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-4lkfz, Server IP: 172.16.54.222 ~
fault filter abort
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-szdbw, Server IP: 172.16.85.217 ~
查看 kiali 可以看到有大概 20%的流量是异常的
2.4 请求重试和超时
在微服务架构下,服务间网络请求经常遇到瞬时失败(如临时网络抖动、节点重启等)。Istio 支持自动对这些蓝本失败进行无感重试,帮助增强应用的健壮性和容错性。
Istio 的重试是由 Sidecar 代理(Envoy)在应用侧透明执行的,无需业务代码修改。
- 重试机制是在 VirtualService 的
<font style="color:rgb(251, 71, 135);">http.route</font>
路由规则下通过<font style="color:rgb(251, 71, 135);">retries</font>
字段配置的。 - 当下游(被调用服务)出现某些可恢复的异常(如 5xx、连接超时等),Envoy 会自动把请求再发出去,充当应用的弹性保护墙。
- 重试间隔和次数由用户自定义;可防喷射(防止瞬时高并发因重试而冲击服务)。
字段 | 含义与作用 |
---|---|
attempts | 最大重试次数(不含首次请求,即最多会发出 attempts 次请求) |
perTryTimeout | 每次重试的最大等待时间(如 2s)。和 route/http.timeout 配合使用。 |
retryOn | 声明哪些返回码或错误类型才触发重试。常见如:5xx,connect-failure,timeout,reset |
retryRemoteLocalReset | 是否对局域网/远程服务主动断开也进行重试 |
2.4.1 HTTP 请求重试条件(route.RetryPolicy)
- 重试条件(同
**<font style="color:#DF2A3F;">x-envoy-retry-on</font>**
标头)- ◼
<font style="color:#DF2A3F;">5xx</font>
:上游主机返回5xx响应码,或者根本未予响应(断开/重置/读取超时) - ◼
<font style="color:#DF2A3F;">gateway-error</font>
:网关错误,类似于5xx策略,但仅为502、503或504的应用进行重试 - ◼
<font style="color:#DF2A3F;">connection-failure</font>
:在TCP级别与上游服务建立连接失败时进行重试 - ◼
<font style="color:#DF2A3F;">retriable-4xx</font>
:上游服务器返回可重复的4xx响应码时进行重试 - ◼
<font style="color:#DF2A3F;"> refused-stream</font>
:上游服器务使用REFUSED——STREAM错误码重置时进行重试 - ◼
<font style="color:#DF2A3F;">retriable-status-codes</font>
:上游服务器的响应码与重试策略或<font style="color:#DF2A3F;">x-envoy-retriable-status-codes</font>
标头值中定义的响应码匹配时进行重试 - ◼
<font style="color:#DF2A3F;">reset</font>
:上游主机完全不响应时(disconnect/reset/read超时),Envoy将进行重试; - ◼
<font style="color:#DF2A3F;">retriable-headers</font>
:如果上游服务器响应报文匹配重试策略或<font style="color:#DF2A3F;"> x-envoy-retriable-header-names</font>
标头中包含的任何标头,则Envoy将尝试重试 - ◼
<font style="color:#DF2A3F;">envoy-ratelimited</font>
:标头中存在x-envoy-ratelimited时进行重试
- ◼
- 重试条件2(同x-envoy-retry-grpc-on标头)
- ◼
<font style="color:#DF2A3F;">cancelled</font>
:gRPC应答标头中的状态码是“cancelled”时进行重试 - ◼
<font style="color:#DF2A3F;">deadline-exceeded</font>
:gRPC应答标头中的状态码是“deadline-exceeded”时进行重试 - ◼
<font style="color:#DF2A3F;">internal</font>
:gRPC应答标头中的状态码是“internal”时进行重试 - ◼
<font style="color:#DF2A3F;">resource-exhausted</font>
:gRPC应答标头中的状态码是“resource-exhausted”时进行重试 - ◼
<font style="color:#DF2A3F;">unavailable</font>
:gRPC应答标头中的状态码是“unavailable”时进行重试
- ◼
- 默认情况下,Envoy不会进行任何类型的重试操作,除非明确定义
2.4.2 修改 frontend 的 virtualservice 配置
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: frontend
spec:hosts:- "fe.dujie.com"- "frontend.dujie.com"- "frontend"gateways:- frontend-gateway - meshhttp:- name: defaultroute:- destination:host: frontendtimeout: 1sretries: # 添加超时配置,1秒中就超时attempts: 5perTryTimeout: 1sretryOn: 5xx,connect-failure,refused-stream
**<font style="color:#DF2A3F;">timeout</font>**
:- 每个 HTTP 请求最多只能处理 1 秒,超时则返回错误。
**<font style="color:#DF2A3F;">retries</font>**
:- 启用重试机制:
**<font style="color:#DF2A3F;">attempts</font>**
: 5:最多重试5次(总共可能发6次请求:1次原始+5次重试)。**<font style="color:#DF2A3F;">perTryTimeout</font>**
: 1s:每次重试最多等1秒,超时就再重试或返回错误。**<font style="color:#DF2A3F;">retryOn</font>**
: 5xx,connect-failure,refused-stream:只有响应为5xx、连接失败、被重置时才自动重试。
- 启用重试机制:
作用:保证在后端 frontend 服务临时出现 5xx 或网络闪断时,前端请求可以自动快速重试,提高系统的鲁棒性,同时防止单个请求卡太久(配合超时)。
2.4.3 修改 demoapp 的 virtualservice 配置
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: demoapp
spec:hosts:- demoapphttp:- name: canarymatch:- headers:x-canary:exact: "true"route:- destination:host: demoappsubset: v2-canaryheaders:request:set:User-Agent: wgetresponse:add:x-canary: "true"fault:abort:percentage:value: 50 # 将比例调整到50%httpStatus: 555- name: defaultroute:- destination:host: demoappsubset: v2fault:delay:percentage:value: 50 # 将比例调整到50%fixedDelay: 5s
2.4.4 测试
重试操作能解决部分程度上的局部故障,从如下的请求结果中可以看出,在50%的请求上注入“中断”故障的场景中,通过重试有效降低了错误响应的比例
MacBook-Pro:~ root# while true; do CONTENT=$(curl -s -H "x-canary: true" frontend.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-szdbw, Server IP: 172.16.85.217 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-fhxzq, Server IP: 172.16.58.240 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-fhxzq, Server IP: 172.16.58.240 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-4lkfz, Server IP: 172.16.54.222 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-4lkfz, Server IP: 172.16.54.222 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-fhxzq, Server IP: 172.16.58.240 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-fhxzq, Server IP: 172.16.58.240 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-4lkfz, Server IP: 172.16.54.222 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-szdbw, Server IP: 172.16.85.217 ~
Demoapp by iKubernetes! App Version: v2.1-canary, Client IP: 127.0.0.6, Server Name: demoapp-canary-559b56b85f-fhxzq, Server IP: 172.16.58.240 ~
注入了5s延迟的请求中,则直接以超时进行响应
MacBook-Pro:~ root# while true; do curl frontend.dujie.com; sleep 0.$RANDOM; done
upstream request timeoutDemoapp by iKubernetes! App Version: v2.1, Client IP: 127.0.0.6, Server Name: demoapp-59598585bf-dlc6r, Server IP: 172.16.248.4 ~
Demoapp by iKubernetes! App Version: v2.1, Client IP: 127.0.0.6, Server Name: demoapp-59598585bf-dlc6r, Server IP: 172.16.248.4 ~
Demoapp by iKubernetes! App Version: v2.1, Client IP: 127.0.0.6, Server Name: demoapp-59598585bf-ddw4b, Server IP: 172.16.135.191 ~
upstream request timeoutDemoapp by iKubernetes! App Version: v2.1, Client IP: 127.0.0.6, Server Name: demoapp-59598585bf-h5z7b, Server IP: 172.16.217.111 ~
Demoapp by iKubernetes! App Version: v2.1, Client IP: 127.0.0.6, Server Name: demoapp-59598585bf-dlc6r, Server IP: 172.16.248.4 ~
Demoapp by iKubernetes! App Version: v2.1, Client IP: 127.0.0.6, Server Name: demoapp-59598585bf-h5z7b, Server IP: 172.16.217.111 ~
Demoapp by iKubernetes! App Version: v2.1, Client IP: 127.0.0.6, Server Name: demoapp-59598585bf-dlc6r, Server IP: 172.16.248.4 ~
Demoapp by iKubernetes! App Version: v2.1, Client IP: 127.0.0.6, Server Name: demoapp-59598585bf-h5z7b, Server IP: 172.16.217.111 ~
2.5 HTTP 流量镜像
- HTTP 流量镜像指的是在将流量转发到原目标地址的同时将流量给另外一个目标地址镜像一份
- 流量镜像一份到另外一个系统上,完全不会对生产系统产生影响,数据平面的代理只需关注原来转发的流量就可以,不用等待镜像目标地址的返回
- 用户请求主服务A,Istio会把同样的请求复制一份,同时悄悄发给镜像服务B,B处理后并不返回给用户,仅用于分析和测试。
主要用于:
- 新版本回放验证(灰度/影子发布)
- 在新版本正式切流前,用真实业务流量检测新版本是否兼容、稳定。
- 线上问题排查
- 在不影响用户的情况下,复现场景,辅助定位BUG。
- 性能测试与容量评估
- 通过生产流量镜像,测新服务/新集群的真实承载力。
- 安全/合规分析
- 例如检测新服务是否有异常行为、符合规范等。
关键配置参数:
- mirror
- 指定流量镜像要发送到哪个服务(destination)
- mirrorPercentage
- 可选,指定被镜像的流量百分比(默认 100%),即复制多少比例的主请求。
- 可选,指定被镜像的流量百分比(默认 100%),即复制多少比例的主请求。
2.5.1 修改 demoapp 的 virtualService
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: demoapp
spec:hosts:- demoapphttp:- name: traffic-mirrorroute:- destination:host: demoappsubset: v2mirror:host: demoappsubset: v2-canary
2.5.2 测试
MacBook-Pro:~ root# while true; do CONTENT=$(curl -s -H "x-canary: true" frontend.dujie.com); echo $CONTENT; sleep 0.$RANDOM; done
可以看到发往 v2 子集的所有流量都会往 v2-canary 子集完整的发送一份
2.6 DestinationRule 常用配置
https://istio.io/latest/docs/reference/config/networking/destination-rule/#TrafficPolicy
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:name: product-dr
spec:host: product-service.svc.cluster.local # 目标服务(必填)# 以下为可选配置subsets: [] # 服务子集定义trafficPolicy: # 流量策略(全局/子集级)loadBalancer: {} # 负载均衡策略connectionPool: {} # 连接池设置outlierDetection: {} # 异常实例检测tls: {} # TLS设置portLevelSettings: [] # 端口级策略
2.6.1 subsets(服务子集)
定义服务的版本/分组,用于金丝雀发布、A/B 测试等场景
subsets:
- name: v1 # 子集名称(VirtualService中引用)labels: # 匹配Pod标签version: v1trafficPolicy: # 子集专属策略(覆盖全局)loadBalancer: { ... }- name: v2-canarylabels:version: v2env: canary
通过标签将服务实例分组,配合 VirtualService 实现流量分割
2.6.2 loadbalancer(负载均衡策略)
支持的算法及参数
trafficPolicy:loadBalancer:# 简单负载均衡算法(四选一)simple: ROUND_ROBIN | LEAST_CONN | RANDOM | PASSTHROUGH# 一致性哈希(会话保持)consistentHash:# 请求特征选择(四选一)httpHeaderName: "x-user-id" # 按Header哈希httpCookie: # 按Cookie哈希name: "user-session"ttl: 3600s # Cookie有效期path: "/" # Cookie路径useSourceIp: true # 按源IP哈希minimumRingSize: 1024 # 最小哈希环大小(默认1024)httpQueryParameterName: # 按照URL查询参数名# 哈希算法配置(二选一)ringHash: # 环哈希算法minimumRingSize: 1024 # 最小环大小maximumRingSize: 8388608 # 最大环大小(默认8M)maglev: # Maglev哈希算法tableSize: 65537 # 哈希表大小(质数)
2.6.3 connection pool
Traffic Policy支持connectionPool设定;存在两种类型的pool
2.6.3.1 TCP 连接池配置:
connectionPool:tcp:maxConnections: 100 # 到目标主机的最大TCP连接数(默认1024)connectTimeout: 10ms # TCP连接超时时间tcpKeepalive: # Keepalive探活interval: 75s # 探测间隔(默认7200s)time: 7200s # 每次探测持续时间probes: 3 # 最大探测次数
字段 | 类型 | 说明 |
---|---|---|
maxConnections | int32 | 最大HTTP1/TCP连接数到目标主机。默认2^32-1。 |
connectTimeout | Duration | TCP连接的超时时间。格式如:1h/1m/1s/1ms。必须≥1ms,默认10秒。 |
tcpKeepalive | TcpKeepalive | 是否设置SO_KEEPALIVE套接字选项以启用TCP Keepalives。 |
maxConnectionDuration | Duration | 单个连接最大持续时长。从连接建立开始计时,超时后关闭连接。未设置则无最大时长。最小为1ms。 |
idleTimeout | Duration | TCP连接的空闲断开时间(读写都没有数据时)。默认1小时,0表示禁用。作为Listener属性,权重路由时仅第一个生效。 |
TCPSettings 支持如下参数
字段 | 类型 | 说明 |
---|---|---|
probes | uint32 | 判断连接死掉前,最多发送的保活探针数量。默认值参考系统级(Linux为9)。 |
time | Duration | 空闲多久后开始发送keep-alive探针。默认值使用操作系统配置(Linux为7200s=2小时)。 |
interval | Duration | 发送两次keep-alive探针之间的间隔。默认值参考系统级(Linux为75s)。 |
2.6.3.2 HTTP Pool
http:http1MaxPendingRequests: 1024 # 等待队列长度(默认1024)http2MaxRequests: 1024 # 最大请求数(默认1024)maxRequestsPerConnection: 32 # 单连接最大请求数(默认无限制)maxRetries: 3 # 最大重试次数(默认1024)idleTimeout: 3600s # 连接空闲超时(默认1h)
字段 | 类型 | 说明 |
---|---|---|
http1MaxPendingRequests | int32 | 等待就绪连接池连接的最大排队请求数,默认2^32-1。HTTP1和HTTP2通用。 |
http2MaxRequests | int32 | 目标主机的最大活跃请求数,默认2^32-1。HTTP1和HTTP2通用。 |
maxRequestsPerConnection | int32 | 到后端的最大请求数;如设置为1会禁用<font style="color:rgb(51, 54, 57);">keep-alive</font> 。默认0(无限制)。 |
maxRetries | int32 | 给cluster所有主机的最大重试数。默认2^32-1。 |
idleTimeout | Duration | 上游连接空闲超时时间,默认1小时。连接空闲超过此时间会关闭。 |
h2UpgradePolicy | H2UpgradePolicy | 是否应将HTTP1.1连接升级到HTTP2。 |
useClientProtocol | bool | 是否在连接后端时保留客户端协议。如果true,则h2UpgradePolicy失效。 |
maxConcurrentStreams | int32 | 单一HTTP2连接允许的最大并发流数,默认2^31-1。 |
2.7 负载均衡配置示例
2.7.1 frontend virtualService 配置:
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:name: frontend
spec:hosts:- "fe.dujie.com"- "frontend.dujie.com"gateways:- frontend-gateway- meshhttp:- name: defaultmatch:- uri: prefix: /route:- destination:host: frontendport:number: 80
2.7.2 demoapp virtualService 配置
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:name: demoapp
spec:hosts:- demoapphttp:- name: canarymatch:- headers:x-canary: exact: "true"route:- destination:host: demoappsubset: v2-canaryheaders:request:set:User-Agent: wgetresponse:add:x-canary: "true"- name: defaultheaders:response:add:X-Envoy: testroute:- destination:host: demoappsubset: v2
2.7.3 demoapp destinationRule 配置:
为 v2 子集启动了 SessionSticky,所有带有"x-user"标头的请求报文,同一标头值得请求都会被调度到同一个后端端点。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: demoapp
spec:host: demoapptrafficPolicy:loadBalancer:simple: LEAST_CONNsubsets:- name: v2labels:version: v2.1trafficPolicy:loadBalancer:consistentHash:httpHeaderName: x-user- name: v2-canarylabels:version: v2.1-canary
2.7.4 测试
进行请求测试;由于proxy不能向后转发标头,因而下面将直接向demoapp发起请求以进行测试
MacBook-Pro:~ root# while true; do curl frontend.dujie.com/hostname; sleep 0.$RANDOM; done
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-dlc6r
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-dlc6r
ServerName: demoapp-59598585bf-ddw4b
ServerName: demoapp-59598585bf-dlc6r
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-dlc6r
为X-User标头使用了不同值的请求,可能被调度至另一端点,但该类请求同样会被sticky至同一端点
MacBook-Pro:~ root# while true; do curl -H "x-user: dujie" frontend.dujie.com/hostname; sleep 0.$RANDOM; done
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
ServerName: demoapp-59598585bf-h5z7b
更换另一个标头值,请求可能会被分发到另一个后端节点了
MacBook-Pro:~ root# while true; do curl -H "x-user: zhangsan" frontend.dujie.com/hostname; sleep 0.$RANDOM; done
ServerName: demoapp-59598585bf-ddw4b
ServerName: demoapp-59598585bf-ddw4b
ServerName: demoapp-59598585bf-ddw4b
ServerName: demoapp-59598585bf-ddw4b
ServerName: demoapp-59598585bf-ddw4b
ServerName: demoapp-59598585bf-ddw4b
ServerName: demoapp-59598585bf-ddw4b
2.8 Connection pool 配置示例
2.8.1 修改 DestinationRule 配置
负载均衡方式
<font style="color:rgb(251, 71, 135);">simple: LEAST_CONN</font>
表示采用最少连接数(Least Connection)方式分配流量,即总是转发给当前活跃连接数最少的后端 Pod。适合请求处理时间长短差异较大场景。
连接池设置
TCP 部分
<font style="color:rgb(251, 71, 135);">maxConnections: 100</font>
单个目的主机(即某个 pod 的 IP:端口)最大并发 TCP/HTTP1 连接数,超过则排队等候。<font style="color:rgb(251, 71, 135);">connectTimeout: 30ms</font>
TCP 连接建立超时时间为 30 毫秒,超时则视为连接失败。<font style="color:rgb(251, 71, 135);">tcpKeepalive:</font>
<font style="color:rgb(251, 71, 135);">time: 7200s</font>
单个连接空闲 7200 秒(2 小时)后才开始发送 keepalive 探针。<font style="color:rgb(251, 71, 135);">interval: 75s</font>
每隔 75 秒发送一次 keepalive 包,检测连接存活状态。
HTTP 部分
<font style="color:rgb(251, 71, 135);">http2MaxRequests: 1000</font>
单一 HTTP2 连接上允许最大并发 1000 个请求。<font style="color:rgb(251, 71, 135);">maxRequestsPerConnection: 10</font>
每个连接最多允许 10 个 HTTP 请求,之后会关闭该连接(可帮助均衡后端及清理长连接占用)。
subsets:分 subset 配置独立流量策略
定义 demoapp 的子版本,让流量按规则打到不同 Pod 版本。
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: demoapp
spec:host: demoapptrafficPolicy:loadBalancer:simple: LEAST_CONNconnectionPool:tcp:maxConnections: 100connectTimeout: 30mstcpKeepalive:time: 7200sinterval: 75shttp:http2MaxRequests: 1000maxRequestsPerConnection: 10subsets:- name: v2labels:version: v2.1trafficPolicy:loadBalancer:consistentHash:httpHeaderName: x-user- name: v2-canarylabels:version: v2.1-canary
2.9 outlier Detection 配置示例
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:name: demoapp
spec:host: demoapptrafficPolicy:loadBalancer:simple: RANDOMconnectionPool:tcp:maxConnections: 100connectTimeout: 30mstcpKeepalive:time: 7200sinterval: 75shttp:http2MaxRequests: 1000maxRequestsPerConnection: 10outlierDetection:maxEjectionPercent: 50consecutive5xxErrors: 5interval: 10s baseEjectionTime: 1mminHealthPercent: 40subsets:- name: v2labels:version: v2.1- name: v2-canarylabels:version: v2.1-canary
**<font style="color:rgb(51, 54, 57);">maxEjectionPercent: 50</font>**
最多可以剔除目标服务实例(pod)的数量不超过所有实例的50%。**<font style="color:rgb(51, 54, 57);">consecutive5xxErrors: 5</font>**
某实例连续返回5次5xx错误(如500),就认为该实例异常可被剔除。**<font style="color:rgb(51, 54, 57);">interval: 10s</font>**
检测异常的时间间隔,10秒检查一次。**<font style="color:rgb(51, 54, 57);">baseEjectionTime: 1m</font>**
实例被剔除的最短时间是1分钟,1分钟后才可以再次被健康检查恢复。**<font style="color:rgb(51, 54, 57);">minHealthPercent: 40</font>**
剔除后健康实例的最小占比为40%,即使其他实例也异常,也不会再剔除,保证基础可用性。