云原生架构演进之服务网格实践

128 阅读12分钟

演进背景

随着技术的发展以及行业竞争的加剧,我们的业务规模和复杂性的也随之增加,我们对于现有服务的管理越发困难。集中体现在以下几个方面:

  • 业务侵入性强,治理能力需要与业务代码同步维护
  • 微服务框架不统一,以Spring-Cloud和Dubbo为典型代表,通信协议不一致
  • 多语言,虽然以Java为主,但是使用C++、Go服务也不占少数
  • 治理碎片化严重,无法统一管理治理策略,依赖各种SDK,诸如Sentinel、Resilemce4J等

这些问题不仅维护成本高,而且服务治理能力不统一且相对单一,对于我们构建高可用、高性能、高并发的分布式系统已经成为了一种制约。因此,我们迫切的需要一种平台化的、无侵入的、协议无关的服务治理方案 - 服务网格。 初次接触ServiceMesh是在一场技术交流会上,那时还是在2019年。虽然时间过去了很久,但是对其透明性、一致性的能力印象非常深刻,这也为后续的技术演进埋下了伏笔。

技术优势

我们选择服务网格作为下一代服务治理平台有如下几点考虑:

  • 简化服务通信:服务网格通过将通信逻辑和功能从应用程序代码中分离出来,集中管理和控制服务间的通信流量。这样可以简化开发者的工作,使其只需关注应用程序逻辑,而不需要处理底层的通信细节。

  • 实现弹性和容错:服务网格可以实现负载均衡、故障转移和容错策略,使得服务能够自动适应变化的负载和故障情况。通过在服务网格中配置这些策略,可以提高系统的弹性和可用性,减少因为单个服务故障而导致整个系统崩溃的风险。

  • 精细化的流量控制:服务网格可以对服务之间的流量进行细粒度的控制和管理,例如可以基于流量来源和目的地等条件进行路由和转发。这样可以实现灰度发布、A/B测试和Canary发布等高级部署策略,同时也可以提高系统的安全性,防止恶意流量的入侵。

  • 多语言和多框架支持:服务网格是独立于具体编程语言和框架的,支持多语言和多框架的应用程序开发和部署。这意味着可以使用不同的技术栈开发不同的微服务,使得团队可以按照自己的喜好和业务需求选择适合的工具和框架,而不需要全部统一。

网格产品

  • Istio istio.png

    • 介绍

      Istio是一个较早的服务网格实现,于2017年发布,由Google、IBM和Lyft等公司联合开源。Istio提供了一种面向微服务的网络层的解决方案,它通过在应用程序之间注入一组专用的网络代理(称为Sidecar),完成服务之间的通信和交互控制。Istio还提供了一套丰富的功能,如流量管理、故障恢复、访问控制、遥测和安全性等。

    • 优点

      • 功能强大:Istio提供了丰富的功能,包括流量管理、安全性、可观察性等,可以满足复杂的微服务架构需求。
      • 社区活跃:Istio拥有大规模的社区支持,可以获得快速的问题解决和新功能更新。
      • 广泛的支持:Istio可以与各种不同的云平台和容器编排系统集成,具有很高的灵活性和可扩展性
    • 缺点

      • 学习成本高:由于Istio具有复杂的功能和概念,学习和使用起来可能比较困难。
      • 配置复杂:Istio的配置比较复杂,需要对其各组件的配置和交互有一定的了解和经验。
  • Linkerd linkerd.jpg

    • 介绍

      Linkerd 是一个开源的服务网格(Service Mesh)工具,由 Buoyant 公司开发并于 2016 年首次发布,目前已经成为 CNCF(Cloud Native Computing Foundation)的孵化项目之一。用于解决在微服务架构下的服务通信、容错和性能问题。

    • 优点

      • 轻量级:Linkerd是一个轻量级的服务网格产品,对环境的依赖较少,适合部署和使用。
      • 易于使用:Linkerd提供了简单的命令行工具和直观的Web界面,使得使用和管理起来相对容易。
      • 低延迟:Linkerd在性能方面表现出色,可以提供低延迟的通信和高吞吐量。
    • 缺点

      • 功能相对简单:相对于Istio而言,Linkerd的功能相对较少,不适合复杂的微服务架构场景。
      • 社区规模相对较小:Linkerd的社区相对较小,可能会导致问题的解决和新功能的更新较慢。
  • Consul consul.png

    • 介绍

      Consul是一种用于构建基于微服务的服务网格的开源工具。它由HashiCorp开发并于2014年首次发布。Consul提供了服务发现、健康检查、负载均衡、键值存储等一系列功能,可以帮助开发者构建弹性和可靠的微服务架构。

    • 优点

      • 去中心化:Consul采用去中心化的服务发现机制,可以避免单点故障,提供更高的可靠性和可用性。
      • 可扩展性强:Consul具有很强的可扩展性,可以适应高并发和大规模的微服务架构需求。
      • 文件系统和键值存储:Consul还提供了文件系统和键值存储等功能,方便微服务之间的配置和共享数据。
    • 缺点

      • 功能相对有限:Consul相对于Istio和Linkerd而言,功能相对有限,特别是对于复杂的流量管理和安全性需求较低。
      • 配置复杂:Consul的配置较为复杂,需要对其各个组件和机制有较深的了解和理解。

技术选型

随着时间的推移,Istio逐渐成为服务网格的事实标准,并得到了广泛的应用和支持。它具有强大的功能、活跃的社区和丰富的生态系统。被许多公司和组织用于构建和管理他们的微服务架构。同时,基础平台部基于Istio自研了服务网格、微服务网关,可以提供标准的接入、运维、技术支持。在前期微服务网关的建设中,我们选择了基于Istio+Envoy的云原生微服务网关。综合考量,基于Istio技术底座的服务网格是我们的首选。

技术挑战

对于service mesh的印象,除了功能强大之外,还有复杂。这个复杂不仅仅是技术层面的复杂,还有使用、维护、排障等方面。我还记得初次给大家介绍service mesh时,很多同事的热情直接被浇灭,甚至是排斥。这也是为什么我们选择了基础平台部的产品。因此,大家在工程实践中,一定要认真对待下面几个问题:

  • 实施成本:实施和管理服务网格需要投入大量时间和精力。配置和部署服务网格所需的工作量会增加,因为需要管理更多的组件和配置。
  • 学习曲线:服务网格是一个相对较新的概念,团队需要花费时间来学习和理解服务网格的工作原理。
  • 性能影响:由于服务网格涉及到额外的网络层和数据传输,会对系统的性能产生一定的影响。尽管现代的服务网格技术在减少延迟和增加吞吐量方面取得了很大进步,但仍然对一些高性能应用程序产生影响。
  • 部署维护:服务网格需要在应用程序中集成额外的代理和控制平面,这增加了部署和维护的复杂性和成本。此外,如果没有适当的资源和专业知识,管理和监控服务网格会变得复杂。
  • 技术风险:由于服务网格是一项新技术,存在一些不成熟或不稳定的实现。这可能导致系统中出现故障或性能问题。

演进要点

协议拓展

Istio原生支持HTTP、gRPC协议,但是不支持Dubbo2协议(Envoy其实是支持Dubbo2协议的)。我们的系统中有许多的服务使用了Dubbo作为微服务框架,如何纳管Dubbo服务流量成为了我们需要面对的第一个问题。早期的Istio版本中实际上是有多注册中心适配能力的,比如Eureka、Consul。但是随着Istio的发展,这些模块已被移除。这不代表着Istio不支持第三方的注册中心的接入,相反,这意味着Istio朝着更加成熟的方向发展。Istio 1.9使用了mcp-over-xds协议,我们可以基于mcp-over-xds实现自己的MCP Server对接各种注册中心。同时,Dubbo也在迅速的发展,Dubbo3为了拥抱云原生,可以透明的接入Istio。至此,我们有了两个方案:

  • 自研MCP-Server

mesh-registry.drawio.png

  • Dubbo2升级Dubbo3

dubbo2-dubbo3.drawio.png

  • 方案对比
方案优点缺点
MCP Server1.业务无感知,无需变动;2.通用性强,依赖其他类型的注册中心也支持需要额外的开发与维护工作
Dubbo2升级升级Dubbo框架,无需适配注册中心需要业务改动,框架升级

结合Istio和Dubbo社区的发展,拥抱云原生已经成为了新的趋势,未来会有更多的注册中心支持mcp-over-xds协议,例如Nacos。因此,我们相信Dubbo未来会更加开放的支持Service Mesh,我们选择了Dubbo框架升级。

环境隔离

traffic-mark.drawio.png 我们日常开发、测试工作中,对于多环境(本地测试、集成测试、生产等环境)的依赖是非常强烈的。常规模式下创建多套环境的成本非常高,而且管理非常复杂。经常发生环境被误用、信息被篡改的问题。现在我们有了Service Mesh,依托其强大的路由能力,结合CI/CD平台,可以灵活的实现环境隔离,即流量标记。设计思路,CI/CD平台开放了服务部署时的label选择能力,用户可以选择可用的label标记当前服务。Istio 根据当前服务的label生成VS/DR。用户在请求时,只需要请求中携带特性的Header就可以实现路由到特定的服务。当然,该能力还需要入口流量标记与标记透传,即从Ingress Gateway设置好流量标识,Ingress Gateway到envoy都会透传该标识。

  • DestinationRule

    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: test-service
    spec:
      host: test-service
      subsets:
        - name: version-test
          labels:
            version: test
        - name: version-default
          labels:
            version: default
    
  • VirtualService

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: test-service
spec:
  hosts:
    - test-service
  http:
    - match:
        - headers:
            x-custom-version:
              exact: test
      route:
        - destination:
            host: test-service
            subset: version-test
    - route:
        - destination:
            host: test-service
            subset: version-default
性能影响

根据我们的压测数据,8C/16G的配置下,在50并发,2000QPS的情况下,与直连相比,使用了Envoy作为sidecar,延时增加了0.66ms左右,对于业务影响需要慎重考虑。尤其是在分布式系统中,服务链路过长的情况下,对于系统层面延时影响还是蛮大的。但是,业务与技术是“双向奔赴”的,一方面,我们需要对引入的代理,Envoy做性能优化,例如网络层面性能优化、路由层面性能优化。另一方面,业务层面的优化,比如服务链路的优化。

资源消耗

在降本增效的大环境下,每个业务Pod都需要多一个envoy代理的资源消耗,对于大规模的集群来说是一笔不小的开支。在我们实际的工程实践中,这是一个很大的挑战。应对策略除了上述的优化服务链路,还需要结合实际的业务场景,例如QPS/RT等指标做好envoy的资源规划。

质量保障

现在的服务治理能力都托管给了service mesh,对于QA来说也是一个不小的挑战。尤其是在进行单个服务的压测、治理能力测试时,暴露出来了envoy的一个路由配置层面的问题。为了减少性能损耗,我们只开启了出流量拦截,即A到B的请求,实际上是A的出口流量,B的入口流量,由A的sidecar负责流量策略。那么,网格中的单个服务的测试,比如A的测试谁来发起调用呢?我们实际的实践中,有两种方案:

  • 压测服务同样部署到测试环境中,开启sidecar注入,这样压测服务作为发起方调用任意的网格内的服务
  • 业务巡检服务作用到网格内的某个服务,通过Ingress Gateway访问,为各个服务配置流量策略

思考总结

由于云计算的兴起和微服务架构的普及,应用程序变得越来越复杂。传统的网络和中间件技术无法满足这种复杂性,并且在应用程序之间的通信、安全性、可观察性等方面存在一些共性问题。Service Mesh为我们提供了一种全新的解决思路去应对这些挑战。从实践的过程中,我们也遇到了一些“硬伤”,比如延时增加、资源成本问题。好在,istio还比较年轻,社区也在积极的应对这些问题,比如Ambient Mesh。相信未来是光明的。同时,技术始终都是围绕业务展开的,服务于业务,为业务创建价值,这是我们技术演进的目的。