使用ASM流量泳道的全链路灰度发布实践

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 服务网格ASM实现全链路灰度发布:通过流量泳道隔离不同版本环境,配置虚拟服务实现灰度比例控制。从创建泳道、打标签、部署新版本到灰度切流、最终上线及下线旧版。

在《最佳实践在哪里-1》中,我们阐述了使用服务网格技术进行全链路灰度流量控制的各种场景以及实现思路。服务网格ASM已经在产品中提供了“流量泳道”能力,通过流量泳道,就可以通过简单的配置将调用链路的不同版本进行环境隔离,从而轻松实现自己的全链路灰度发布场景。产品功能参考:什么是流量泳道_服务网格(ASM)-阿里云帮助中心

本文是一篇小品级示例,主要阐释全链路灰度发布是如何通过流量泳道功能来实现的,来指导用户的最佳实践。

背景、需求与前提条件

我们首先明确问题背景与用户需求,以更好地理解后面要进行的操作。

作为服务网格技术的用户,小帅开发了一套在k8s上部署的业务系统,该系统由三个云原生服务组成,分别是mocka、mockb和mockc,服务之间存在调用关系:mocka -> mockb -> mockc。现在,小帅希望对自己的这套系统构建一套完整的灰度发布流程。期望的方式是新版本的服务上线后,先将10%左右的入口流量发往新版本进行测试(灰度需要是全链路的,要保证流量不会打向老版本)。经过逐步的灰度、新版本的流量比例不断提高直到100%,最后下线老版本,期间需要保持流量无损。

让我们看看使用服务网格ASM如何实现这个需求,首先我们需要满足一些前提条件:

1、小帅已经在线上部署了自己的系统,mocka、mockb、mockc,每个服务自己的Service和Deployment都已经部署。

通过kubctl链接到Kubernetes集群,然后通过以下指令就可以部署这套示例应用:

kubectl apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-labs/swimlane/v1/mock-v1.yaml

2、系统使用了ASM网关作为入口网关(本例中网关名字叫ingressgateway),通过网关规则(Gateway)和虚拟服务(VirtualService)、让入口网关向mocka服务转发请求。相关资源YAML如下——

网关规则:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: ingressgateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - hosts:
        - '*'
      port:
        name: http
        number: 80
        protocol: HTTP

虚拟服务:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: mockvs
  namespace: istio-system
spec:
  gateways:
    - ingressgateway
  hosts:
    - '*'
  http:
    - route:
        - destination:
            host: mocka.default.svc.cluster.local

可以通过kubectl连接到ASM实例,然后应用这些YAML资源(同时别忘了在ASM实例中创建一个默认的ASM网关)。

做完之后,应该已经可以通过网关访问我们的系统了。

curl {网关ip地址}
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)%

本示例中使用的服务可以打印业务的调用链条,以便我们观测全链路灰度的结果,可以看到当前我们只部署了基础的mock-v1版本,调用链路是mocka-v1 -> mockb-v1 -> mockc-v1。现在可以着手准备我们的新版本上线流程了

步骤一:准备工作负载的版本标签、初始化流量泳道

要对全链路进行灰度发布,首先需要给系统重的每个服务pod进行打标,确保服务网格能够识别服务的不同版本。

我们可以看到目前部署的mock-v1版本的三个服务的pod都带有version: v1的标签,来标识它们都属于v1这个版本:

image.png

如果线上的业务系统pod没有这种可以标识版本信息的标签,则需要先添加标签。

准备好版本信息后,我们参考https://help.aliyun.com/zh/asm/user-guide/full-link-traffic-management-using-strict-mode-traffic-swimlanes官方文档,在  流量管理中心 > 流量泳道  页面中,建立一条泳道组:

image.png

泳道组建好后,点击“创建泳道”按钮,按照参考文档创建一条名字叫v1的泳道,并选择使用version: v1这个标签来区分泳道内的服务。这条泳道就代表着我们应用最基本的v1版本。

image.png

创建好后的泳道:

image.png

创建好之后,我们已经可以在虚拟服务中通过subset来指定流量应该发往的版本,我们更新之前在前提条件中创建的虚拟服务为:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: mockvs
  namespace: istio-system
spec:
  gateways:
    - ingressgateway
  hosts:
    - '*'
  http:
    - route:
        - destination:
            host: mocka.default.svc.cluster.local
            subset: v1

主要的区别就是在destination中添加了subset: v1,让网关将流量转发到v1版本的流量泳道。这对当前的业务访问没有任何的影响,因为我们还没有新版本的服务,后面要通过这个虚拟服务实现流量灰度比例的逐步切换。

步骤二:部署新版本(v2)服务

接下来部署我们开发好的v2版本的服务。对于云原生应用来说,都是以k8s Service name来进行相互调用的,我们的mock应用也不例外。当我们发布应用的新版本时,服务之间肯定还是以相同的service name互相调用,因此实际部署的是新服务的deployment。

通过kubectl链接到Kubernetes集群,然后通过以下指令部署mock应用的v2版本

kubectl apply -f https://alibabacloudservicemesh.oss-cn-beijing.aliyuncs.com/asm-labs/swimlane/v2/mock-v2.yaml

部署后可以看到集群中新版本服务的pod。

image.png

可以看到这些新版本的服务pod都带有version: v2的标签,用来和最初的v1版本进行区分。

此时我们再试着调用业务:

curl {网关ip地址}
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)%

可以发现当下无论怎么发起调用,流量还是只流经v1版本的服务。v2版本的服务并不会有流量进来,这是因为我们在步骤一中已经初始化了流量泳道,对这个流量进行了控制隔离,保证业务能够正常灰度发布。

接下来,我们需要为v2版本的服务创建一条泳道,以进行接下来的灰度流程。还是效仿步骤一中创建流量泳道的操作,不过这次指定泳道名为v2、匹配version: v2标签的pod。

image.png

现在可以在ASM控制台上看到,我们有两条泳道了(v1和v2)。

image.png

步骤三:开始灰度流程,部分流量切到v2版本

流量泳道代表着流量调用链路的隔离环境。通过上面创建的两条泳道,我们已经保证到达服务上的流量只会在服务的相同版本中传递。接下来,只需要调整网关上的虚拟服务,向v2版本进行灰度切流即可。

还是之前的那个虚拟服务,这次我们改成:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: mockvs
  namespace: istio-system
spec:
  gateways:
    - ingressgateway
  hosts:
    - '*'
  http:
    - route:
        - destination:
            host: mocka.default.svc.cluster.local
            subset: v1
          weight: 90
        - destination:
            host: mocka.default.svc.cluster.local
            subset: v2
          weight: 10

可以看到这里多了一条路由目的地,指定为mocka服务的v2版本。同时,两个版本之间的流量比例通过weight参数调整为90:10。 这样就会有10%的流量灰度到v2版本。

通过连续不断的访问我们的系统,我们可以观测到发往服务不同版本的流量比例。v1 : v2 ~= 90: 10。也就是v2版本正在进行10%流量的灰度。

for i in {1..100};  do curl {ASM网关ip地址};  echo ''; sleep 1; done;
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)
-> mocka(version: v1, ip: 10.1.0.149)-> mockb(version: v1, ip: 10.1.0.173)-> mockc(version: v1, ip: 10.1.0.157)

步骤四:完全上线v2版本,下线v1版本

通过调整步骤三中虚拟服务的weight参数,我们能够轻松控制两个版本服务的流量比例。当我们充分对v2版本进行灰度测试后,就可以考虑上线v2版本并对v1版本进行下线。

将虚拟服务改成:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: mockvs
  namespace: istio-system
spec:
  gateways:
    - ingressgateway
  hosts:
    - '*'
  http:
    - route:
        - destination:
            host: mocka.default.svc.cluster.local
            subset: v2

此时流量将完全发往v2版本。我们可以再次访问系统来验证一下:

for i in {1..100};  do curl {ASM网关ip地址};  echo ''; sleep 1; done;
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)
-> mocka(version: v2, ip: 10.1.0.216)-> mockb(version: v2, ip: 10.1.0.217)-> mockc(version: v2, ip: 10.1.0.215)

可以看到已经没有请求发往v1版本了,这时就可以对v1版本进行安全的下线。

首先在ASM控制台侧删除v1版本的流量泳道:

image.png

接下来就可以删除v1版本所有服务的deployment了,可以直接在ACK控制台进行删除:

image.png

删除后,mock服务的v1版本已经完全下线,线上运行的已经100%是v2版本了~

小结

我们通过一个常见的客户需求拓展出的小品案例,给各位简要阐述了如何使用ASM的流量泳道功能、对自己的业务系统进行一个全链路的灰度发布。同时,灰度发布的整个过程中,通过流量泳道的控制,业务的流量不会受到损失~

用服务网格ASM,灰度发布不费劲!🤷🏿‍♀️

相关文章
|
2月前
|
运维 负载均衡 监控
探索微服务架构下的服务网格(Service Mesh)实践之路
【8月更文挑战第30天】 在当今日益复杂的分布式系统中,微服务架构已成为众多企业解决系统扩展与维护难题的利器。然而,随着服务的不断增多和网络交互的复杂性提升,传统的微服务管理方式开始显得力不从心。服务网格(Service Mesh)作为一种新兴的解决方案,旨在通过提供应用层的网络基础设施来简化服务间通讯,并增强系统的可观察性和安全性。本文将分享我在采用服务网格技术过程中的经验与思考,探讨如何在现代云原生环境中有效地实施服务网格,以及它给开发和运维带来的变革。
|
4月前
|
Cloud Native 容器 Kubernetes
基于阿里云服务网格流量泳道的全链路流量管理(三):无侵入式的宽松模式泳道
本文简要讨论了使用流量泳道来实现全链路流量灰度管理的场景与方案,并回顾了阿里云服务网格 ASM 提供的严格与宽松两种模式的流量泳道、以及这两种模式各自的优势与挑战。接下来介绍了一种基于 OpenTelemetry 社区提出的 baggage 透传能力实现的无侵入式的宽松模式泳道,这种类型的流量泳道同时具有对业务代码侵入性低、同时保持宽松模式的灵活特性的特点。同时,我们还介绍了新的基于权重的流量引流策略,这种策略可以基于统一的流量匹配规则,将匹配到的流量以设定好的比例分发到不同的流量泳道。
73521 16
基于阿里云服务网格流量泳道的全链路流量管理(三):无侵入式的宽松模式泳道
|
4月前
|
负载均衡 测试技术 网络安全
阿里云服务网格ASM多集群实践(一)多集群管理概述
服务网格多集群管理网络打通和部署模式的多种最佳实践
|
3月前
|
人工智能 自然语言处理 安全
使用阿里云服务网格高效管理LLM流量:(一)流量路由
ASM支持通过LLMProvider和LLMRoute资源管理大型语言模型流量。LLMProvider负责注册LLM服务,LLMRoute负责设定流量规则,应用可灵活切换模型,满足不同场景需求。
|
3月前
|
Cloud Native 测试技术 开发者
阿里云服务网格ASM多集群实践(二):高效按需的应用多环境部署与全链路灰度发布
介绍服务网格ASM提出的一种多集群部署下的多环境部署与全链路灰度发布解决方案。
|
5月前
|
监控 负载均衡 数据安全/隐私保护
探索微服务架构下的服务网格(Service Mesh)实践
【5月更文挑战第6天】 在现代软件工程的复杂多变的开发环境中,微服务架构已成为构建、部署和扩展应用的一种流行方式。随着微服务架构的普及,服务网格(Service Mesh)作为一种新兴技术范式,旨在提供一种透明且高效的方式来管理微服务间的通讯。本文将深入探讨服务网格的核心概念、它在微服务架构中的作用以及如何在实际项目中落地实施服务网格。通过剖析服务网格的关键组件及其与现有系统的协同工作方式,我们揭示了服务网格提高系统可观察性、安全性和可操作性的内在机制。此外,文章还将分享一些实践中的挑战和应对策略,为开发者和企业决策者提供实用的参考。
|
5月前
|
运维 监控 负载均衡
探索微服务架构下的服务网格(Service Mesh)实践之路
【4月更文挑战第30天】 在现代云计算的大背景下,微服务架构以其灵活性和可扩展性成为众多企业转型的首选。然而,随着服务的激增和网络交互的复杂化,传统的服务通信模式已无法满足需求,服务网格(Service Mesh)应运而生。本文通过分析服务网格的核心组件、运作机制以及在企业中的实际应用案例,探讨了服务网格在微服务架构中的关键作用及其带来的变革,同时提出了实施过程中面临的挑战和解决策略。
|
5月前
|
运维 监控 Cloud Native
云原生架构下的服务网格演进与实践
【5月更文挑战第23天】 随着云计算技术的不断成熟,云原生架构已成为推动企业数字化转型的关键动力。本文将深入探讨服务网格在云原生环境中的重要性,分析其在微服务管理、流量控制和安全性方面的创新应用。通过对服务网格的技术和实践案例的剖析,揭示其如何优化云原生应用的部署、运行和管理,为企业构建更加动态、可靠和高效的分布式系统提供策略指导。
|
5月前
|
运维 监控 负载均衡
探索微服务架构下的服务网格(Service Mesh)实践
【4月更文挑战第28天】 在现代云原生应用的后端开发领域,微服务架构已成为一种广泛采用的设计模式。随着分布式系统的复杂性增加,服务之间的通信变得愈加关键。本文将深入探讨服务网格这一创新技术,它旨在提供一种透明且高效的方式来管理、监控和保护微服务间的交互。我们将从服务网格的基本概念出发,分析其在实际应用中的优势与挑战,并通过一个案例研究来展示如何在现有的后端系统中集成服务网格。
|
11月前
|
Kubernetes API 容器
基于阿里云服务网格流量泳道的全链路流量管理(二):宽松模式流量泳道
基于阿里云服务网格流量泳道的全链路流量管理(二):宽松模式流量泳道
10965 12