熟悉服务网格和 Istio 概念的读者朋友们,可以跳过这一章节,直接进入下一章节。
Service Mesh 一词最早由开发 Linkerd 的 Buoyant 公司提出,这一术语于 2016 年 9 月 29 日第一次公开使用,并被翻译成“服务网格”,逐步在国内传播开来。William Morgan,Buoyant CEO,对 Service Mesh 这一概念定义如下:
翻译成中文如下:
服务网格是一个专门处理服务通讯的基础设施层。它的职责是在由云原生应用组成服务的复杂拓扑结构下进行可靠的请求传送。在实践中,它是一组和应用服务部署在一起的轻量级的网络代理,并且对应用服务透明。
Istio 是一个开源的服务网格实现产品,一经推出就备受瞩目,成为了各大厂商和开发者争相追捧的对象。Istio 官方文档是这样来定义自己的:
从官方定义我们可以看出,Istio 提供了一个完整的解决方案,可以以统一的方式去管理和监测你的微服务应用。同时,它还具有管理流量、实施访问策略、收集数据等方面的能力,而所有的这些都对应用透明,几乎不需要修改业务代码就能实现。有了 Istio,你几乎可以不再需要其他的微服务框架,也不需要自己去实现服务治理等功能。只要把网络层委托给 Istio,它就能帮你完成这一系列的功能。简单来说,Istio 就是一个提供了服务治理能力的服务网格。
好的,前面背景交代清楚了,现在可以开始正文了。
Istio 会是服务网格领域的事实标准吗?我觉得今天我可以给一个答案了,NO。
Istio 2017 年 5 月发布第一个版本 v0.1,从发布 v1.0 开始得到大规模关注,发布 v1.5 做了控制面架构的大调整,后持续迭代,每三个月发布一个大版本,截止日前,已经发布了 v1.12 了。Istio 支持丰富的流量治理策略,具有丰富的可观测性集成能力,且积极拥抱变化,迈向架构简约主义,增强易用性,提供对虚拟机的支持等。
Istio 是一款优秀的开源软件,具有极高的社区活跃度和强大的社区生态,也具备比较优秀的架构设计,这一点毋庸置疑。但是,有一个缺陷,也是比较致命的缺陷,Istio 不是从企业中大规模落地验证后开源出来的,Istio 是从出生就是一个开源软件,Istio 是一个理想型的开源软件(譬如强调流量劫持的无侵入性)。
软件架构没有银弹,往往是取舍。在设计之初,Istio 考虑的是普适性和功能的完备性,支持流量管理、安全、可观测性等多个维度的功能设计,并且随着项目的发展,这个功能不断增强,其实带来的损害就是性能,以及海量实例场景下 CPU 与 内存的巨量消耗。
我们可以看到,Istio 在很多实例规模比较小的公司或者业务团队,是可以逐步落地和推广的,但是一旦上了体量,问题就暴露出来了。早期 mixer 组件带来的性能问题尚且不谈,毕竟已经废弃了,但是 iptable 的流量劫持机制,在一定程度上来讲,就是在大规模公司落地的拦路虎。目前 Istio 使用 iptables 实现透明劫持,主要存在以下三个问题:
从一些公开信息如技术演讲和博客来看,蚂蚁集团、百度、字节跳动等大规模落地了服务网格的公司来看,基本上都舍弃了 iptables 的流量劫持方案,采用的是基于约定的流量劫持(接管)机制,从而优化了大规模场景下流量劫持和服务间通信的时延和性能。流量劫持方案往往是和公司内部的 Naming Service 以及 服务注册发现机制相结合的,不会一昧地追求零侵入式方案。
以字节跳动为例,采取框架和 Mesh Proxy 进行约定的方式进行接入服务网格治理体系。
此外,社区还有一种方案,采用 eBPF 来实现流量劫持。eBPF(extended Berkeley Packet Filter) 是一种可以在 Linux 内核中运行用户编写的程序,而不需要修改内核代码或加载内核模块的技术,目前被广泛用于网络、安全、监控等领域。在 Kubernetes 社区最早也是最有影响的基于 eBPF 项目是 Cilium,Cilium 使用 eBPF 代替 iptables 优化 Service 性能。
入流量,对比 iptables 和 eBPF 对入流量的劫持,iptables 方案每个包都需要 conntrack 处理,而 eBPF 方案只有在应用程序调用 bind 时执行一次,之后不会再执行,减少了性能开销;出流量,对于 TCP 和 connected UDP,iptables 方案每个包都需要 conntrack 处理,而 eBPF 方案的开销是一次性的,只需要在 socket 建立时执行一次,降低了性能开销。
总得来说,使用 eBPF 代替 iptables 实现流量劫持,在一定程度上降低了请求时延和资源开销,但是受限于内核版本,因此短时间内很难大规模落地。
再来看数据面 envoy 与控制面 istiod 的通信协议 xDS。xDS 包含多种协议的集合,比如:LDS 表示监听器,CDS 表示服务和版本,EDS 表示服务和版本有哪些实例,以及每个服务实例的特征,RDS 表示路由。可以简单的把 xDS 理解为,网格内的服务发现数据和治理规则的集合。xDS 数据量的大小和网格规模是正相关的。
Istio 下发 xDS 使用的是全量下发策略,也就是网格里的所有 sidecar,内存里都会有整个网格内所有的服务发现数据,理由是用户很难梳理清楚服务间依赖关系并且提供给 Istio。按照这种模式,每个 sidecar 内存都会随着网格规模增长而增长。根据社区有团队对其做的性能测试可以看出,如果网格规模超过 1 万个实例,单个 envoy 的内存超过了 250 兆,而整个网格的开销还要再乘以网格规模大小,即 2500 千兆,惊人的消耗!!!
当然,社区也提供了一些解决方案,比如通过手动配置 Sidecar 这个 CRD,可以显示地定义服务间的依赖关系,这要求用户需要手动配置梳理好每一条调用链关系,服务间才能发现彼此,这在大规模场景下也是有一定的局限性。也有社区同学开源出来了一些解决方案,但是都或多或少带来了一些其它问题,譬如单点问题、系统的复杂度提高、运维复杂性、峰值压力等。
国内很多服务网格玩家最熟悉的就是 Istio,这与早期国内一批服务网格布道师都比较看好 Istio,对其做了很多布道有关系,譬如技术演讲、官网英文文档的汉化、英文博客的翻译、中文社区的搭建(如 ServiceMesher),这些对 Istio 在国内大范围普及起到了至关重要的作用。Linkerd 作为市场上第一个服务网格开源项目,在国内却没有那么受欢迎,没有被布道师们选中。事实上,根据 CNCF 在 2020 年的全球调查报告显示,69% 的人正在评估 Istio,64% 的人正在评估 Linkerd,在国际视野中,两者的差距并没有那么大。
Linkerd 是 Buoyant 为 Kubernetes 设计的开源超轻量级的服务网格。数据面用 Rust 完全重写以使其具有超轻量级和高性能的特征,它提供运行时调试、可观察性、可靠性和安全性,而无需在分布式应用中更改代码。
从用户体验侧来看,两者并无太大差异,有些功能或支持或不支持,有些外部组件或者接口或可对接或不可对接,这些都无关大雅,只要是大多数用户的需求,时间会解决这些问题,换句话说,随着时间的推移,项目最终多会支持起来,不管是 Istio 还是 Linkerd。
社区有很多人,不喜欢去谈 Istio 和 Linkerd 究竟谁更好,因为缺乏技术背景和落地场景,因此不能一概而论。仅仅是技术角度来看,Linkerd 的性能特别快,根据 2019 年的第三方基准测试,它比 Istio 快 3-5 倍,内存的消耗也 Istio 的近五分之一,CPU 消耗不相上下。路由和服务弹性方面,Linkerd 似乎并不追求 Istio 那样的完备性,没有那么多花里胡哨的细粒度功能。用两个词来形容 Linkerd ,那就是:轻巧、简约。从上述这个角度来看,Linkerd 貌似更适合商业化以及在大规模场景下进行落地。
Linkerd 官网关于设计原则的表述 :
Linkerd 是 CNCF 基金会的毕业项目,拥有 Expedia、HP、Cisco webex 等客户,虽然比起 Istio 的用户不够看,但是落地的用户数量还是不少的,影响力也是杠杠的。
但是,回过头来看看,前面提到的 iptables 流量劫持机制以及服务发现数据和治理规则的全量下发问题,在 Linkerd 里面也是存在的,并没有得到解决,也没有提出更优的解决方案。从架构上来看,Linkerd 与 Istio 竟没有本质的区别。因此,在性能、CPU & 内存消耗方面,Istio 与 Linkerd 均不是最优解。大规模落地场景下,Linkerd 也不是一剂良方。
Istio 与 Linkerd 都培养了一定的社区影响力,在一定程度上,也形成了社区标准,总得来说,这两个项目是长期可靠的。一些初创公司和小服务的业务团队,大可放心使用二者其一,因此,其它开源项目笔者也不做推荐了。不推荐不代表其它项目不够好,相信它们也都有各自的落地场景,只是笔者未曾花时间去研究过,也就不班门弄斧了。
这里简单介绍下部分大公司落地服务网格的一些思路。互联网大厂目前有两种思路,第一种,就是拿 Istio 进行魔改,并且基于 Istio 做一层产品化封装;第二种,自研,从更本身解决 Istio 的缺陷,并且从自身业务实际需求出发,完成架构设计和产品化。
首先,我们来看看第一种思路。某公司在技术选型的时候,最终还是选择了拥抱开源,把 Istio 拿过来测试用了用,发现了一些问题,就直接 fork 了一个分支到内部代码库进行改造、部署、上线。随着时间推移,发现内部 fork 分支与开源版本越走越远,想要 rebase 上游代码已经是不可能,拿着新版本重新去补充内部功能和需求,成本也是极大,最终与开源的 Istio 就成了两个项目。把 Istio 拿过来改造,主要也是为了解决上面提到的两个问题:
第二种思路,就是完全摒弃 Istio 的架构设计思路,从零出发,基于实际业务需求和大规模生产可用的角度出发,设计一套新的架构。为了解决配置按需加载同时又不增加系统的复杂性,可能完全摒弃 xDS 的配置推送协议,采用一套“全新”的协议,实现配置的多协议支持,支撑海量实例和海量治理配置场景下的服务发现和路由。
字节跳动就是采用了上述第二种思路。2018 年,字节跳动基础架构团队自研了一套新的服务网格架构。这套架构除了以线上业务实际需求为出发点,解决了流量劫持性能问题以及全量配置下发性能问题,更多是做了一些权衡与取舍。比如,字节跳动服务网格方案倾向于将一部分计算与复杂性由数据面上升至控制面,在控制面这样的中央节点完成复杂的流量治理逻辑计算,这样数据面拿到的就是相对比较精确的服务实例与配置数据,减少了分布式数据面不必要的 CPU 与 内存消耗,以及频繁大量计算带来的性能问题。另外,字节跳动服务网格方案并不追求完全无侵入的解决方案,在一定层面上,服务网格是与服务框架紧密结合的,在完成治理能力下层的同时,两个微服务中间件各司其职,共同完成实现了微服务系统的通信、治理、安全、可观测性、混沌工程等一系列能力。经过 3 年左右的研发,字节跳动服务网格在线服务数量达到了 3w+,在线实例数 300w+。
最近社区兴起了一种新的架构的探讨,这始于 gRPC 开始实现了 xDS 协议,并且 Istio 1.11 版本支持了将 gRPC 服务直接添加到 Istio 中,从而不需要再向 Pod 注入 Envoy 代理,这一架构被称为 Proxyless Service Mesh,或无 Sidecar 代理的服务网格,与之相对应的就是 Proxy Service Mesh (Istio + enovy 架构)。
作为两大知名开源项目,Istio 和 gRPC 这一举动也是震惊了各大吃瓜群众,起到了风向标的作用。有人问,这是又要回退到裸服务框架的时代了吗?Proxy Service Mesh 模式是要被舍弃了吗?
笔者认为,我们应当理性看待。从大环境来看,我们应当能够充分理解需求的多样性,并且可以包容这种多样性,但不代表某一种需求和实现的出现就一定是主流。gRPC 这种 Proxyless Service Mesh 模式,在一定程度上,确实解决了传统服务网格架构的缺陷、譬如不用再考虑进程外流量劫持了,支持在框架侧完成服务发现和路由。但是同样也具备传统微服务架构的缺点,包括耦合性问题、版本碎片问题、以及多语言一致性问题。
Proxyless Service Mesh 本质上解决了服务治理标准化问题,两种模式可以同时对接一个控制面、一套治理体系,对于部分业务在做云原生一体化转型、或者网关等场景下,还是非常有价值的。此外,如果内部语言统一,框架版本管理能力强,也是适应于这种架构的。但是,它终究还不是主流,不能解决微服务的共性问题,不符合微服务架构演进的趋势。
从 2016 年 William Morgon 给出服务网格的定义,到 2021 年底 Istio 发布到了 1.12 版本,服务网格发生了很多的变化。早期服务网格的定位共识是提供服务间通信的基础设施层,工作原理是实现原协议转发,原则上不改变协议内容。但随着 sidecar 模式的成熟与推广,服务网格的定位与工作原理也发生了一些变化,逐渐泛化到更多层面和领域。
2020 年初,Bilgin Ibryam (Author of Kubernetes Patterns | Product Manager at Red Hat)提出了微服务架构的一个新的设想:Multiple Runtime(多运行时),并总结了分布式应用存在的四大类需求:生命周期、网络、状态、绑定。很可能在将来,我们最终将使用多个运行时来实现分布式系统。多个运行时,不是对应有多个微服务,而是对应每个微服务都将由多个运行时组成,最有可能是两个运行时:自定义业务逻辑运行时和分布式原语运行时。
服务网格的本质是服务间通讯的抽象层,多运行时的本质是应用需要的各种分布式能力和原语,包括但不限于服务间通讯。从这个角度上说,多运行时 覆盖的范围是服务网格的超集:毕竟服务网格只覆盖到应用的部分需求(即服务间通讯),还有更多的分布式能力和原语有待覆盖。
有观点称:随着云原生的推进,分布式能力(以传统中间件为典型代表)下沉是大势所趋,Mesh 化的范围必然会继续扩大,也就离多运行时机甲的形态越来越近了。
Sidecar 模式除了可以应用到 Service Mesh 上面,还可以推广到其他中间件领域,如消息 Mesh,数据库 Mesh 等在内的多种 Mesh 形态,有文章表明,蚂蚁集团在 DB Mesh 和 消息 Mesh 这两种 Mesh 形态做了尝试和落地。
回过头来,我们可以发现,服务网格的出现源于技术社区希望用它解决多语言、运维、迭代等问题,那么这套服务网格技术是否可以应用到更多场景呢?毫无疑问,所有的中间件 sidecar 都属于这个领域,DB、消息、API Gateway、风控组件、登录组件等。
既然服务网格可以把负责流量转发的 proxy sidecar 分发到线上任意一个容器,并完成安全的热升级,那么同样的方法也可以被用于中间件的 sidecar。对业务侧的影响也是类似,需要应对性能、可观测性、稳定性等问题。
字节跳动基于上述需求,将 sidecar 治理问题与运维问题打造成一套标准技术方案,并已经在 API Gateway、登录组件、风控组件等旁路 sidecar 领域大规模落地,后续相关标准技术方案成熟后也会分享给大家。
即将步入 2022 年,服务网格大势所趋,Proxy Service Mesh 仍旧是主流,社区生态逐步完善,但是也存在更多 Istio 的竞争者出现。相比于 PaaS 底层能力,微服务领域是一个面向用户、与业务联系最近的一套架构,场景复杂,需求多变,因此很难出现所谓的“事实标准”。我们期待服务网格继续呈现百花齐放、多家争鸣的状态,持续给用户带来更大的价值,解放生产力,为全行业实现全面云原生化做出贡献。
作者介绍:
罗广明 字节跳动基础架构服务框架团队架构师
毕业于比利时 KU Leuven 大学,先后在爱立信、百度从事微服务领域工作,后加入字节跳动,负责微服务流量治理体系的能力建设与 CloudWeGo 项目的开源治理工作。长期关注云原生 & 微服务领域前沿技术、架构演进以及标准化工作,也是早期的服务网格社区布道者,是国内多个云原生领域开发者社区的管理委员会成员。
参考链接:
https://www.servicemesher.com/istio-handbook/concepts/basic.html
https://www.servicemesher.com/istio-handbook/concepts/istio.html
https://mosn.io/docs/concept/traffic-hijack/#%E9%80%8F%E6%98%8E%E5%8A%AB%E6%8C%81
https://mp.weixin.qq.com/s/LbeQAeADllUbrxaeTTbvyg
https://cloudnative.to/blog/service-mesh-comparison-istio-vs-linkerd/
https://cloudnative.to/blog/grpc-proxyless-service-mesh/
https://skyao.io/talk/202103-dapr-from-servicemesh-to-cloudnative/
今日好文推荐
解读编程语言的2021:Go与Rust走向「成熟」,Kotlin、wasm、Julia「无限生长」
解读数据库的2021:资本进来添了一把火,开源已占据半壁江山
下载量和Vue一样大的开源软件被作者恶意破坏,数千款应用受到牵连