istio(三)探索”目标规则(DestinationRule)”概念

接前文《istio(二)探索”虚拟服务”概念》,我们还有一点点剩余的内容需要继续探索,但相信你已经渐入佳境,所以下面的内容就单枪直入了。

本文要了解的概念叫做“目标规则”,英文DestinationRule,我们构造的场景是:

我们部署2套nginx deployment,分别叫做a版本和b版本,仅配置1个service同时负载均衡到2个版本的deployment。

当我们从ubuntu容器访问nginx.com时,如果访问的url是http://nginx.com/index.html则流量被路由给a版本deployment,否则路由给b版本deployment。

这其实展示了一种多版本小流量发布的效果,从中我们就理解了destinationRule。

准备工作

创建2套nginx deployment:

注意service通过run:my-nginx的标签selector同时关联到了2个deployment的POD,也就是说这个service关联了一共4个POD可以被istio服务发现。

同时注意到,两组POD的version标签分别是a和b,这样istio对这个service的4个POD又能进一步划分出2个a POD和2个b POD,这对于我们控制istio做蓝绿版本路由很关键。


创建ubuntu作为客户端:

一会我们从ubuntu容器里调用nginx.com,然后被ubuntu容器里的istiod控制流量调度。

我们现在的POD列表:

探索

我们知道istiod默认已经服务发现my-nginx service的4个POD了,但是我们一会要把/index.html路由到a版本的2个POD,其他URI则路由器到b版本的2个POD,显然我们要告诉istio如何从my-nginx的4个POD中划分出2组来,这就是destination rule要做的事情。

当然首先还是靠virtualservice做路由选路,之后才轮到destination rule做事。

配置规则

virtualservice识别HTTP协议host是nginx.com的请求,然后配置了route-a和route-b两个路由规则:

  • 如果URI是/index.html则把流量打给my-nginx这个service的subset=a的2个POD。
  • 否则把流量打给my-nginx这个service的subset=b的2个POD。

这里destination的host是istio服务注册表中的服务,是要对应后端若干endpoint(POD)的,这里my-nginx实际就是default命名空间中my-nginx service的域名简写,istio能够根据它找到背后的POD列表。

一开始接触istio很容易搞不明白virtualservice的host和destination host的关系,前者是7层协议的识别与匹配的Host,后者是服务注册&发现的host(就是service域名或者通过serviceentry注册的外部域名)。

有了这个认识,我们就知道subset大概要表达的就是my-nginx这个service中的一个POD子集,这时候我们就需要引入DestinationRule了。

在DetinationRule中的host应该是istio服务发现&注册中存在的域名(就是service域名或者通过serviceentry注册的外部域名),然后subsets可以对该service域名关联的POD进一步根据label进行子集划分,这里我们就是根据version:a和version:b划分出来的,这样virtualservice中就可以通过subset字段分别路由了。

验证效果

进入ubuntu容器,安装好curl,然后多访问几次nginx.com/index.html:

然后查看一下a组nginx有/index.html访问日志,b组完全没有。

如果反过来调用nginx.com的话,则会发现b组nginx有日志,a没有。

同时,你会发现请求nginx.com/index.html会卡顿1秒才返回,这是因为我们在virtualservice中注入了1秒的延迟,你可以回看上面的配置。

我们看一下istio下给ubuntu sidecar下发的路由(istioctl proxy-config route my-ubuntu-f464f6885-jmkg5 -o json ):

可见我们在virtualservice中配的2个HTTP规则都在,并且分别打到了2个cluster:

  • outbound|80|a|my-nginx.default.svc.cluster.local
  • outbound|80|b|my-nginx.default.svc.cluster.local

然后再看一下istio下发的这两个cluster(istioctl proxy-config cluster my-ubuntu-f464f6885-jmkg5 -o json):

可见2个Cluster都是直接从istiod那边EDS服务发现过来的,并且a和b两个subset在cluster服务发现的名字上都有体现,说明istiod那边已经做了区分。

总结

destination用来控制服务注册中某个名字(可以是service,也可以是外部服务serviceentry)的访问行为,而virtualservice用来控制7层流量的路由行为,它们俩管控的层级与概念完全不同,一定要注意理解这块,其他就没啥了。

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~