前言

在传统的单体应用架构中,灰度发布相对简单。只需要在服务的网关侧流量入口处进行分流即可实现。

然而,微服务架构引入了新的复杂性,服务之间的依赖关系错综复杂。

有时候,某个功能的发布可能依赖于多个服务,要求灰度流量在整个调用链中准确路由到灰度版本的服务。

传统的单个服务流量入口设置分流的做法无法满足这一需求。

为了解决微服务架构下的灰度发布问题,全链路灰度发布引入了泳道(Lane)的概念。

泳道将灰度视角从单个服务扩展到整个请求的调用链上,确保流量能够精确地在一组指定规则的服务之间流动,就像在预先设置好的泳道中一样。全链路灰度发布方案专为微服务架构设计,旨在应对微服务架构下的灰度发布挑战。

一、常见部署策略

CD的最终目的是将CI产出的构建产物部署到生产环境,在CD部署时采用不同部署策略,可以发现新功能的价值收益,降低软件发布风险。

想要做微服务全链路的流量控制,需要先把微服务按照一定的部署策略,将微服务架构部署出来

1.蓝绿发布

蓝绿部署中,一共有2套完全独立、功能完善、且正在运行的系统:

  • 一套是正在提供服务系统(也就是上面说的旧版),标记为“绿色”;
  • 一套是准备发布的系统,标记为“蓝色”;

不同的是系统版本对外服务情况

  • 蓝:老系统标记为绿色,对外提供服务
  • 绿:新部署标记为蓝色,不对外提供服务

新部署的蓝色系统不对外提供服务,用来做什么?

用来做发布前测试,测试过程中发现任何问题,可以直接在蓝色系统上修改,不干扰用户正在使用的系统。

蓝色系统经过反复的测试、修改、验证,确定达到上线标准之后,直接将用户切换到蓝色系统, 切换后的一段时间内,依旧是蓝绿两套系统并存,但是用户访问的已经是蓝色系统。

这段时间内观察蓝色系统(新系统)工作状态,如果新部署的系统出现问题,直接一刀切换回绿色系统。

当确信对外提供服务的蓝色系统工作正常,不对外提供服务的绿色系统已经不再需要的时候,蓝色系统正式成为对外提供服务系统,成为新的绿色系统。

原先的绿色系统可以销毁,将资源释放出来,用于部署下一个蓝色系统。

2.A/B测试

A/B测试和蓝绿发布的区别之一是:A和B系统都对外提供服务,但是流量比例不一样;

  • 蓝绿发布、滚动发布和金丝雀是发布策略,目标是确保新上线的系统稳定,关注的是新系统的BUG、隐患
  • A/B测试关注的是不同版本的服务的实际效果,譬如说转化率、订单情况等。

A/B测试时,线上同时运行多个版本的服务,但对于用户侧来说这些服务通常存在一些体验上的差异;

譬如说页面样式、颜色、操作流程不同。相关人员通过分析各个版本服务的实际效果,选出效果最好的版本。

3.灰度/金丝雀发布

灰度发布, 也叫金丝雀发布,是指在同1个系统内部划分为黑与白2个版本进行平滑过渡的一种发布方式,相较于蓝绿部署和A/B测试更节省服务器成本;

逐步切换:灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度,而我们平常所说的金丝雀部署也就是灰度发布的一种方式。

3.1.Service+Devployment实现金丝雀部署

1个service+2个Deployment可以实现金丝雀部署

1个Service路由流量到以下2个Deployment

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer

稳定版本(假设为 v1)

# stable-deployment.yaml
apiVersion: v1
kind: Deployment
metadata:
  name: my-app-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
      version: v1
  template:
    metadata:
      labels:
        app: my-app
        version: v1
    spec:
      containers:
      - name: my-app-container
        image: my-app-image:v1
        ports:
          - containerPort: 80

另一个用于新版本(假设为 v2):

# canary-deployment.yaml
apiVersion: v1
kind: Deployment
metadata:
  name: my-app-v2
spec:
  replicas: 0 # 初始时没有副本
  selector:
    matchLabels:
      app: my-app
      version: v2
  template:
    metadata:
      labels:
        app: my-app
        version: v2
    spec:
      containers:
      - name: my-app-container
        image: my-app-image:v2
        ports:
          - containerPort: 80

不断地减少v1的副本数量,来增加v2的副本数量实现金丝雀发布;

二、微服务全链路流量控制

微服务架构确定之后,针对不同的微服务架构做全链路流量控制;

全链路灰度发布的核心在于流量泳道概念的实现,而泳道正如上文所说,是对满足指定规则的流量定下一个活动范围,它有以下两种实现思路:

1.微服务网关

在微服务网关侧:可以实现

  • 用户流量染色
  • 用户流量按百分比分

转发到后端微服务泳道;

流量染色

流量染色是指根据流量协议设置对应的流量染色规则,对指定的流量进行染色标记,并在整个调用链中携带该标记。

通过染色流量可以对特定的流量进行跟踪和路由,所以流量染色功能常被用于灰度发布的场景。

在MSE网关设置插件中心,开发钩子Golang插件,进行用户打标(流量染色);

在MSE网关鉴权中心,设置鉴权的URL路径,开发对应服务;

根据自身业务需求,基于用户的HTTP请求内容,例如URL、请求体、IP归属地(地域)等信息,在HTTP请求Header中设置参数或者Cookie。

2.微服务泳道

微服务后端划分不通泳道,用于接收和路由来自微服务网关的不通流量;

微服务泳道可以根据微服务本身进行划分,也可以进行逻辑划分;

2.1.不分叉型微服务泳道

泳道实现的主要难点在于,流量在服务间调用的过程中如何路由到正确的服务版本,但有一个简单的实现思路可以规避这个问题:复制一个包含所有微服务的完整环境,将需要灰度的服务替换为灰度版本。然后只需要在两个环境的流量入口处通过网关对流量进行规则分流,由于两套环境间存在网络隔离,灰度环境天然成为了一个灰度流量泳道。

完全隔离的微服务泳道缺点

然而,对于服务数量较多的微服务项目来说,这种方法会浪费资源,因为在灰度环境中创建非灰度服务会消耗额外的资源。如果要同时灰度多个版本,就需要创建多套完整环境,进一步增加了资源的浪费。

2.2.分叉型微服务泳道

逻辑上隔离的微服务泳道,需要每个微服务节点,具备流量路由的功能;

想要每个微服务节点,具备流量路由功能,在不修改应用代码的前提下,可以借助服务网格技术实现,例如Istio和Envo

若能赋予每个服务路由流量的能力,泳道的设置就可以共用正常服务从而充分利用资源,多版本的全链路灰度发布也可以同时在同1个环境中进行。

3.微服务泳道功能

无论是分叉型微服务泳道还是不分叉型微服务泳道,都需要具备以下能力;

  • 微服务环境隔离
  • 全链路流量路由
  • 全链路数据透传

全链路流量路由

流量路由指的是服务本身发送流量时,可以根据指定规则将其路由到正确的目的地,例如带有灰度标的流量应该优先发往灰度版本的服务,全链路流量路由则要求每个服务都具备这种能力。

全链路流量路由目前有两种主流实现:

  1. 基于 Istio:采用 Istio 这个开源 Service Mesh 组件,通过在每个服务的容器中部署 Envoy 透明代理,拦截服务之间的网络通信并按指定规则转发,从而实现了全链路流量路由,无需对现有代码进行修改。
  2. 基于服务发现组件:通过支持为服务设置元数据的服务注册中心,如 Nacos,可以标记服务实例的特征,例如灰度版本。每个服务可以通过注册中心获取其他服务实例的版本信息,并通过修改代码逻辑或 Java Agent 实现流量路由。

全链路数据透传

为了实现全链路灰度发布,流量路由规则基于流量染色标记,因此需要将染色标记传递到整个请求链路中,即实现全链路数据透传能力。简单的数据透传可以基于原生的 HTTP Header、Query Parameters 等资源来实现,但在复杂的微服务场景下,应该使用 Tracing Baggage 机制。Tracing Baggage 是分布式链路跟踪工具提供的一种能力,可以携带用户自定义的键值对,主流的跟踪工具如 Skywalking 和 OpenTelemetry 都支持该功能。使用分布式链路追踪框架可以方便地进行日志记录和问题排查,特别适用于灰度发布场景下的需求。

三、微服务全链路流量控制实现方案

主要有 Istio、JavaAgent 等主流方案,基于流量路由的能力,ZadigX 提供了两套通用方案:

1.阿里云 MSE + ZadigX

阿里云 MSE 为 Java 应用提供了便捷实现全链路灰度的能力。MSE 微服务引擎是基于 Java Agent 实现的无侵入式企业生产级服务治理产品,不需要修改任何一行业务代码,即可拥有不限于全链路灰度的治理能力,并且支持近 5 年内所有的 Spring Boot、Spring Cloud 和 Dubbo。

使用 MSE 进行灰度发布的过程中,ZadigX 可以便捷得创建灰度环境和灰度 K8S 资源、结合发布工作流编排能力,自动为 K8S 资源设置 MSE 所需的资源标记,集成了 MSE API 降低重复工作量。

2.Istio+Distributed Tracing+ZadigX

Istio 可以无侵入得实现全链路流量路由能力,同时还可以设置基于比例、权重、HTTP Header 等条件的流量路由,但全链路数据透传需要服务本身实现,为此需要服务接入支持 Baggage 的分布式链路追踪框架,若还没接入则会涉及到一定的改造成本。

ZadigX 可以根据指定的灰度任务与灰度标记规则,结合发布工作流编排能力与环境的监测管理能力,自动创建 Istio VirtualService 与 DistinationRule 资源以实现相应的泳道,达到了让开发者轻松进行全链路灰度发布的效果。

 

MSE

浅析微服务全链路灰度解决方案

posted on 2024-03-22 13:24  Martin8866  阅读(101)  评论(0编辑  收藏  举报