通过Ingress-APISIX提供的灵活的路由功能,您可以在不需要修改任何业务代码的情况下,实现全链路灰度能力。本文介绍如何通过Ingress-APISIX实现全链路灰度功能。
前提条件
背景信息
微服务架构下,有一些需求开发涉及到微服务调用链路上的多个微服务同时改动。通常每个微服务都会有灰度环境或分组来接收灰度流量。您可能希望进入上游灰度环境的流量也能进入下游灰度的环境中,从而能确保1个请求始终在灰度环境中传递,即使这个调用链路上有一些微服务应用不存在灰度环境,这些微服务应用在请求下游应用的时候依然能够回到下游应用的灰度环境中。通过将APISIX提供的灵活的路由功能与MSE提供的全链路灰度能力结合,您可以在不需要修改任何业务代码的情况下,轻松实现全链路灰度能力。
本文为您介绍基于Ingress-APISIX的全链路灰度功能。假设应用的架构由Ingress-APISIX网关以及后端的微服务架构(Spring Cloud)组成,后端调用链路有3个:商品中心(A)、交易中心(B)、库存中心(C),可以通过客户端或者HTML来访问后端服务,这些服务之间通过Nacos注册中心实现服务发现。
准备工作
安装ingress-apisix组件
安装Apisix、apisix-ingress-controller和Dashboard组件。具体操作,请参见Apache APISIX Helm Chart。
开启MSE微服务治理
微服务应用接入
将ACK微服务应用接入MSE治理中心。具体操作,请参见ACK微服务应用接入MSE治理中心。
部署Demo应用程序
登录容器服务管理控制台,在左侧导航栏选择集群。
在集群列表页面,单击目标集群名称或者目标集群右侧操作列下的详情。
在集群管理页左侧导航栏,选择 。
在无状态页面,选择命名空间,然后单击使用YAML创建资源。
使用如下YAML部署A、B、C三个应用,每个应用分别部署一个基线版本和一个灰度版本,并部署一个Nacos Server应用,用于实现服务发现。
A应用
基线(Base)版本YAML:
灰度(Gray)版本YAML:
B应用
基线(Base)版本YAML:
灰度(Gray)版本YAML:
C应用
基线(Base)版本YAML:
灰度(Gray)版本YAML:
Nacos Server应用YAML:
网络配置
针对入口应用A ,配置两个K8s Service。
spring-cloud-a-base
对应A的基线(Base)版本:apiVersion: v1 kind: Service metadata: name: spring-cloud-a-base spec: ports: - name: http port: 20001 protocol: TCP targetPort: 20001 selector: app: spring-cloud-a
spring-cloud-a-gray
对应A的灰度(Gray)版本:apiVersion: v1 kind: Service metadata: name: spring-cloud-a-gray spec: ports: - name: http port: 20001 protocol: TCP targetPort: 20001 selector: app: spring-cloud-a-new
登录APISIX控制台,左侧导航栏单击上游,在上游列表单击+创建对步骤1中配置Service进行上游服务配置,配置完成后单击下一步预览配置,最后单击提交即可完成配置。
spring-cloud-a-svc
的上游配置如下:{ "nodes": [ { "host": "spring-cloud-a-svc", "port": 20001, "weight": 1 } ], "timeout": { "connect": 6, "send": 6, "read": 6 }, "type": "roundrobin", "scheme": "http", "pass_host": "pass", "name": "spring-cloud-a-svc", "keepalive_pool": { "idle_timeout": 60, "requests": 1000, "size": 320 } }
spring-cloud-a-gray-svc
的上游配置如下:{ "nodes": [ { "host": "spring-cloud-a-gray-svc", "port": 20001, "weight": 1 } ], "timeout": { "connect": 6, "send": 6, "read": 6 }, "type": "roundrobin", "scheme": "http", "pass_host": "pass", "name": "spring-cloud-a-gray-svc", "keepalive_pool": { "idle_timeout": 60, "requests": 1000, "size": 320 } }
返回上游列表页面可查看已创建的上游服务。
场景一:按照域名路由,实现全链路灰度
如果您想通过不同的域名来区分线上基线环境和灰度环境,灰度环境有单独的域名可以配置。例如想通过访问www.example.com
来请求灰度环境,访问www.aliyundoc.com
走基线环境,如下图所示:
调用链路为Ingress-APISIX > A > B > C ,其中A可以是一个Spring Boot的应用。
配置APISIX路由规则
登录APISIX控制台,单击左侧导航栏路由,然后单击+创建。
在创建路由页面配置路由信息分为4步,依次是 。
在设置路由信息页面配置路由基本信息,单击下一步。
分别配置如下路由:
Base对应的路由配置
{ "uri": "/*", "name": "spring-cloud-a", "methods": [ "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE" ], "host": "www.aliyundoc.com", "upstream_id": "40115245*****54748", "labels": { "API_VERSION": "0.0.1" }, "status": 1 }
Gray对应的路由配置
{ "uri": "/*", "name": "spring-cloud-a-gray", "priority": 1, "methods": [ "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE" ], "host": "www.example.com", "upstream_id": "40116333*****15388", "labels": { "API_VERSION": "0.0.1" }, "status": 1 }
在设置上游服务页面,单击选择上游服务下拉框,选择所需的上游服务,然后单击下一步。
设置路由信息页面的域名Host为www.aliyundoc.com时,路由到ID为40115245*****54748所对应的上游,即spring-cloud-a-svc;当Host为www.example.com时,路由到ID为40116333*****15388所对应的上游,即spring-cloud-a-gray-svc。
在插件配置页面单击下一步。
在预览页面查看路由配置,最后单击提交即可完成配置。
配置MSE全链路灰度
登录MSE治理中心控制台,并在顶部菜单栏选择地域。
在左侧导航栏,选择治理中心 > 全链路灰度。
在全链路灰度页面,创建泳道组。在创建泳道组面板,输入泳道组名称,并添加spring-cloud-a、spring-cloud-b和spring-cloud-c应用进入泳道组,然后单击确定。
如果您选择的微服务空间没有创建过泳道组,单击创建泳道组及泳道。
如果您选择的微服务空间已经创建过泳道组,单击+创建泳道组。
在全链路灰度页面下方,单击点击创建第一个分流泳道。在创建泳道面板中选择泳道标签gary并设置相关参数,然后单击确定。
结果验证
下方代码中47.97.xx.xx为APISIX的公网IP。
执行如下代码访问www.aliyundoc.com,路由到基线环境验证结果。
curl -H"Host:www.aliyundoc.com" http://47.97.xx.xx/a A[172.18.xx.xx] -> B[172.18.xx.xx] -> C[172.18.xx.xx]%
执行如下代码访问www.example.com,路由到灰度环境验证结果。
curl -H"Host:www.example.com" http://47.97.xx.xx/a Agray[172.18.xx.xx] -> Bgray[172.18.xx.xx] -> Cgray[172.18.xx.xx]%
场景二:按照指定请求参数进行路由,实现全链路灰度
若您无法改写域名,但希望能访问www.example.com
通过传入不同的参数来路由到灰度环境。例如想通过env=gray这个请求参数,来访问灰度环境,如下图所示:
调用链路为Ingress-APISIX > A > B > C ,其中A可以是一个Spring Boot的应用。
配置APISIX路由规则
登录APISIX控制台,单击左侧导航栏路由,然后单击+创建。
创建路由页面配置路由信息分为4步,依次是 。
在设置路由信息页面配置路由基本信息,单击下一步。
分别配置如下路由:
Base对应的路由配置
{ "uri": "/*", "name": "spring-cloud-a", "methods": [ "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE" ], "host": "www.example.com", "upstream_id": "40115245*****54748", "labels": { "API_VERSION": "0.0.1" }, "status": 1 }
Gray对应的路由配置。
{ "uri": "/*", "name": "spring-cloud-a-gray", "priority": 1, "methods": [ "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "CONNECT", "TRACE" ], "host": "www.example.com", "vars": [ [ "arg_env", "==", "gray" ] ], "upstream_id": "40116333*****15388", "labels": { "API_VERSION": "0.0.1" }, "status": 1 }
在设置上游服务页面,单击选择上游服务下拉框,去选择所需的上游服务,然后单击下一步。
设置路由信息页面的域名Host为www.example.com时,请求参数
env=gray
时,路由优先匹配到ID为40116333*****15388所对应的上游,即spring-cloud-a-gray-svc;否则,路由到ID为40115245*****54748所对应的上游,即spring-cloud-a-svc。在插件配置页面单击下一步。
在预览页面查看路由配置,最后单击提交即可完成配置。
配置MSE全链路灰度
配置MSE全链路灰度的操作步骤和场景一:按照域名路由,实现全链路灰度相同。
结果验证
下方代码中的47.97.xx.xx为APISIX的公网IP。
执行下方代码访问www.example.com,路由到基线环境。
curl -H"Host:www.example.com" http://47.97.xx.xx/a A[172.18.xx.xx] -> B[172.18.xx.xx] -> C[172.18.xx.xx]%
执行下方代码访问www.example.com,同时env=gray时路由到灰度环境。
curl -H"Host:www.example.com" http://47.97.xx.xx/a?env=gray Agray[172.18.xx.xx] -> Bgray[172.18.xx.xx] -> Cgray[172.18.xx.xx]%