针对标准泳道托管资源限制用户自定义配置的情况,为实现路由策略与泳道隔离的解耦,可创建自定义虚拟服务(VirtualService)并指向泳道生成的委托(Delegate)虚拟服务,从而允许在不破坏泳道隔离性的前提下,为泳道服务注入超时、重试等自定义路由策略。
工作原理
在标准模式下,流量泳道会自动创建并托管一个包含hosts字段的VirtualService,该资源全权负责流量的接管与版本(Subset)分发,用户无法直接修改以注入自定义策略。
启用委托(Delegate)功能后,ASM 对路由过程进行了调整:
解除Host绑定:ASM 自动剥离原VirtualService中的
hosts字段,它不再直接处理入口流量,而是等待其他VirtualService将流量委托给它。构建委托关系:用户需创建一个新的自定义VirtualService来指定
hosts及超时、重试等高级策略,并将流量委托给原VirtualService,完成最终的泳道版本匹配和路由。
这种组合式路由机制,实现了路由策略的解耦:既允许灵活定义顶层治理规则,又保留了泳道原生的自动化隔离能力。
为泳道服务启用自定义路由规则
前提条件
部署完成的宽松泳道示例环境,请参考宽松模式流量泳道实施前的准备。
通过场景一:在链路中透传trace ID方式来实现应用版本隔离。
步骤一:为目标服务启用委托虚拟服务
此步骤修改泳道自动生成的VirtualService,使其进入可被委托的状态。
登录ASM控制台,在左侧导航栏,选择。
在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择。
在泳道服务列表下,找到需要操作的服务(例如
mockb),在其对应的启用委托虚拟服务列,单击启用开关。
步骤二:创建自定义虚拟服务并委托路由
启用委托后,必须创建自定义虚拟服务来接管流量,并将其委托给泳道虚拟服务,以恢复并扩展路由能力。
在实例左侧导航栏,选择。
单击 创建,配置一个新的虚拟服务。
作用范围:开启作用于所有Sidecar,以匹配泳道VirtualService的东西向流量范围。
所属服务:选择要配置的服务,例如
mockb.default.svc.cluster.local。虚拟服务代理:这是实现委托的关键。必须将流量委托给泳道自动创建的VirtualService。
虚拟服务名:命名规则
trafficlabel-vs-{泳道组名称}-{服务命名空间}-{服务名称}。示例:对于
test泳道组内、default命名空间下的mockb服务,其对应的虚拟服务名为trafficlabel-vs-test-default-mockb。虚拟服务所属命名空间:泳道自动创建的VirtualService统一位于
istio-system命名空间。
以下通过两个具体场景,演示配置自定义VirtualService的高级路由项。
场景一:为泳道内服务启用故障注入
此场景为泳道中的
mockb服务增加50%的请求中止故障。在创建虚拟服务页面,完成以下配置。控制台
在虚拟服务创建页面,开启故障注入:开启请求中止,在中止响应码输入
502,在故障注入百分比输入50。YAML示例
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: my-mockb-fault-injection namespace: default spec: hosts: - mockb.default.svc.cluster.local http: - name: my-mockb-fault-rule fault: abort: percentage: value: 50 httpStatus: 502 delegate: name: trafficlabel-vs-test-default-mockb namespace: istio-system在目标ASM实例详情页,左侧导航栏选择,查看并记录目标网关的服务地址。
将
<ASM_GATEWAY_IP>替换为网关地址,向应用入口(/mock)发送100次请求。for i in {1..100}; do curl -s -H 'x-asm-prefer-tag: s1' -H "my-trace-id: x000$i" http://<ASM_GATEWAY_IP>/mock echo '' sleep 0.5 done预期输出:约一半的请求因故障注入而中止,另一半请求则成功完成了整个链路调用,并保持在
v1版本的泳道中。-> mocka(version: v1, ip: 10.144.xxx.xxx)fault filter abort -> mocka(version: v1, ip: 10.144.xxx.xxx)-> mockb(version: v1, ip: 10.144.xxx.xxx)-> mockc(version: v1, ip: 10.144.xxx.xxx) -> mocka(version: v1, ip: 10.144.xxx.xxx)fault filter abort -> mocka(version: v1, ip: 10.144.xxx.xxx)-> mockb(version: v1, ip: 10.144.xxx.xxx)-> mockc(version: v1, ip: 10.144.xxx.xxx) ...
场景二:为泳道内服务启用路由级熔断
此场景为从mocka到mockb的调用配置路由级熔断。
完成自定义虚拟服务创建后,配置熔断降级规则。
在ASM实例详情页,左侧导航栏选择,然后单击创建。
配置熔断规则:
熔断流量类型:选择服务间调用东西向流量熔断。
关联工作负载:选择调用方工作负载,标签名输入
app,标签值输入mocka。服务域名:输入
mockb.default.svc.cluster.local。服务端口:
8000。匹配虚拟服务路由项:单击选择路由项,勾选步骤二中创建的路由名称。
配置具体的熔断策略。
为验证熔断规则是否生效,可使用直接响应插件临时让
mockb服务持续返回错误。在ASM实例详情页,左侧导航栏选择,搜索定位直接响应插件,进入插件页后单击新建插件实例。
在新建页面,插件生效范围选择工作负载生效,然后单击添加工作负载到生效范围,搜索并选择
mockb服务。插件配置:使用以下配置,使
mockb服务的/路径在被访问时直接返回502状态码。patch_context: SIDECAR_INBOUND port: '8000' path: / response: direct_response response_status: '502'
验证实际效果。
在目标ASM实例详情页,左侧导航栏选择,查看并记录目标网关的服务地址。
将
<ASM_GATEWAY_IP>替换为网关地址,向应用入口(/mock)发送20次请求。for i in {1..20}; do curl -s -H 'x-asm-prefer-tag: s1' -H "my-trace-id: x000$i" http://<ASM_GATEWAY_IP>/mock echo '' sleep 1 done预期输出:在连续几次请求收到
direct_response(由插件模拟的502错误)后,后续请求的输出变为break,表明从mocka到mockb的调用已被熔断。-> mocka(version: v1, ip: 10.144.xxx.xxx)direct_response -> mocka(version: v1, ip: 10.144.xxx.xxx)direct_response ... -> mocka(version: v1, ip: 10.144.xxx.xxx)break -> mocka(version: v1, ip: 10.144.xxx.xxx)break -> mocka(version: v1, ip: 10.144.xxx.xxx)break ...测试完成后,及时关闭直接响应插件,以恢复
mockb服务的正常访问。