LabHub
学习 学习路径 课程

Istio 服务网格

VirtualService 与 DestinationRule — 角色分开的原因

在 LabHub 中继续学习

一句话总结

VirtualService决定将哪个请求发送到哪里,DestinationRule决定到达那里后如何处理

流程图: 将哪个请求发送到哪里 · 到达那里后如何处理 · 匹配是有顺序的。 · 条件越窄的规则越往上走,无条件的基本路径一定要放在最下面。

为什么需要这个?

容器服务只把请求扔到队列中。没有更多。只有“只有带有此头部的请求作为新版本”,“如果此服务在3秒内没有响应,就放弃”,“连续发出5xx的实例将被扣除30秒”等请求都必须由应用程序或前端网关承担。

Istio将这个要求分解为两个资源。分解的理由很重要。**路由规则经常变化,每个部门都不一样,但目标的性质(哪些标签是哪个版本,连接池留多少)相对稳定。**所以每次部署时只需要修改一个VirtualService,DestinationRule只要服务所有者设定一次就很长一段时间了。

怎么行动

看看两个资源翻译成Envoy的哪个地方,角色分工就变得清晰了。

Istio资源 Envoy对应 决定
VirtualService RouteConfiguration 匹配条件、权重、重写、超时、重试、注入故障、映象
DestinationRule Cluster subset(按标签划分的对象)、负载平衡、连接池、异常检测、客户端TLS

Envoy 群集名称是방향|포트|서브셋|FQDN因为是形式outbound|9080|v2|reviews.mesh-lab.svc.cluster.local看起来像这样。只要记住subset的名字就那样粘在原处,就能更容易地读取日志。

匹配是有顺序的。spec.http是数组,Envoy从上面往下走,使用第一个遇到的。所以如果把无条件的catch-all路由放在最上面,下面规则就永远不会执行。实际规则只有一条——**条件越窄的规则越往上走,无条件的基本路径一定要放在最下面。**而且如果根本没有基本路径,匹配失败的请求是NR(no route)和标志一起变成503。

subset不是名字,而是用标签来选择pad。在DestinationRule中name: v2, labels: {version: v2}写上的话,那个subset是version=v2只指着有标签的pad。如果把名字和标签弄混了,丢掉了标签或出错的话,那个subset中就没有端点,流量是UH(no healthy upstream)变成503。在消息中最常见的503的原因正是这个标签不一致。

协议辨别也很容易错过。梅西根据Service的端口名称决定L7处理是否。端口名称httphttp-apigrpctcp必须像这样开始才能进行HTTP路由。如果名称不存在或不正确,就会被视为TCP,整个头衔匹配被忽略。

恢复力设置必须以数字依据为基础进行确定。

在现场相遇的样子

**第一,重试风暴。**在A→B→C链中,如果每个阶段有2次重试,C接收的请求在最坏的情况下会增加9倍。4段的话是27倍。就像在死去的服务上插上棍子一样,重试只放在链的某个地方(最好是外面),里面保持0~1。

**第二,超时叠加。**如果外部超时比内部短,那么内部在认真工作时,外部会中断并重新尝试。内部服务会重复“绝对无法完成的工作”。截止日期应该从外部向内部越来越短。

第三,503从标志开始看。UH没有端点(确认subset标签),UO是连接池超出(电路断路器运行中),UF是连接失败(只有一方是STRICT的mTLS不一致是常客),NR没有路由(确认catch-all),URX重试消耗完毕。只要知道这五个就能将调试时间缩短一半。

下次实习要做的事情

上传图片的reviews v1/v2工作量,定义subset后,将基本路径设为v1,只将带有特定头部的请求发送为v2的VirtualService。ratings中,对路径前缀匹配和重写进行延时和重试,然后加上异常检测和缺陷注入。最后istioctl analyze验证设置,将路由顺序整理为JSON。虽然流量实际上没有流过,但路由数组的顺序和subset的标签一致,即使只通过静态分析也能准确判断。