本文共 6114 字,大约阅读时间需要 20 分钟。
Service Mesh(服务网格)是一个基础设施层,让服务之间的通信更安全、快速和可靠,是云原生技术栈的关键组建之一。2018年是Service Mesh 高歌猛进的一年,Service Mesh数据面板百花齐放,遍地开花,业界几乎所有大厂都在推出自己的Service Mesh 产品。2018年Service Mesh大事件如下:
早在2017年腾讯云中间件团队就选定Istio为技术路线,开始Service Mesh的相关研发工作,作为腾讯云TSF(微服务平台)的无侵入式服务框架的核心实现,并在18年初在腾讯广告平台投入,打磨稳定后陆续开始对外输出,目前在银行、电商、零售、汽车等行业都有落地案例。
落地过程并非一帆风顺,本文将对腾讯云Service Mesh 在生产实践过程中遇到的典型问题以及解决方案进行总结分享,同时对腾讯云Service Mesh后续重点探索的技术方案进行简要阐述。
腾讯云Service Mesh,遵循Service Mesh的理念进行设计,为应用提供服务自动注册发现、灰度路由、限流、熔断等服务治理能力,且应用无需对源码进行侵入式变更即可与该服务框架进行集成。
在实现上,基于业界达到商用标准的开源软件Istio、envoy进行构建。整体架构上,从功能逻辑上分为数据面和控制面:
控制面主要提供配置及控制指令支撑sidecar的正常运行,以及对服务运行过程中的相关数据进行采集。
数据面主要是提供通信代理(sidecar)来进行透明的服务调用,支撑正常的业务流程。
接下来,让我们对腾讯云Service Mesh各关键优化点做详细的描述。
众所周知,Istio强依赖于Kubernetes ,大部分功能都依托于Kubernetes 平台进行构建。下面列举几个核心的功能:
但实际落地过程中,TSF的用户并非全部是Kubernetes用户,例如公司内部的一个业务因历史遗留问题,不能完全容器化部署,同时存在VM和容器环境,架构如下:
从业务架构图可以看出,业务要求TSF可以支持其部署在自研PAAS以及Kubernetes 的容器、虚拟机以及裸金属的服务都可以通过Service Mesh进行相互访问。
因此,为了实现多平台的部署,必须与Kubernetes 进行解耦。经过分析发现,脱离Kubernetes 后,Istio存在以下三个问题:
针对这3个问题,TSF团队对Istio的能力进行了扩展和增强,增强后的架构如下:
下表更详细的描述了存在的问题、解决方案以及所得到的目的,同时TSF 团队实现了Istio 对Consul的完整适配。
经过改造后,Service Mesh成功与Kubernetes 平台解耦,组网变得更加简洁,通过REST API可以对数据面进行全方位的控制,可从容适配任何的底层部署环境,对于私有云客户可以提供更好的体验。
解决了跨平台部署问题后,第二个面临的问题就是服务的寻址互通问题。
Istio下的应用使用FQDN(fully qualified domain name)进行相互调用,基于FQDN的寻址依赖DNS服务器,Istio官方对DNS服务器的说明如下:
中,Reviews与Ratings之间的完整的服务调用会经过以下过程:
从图上可以看出,Reviews和Ratings的互通,kube-dns主要实现2个功能:
在私有云的实际交付中,客户的生产环境不一定包含Kubernetes 或者kube-dns,我们需要另外寻找一种机制来实现上面的两个功能。
在DNS选型中,有集中式和分布式两种方案,分别如下:
kube-dns也属于集中式DNS的一种,集中式DNS存在以下问题:组网中额外增加一套DNS集群,并且一旦DNS Server集群不可服务,所有数据面节点在DNS缓存失效后都无法工作,因此需要为DNS Server考虑高可用甚至容灾等一系列后续需求,会导致后期运维成本增加。
分布式DNS运行在数据面节点上,DNS无单点故障,无需考虑集群容灾等要素,只需要有机制可以在其down掉后重新拉起即可。但是,由于其与业务进程运行在同一节点,因此其资源占用率必须控制得足够低,才不会对业务进程产生影响。
综合考虑,最终选用了分布式DNS的方案,最开始团队采用独立进程作为DNS Server的方案,如下图:
该方案新增监听在127.0.0.1:53 上的mesh-dns进程,该进程实时从Pilot同步服务列表。Mesh-dns在节点启动时将127.0.0.1写入到/etc/resolv.conf首行中,同时接管/etc/resolv.conf的其他nameserver。这样,当app发起DNS查询时,DNS请求首先会到达mesh-dns,遇到匹配服务名的查询则直接返回,而当遇到不是针对服务名的DNS查询时,就把DNS请求转发给其他nameserver进行处理。该方案看起来简单可行,但是经测试验证后发现存在以下问题:
针对上述问题,对方案进行了进一步的优化,优化后的方案如下图:
mesh-dns不再监听53端口,而是监听在5353端口(可配置),启动时无需修改resolv.conf。通过增加iptables规则,将所有发往nameserver的流量导入到mesh-dns,从而解决了上文中的“端口监听冲突”以及“nameserver选择策略”的问题。
mesh-dns通过inotify监听/etc/resolv.conf,可以随时获取环境中dns配置的更改,从而解决了上文中的“resolv.conf修改时间差”的问题。
现实总是复杂的,前面解决mesh服务之间相互访问的问题,如何解决用户Service Mesh应用和其他非Mesh 应用的相互访问呢? 用户内部有不同技术栈,一部分服务基于service mesh进行实现服务,另外一部分服务基于spring cloud框架进行实现。同时,客户的微服务组网中,存在大量第三方服务如支付网关、分布式存储、设备等,微服务需要与这些第三方服务也存在交互。用户期望支持的架构如下图所示:
这个架构中,最大的挑战在于涉及了两个不同的微服务框架之间的互通。但是,这两个微服务框架从架构模式、概念模型、功能逻辑上,都存在较大的差异。唯一相通的点,就是他们都是微服务框架,可以将应用的能力通过服务的形式提供出来,给消费者调用,消费者实际上并不感知服务的具体实现。
基于这个共通点,为了使得不同框架开发的服务能够正常工作,TSF团队做了大量的开发工作,将两个微服务框架,从部署模式、服务及功能模型上进行了拉通,主要包括如下几点:
用户的需求是多种多样的,在交付过程中存在如下多服务场景:
为了支持多服务场景,简化用户的使用流程,TSF提供了服务描述文件,可支持多服务场景,服务配置文件与Kubernetes 标准格式一致:
pilot-agent会根据服务配置,按照--的格式将配置中services注册成多个独立的服务实例。
在OutBound服务路由时,可以通过LDS-\u0026gt;RDS-\u0026gt;CDS-\u0026gt;EDS的方式进行路由,和独立部署的服务没有区别:
然而,在InBound服务路由过程中,通过开源Istio生成的listener会遇到一些坑。
对于多服务监听同一端口的场景,开源Istio在生成inbound的时候,会将同IP+Port的其中一个服务给reject掉。
因此,生成的LDS中,只有其中一个服务的相关路由信息:
这样一来,普通消息投递,不会有什么问题(目标端点信息是一致的),但是假如需要与mixer结合,做api鉴权或者限流等操作,则会出现两个服务的mixer_attribute互相混淆的情况,导致功能不可用。
为了解决这个问题,团队分析了,对pilot进行改造,扩展了listener能力,通过server_name来分流数据包到不同的filter中。
最终生成的LDS如下:
经过这样的改造,同一端口上,不同的服务的filter配置不再冲突,两个服务的mixer_attribute也能相互隔离,顺利支持同端口多服务的场景。
在当前业界的开源Service Mesh产品中,主打的协议都是标准协议(HTTP1/2, GRPC),标准协议都有一个特点,那就是协议头中包含了目的端相关的所有信息,Service Mesh会根据这些信息进行路由。如下表所示:
对于其他二进制协议,则分为2大类:
第一种是协议中带有目标端信息的二进制协议,如thrift,dubbo等;
第二种是协议中不带有目标端信息的二进制协议,这种就比较多了,一般常见于私有云中的各种私有通信协议。
开源Istio中,对于二进制协议的支持,仅仅局限于四层的端口转发,一般用于集成外部服务(mysql, mongodb等),典型场景是对不同入口的流量做转发,如下图所示:
单纯的四层转发,无法满足复杂的微服务路由的需求。当前TSF交付的客户中,多个客户都提出了需要支持私有协议路由的需求,因此,针对这个问题,TSF团队提供了两种解决方案。
由于GRPC的Data Frame本身传输的就可以是TCP协议,因此用户可以直接把自己的二进制协议通过GRPC的bytes类型编码,然后通过Data Frame传输过来.
该方案适用于本身有一定的技术积累,愿意去做GRPC改造的用户。该方案适用于自身带有目标端信息的二进制协议,可以让私有协议的用户无需任何的改造,即可接入Service Mesh。
腾讯云Service Mesh当前通过TSF平台在持续交付中,上文主要针对落地过程中遇到的典型功能性需求及技术方案演进进行了总结介绍,除此之外,中间件团队在Service Mesh性能方面也有很多优化和探索,主要包括减少envoy和mixer之间的网络交互、优化数据包在envoy节点内部从内核态到用户态的拷贝次数、envoy 到envoy之间数据的转发性能等,后续将针对性能优化进行专项分享。
作者简介:
单家骏,来自腾讯公司。腾讯云高级工程师,负责腾讯云中间件paas以及servicemesh的研发与架构,关注云原生与中间件技术。热爱开源、崇尚技术,希望能够使用技术使软件的应用变得简单、高效和美好。
转载地址:http://wjill.baihongyu.com/