原文地址:https://mp.weixin.qq.com/s/543MsQkrtTdIfnfGd7LciA
Service Mesh 是什么?
- 基础设施层:这是 Service Mesh 的定位;
- 服务间通讯:这是 Service Mesh 的功能和范围;
- 实现请求的可靠传递:是 Service Mesh 的目标;
- 轻量级网络代理:是 Service Mesh 的部署方式;
- 对应用程序透明:是 Service Mesh 的重要特性,零侵入,Service Mesh 的最大优势之一。
SOFAMesh 项目
SOFAMesh 是蚂蚁金服推出的 Service Mesh 开源产品,大家可以简单的理解为是 Istio 的落地增强版本。
- 跟随社区
- 实践检验
原则上:Istio 做好的地方,我们简单遵循,保持一致;Istio 做的不好或者疏漏的地方,我们努力改进和弥补。
SOFAMesh 架构继续延续 Istio 的数据平面和控制平面分离的方式,主要工作内容是:
- 用 Golang 开发 Sidecar,也就是我们的 SOFAMosn 项目,替代 Envoy。
- 集成 Istio 和 SOFAMosn,同时针对落地时的需求和问题进行扩展和补充,这是我们的 SOFAMesh 项目
在这个架构中,和 Istio 原版最大的不同在于我们没有选择 Istio 默认集成的 Envoy,而是自己用 Golang 开发了一个名为 SOFAMosn 的 Sidecar 来替代 Envoy。
在 Istio 和 Envoy 中,对通讯协议的支持,主要体现在 HTTP/1.1 和 HTTP/2 上,这两个是 Istio / Envoy 中的一等公民。而基于 HTTP/1.1 的 REST 和基于 HTTP/2 的 gRPC,一个是目前社区最主流的通讯协议,一个是未来的主流,Google 的宠儿,CNCF 御用的 RPC 方案,这两个组成了目前 Istio 和 Envoy(乃至 CNCF 所有项目)的黄金组合。
SOFAMosn 干了啥?
MOSN 的全称是 "Modular Observable Smart Network",正如其名所示,这是一个模块化可观察的智能网络。
而我们 SOFAMesh,在第一时间就遇到和 Istio/Envoy 不同的情况,我们需要支持 REST 和 gRPC 之外的众多协议:
- SOFARPC:这是蚂蚁金服大量使用的 RPC 协议 (已开源);
- HSF RPC:这是阿里集团内部大量使用的 RPC 协议 (未开源);
- Dubbo RPC: 这是社区广泛使用的 RPC 协议 (已开源);
- 其他私有协议:在过去几个月间,我们收到需求,期望在 SOFAMesh 上运行其他 TCP 协议,大部分是私有协议。
为此,我们需要考虑在 SOFAMesh 和 SOFAMosn 中增加这些通讯协议的支持,尤其是要可以让我们的客户非常方便的扩展支持各种私有 TCP 协议。
为什么不直接使用 Envoy?
Envoy 是 C++。
我们在选择之前,内部做过深入讨论,焦点在于:未来的新一代架构的底层平台,编程语言栈应该是什么?最终一致觉得应该是 Golang,配合部分 Java。
SOFAMesh 在落地期间遇到的典型问题
通讯协议扩展
前面也刚谈到过,就是我们会需要支持非常多的 TCP 协议,包括各种私有协议。
这个问题主要源于现在 Istio 的设计,按照 Istio 现在的方式,如果要添加一个新的通讯协议,是有几大块工作要做的:
- 添加协议的 Encoder 和 Decoder;
- 修改 Pilot 下发 Virtual Host 等配置;
- 修改 Sidecar 如 Envoy,MOSN 去实现请求匹配。
后两者是大量重复的,就技术实现而言,需要修改的内容和现有的东西差不多,但是必须要再改出一份新的来。因为我们协议比较多,由此带来的改动量非常大。根据我们之前的实践,以这样的方式加一个新的通讯协议可能需要几天的工作量,而且每次改动都重复大量代码。
在这里我们最后给出了一个名为 x-protocol 的通用解决方案。根据我们最新的验证情况,如果我们要添加一个新的通讯协议,大概就是一两百行代码,一两个小时就能完成。
平滑迁移传统架构
所谓传统架构指的是传统的 SOA 架构,如基于 Dubbo 的很多现有应用,我们希望它们能够在 Service Mesh 中直接跑起来,而不必一定要先进行微服务改造。
SOA 框架当中,通常是以接口为单位来做服务注册,也就是一个应用里面部署多个接口的,在运行时是一个进程里面有多个接口(或者说多个服务)。实际上是以接口为粒度,服务注册和服务发现,包括服务的调用都是以接口为粒度。
但是有个问题,部署到 Istio 中后,Istio 做服务注册是以服务为粒度来做服务注册,这个时候不管是注册模型,还是按接口调用的方式都不一致,就是说通过 Interface 调用是调不通的。
怎么解决这个问题?最正统的做法是,是先进行 微服务改造:把原有的 SOA 的架构改成微服务的架构,把现有应用拆分为多个微服务应用,每个应用里面一个服务(或者说接口),这样应用和服务的关系就会变成一对一,服务注册模型就可以匹配。
但是在执行时会有难处,因为微服务改造是一个比较耗时间的过程。我们遇到的实际的需求是:能不能先不做微服务改造,而先上 Service Mesh ?因为 Service Mesh 的功能非常有吸引力,如流量控制,安全加密。那能不能先把应用搬迁到 Service Mesh 上来,先让应用跑起来,后面再慢慢的来做微服务改造。
这就是我们实际遇到的场景,我们需要找到方案来解决问题:注册模型不匹配,原有用接口调用的代码调不通。
我们设计了一个名为 DNS 通用选址方案 的解决方案,用来支持 Dubbo 等 SOA 框架,容许通过接口名来调用服务。我们会在 DNS 中增加记录,我们会在 DNS 中把这个三个接口指向当前服务的 Cluster IP。k8s 的 Cluster IP 通常是一个非常固定的一个 IP,每个服务在 k8s 部署时都会分配。在增加完 DNS 记录之后,再通过 Interface 的方式去调用,中间在我们的 Service Mesh 里面,我们会基于 Cluster IP 信息完成实际的寻址,并跑通 Istio 的所有功能,和用服务名调用等同。
适配异构体系
异构体系指的是,当我们进行 Service Mesh 落地时,会存在新旧两条体系,比如说新的应用是基于 Service Mesh 开发的,而旧的应用是基于传统框架比如说 Dubbo 或者是 Spring Cloud。
当我们做应用迁移的时候,考虑到原来的存量应用会有很多的,比如上千个应用,这些应用肯定不可能说一个晚上全部切过去。中间必然会有一个过渡阶段,在这个过渡阶段新旧体系中的应用应该怎么通讯,如何才能做到最理想。
涉及到流量劫持的方案
Service Mesh 有一个很重要的特性,就是无侵入,而无侵入通常是通过流量劫持来实现的。通过劫持流量,在客户端服务器端无感知的情况下,可以将 Service Mesh 的功能插进去。
但 Istio 的流量劫持方案做的还不够好,目前 Istio 只给了一个方案就是 iptables。这个方案有比较多的问题,所以我们有几个思路:
- 优化 iptables
- 调研 IPVS 方案。我能告诉大家的是,到目前为止,蚂蚁金服内部的机器上,iptables 不仅仅是禁用,而是整个 iptables 模块都被卸载。原因是性能、安全、维护等大家周知的原因,总之我们蚂蚁金服内部是没有这个模块的。为了解决这个问题,我们现在正在调研 IPVS 的方案,准备用 IPVS 来替换 iptables。这块工作正在进行,目前方案已经验证,但是还有一些细节没有完善,后面有更多的消息也给大家继续介绍。
- 轻量级客户端的实践。另外还有一个实践是考虑不做流量劫持。比如说,最典型的 RPC 方案,因为 RPC 通常来说总是会有一个客户端的。在上 Service Mesh 之后,可以将原来的客户端的一些功能如服务发现、负载均衡、限流等精简,形成一个新的轻量级客户端,但此时终究还是有一个客户端在的。
但上面这三个都不是今天的重点,今天的重点是下面这个 Cilium + eBPF 的思路,这是我们目前最密切关注的一个方案。
Cilium 的这个思路是我们非常赞赏的,通过这样的方式减少服务和 Sidecar 之间的性能损失,可以解决 Service Mesh 中至关重要的一个问题:性能与架构的取舍。
熟悉 Service Mesh 技术的同学,应该多少都有这样的认知: Service Mesh 是一门中庸的艺术。
在性能与架构之间, Service Mesh 选择牺牲性能来换取架构。
- 在传统的侵入式框架中,客户端业务代码和框架代码之间是通过函数来进行调用的,速度非常快完全可以忽略。
-
而 Service Mesh 是强行把框架和类库剥离出来,将上述的方法调用变成一个远程调用,以牺牲了一次远程调用的开销为代价来换取整个架构的优化空间。
这是 Service Mesh 技术和传统侵入式框架的一个本质差异,也是 Service Mesh 技术和传统侵入式框架所有差异的源头。
服务间通讯范围的探索
Service Mesh 起初关注的是东西向通讯,即系统内部各个服务之间的通讯,而这通常都是同步的,走 REST 或者 RPC 协议。
在 Service Mesh 的实践过程中,我们发现,Service Mesh 可以提供的功能:
- 请求转发:如服务发现,负载均衡等;
- 路由能力:如强大的 Content Based Routing 和 Version Based Routing ;
- 服务治理:基于路由能力而来的灰度发布,蓝绿部署,版本管理和控制;
- 纠错能力:限流,熔断,重试,测试目的的错误注入;
- 安全类:身份,认证,授权,鉴权,加密等。
第一个探索的方向是 API Gateway,和东西向通讯直接对应的南北向通讯。
第二个探索的方向是 Serverless 和 Knative。
Cloud Native 云原生
云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。
Service Mesh 的归宿
Service Mesh 的归宿,或者说最终的形态,是下沉到基础设施!
从 Service Mesh 的发展看,从简单的 Proxy,到功能完善的 Sidecar(如 Linkerd 和 Envoy),再到以 Istio 为代表的第二代 Service Mesh,演进的方式如上图:
第一步:从应用剥离
通过将原有的方法调用改为远程调用,将类库的功能套上 Proxy 的壳子,Service Mesh 成功的将服务间通讯从程序中剥离出来,从此服务间通讯不再是应用程序的一部分。
第二步:下沉为抽象层
这些剥离出来的服务间通讯的能力,在剥离之后,开始下沉,在应用程序下形成一个单独的抽象层,成为 服务间通讯专用基础设施层。此时,这些能力以一个完成的形态出现,不再存在单独的类库或者框架形式。
第三步:融入基础设施
继续下沉,和底层基础设施密切联系,进而融为一体,成为平台系统的一部分,典型就是和 kubernetes 结合。
Istio 在这方面做了一个非常大的创新,Istio 的创新,不仅仅在于增加控制平面,也在于和 kubernetes 的结合。
Service Mesh 和 Spring Cloud / Dubbo 的本质差异,不仅仅在于将服务间通讯从应用程序中剥离出来,更在于一路下沉到基础设施层并充分利用底层基础设施的能力。
有疑问加站长微信联系(非本文作者)