通过 OpenKruise 实现基于 Higress 的全链路灰度

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: OpenKruise 是一个基于 Kubernetes 的扩展套件,主要聚焦于云原生应用的自动化,比如部署、发布、运维以及可用性防护。本文介绍通过 OpenKruise 构建自动化运维的方式实现全链路灰度功能。

作者:十眠、立衡

OpenKruise 是一个基于 Kubernetes 的扩展套件,主要聚焦于云原生应用的自动化,比如部署、发布、运维以及可用性防护。本文介绍通过 OpenKruise 构建自动化运维的方式实现全链路灰度功能。


灰度发布提高应用交付的稳定性和效率


在发布应用的过程中,我们通常希望用少量特定流量来验证新版本的发布是否正常,以保障整体稳定性。这个过程被称为灰度发布。关于灰度发布,我们通过逐步增加发布的范围,来验证新版本的稳定性。如果新版本出现问题,我们也能及时发现,控制影响范围,保障整体的稳定性。

渐进式发布一般具有以下特点:

  • 逐步增加发布的影响范围,拒绝一次性全部发布;
  • 阶段性的发布过程,可以通过金丝雀发布方式小心验证,以验证新版本的稳定性;
  • 可暂停、可回滚、可继续、可自动化状态流转,以便灵活地控制发布过程并确保稳定性。

据调研数据 70% 的线上问题都是由于变更导致,我们常说安全生产三板斧,可灰度、可观测、可回滚,也是为了控制变更带来的风险与影响面。通过采用灰度发布的方式,我们能够更加稳健地发布新版本,避免因发布过程中出现的问题而带来的损失。


微服务架构对灰度发布提出了更高的要求



在微服务架构的场景下,传统的灰度发布模式往往不能满足微服务交付的复杂、多样化的需求。这是因为:

  • 微服务调用链路比较长,比较复杂。在微服务架构中,服务之间的调用链路比较复杂,一个服务的改动可能会影响到整个调用链路,从而影响整个应用的稳定性。
  • 一次灰度可能涉及多个模块,整个链路都要调用新版本。由于微服务架构中服务之间相互依赖,一个服务的修改可能需要其他服务的相应调整。这就导致了在进行灰度发布时,需要同时调用多个服务的新版本,增加了发布的复杂度和不确定性。
  • 多个项目并行,需要部署多套环境,环境构建不灵活、成本高。在微服务架构中,往往会有多个项目并行开发,需要部署多套环境来支持不同的项目。这就增加了环境构建的难度和成本,从而导致发布效率低下。

为了解决这些问题,我们需要采用更加灵活、可控并且适用于微服务场景的发布方式,全链路灰度发布的场景也就应运而生。通常每个微服务都会有灰度环境或分组来接受灰度流量。我们希望进入上游灰度环境的流量也能进入下游灰度的环境中,确保1个请求始终在灰度环境中传递,从而形成流量“泳道”。在“泳道”内的流量链路中,即使这个调用链路上有一些微服务应用不存在灰度环境,那么这些微服务应用在请求下游应用的时候依然能够回到下游应用的灰度环境中。

全链路灰度为微服务发布保驾护航


这种方式可以根据服务的实际情况,可以对单个服务可以进行独立的发布和流量控制,也可以控制多个服务同时进行发布变更,从而保证整个系统的稳定性。同时,还可以采用自动化的部署方式,实现快速、可靠的发布过程,提高发布效率和稳定性。


实践全链路灰度的挑战


在 K8s 中实现微服务全链路灰度发布是一个非常复杂的过程,需要涉及多个组件和配置的修改与协调。以下是具体的一些步骤和问题:

  • 在微服务架构中,网关是服务的入口,需要根据灰度发布的要求,调整网关配置,实现路由匹配和流量特征(比如 Header 修改)。
  • 为了实现全链路灰度发布,需要新部署一套灰度应用环境,并为其打上灰度标记(新部署一套 Gray 应用以及 Gray 灰度标)。这样可以将流量流向灰度环境,从而实现灰度发布。
  • 验证流量正常,将基线环境升级,销毁灰度环境,恢复网关配置。在灰度发布过程中,需要对流量进行验证,确保流量的正常流向和服务的正常运行。如果验证通过,可以将基线环境升级到灰度版本,并销毁灰度环境。最后,需要恢复网关的配置,以确保流量正常流向。
  • 如果发生异常,需要快速回滚。由于微服务架构复杂,可能会出现各种异常情况,比如服务崩溃、流量异常等。在这种情况下,需要快速回滚,以避免产生更大的损失。因此,需要预先设计好回滚方案,并在发生异常时快速执行回滚操作。

另外一方面,生产的流量是端到端的,那么意味着我们需要控制流量在前端、网关、后端各个微服务等组件中闭环。不仅仅是 RPC/Http 的流量,对于异步调用比如 MQ 流量我们也需要符合全链路“泳道”调用的规则,这整个过程中涉及到的流量控制的复杂度也是非常高的。

为了简化微服务全链路灰度发布的过程,可以使用一些自动化工具和产品,如 MSE、Kruise Rollout 等。这些工具和产品可以帮助我们更加便捷地实现微服务全链路灰度发布,并提高发布的效率和稳定性。


Kruise Rollout+MSE 端到端的全链路灰度发布实践


为什么要 Kruise Rollout?
Kruise Rollout[1]是 OpenKruise 社区开源提出的一个渐进式交付框架。其设计理念是提供一组能够将流量发布与实例灰度相结合,支持金丝雀、蓝绿、A/B Testing 等多样化发布形式,以及支持基于 Prometheus Metrics 等自定义 Metrics 实现发布过程自动化,无感对接、易扩展的旁路式标准 Kubernetes 发布组件。主要特性如下:

  • 非侵入性:不对用户的应用交付配置做任何的侵入,使用旁路的方式来扩展渐进式交付的能力,并且能够做到即插即用的效果。
  • 可扩展性:充分考虑了对多种类似的工作负载的支持(Deployment、StatefulSet、CloneSet 以及自定义 CRD 工作负载);在流量调度方面,通过 lua 脚本的方案能够支持 Nginx、Alb、Mse、Gateway API 等多种流量调度方案。

       


Kruise Rollout 本身就支持各种灰度发布的能力(金丝雀、A/B Testing、蓝绿发布),深入了解后发现它的发布模型非常契合 MSE 全链路灰度,因此与 Kruise Rollout 结合后可以非常方便的让用户实现 MSE 全链路灰度发布能力。


MSE 全链路灰度发布的最佳实践


01. 部署应用 & 配置全链路灰度发布 CRD

我们可以参考 MSE 云原生网关全链路灰度[2]文档部署 Demo 应用。

➜  ~ kubectl get deployments         
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
demo-mysql       1/1     1            1           30h
nacos-server     1/1     1            1           46h
spring-cloud-a   2/2     2            2           30h
spring-cloud-b   2/2     2            2           30h
spring-cloud-c   2/2     2            2           30h

部署完应用之后,我们首先要区分线上流量和灰度流量。

我们通过创建 Rollout CRD 来定义全链路灰度发布的流程。1. 将整个链路涉及到的应用创建 Rollout 配置

# a rollout configuration
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-a
spec:
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: spring-cloud-a
  ...
# b rollout configuration
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-b
  annotations:
    rollouts.kruise.io/dependency: rollout-a
spec:
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: spring-cloud-b
  ...
# c rollout configuration
---
apiVersion: rollouts.kruise.io/v1alpha1
kind: Rollout
metadata:
  name: rollout-c
  annotations:
    rollouts.kruise.io/dependency: rollout-a
spec:
  objectRef:
    workloadRef:
      apiVersion: apps/v1
      kind: Deployment
      name: spring-cloud-c
  ...

2. 然后为了表明线上流量与灰度流量的特征,即在入口服务上配置灰度流量规则

canary:
  steps:
    - matches:
        - headers:
            - type: Exact
              name: x-user-id
              value: '100'
      requestHeaderModifier:
        set:
          - name: x-mse-tag
            value: gray
  trafficRoutings:
    - service: spring-cloud-a
      ingress:
        name: spring-cloud-a
        classType: mse

3. 针对灰度发布中的应用,Kruise 会自动给他标识 gray 版本

# only support for canary deployment type
patchCanaryMetadata:
  labels:
    alicloud.service.tag: gray

安装完成 Rollout CRD 后,我们可以查看一下:

➜  ~ kubectl get Rollout             
NAME        STATUS    CANARY_STEP   CANARY_STATE   MESSAGE                            AGE
rollout-a   Healthy   1             Completed      workload deployment is completed   4s
rollout-b   Healthy   1             Completed      workload deployment is completed   4s
rollout-c   Healthy   1             Completed      workload deployment is completed   4s

到目前为止我们定义了这样一组全链路灰度发布的规则,发布链路涉及 MSE 云原生网关、A、B、C 应用,其中 x-user-id=100 的流量为灰度流量。

接下来,我们快速进行一次灰度发布与验证吧。

02. 灰度发布&验证流量

1. 本次发布涉及到应用 A、C 的改动,因此我们直接编辑应用 A、C 的 Deployment yaml,进行变更操作

# a application
---        
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-a
spec:
  ...
  template:
    ...
    spec:
        # 修改 mse-1.0.0 -> mse-2.0.0,触发应用A发布,以及MSE全链路灰度
        image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-a:mse-2.0.0
# c application
---        
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-c
spec:
  ...
  template:
    ...
    spec:
        # 修改 mse-1.0.0 -> mse-2.0.0,触发应用A发布,以及MSE全链路灰度
        image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-c:mse-2.0.0

2. 变更完成之后,我们查看我们当前应用的形态

➜  ~ kubectl get deployments
NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
demo-mysql             1/1     1            1           30h
nacos-server           1/1     1            1           46h
spring-cloud-a         2/2     0            2           30h
spring-cloud-a-84gcd   1/1     1            1           86s
spring-cloud-b         2/2     2            2           30h
spring-cloud-c         2/2     0            2           30h
spring-cloud-c-qzh9p   1/1     1            1           113s

我们发现,Kruise Rollout 并没有直接修改我们原先的 deployment,而是先给我们创建了两个灰度应用 spring-cloud-a-84gcd、spring-cloud-c-qzh9p。


3. 等应用启动就绪我们分别来验证线上正常流量以及灰度流量
a. 访问网关,如果不符合灰度规则,走基线环境:

➜  ~ curl -H "Host: example.com" http://39.98.205.236/a
A[192.168.42.115][config=base] -> B[192.168.42.118] -> C[192.168.42.101]% 

b. 如何符合灰度规则,走灰度环境:

➜  ~ curl -H "Host: example.com" http://39.98.205.236/a -H "x-user-id: 100"
Agray[192.168.42.119][config=base] -> B[192.168.42.118] -> Cgray[192.168.42.116]% 

4. 如果碰到预期外的行为,我们如何进行快速回滚?我们尝试回滚一下 C 应用,只需将 C 应用的 Deployment 改回原先配置即可。

# c application
---        
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-c
spec:
  ...
  template:
    ...
    spec:
        # 修改 mse-2.0.0 -> mse-1.0.0,回滚c应用
        image: registry.cn-hangzhou.aliyuncs.com/mse-demo-hz/spring-cloud-c:mse-2.0.0

修改完成后,我们发现 C 应用的灰度 Deployment 已经没了。

➜  ~ kubectl get deployments
NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
demo-mysql             1/1     1            1           30h
nacos-server           1/1     1            1           46h
spring-cloud-a         2/2     0            2           30h
spring-cloud-a-84gcd   1/1     1            1           186s
spring-cloud-b         2/2     2            2           30h
spring-cloud-c         2/2     0            2           30h

5. 如何完成发布?只需 kubectl-kruise rollout approve rollouts/rollout-a 将灰度中的应用进行完成发布

03. 整合 ArgoCD 实现基于 GitOps 的全链路灰度

GitOps 是一种持续交付的方式,它的核心思想是将应用系统的声明性基础架构和应用程序存放在 Git 版本库中。将 Git 作为交付流水线的核心,每个开发人员都可以提交拉取请求(Pull Request)并使用 Git 来加速和简化 Kubernetes 的应用程序部署和运维任务。通过使用像 Git 这样的简单工具,开发人员可以更高效地将注意力集中在创建新功能而不是运维相关任务上(例如,应用系统安装、配置、迁移等)。




试想一下,做为Developer,我们希望提交的 YAML 编写的应用程序定义(Deployment)可以先进行自动化的灰度环境发布,流量经过充分验证后,确定新版本的应用程序没有问题后,再进一步进行全量的应用发布。如何可以做到呢?接下来我们演示通过整合 ArgoCD 来实现的全链路灰度能力。

前提条件

安装 ArgoCD,参考 ArgoCD[3],ArgoCD 是用于 Kubernetes的 声明性 GitOps 连续交付工具。

通过 ArgoCD 配置部署应用资源

1. 在 ArgoCD 中创建 spring-cloud-c 应用

2. 在 ArgoCD 管理界面,单击 NEW APP,进行如下配置。

    a. 在 GENERAL 区域,配置 Application为spring-cloud-c,Project 为 default。 b. 在 SOURCE 区域,配置 Repository URL 为 https://github.com/aliyun/alibabacloud-microservice-demo.git ,Revision 为 argocd-samples,Path 为 argocd-samples/spring-cloud-c。 c. 在 DESTINATION 区域,配置 Cluster URL 为 https://kubernetes.default.svc,Namespace为 default。 d. 配置完成,单击页面上方的 CREATE。

3. 创建完成后,在 ArgoCD 管理界面,即可查看 spring-cloud-c 应用状态



4. 单击对应应用即可查看资源部署状态



5. 我们修改 argocd-samples/spring-cloud-c 中的 spring-cloud-c.yaml,并通过 git 提交


6. 我们可以发现,自动部署了 spring-cloud-c 应用的灰度版本

✗ kubectl get pods -o wide  | grep spring-cloud
NAME                                   READY   STATUS    RESTARTS   AGE    IP              NODE                      NOMINATED NODE   READINESS GATES
spring-cloud-a-69d577cc9-g7sbc         1/1     Running   0          16h    192.168.0.191   us-west-1.192.168.0.187   <none>           <none>
spring-cloud-b-7bc9db878f-n7pzp        1/1     Running   0          16h    192.168.0.193   us-west-1.192.168.0.189   <none>           <none>
spring-cloud-c-554458c696-2vp74        1/1     Running   0          137m   192.168.0.200   us-west-1.192.168.0.145   <none>           <none>
spring-cloud-c-554458c696-g8vbg        1/1     Running   0          136m   192.168.0.192   us-west-1.192.168.0.188   <none>           <none>
spring-cloud-c-md42b-74858b7c4-qzdxz   1/1     Running   0          53m    192.168.0.165   us-west-1.192.168.0.147   <none>           <none>

架构图如下:


7. 等应用启动就绪我们分别来验证线上正常流量以及灰度流量
a. 访问网关,如果不符合灰度规则,走基线环境:

➜  ~ curl -H "Host: example.com" http://39.98.205.236/a
A[192.168.0.191][config=base] -> B[192.168.0.193] -> C[192.168.0.200]%

b. 如何符合灰度规则,走灰度环境:

➜  ~ curl -H "Host: example.com" http://39.98.205.236/a -H "x-user-id: 100"
A[192.168.0.191][config=base] -> B[192.168.0.193] -> Cgray[192.168.0.165]%

8. 回滚只需我们通过 git 回滚 argocd-samples/spring-cloud-c 中的 spring-cloud-c.yaml 的上一次提交即可。

9. 结束发布通过 kubectl-kruise rollout approve rollouts/rollout-c 将灰度中的应用进行完成发布。


展望与总结


Kruise Rollout 是 OpenKruise 社区在渐进式交付领域的探索,此次与 MSE 合作在云原生领域落地了微服务场景的灰度发布场景。未来,Kruise Rollout 将在可扩展性方面做出持续的努力,比如:基于 Lua 脚本的可扩展流量调度方案,从而兼容社区更多的网关与架构(Istio、Apifix 等)。

在微服务治理架构中,全链路灰度功能能提供流量泳道,极大的方便了测试、发布时的快速验证,通过精确的引流规则将“爆炸半径”控制到最小,能够帮助 DevOps 提升线上稳定性。




MSE 的全链路灰度能力也在随着客户场景的深入而不断扩展与迭代。我们除了通过 MSE 全链路灰度能力保障发布态的稳定性外,还可以在运行态通过 MSE 解决流量、依赖、基础设施等不稳定的风险,MSE 微服务引擎一直致力于帮助企业打造永远在线的应用,相信只有经过客户场景持续打磨的产品才会愈发历久弥新。


相关社区


加入 OpenKruise 社区
最后,非常欢迎你通过 Github/Slack/钉钉/微信 等方式加入我们来参与 OpenKruise 开源社区。

  • 加入社区 Slack channel (English)
  • 加入社区钉钉群:搜索群号 23330762 (Chinese)
  • 加入社区微信群(新):添加用户 openkruise 并让机器人拉你入群 (Chinese)


加入 Higress 社区


如果您觉得 Higress 对您有帮助,欢迎前往 github: Higress[4]为我们 star 一下!


相关链接:

[1] Kruise Rollout

https://openkruise.io/rollouts/introduction

[2] MSE云原生网关全链路灰度

https://help.aliyun.com/zh/mse/configure-an-end-to-end-canary-release-based-on-mse-ingress-gateways#p-omu-6xu-8wm

[3] ArgoCD

https://argo-cd.readthedocs.io/en/stable/getting_started/

[4] github: Higress

https://github.com/alibaba/higress

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
7月前
|
Kubernetes 测试技术 微服务
Kruise Rollout 全链路灰度实践
OpenKruise 是一个基于 Kubernetes 的扩展套件,主要聚焦于云原生应用的自动化,比如部署、发布、运维以及可用性防护。本文介绍通过 OpenKruise 构建自动化运维的方式实现基于 Istio 的全链路灰度功能。
|
7月前
|
Cloud Native 前端开发 测试技术
MSE微服务引擎中我想实现灰度发布,怎么来实现灰度发布流量控制
MSE微服务引擎中我想实现灰度发布,怎么来实现灰度发布流量控制?
63 1
|
8月前
|
Kubernetes Serverless 应用服务中间件
通过EDAS实现K8s微服务应用的金丝雀发布
本实验旨在通过使用分布式应用服务EDAS纳管容器服务ASK,体验微服务应用的部署、访问和高级发布能力。
248 0
|
9月前
|
Cloud Native 测试技术 开发工具
通过 OpenKruise 实现基于 Higress 的全链路灰度
通过 OpenKruise 实现基于 Higress 的全链路灰度
|
11月前
|
消息中间件 Cloud Native 前端开发
基于云原生网关的全链路灰度实践
本文完整介绍了基于物理环境隔离和基于逻辑环境隔离两种方案,其中对基于逻辑环境隔离方案进行详细分析对涉及到的各个技术点做了相关介绍,并基于 EDAS 及 MSE 云原生网关的落地方案,并给出相关产品配置用例。
|
运维 Kubernetes Cloud Native
Higress & Kruise Rollout: 渐进式交付为应用发布保驾护航
相比于传统人工手动方式,Higress & Kruise Rollouts提供了无侵入、自动化运维方式让应用发布丝滑般顺畅。
Higress & Kruise Rollout: 渐进式交付为应用发布保驾护航
|
Kubernetes Cloud Native 前端开发
构建基于 Ingress 的全链路灰度能力
微服务架构下,有一些需求开发,涉及到微服务调用链路上的多个微服务同时发生了改动,通常每个微服务都会有灰度环境或分组来接受灰度流量,我们希望通过进入上游灰度环境的流量,也能进入下游灰度的环境中,确保1个请求始终在灰度环境中传递,即使这个调用链路上有一些微服务没有灰度环境,这些应用请求下游的时候依然能够回到灰度环境中。通过 MSE 提供的全链路灰度能力,可以在不需要修改任何您的业务代码的情况下,能够轻松实现上述能力。
构建基于 Ingress 的全链路灰度能力
|
运维 监控 Kubernetes
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(一)
快速学习 KubeVela 对接 Istio 实现应用灰度发布实践
607 0
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(一)
|
测试技术 开发者
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(二)
快速学习 KubeVela 对接 Istio 实现应用灰度发布实践
364 0
KubeVela 对接 Istio 实现应用灰度发布实践|学习笔记(二)
|
Prometheus 监控 Kubernetes
进阶:对接 Istio 实现应用灰度发布实践| 学习笔记
快速学习进阶:对接 Istio 实现应用灰度发布实践。
151 0
进阶:对接  Istio 实现应用灰度发布实践| 学习笔记