摘要: Service Mesher Meetup 上海站演讲内容整理。
小蚂蚁说:git
本文是基于在 Service Mesher Meetup 上海站的主题分享《蚂蚁金服 Service Mesh 渐进式迁移方案》内容整理,完整的分享 PPT 获取方式见文章底部。github
敖小剑,蚂蚁金服高级技术专家,十六年软件开发经验,微服务专家,Service Mesh 布道师,Servicemesher 社区联合创始人;龙轼,阿里巴巴技术专家、前京东 Hadoop 负责人、Hadoop 代码贡献者、现负责UC 基于 Kubernetes 自研的 PaaS 平台总体的稳定性。编程
你们好,今天给你们带来的演讲主题是《蚂蚁金服 Service Mesh 渐进式迁移方案》,给你们介绍一下咱们蚂蚁金服主站的 Service Mesh 迁移方案,在稍后的内容中我会给你们解释什么是“渐进式”。今天的演讲方式有些特殊,将会是两位讲师合做。我是敖小剑,来自蚂蚁金服中间件团队,另一位讲师 龙轼 ,来自 UC 基础研发部。json
今天的内容将会有四块主要内容:后端
前两块内容将由我来为你们介绍,后两块内容将由个人同事 龙轼 为你们介绍。api
在展开内容以前,先看一下背景,Service Mesh在蚂蚁金服主站落地的背景:缓存
今天演讲的内容,要给你们介绍的就是,在这样的背景下,咱们蚂蚁金服选择的Service Mesh主站落地演进方案。这个方案预期会在2019年初全面铺开。安全
主站落地方案的实施原则,这是咱们在过去半年的实践中,总结概括出来的行为指导:服务器
在接下来的演进路线中,你们将会体会到这三个原则在实际落地时的指导做用。网络
这个图的信息量有点大,描述的是 Service Mesh 和 k8s 落地可能的多种演进路线。
咱们先从最下面开始看,这是当前蚂蚁金服主站大多数应用的现状:即应用"部署在非k8s上",应用也"不是Service Mesh形态"。 而后看最上面,这是咱们指望的蚂蚁金服主站将来的应用终极形态:应用"部署在k8s上",应用也迁移到了"Service Mesh形态"。
这里有个特别的地方,咱们将Service Mesh形态细分为两种模式:
之因此将Service Mesh形态细分,是由于咱们有着这样一个特殊背景:目前的原生Istio没法支撑咱们蚂蚁金服的规模,所以在改进完善Istio以前,咱们不得不暂时在Sidecar模式下短暂停留。另一个缘由就是考虑到存量应用的迁移,多一个Sidecar模式做为中间缓冲,会让整个迁移过程平滑不少。
如今咱们来介绍图中展现的四条演进路线:
下面咱们来详细分析各条演进路线的优劣和实施条件。
演进路线2,和路线1的核心差异,在于:是先上k8s,仍是先上Service Mesh。并且路线2是在非k8s条件下一路演进Service Mesh到咱们指望的终极形态Istio模式,这意味着过程当中和最终目标有很是大的偏移。
演进路线2的好处,在于第一步很是的天然:
所以,路线2特别容易落地,能够快速达成短时间目标,直接拿到Service Mesh的部分成利,如:多语言支持,方便类库升级等。
可是,这个路线的问题在于再日后走,开始完善Service Mesh的功能以向Istio模式靠拢时,因为没有k8s的底层支持,所以不得不作大量的工做来提供类k8s的功能。尤为是Istio的非k8s支持,官方方案基本上只是一个demo,彻底不具有生产可用性,要完善好,工做量很大。而关键点在于,这些投入,在迁移到k8s时,又由于和k8s提供的功能重复而被放弃。
所以,结合咱们前面的原则(符合远期规划,不浪费投资),路线2对蚂蚁金服主站落地是不合适的。
演进路线4是一个很是特殊的路线,能够理解为路线1(先上k8s再上Service Mesh)的短时间妥协版本。由于路线1的前提条件是要先大规模铺开k8s,将现有应用迁移到k8s以后再继续往Service Mesh演进,这对于尚未普及k8s的公司来讲是一个很是高的门槛,很容易所以受阻而没法启动。
所以,若是暂时不具有k8s条件, 又不想就此止步,那么选择路线2是惟一的出路。而上面咱们分析过,路线2虽然可以在第一步快速拿到短时间红利,可是因为偏离长期目标后续发展会有问题。怎么办?
路线4能够是这种场景下的一个折衷选择:在k8s没有铺开以前,第一步沿路线2走,先吃下非k8s下Sidecar模式快速落地的红利。而后第二步避开非k8s下继续演进到Istio模式的大坑,切换到路线1,回归长期目标。
好处很是明显:
缺点就是存在少许的投资浪费,毕竟非k8s下的Sidecar模式仍是有些工做内容在迁移到k8s以后会有改动。不过,这个改动不会太大,和拿到的红利相比仍是值得的。
路线4在操做时,存在一个变数:现有应用在向Sidecar模式的Service Mesh迁移,是须要必定时间的。有一种可能,就是在迁移过程当中,k8s的普及开始了。这个变数的发生,取决于Sidecar模式的Service Mesh普及快,仍是k8s的普及快。
对路线4的分析结果:这是(k8s没有普及的)特殊时期的选择。
在对四条可能的演进路线分析完成以后,咱们来具体介绍蚂蚁金服的最终选择。
坦言说,在过去半年中,咱们的演进路线有几回摇摆和修订,今天咱们公布的路线,和过去几个月中咱们经过 meetup/技术大会/博客文章 等方式透露出来的方式会有一些变化。主要缘由是在过去的这半年中,一方面咱们对Sercice Mesh的认知更加深刻,另外一方面是蚂蚁金服的k8s背景也在变化。
首先,在今年年初,咱们确认Service Mesh大方向时,k8s尚未在蚂蚁金服普及,并且也没有明确的时间表。所以,咱们在一番调研以后,选择了两条腿走路的方式:
在今年6月底的杭州第一届Service Mesh 线下 meetup 中,咱们公布了 SOFAMesh 项目,我当时作了一个演讲 大规模微服务架构下的Service Mesh探索之路 ,有兴趣的同窗能够去回顾一下咱们当时的背景/需求/设计方案。
大概在今年九月,咱们完成了对非k8s下运行istio的深刻调研,得出的结论是要实现这个模式须要很是多的工做。并且,咱们对Service Mesh的认知也更加深入,明确了经过Service Mesh将传统中间件能力向以k8s为表明的基础设施层下沉的战略方向。期间,内部也明确了k8s普及的大方向,所以,综合这两个重要输入,咱们选择放弃继续在路线2上继续演进(即 istio on 非k8s)的想法。关于这一点,有兴趣的同窗能够去阅读我在10月份QCon大会上的演讲内容 长路漫漫踏歌而行:蚂蚁金服Service Mesh实践探索 。
最近,k8s普及的时间表再一次明确提早,蚂蚁金服将会在短期内开启k8s的大面积普及。所以,咱们的演进路线再一次发生变化。目前最新的演进路线将会是这样:
须要强调的是:这个演进路线针对的是蚂蚁金服主站的特殊场景,并不具体普适性。你们能够在理解咱们演进路线背后的思路和权衡方式以后,再结合自身的实际状况进行决策。好比,咱们在UC落地时,因为UC有完善的k8s支持,并且目前落地的规模没那么夸张,所以是直接从"部署在k8s上" + "不是Service Mesh形态",直接迁移到终态的。预计在金融云落实时,也会是如此,由于客户也不会有如此规模。
总结:前面咱们介绍了当应用程序向Service Mesh和K8s迁移时的几种可能的演进路线,分析了各条路线的利弊。并以蚂蚁金服主站为例,介绍了咱们迁移的背景和演进路线的选择思路,但愿可以帮助你们更好的理解Service Mesh的落地实践,以便在将来设计自家的落地方案时能有所参考。
实现平滑迁移的关键
前面给你们介绍了蚂蚁金服主站的Service Mesh演进路线,期间谈到要实现现有应用的平滑迁移。今天的第二个内容,将给你们介绍平滑迁移实现中的几个关键作法。
首先,第一个关键是尽可能保证迁移先后服务间网络互通。
以向k8s迁移为例,在非k8s环境,典型的服务间访问方式是这样:
在向k8s迁移的过程当中,咱们的作法是保证k8s内外网络打通,即服务的IP地址(在k8s中是pod ip)是能够相互直接访问的。基于这个前提,服务在迁移到k8s的过程当中,原有的服务注册/服务发现/发起请求等逻辑都无需修改,是否是在k8s内,是否是pod ip,对原有服务化体系彻底是透明的。
所以,向k8s的迁移能够作到对业务应用很是的平滑,基本感知。
透明拦截在迁移过程当中,能够起到很是关键的做用。
以Service-A要访问Service-B,在应用向Sidecar模式的Service Mesh迁移先后,会有有四种排列组合场景:
在这四种场景中,全部的网络请求,请求报文都是彻底一致的,即无论是否被劫持到Sidecar,对请求报文都没有影响,也就是对发出请求报文的客户端和接受请求报文的客户端都是透明的,彻底无感之。
所以,在迁移过程当中,能够单个服务逐个迁移,甚至服务的单个实例逐个迁移,而无需修改应用自己。
在展开第三个关键点以前,咱们来探讨一下:在Service Mesh时代,理想的客户端应该是什么样子?
图中咱们列举了一个传统的侵入式框架的客户端所包含的功能,在侵入式框架中,大部分的功能都是由客户端实现,所以会包含很是多的功能,如服务发现、负载均衡等基本功能,加密、认证、路由等高级功能。在应用迁移到Service Mesh以后,这些功能都下沉到Service Mesh中。所以,Service Mesh下的客户端能够进行大幅度的简化,成为一个新的轻量级客户端。
对于这个轻量级客户端,咱们但愿能够尽量的作的轻薄通用:实现简单,无论哪一个编程语言均可以作到轻松实现,所以跨语言就方便了。并且越简单以后升级的可能性就会越少,以免升级客户端。
那咱们来继续看,这个轻量级客户端里面最后还能剩下什么内容?
图中列出了三个,其中最重要的,也是必不可少的是目标服务的标识,即不管如何简化,最低限度应该告之要访问谁吧?而后是序列化,对于RPC类确定须要提供编解码功能,不过对于HTTP/REST类不少语言直接内置了标准实现。而后链路追踪,须要作一点工做来传递诸如SpanID之类的参数,一样这块也有可能经过自动埋点来实现。所以,最理想最单薄的客户端,可能只保留最后一个信息:目标服务的标示。
在侵入式框架下,目标服务的标示是和服务注册/服务发现是直接关联的,这个标示一般都是服务名,经过服务发现机制实现了一个服务名到服务实例的寻址方式。在Service Mesh机制下,因为服务发现机制被下沉到Service Mesh中,所以只要底层Service Mesh能支持,这个目标服务的标示能够没必要拘泥于服务名。
那么,问题来了,对客户端来讲:最简单,最通用,支持最普遍的寻址方式是什么?是DNS!
在咱们的迁移方案中,咱们考虑引入DNS寻址方式。除了前面说的DNS是支持度最好,使用最广泛的寻址方式,在全部的编程语言和平台上均可以支持以外,咱们还但愿将DNS寻址方式做为将来产品的长期方向:
所以,在咱们的演进过程当中,对于客户端SDK,咱们有这样一个思路:
图中描述的是在Service Mesh下,客户端经过域名来指定要访问的目标服务,而后经过DNS解析机制来串联底层的服务注册/DNS记录更新/透明劫持传递原始信息/Sidecar查找路由目标等详细实现机制。
这里仅作简单示意,我就不详细展开了。在接下来的内容中,个人同事,来自UC基础研发部的 龙轼 同窗,将为你们详细的展开DNS寻址方案的细节实现。
DNS寻址方案的演进
你们好,我是来自UC基础研发部的龙轼。 感谢小剑老师给咱们介绍了蚂蚁和UC共建的Service Mesh的演进路线和实现平滑迁移的关键。
接下来由我来向你们分享下实现平滑迁移的关键中的DNS寻址方案的演进。
你们能够看上面的所示的DNS寻址方案的演进,咱们先了解下各个服务寻址方案的背景。
从 SOA 的寻址,到 Kubernetes 的寻址,而后再到 Istio 的寻址,最后是咱们的 SOFAMesh 的DNS寻址方案。
它们的寻址方案有什么不一样,咱们将一一分析它们的细节和整体寻址方案的演进路线。
如今你们能够先来看下 SOA 架构下基于服务注册和服务发现的寻址。
咱们能够看到图中的 SOA 实际上是单进程多接口的,依赖于 SOA 的服务注册与服务发现的。
接下来咱们看下 Kubernetes 的 DNS 寻址方式,它的寻址方式实际上是经过DNS 的。
从图中咱们能够看到部署到K8S 上面的userservice 服务会生成一条DNS记录指向K8S 的ClusterIP。
咱们在 Pod 里面发起请求时经过 DNS 的 SearchDomain 域名补全规则就会从 DNS 里面查询获得ClusterIP,咱们能够看出 Kubernetes 的寻址方案是单进程单接口的。
看完 Kubernetes 的服务发现以后咱们继续来看 Istio 的服务发现。
从图中咱们能够看出以前的流程都和 K8S 一脉相承,不一样的地方在于 Istio 里面有个 SideCar 它把ClusterIP 拿到以后根据 ClusterIP 从 VirtualHost 里面匹配到 Rule 规则 转发给目标的 Pod 地址。
最后咱们来看下 SOFAMesh 的 DNS 通用寻址方案。
你们看这张图:
好的,说完这个方案的细节以后。咱们能够看出其实其余的问题都不大,可是要更新DNS的这个咱们须要支持。
一开始咱们 K8S 集群里面是用 Kube-DNS 来作 DNS 寻址的,但咱们看这张 Kube-DNS 的架构图。
能够看出修改它成本是比较大的,并且全部的DNS 都在同一个域里面,这个风险系数很高。 若是一旦修改错误势必会影响到以前的 k8s 的 service,致使线上的故障。
OK,既然 CoreDNS 的 Plugins 这么强大,咱们可不能够用它来实现咱们刚才说到的 Renew DNS的机制。 答案很显然是能够。
咱们看下上面的图,实现CoreDNS 的插件很简单,只须要继承上面的接口就能够了。 CoreDNS 官网有具体的教程在教咱们怎么写一个插件。这个就不具体的展开了。
咱们能够看下 CoreDNS 后端存储的接口,其实和咱们以前对数据操做的接口是没有什么差异的。
目前 CoreDNS 的 DynAPI 还在主库代码没合并的状态。以后 DynAPI 这个项目会独立成一个插件项目。咱们能够看下 CoreDNS 社区的 DynAPI 插件进展。
OK,咱们来看下咱们的DynAPI 实现DNS 更新的一个效果。从图中咱们能够看出 record.json 里面的一个域名的更新。经过 DynAPI 咱们成功把 record.json 的DNS 记录给更新进去而且dns正常工做了。到如今咱们经过CoreDNS 的插件就把DNS 更新的需求给解决了。
其实CoreDNS 官网还有许多有趣的插件,能够丰富 CoreDNS 的功能和提高 CoreDNS 的性能。 你们能够看下中间的 autopath 插件,他把咱们屡次的在 searchdomain 拼凑的 DNS 记录的查询在在服务器上给实现了。 避免了屡次的 Client 端和 Server 端的数据交互。有兴趣的同窗能够看下 A-Deep-Dive-into-CoreDNS-2018。
咱们把 CoreDNS 的功能开发完了,上线的话不少人关注它的性能。 咱们这边作了一个简单的性能测试,能够看出 CoreDNS 和 Bind DNS 这种如今比较通用的DNS的性能仍是有点差距的。
可是,咱们经过上面的图能够看到在必定的QPS 下,CoreDNS 的延时是很低的。 咱们能够看到全部的延时都落在4ms 以内。
为了解决QPS的问题,咱们经过 Kubernetes 的 HPA 给 CoreDNS 进行横向的扩展。
一开始咱们只是经过CPU的维度给 CoreDNS 扩展,但发现波动有点大。 以后咱们切换成经过QPS的维度来进行扩容。
CoreDNS 将会在Kubernetes 1.13 以后成为 Kubernetes 的默认的DNS服务。咱们将会紧跟社区实施咱们的方案而且反馈给社区。
DNS寻址方案的后续规划
咱们再来看下咱们后续的一些规划。
能够看到咱们的 DynAPI 其实在安全上仍是有欠缺的。咱们后续会把 HTTP 增强成 HTTPS 协议来加强 DynAPI 的安全性。
还有若是咱们 CoreDNS 的后端变化的更新的 Watch 因为 Watch的范围过大的话,会返回过多的数据。这样会影响到 Watch 的性能,CoreOS 在 ETCD3.2 增长了proxy 可让咱们根据不一样的 ETCD KeySpace 去Watch,这样大大的提升了Watch的性能。
最后一个,咱们建议在建立 Kubernetes 集群的时候把 idc 的信息给带进Kubernetes的后缀域名中。这样咱们以后能够经过 kubernetai 插件把不一样的 Kubernetes 集群的域名进行整合经过本 IDC 缓存提升跨 IDC DNS 的访问速度。
最后咱们总结下,整体方面小剑老师给咱们讲了蚂蚁金服主站 Service Mesh 的渐进式演进路线和实现平滑迁移的几个关键。 具体细节方面咱们经过CoreDNS 的单点突破解决了 SOFAMesh 的 DNS 寻址的问题。
感谢你们,但愿此次演讲能让你们有所收获。
地址:https://tech.antfin.com/activ...(点击阅读原文可跳转到该网页)
相关连接:
SOFA 文档: http://www.sofastack.tech/
SOFA: https://github.com/alipay
SOFAMosn:
https://github.com/alipay/sof...
SOFAMesh:
https://github.com/alipay/sof...
本文为云栖社区原创内容,未经容许不得转载。