Service Mesh下的微服务落地实践,听听他怎么说

709 阅读11分钟

在微服务架构中,Service Mesh 技术提供了代码无侵入地解决方案。如何解决Service Mesh和部署架构的解耦,以及在跨平台场景下如何实现服务间寻址。

作者:陆绪之

来源:腾讯云中间件公众号

陆绪之,安畅微服务架构师;拥有10年软件开发经验,4年微服务架构经验;具有J2EE,Springcloud,微服务方面有多项实践经验;现为安畅云原生产品研发负责人。

在微服务架构中,Service Mesh 技术提供了代码无侵入的解决方案。本文我们一起探讨如何解决Service Mesh和部署架构的解耦,以及在跨平台场景下如何实现服务间寻址。

本文给大家带来的分享主要围绕TSF Mesh框架的一些技术点,我目前带的团队跟TSF合作比较多,我们自己的研发团队也深入的去学习和研究了TSF Mesh框架,本次希望将我们在学习和使用过程中遇到的比较有启发、有意义的技术点,以及我们学习的一些心得,学有所得,学以致用之后,通过这样的方式传递给各位。

平台解耦,TSF Mesh对Istio的扩展与增强

我们在给一个做零售电商的客户架构做微服务落地过程中,发现原架构更多是偏向于混合云架构。基于历史的原因,一部分在IDC机房的业务会逐渐迁移到云上做一些灾备,或者在流量高峰期通过云的弹性伸缩做一些扩展。而东西向的流量希望接入Mesh框架对流量进行统一管理。

不同的应用基础架构不一样,比如在机房更多是服务器,在云上更多是虚拟机或者容器。有的业务可能是同一个应用要部署在不同的平台,需要相互之间的通信,这是我们通常面对的一个挑战。我们知道早期的Istio跟K8S平台是强绑定的,尤其是他们的服务路由依赖于K8S的CRD。我们分析如果用Istio去适配这样的场景有以下几个问题:

  • 在Istio控制面,它Pilot/Mixer的远程动态配置能力不可用;因为原先的Istio是基于K8S CRD和ConfigMap。在脱离K8S平台后这一块要考虑用新的方式去切换。

  • 关于健康检查,原先的Istio是基于K8S探针来帮助服务做健康检查。

  • 无法使用istioctl进行服务的注册和注销,因为istioctl本身就是对Istio对K8S的CRD等功能的封装,便于我们运维和调整。

我们通过分析这三个问题在原生的Istio架构上做了扩展,整体上还是基于Mesh控制面和数据面的一个大框架,图中蓝色虚线框的控制面上,TSF Mesh增加了一个Consul Server集群作为服务发现的中心。额外增加这个集群之后,后期控制面的一些组件会对它进行一定的扩展,让它拥有对Consul Server集群的读取能力,而我们所有的配置和服务注册都是基于Consul Server实现。

关于健康检查,原来的K8S探针不能用,Envoy作为数据面,会定期对经常跑在VM、Container上的服务做定期检查,基于HDS接口上报到控制面的Pilot,Pilot实现接口的解析,将实时的数据健康状态刷到Consul集群保证数据实时的有效性。

在数据面上,原先的Istio会有一个Polit-agent进程。对于服务的注册发现也做了一些小小的改动,我们会要求用户基于内容规则提供一个服务描述文件,跟我们的业务应用一起发布。

Pilot-agent在启动的时候,会优先获取服务描述文件,这个描述文件其实很简单,里面是这个服务的名称、对应的端口、健康检查的地址;Pilot-agent在启动的时候先读取配置文件,将这一批解析完了之后上传到控制面的Pilot,Pilot对请求进行处理刷新到Consul进行后续操作。

Server Mesh额外在控制面上增加了API Server接口,对外提供Restful Api,比如说平台管理端或者是SDK对整个Server Mesh控制面的查询和配置管理。比如说我要下发一个路由规则、黑白名单等。

总结一下,在平台解耦过程中,我们主要面临着三个问题:

  • 第一远程动态配置,通过增加Consul Server集群,替换掉K8S的CRD。然后对Pilot/Mixer进行扩展让它拥有对Consul进行读取的能力。

  • 第二健康检查基于Pilot HDS接口做上报,Pilot这边的改造能够正确的解析HDS接口,让它的信息能读取从而取代了K8S的探针。

  • 第三个是服务注册注销,也就是扩展了Pilot-agent,代码上比较简单,新增API Server,最终结果实现服务能够注册、能够发布,在服务通过描述文件自动注册,对外提供统一的Restful接口。

跨平台服务互通,DNS寻址模式演进

上面提到了在不同环境当中,我们实现了应用的跨容器部署,之后紧接着面临一个问题,不同的平台可以部署不同的微服务,这些不同的微服务怎样相互寻址,相互调度的? 我们先看一下原生的Istio解析的过程,这里的Reviews会向Ratings服务发出请求。

首先Reviews应用会发一个GET,带上Ratings的服务名称以及DNS和请求路径。这个请求首先会被K8S解析,将名称解析成Cluster IP,然后Cluster IP加端口继续进行请求到Envoy,Envoy拿到这些信息同时会跟控制面进行长连接获取到协议消息,最终找到10.0.2.3机器,一直将请求发到对端这台机器。紧接着又被iptables redirect所截获,最终解析为Ratings的内部请求。两个应用相互请求逻辑梳理清楚之后,我们可以看到问题在于如果跨平台,要剥离掉Kube-dns组件,其他没有任何改动。

接下来是DNS选型问题,DNS从组网架构上分为集中式和分布式。集中式是一组独立的DNS服务器,利用扩展插件的机制将DNS Server跟注册中心做实时数据同步,保证注册的服务能有效的解析。

这是集中式服务,优势是市面上有很多成熟的产品,比如CoreDNS,ConsulDNS等等。缺点是额外需要增加一些资源和运维的成本,也就是说DNS本身也是一个比较重要的中间件,如果它挂掉就会面临大量的服务不可调用。

分布式DNS原理是将DNS解析的能力下沉到节点上,我们的应用首先会把所有的流量导入到DNS Server进程,由它去跟注册中心进行实时同步,同时会解析和转化我们的请求。相对来说,如果某一个DNS Server挂掉之后,可能只会影响到节点上的应用,不会对整个的系统会造成大面积的影响。

经过这样的分析和梳理之后,TSF Mesh选择分布式的方案,缺点是市面上并没有一套这么成熟具体的方案,可能面临着研发成本,需要自研。

这就是最终的实现方案,主要做三件事:

  • 在节点增加iptables规则,转发node上所有发往name Server的流量。

  • Mesh-dns 通过 Inotify 监听 /etc/resolv.conf,变更实时生效。

  • 与控制面Pilot同步服务列表。

多服务场景适配,代理单节点多服务

这个听上去比较绕,但是它的场景比较好理解,在交付过程中客户的一些应用可能并不是一个理想完美的微服务,因为一些历史遗留的原因,比如下图左边是基于OSGI模块化的技术,它的服务可以理解为一个单体应用,但又想去享受微服务的治理能力,这就是一个进程暴露一个端口,从微服务上来讲它就是一个服务,但是内部却是多个服务之间进行的通信。它希望能有一个平台对这个进程中某一个模块做服务的路由,使得在调用链追踪上也能看到,体现的是一个服务中的多个模块。

右边像Tomcat容器,在虚拟机上一个进程同时监测多个端口也想注册多个服务,这种相对比较小众的场景我们第一反应让客户去做应用的改造,一般客户不太容易接受,归根到底需要一个平台和产品侧去适配这种场景。

前面我们说到平台解耦时,提到过服务注册、服务描述文件,描述服务的端口、服务名称,以及健康检查的信息。为了适配单端口多服务,或者是多端口多服务的场景,在服务注册上就取决于服务描述的问题,如果服务描述能正确描述是单端口多服务还是多端口多服务,那么启动的时候就能正确解析描述文件正确进行操作。

下面是服务描述文件的具体实现方式,左边对于多服务单端口举例是两个服务,但是两个服务都监听到8091端口。

右边多服务多端口是User 8092,Order 8093,把这个解析正确之后比较好注册。完成服务注册后需要面对的是服务路由的问题,比如说数据面请求进来请求出去的时候,怎么样正确的把对应的请求流量路由到正确的服务上?

首先看OutBound的服务器路由,通过LDS、RDS、CDS、EDS对应到具体的IP地址端口。在LDS通过8089找到路由服务信息,然后找到RDS Cluster out,最终对应到服务端点,就能拿到具体的IP端口,通过它的负载均衡算法,再进行流量分配。

对于InBound请求稍微有点复杂,在原生的Istio版本,生成InBound Listeners过程中提示冲突。对于单端口多服务的场可能IP和端口是重复的,我认为IP端口重复就是一个服务甚至可能是配置上有问题。所以如果发现这个Map里面IP端口有重复就会导致生成的LDS出现问题,也就是说user、shop是8089,都共用8089端口,可以说最终生成的LDS就是一个user8089。这种正常路由没有问题如果配合组件做微服务的话,最终会出现跟实际想的效果不一致。

发现这种问题之后,后面的解决方案也比较好理解。因为生成LDS的逻辑对它稍加修改,进行流量请求的逻辑做一些匹配,最终生成右边的结构监听到8090端口,下面有一个Shop,一个是Promotion,这样的请求流量能进8090,通过Route_confiq name就可以做一些流量的控制。

简单分享一下这三个方法:

  • 第一个是在遇到跨平台请求的时候,怎样通过去改掉原生的架构让它支持跨平台的部署。

  • 第二个话题是支持到跨平台部署之后,面对跨平台的互信涉及到分布式DNS和集中式DNS的一些区别,我们最终怎样做出决策。

  • 第三个是兼容一些老的应用,单端口多服务,和多端口多服务遗留的老系统,怎样更改服务描述文件场景配置进行代理单节点服务。

热列庆祝Techo大会精彩回顾完美收官,评论留言告诉我们关于微服务你想说的话,还有机会解锁惊喜礼包!

传送门