服务网格在好未来学而思网校的实践和思考

386 阅读16分钟

服务网格方案介绍

服务架构从单体发展到微服务,在云原生时代,微服务发展成服务网格。依托容器等技术,服务治理功能独立成基础设施层,与被治理的服务相互分离。

服务治理介绍

软件领域一直追求高可用、高性能、易扩展。在软件变得复杂之后,需要多人进行协作开发,服务的可用性、高性能和可扩展性受到越来越多的挑战。在一个庞大、复杂的单体服务下进行产品迭代,牵一发而动全身的窘境,简直是开发者的噩梦。为改变这种状况,很自然地会将单一庞大而复杂的服务做拆分,即进行服务化拆分。一个服务由多个微服务组成,微服务通过接口相互调用来提供完整的服务。软件架构大师马丁·福勒在2014年给出了微服务软件架构的综述性论文,译文见参考1。在微服务架构下,软件被拆分成有边界的、能独立开发和部署的、能相互通信的微服务。

服务拆分成微服务后,服务的边界明确了,功能和逻辑也清晰了,维护起来也更容易了。随着spring cloud全家桶的流行,微服务几乎成为软件开发的必选项。各种其他语言(golang,php等)也模仿了spring cloud提供了微服务框架。服务拆分成微服务后,带来显而易见的好处有以下部分。

  • 服务之间边界清晰
  • 每个服务更容易维护
  • 服务独立部署
  • 服务独立扩展
  • 更好的隔离
  • 多种技术栈容易共存

然而,软件领域经常提到“没有银弹”,微服务也不是银弹。细小的服务变多,会带来新的问题,诸如:

  • 分布式架构让设计变得复杂
  • 系统拆分成多个服务部署流程复杂
  • 系统吞吐量变大但响应时间变长
  • 排查问题复杂,涉及到多个不同服务
  • 技术多元化、整体维护复杂度增加

针对这些问题,出现服务治理的概念。服务治理旨在提供对应的基础设施或机制,来解决众多微服务面临的一系列管理问题。微服务治理的框架或者套件一般提供以下的能力。

  • 服务注册发现
  • 服务链路追踪
  • 服务弹性容错
  • API网关

同样,服务拆分成更多的微服务之后,也需要一些自动化工具来提供研发效率,通常包括自动化测试和自动化部署。完全定制实现一套支持微服务的基础设施挑战比较大,尤其是需要支持多种开发语言时。在spring cloud及其模范者定义了微服务基础规范后,在云计算时代,伴随着容器技术的普及,云原生技术栈带了新的微服务治理方式。

服务网格介绍

提到服务网格,不得不提linkerd。目前流行的服务网格技术也是由linkerd提出的。在服务网格下,服务治理能力不是SDK形式提供给应用,而是单独提供一层基础服务设施层,为服务提供服务治理能力。参考2详细描述了微服务到服务网格的演变过程,如果对这个过程感兴趣,非常推荐阅读原文,本文直接简要描述这种模式下服务治理如何实现。

image.png

引用参考2中的示意图,如上图所示,服务网格提供一个sidecar(边车),该边车提供了服务发现、熔断、限流、负载均衡、超时重试、trace采集等等服务治理的能力。多个代理连接成一个网状结构,如下图所示。通过一个集中式的控制面板来控制各个代理边车的行为,从而实现各个被代理服务的精确的行为控制。在服务网格模式下,被代理的服务和代理服务通过进程间通讯,被代理的服务获得服务治理的能力,它本身是不需要关心服务治理的,与提供服务治理基础设施彻底解藕。

image.png

网校服务治理现状

在网校,大部分服务还是依赖API网关实现服务治理,API网关提供了非常丰富的功能:服务发现、负载均衡、限流、鉴权等等。API网关在openresty开发而成,使用nginx的路由机制,来实现服务发现,并提供丰富的插件,来完成其他服务治理。使用HTTP协议相互访问的服务,API网关支持的非常好,并且在多次重大活动中提供稳定、可靠的服务,是非常成熟的方案。除API网关之外,还有部分服务采用rpcx实现服务治理,使用zookeeper提供服务注册中心,并利用rpcx提供的服务治理能力,实现其他诸如超时重试等需求。这部分服务治理工作也运行的非常好。除此之外,随着容器化在网校逐渐的落地,部分服务直接使用了k8s提供的基于coredns用于服务发现,并采用k8s的服务虚IP地址到pod地址的映射实现负载均衡。这一类服务利用k8s的基本能力,实现了基础的服务注册发现和负载均衡。而另外一些服务治理能力,例如trace采集、服务弹性容错等需要自行实现。

这里仅列举了几种使用较多的服务治理方案,在不同技术栈下,有不同的服务治理方式可供选择,这些方式在各自预期的目标下工作良好,但各个服务治理体系互不兼容,不能很好的复用已有的基础能力。服务网格为解决此类问题,它为不同场景提供通用的服务治理能力。

选择的方案

服务网格方案,目前最活跃的开源项目就是istio。尽管宣称支持vm等形式的部署,但istio依然是针对k8s深度定制的服务网格开源方案。如下图所示,依托envoy智能代理,istio服务网格方案分为数据面和控制面。其中控制面istiod由三部分组成,包括服务发现pilot,安全和证书相关的citadel,以及配置管理相关的galley。而数据面采用lyft开源的envoy proxy,实现服务的4/7层代理,并提供诸如服务发现、负载均衡、流量管理、弹性容错等等能力。

image.png

在平台研发部的项目落地实践

开源的istio方案,并不是一个开箱即用的方案,很多地方需要根据业务当前现状做扩展,从目前各大厂公开的技术文章来看,都针对istio方案进行深度定制,以满足业务需求。典型的有优化服务网格代理性能、优化支撑的服务规模、优化流量劫持方式、优化插件扩展方式移植openresty等等。各个公司根据自己的业务形态和诉求,对istio这套方案进行不同程度的定制化开发。我们根据当前网校的业务特点,总结出网校业务对服务网格的诉求包括以下几点。

  • 统一服务治理基础能力
  • 支持多种语言和场景
  • 兼容API网关,需求极高稳定性,支持平滑迁移或平滑降级
  • 不必追求极致的性能
  • 易用性是关键目标之一,尤其是很多业务线刚接触容器,产品需要容易上手
  • 与日志、监控等基础设施打通,而不是重新打造新的基础设施
  • 在开源方案上进行扩展,不对开源方案进行不兼容的定制

在确定上述目标后,我们在开源istio上开发了一些插件,并与日志等基础服务打通,整个产品架构如下图所示。整个服务网格目前基于k8s和容器,兼容未来云的日志基础服务和网校trace标准。通过扩展EnvoyFilter实现诸如限流、重试、鉴权等功能。考虑到istio社区非常活跃且版本迭代比较快(每个季度一个较大版本发布),我们避免修改istio或者envoy的代码,需要的特殊功能通过lua或者wasm插件形式进行扩展。当然,就目前来看,这两种扩展方式还存在较大的限制。对于HTTP协议,基本上能完整支持HTTP处理流程,扩展也较方便。对于非HTTP协议,例如rpcx协议,目前通过wasm实现了对rpcx协议的解析。尽管wasm扩展方式是istio社区极力推广的,也被认定为是envoy未来扩展的标准形式,但目前看限制还较多,例如修改一个请求的处理流程还不支持。大部分业务目前采用HTTP进行通信,使用常规的扩展也能满足多数需求。

image.png

服务流量接入

流量接入包括两部分,一部分是如何兼容API网关实现流量进入服务网格,一部分是流量在被代理的服务和sidecar之间如何接入。在外部流量接入时,我们考虑了几种方案,最终选择的方案如下图所示。流量进入k8s集群后,需要经过istio ingress gateway进入服务网格网络,当然在服务网格内部的网关istio ingress gateway是可选择的,用于支持服务网格边缘流量的处理。这里我们考虑过另外一种方案,就是直接将k8s ingress注入sidecar,以此实现k8s ingress直接将流量转发到pod上,但目前采用了iptables的流量劫持方式,且k8s ingress为规避NAT问题使用了host network方式部署,无法通过iptables劫持流量。在服务网格上我们添加了istio推荐的gateway来处理入口的边缘流量。

在pod内部流量劫持,不同需求有不同方式。美团octo方案采用提供常用开发语言的sdk,app通过uds方式与proxy进行通信。使用sdk方式也比较普遍,很多大厂采用这种方式。采用sdk方式,主要考虑的是iptables难以管理和性能瓶颈。考虑到sdk对业务有轻微的侵入性,并且我们对极致性能要求不是那么迫切,快速使用服务网格且对业务透明利于这项技术的推广,我们采用了iptables形式进行流量劫持。从目前测试数据来看,单个pod性能如果在2000 qps,使用iptables进行流量劫持到envoy代理,进过优化后,性能损失并没有想象中的那么大。优化后测试表明整体的性能损失小于2%,而单个pod 2k qps代表了大多数的应用,采用iptables进行流量劫持,不会是整体性能的瓶颈。

image.png

项目平滑迁移

对于一项新技术,如果使用成本巨大,无疑会阻碍新技术的推广,在这里我们设计了兼容API网关的平滑迁移方案。下图给出了几条典型的访问路径。app1和app2部分流量在服务网格上,app3全部流量在k8s上。无论是服务网格上的应用还是k8s上的应用,访问app3,依然通过旧的api网关方式进行访问。项目不需要进行任何修改,就可以接入服务网格。app2在k8s上的流量访问app1时,通过API网关进行分流,可以根据需要将部分流量转发到服务网格上。而服务网格上的app2在访问app1时,envoy接收到劫持的流量后,会对目标进行rewrite,流量直接转发到服务网格上的app1,不再经过API网关。为实现平滑降级,紧急情况下可回滚可降级,服务网格集群和目前线上k8s集群独立。这样用户在迁移/试用服务网格也比较容易,几乎不需要做任何改造,仅仅在容器平台上将该应用同步到服务网格集群,相应的webhook会自动注入sidecar,进而能够使用服务网格。

image.png

快速平滑降级

从上一节可以看到,服务网格流量劫持采用webhook进行sidecar的注入。在sidecar注入后,会有init-container进行iptables规则的注入,注入的iptables规则透明地劫持访问应用的流量。在接入线上流量时,要求能进行服务平滑降级,即服务网格代理出现故障时,能平滑地从服务网格中卸载。使用sdk转发流量到代理通常会检测代理的健康状况,一旦代理出现异常,sdk会直接将流量转发给目标服务而不经过代理,从而实现流量平滑降级。我们采用iptables进行流量劫持,在应用需要退出服务网格时,只需要将iptables的流量劫持规则去掉,就实现了服务平滑降级。我们开发了webhook,在注入sidecar时,会注入我们开发的iptables工具,该容器负责平滑的清理/添加iptables流量劫持规则。配合服务网格控制台和网关,我们能方便的管理单个应用、某个命令空间、整个集群的流量,从而实现平滑降级。

image.png

未来的展望

目前服务网格所支持的功能大部分工作是在几个月前开发的,目前容器团队联合网校平台研发部共创,使用这些已经具备的功能接入服务网格的项目,并根据业务需求再做改造和开发。目前已与日志/trace等基础设施打通,并提供统一的服务治理能力。截止目前,在平台研发部老师的全力支持下,整个服务网格有10个项目在承接线上流量,另外有6个项目具备线上切流条件。我们在开源istio方案上进行了扩展开发,但整个服务网格仍然有很多工作需要完善。

服务配置懒加载

服务网格sidecar实现了服务发现和负载均衡,服务的信息存储在sidecar中,对于大规模的集群或多集群来说,服务信息会非常多,每个sidecar存储全量的信息非常冗余。istio社区也意识到这个问题,并推出限制sidecar接收服务信息的范围。一个服务会依赖哪些服务,该服务的代理就存储这些服务的信息。梳理服务的依赖关系非常枯燥且容易出错,如何实现服务配置的懒加载,目前社区已经有相应的开源项目,即网易开源的Slime。Slime原理比较简单,服务A访问服务B时,默认服务A的sidecar没有服务B的信息,服务A代理会将请求服务B的流量发送至包含全量服务信息的服务C,服务C在处理完来自A的访问B的请求后,将服务B的信息下发至服务A,从而实现服务A依赖服务B懒加载操作。服务网格支持懒加载,能大大减少了sidecar代理内存的使用,避免繁琐的依赖梳理工作。

envoy灰度发布

服务网格使用envoy作为代理,目前整个mesh集群都采用一个版本的envoy,对于envoy新版本的升级也是统一进行。统一变更风险较大,社区也有方案探索envoy灰度发布机制。关于envoy代理在mesh上灰度,也是需要解决的问题。解决的思路也很多,例如在注入sidecar的webhook中加入某些项目名单,此名单中使用新版envoy实现灰度更新。同样,被代理的服务,不期望因为envoy的更新而重建pod,pod原地升级也是需要解决的问题,目前社区也有相应的方案。

监控打通

服务网格重要的价值之一就是完善的可观测性,不管是代理4层服务还是7层服务,丰富的监控指标能帮助我们快速预警和定位处理各种故障。但envoy目前指标太多,以至于开启指标采集给单机prometheus带来较大的压力,如何有效的采集服务网格的监控指标,并与报警等系统打通,也需要逐渐完善。

支持更多的自定义插件

目前服务网格的各种插件,并没有很好的管理方式。众多插件都是以crd的形式存在于k8s中。合理的管理这些插件,并开放插件能力给更多的开发者,也是mesh平台需要考虑的问题。

服务网格采用新的方式来实现统一的服务治理能力,在各个大厂都有不同程度的落地,需求不同,采用的落地方式也不同,但基本上都是参考istio或者改造istio方案。服务网格带来的透明且统一的服务治理能力,以更优雅的形态促进业务和基础设施分离,让业务和基础可以相互不影响而独自发展。但新技术并不是一蹴而就的和开箱即用的,我们仍然需要结合面临的实际需求,进行开发适配和扩展工作。服务网格作为云原生技术栈的核心之一,已经在各个大厂逐渐落地。随着越来越多的技术力量加入云原生浪潮,当前服务网格面临的不足一定会迅速弥补,也会逐渐在各行业被广泛地采纳和接受。

参考

  1. 马丁·福勒 《微服务》中文译文 developer.aliyun.com/article/385…
  2. 服务网格模式 philcalcado.com/2017/08/03/…
  3. 美团OCTO2.0 服务网格介绍 tech.meituan.com/2021/03/08/…
  4. istio官方手册 istio.io/latest/docs…
  5. 网易服务网格配置管理项目 github.com/Slime-io/Sl…

作者:好未来高军

想要了解更多关于教育技术干货可扫码下方二维码加入好未来官方交流群