istio(四)外部如何访问集群中的服务 — ingressgateway

接前文《istio(三)探索”目标规则(DestinationRule)”概念》,此前我们主要分析了istio如何实现集群内服务间的调用或者是集群内调用外部服务,本文则分析外部如何调用集群内的服务,这是依靠istio的ingress-gateway网关组件实现的。

准备工作

istio已经帮我们部署了一个叫做istio-ingressgateway的deployment,它充当集群边缘的反向代理:

我们看到istio-ingressgateway这个service向集群外暴露访问地址和端口,包括80、443这些经典端口,因此我们从集群外肯定可以访问到ingress gateway服务。

其实ingress gateway也是跑的envoy,同样是从istiod那边下发规则,只不过和应用POD中的sidecar envoy角色不一样,在这里充当集群边缘代理角色。

接下来,我们要实现的效果是:

1,从集群外调用ingress-gateway访问http://nginx.com时,由gateway将请求转发给k8s集群内的my-nginx deployment。

2,从集群外调用ingress-gateway访问https://nginx.com时,由gateway将请求转给俄罗斯的nginx官网。

我们先部署my-nginx,这样istio才能服务发现这个K8S服务:

然后我们将nginx.com解析到ingress gateway的loadbalancer ip,这样后续就可以通过gateway反向代理访问到背后的真实服务了:

然后我们开始探索如何配置ingress gateway实现反向代理。

探索

gateway的对外监听

我们为上面的istio-ingressgateway配置一个gateway规则,这样istio-ingressgateway就会按我们的要求进行端口监听,等待外部流量进入:

selector过滤该gateway规则下发到哪一组istio-ingressgateway POD,这是因为istio没有限制我们部署多套不同的边缘istio gateway,可能我们会有为不同业务隔离网关的需求。

接着,我们创建了2个路由规则:

  • 监听80端口,识别HTTP协议,尝试匹配HOST是nginx.com,则命中该路由。
  • 监听443端口,从TLS的SNI中提取HOST,尝试匹配HOST是nginx.com,则命中该路由,因为TLS流量没法中间劫持明文,所以做TCP连接的流量透传(passthrough)。

gateway的向内转发

当ingress gateway程序完成路由匹配后,它会将请求进行向内转发,目标是host: nginx.com,此时ingress gateway是主动发起连接的一方,会开始走virtualservice进行clientside的路由匹配,我们需要进一步配置virtualservice:

这里有2条路由规则+1个外部服务注册:

  • serviceEntry向istio服务注册中心注册了nginx.com这样一个服务名,因此在virtualservice中有一条路由规则通过SNI识别nginx.com访问然后destination给nginx.com这个服务名,也就是这个serviceentry,从而转发TCP透明转发给了俄罗斯的nginx官网。
  • 另外一条路由就是匹配HTTP的host是nginx.com,然后destination给my-nginx这个k8s service。

因此,当ingress gateway向集群内转发时,就会被上述virtualservice进行计算,然后决定流量的转发去向,要么是HTTPS发往俄罗斯,要么是HTTP发往集群内my-nginx。

验证效果

我们可以直接从宿主机上调用nginx.com,查看HTTP和HTTPS两种情况的表现(在文章开始的时候,我们已经将nginx.com解析到istio ingress gateway的对外IP)。

这是HTTP访问,的确是my-nginx的返回页面:

然后访问HTTPS,的确是俄罗斯官网返回的重定向HTML:

说明我们对istio-ingressgateway的工作流程理解正确,我们可以进一步看一下gateway里面下发的envoy规则。


首先是listener:

其实istio ingress gateway的service映射端口是从80->8080,443->8443,所以我们看到gateway内是监听的8080和8443端口,分别来应对HTTP和HTTPS流量。

对于8080端口,我们看到它其实走的是Route http.80路由规则,也就是对80端口访问的进一步路由,一会我们会看到。

对于443端口,我们看到它直接下发了一个listener去match SNI中nginx.com,然后直接destination到了outbound|443||nginx.com这个外部集群(俄罗斯官网)。


接着看route 80规则:

看到http.80路由会对nginx.com识别,然后向集群内转发时经过vs-nginx这个virtualservice进一步路由,我们可以看JSON发现细节:

在Route时匹配nginx.com:80的HTTP请求,会转发给outbound|80||my-nginx.default.svc.cluster.local集群,也就是my-nginx。

总结

ingress网关处于集群边缘,将流量从集群外引入集群内的对应服务,可以从4层或者7层来做规则,结合virtualservice和destinationrule可以实现有趣的效果。

istio还有一个egress网关,可以强制引导集群内调用外部服务的流量经过egress gateway离开集群,从而实时访问外部的强制管控能力,由于用的较少就不专门写了。

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