通过云原生API网关实现蓝绿部署、A/B测试和金丝雀发布

云原生API网关以托管的方式来做流量入口,提供丰富的流量治理能力,支持多种服务发现方式,如容器服务、MSE Nacos、MSE Zookeeper、EDAS注册中心、SAE注册中心、固定地址和DNS域名,并以统一的模型支持服务版本以及灰度发布能力。本文介绍基于容器服务K8s和Nacos注册中心两种服务发现机制来实践不同的服务发布策略。

前提条件

服务发现方式:容器服务K8s

在本示例中,使用容器服务K8s原生的服务发现方式,即通过声明式Service API资源将后端服务注册到CoreDNS。示例中的后端服务提供一个查询当前版本的接口:请求路径为/version,并且当前版本为v1。云原生API网关深度集成容器服务ACK,可以实时动态地从ACK集群中获取服务信息,方便通过云原生API网关将该后端服务暴露给外部用户。

基于容器服务K8s服务发现方式的业务架构图

部署应用

  1. 登录容器服务管理控制台使用如下YAML部署应用,当前应用版本为v1。

    应用部署的具体操作,请参见创建无状态工作负载Deployment

    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
    spec:
      ports:
      - port: 8080
        protocol: TCP
      selector:
        app: httpbin
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin-v1
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: httpbin
          version: v1
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          containers:
          - image: specialyang/spring-cloud-httpbin-k8s:v1
            imagePullPolicy: Always
            name: spring-cloud-httpbin-k8s
            ports:
            - containerPort: 8080
  2. 登录云原生API网关控制台

  3. 在左侧导航栏,选择实例管理,并在顶部菜单栏选择地域。

  4. 实例管理页面,单击目标网关实例名称。

  5. 在左侧导航栏,单击路由管理,然后选择来源页签。单击创建来源,选择服务来源为容器服务

    为云原生API网关添加服务来源的具体操作,请参见创建服务来源

    image

  6. 在左侧导航栏,选择路由管理 > 服务。导入要暴露给云原生API网关的服务httpbin。

    为云原生API网关添加服务的具体操作,请参见创建服务

  7. 在httpbin服务的策略配置中添加服务版本v1。

    为云原生API网关添加服务版本的具体操作,请参见管理服务版本

    说明

    需要选择对应的标签来筛选出v1版本的节点,目前只部署了v1版本,所以v1版本的节点数占总实例数100%。

    image

  8. 在路由管理中为该服务创建一条路由规则,从而将服务暴露给外部用户。httpbin服务暴露的API的路由为/version,请求转发至服务httpbin的v1版本。

    为云原生API网关配置路由的具体操作,请参见创建路由

  9. 执行以下测试请求命令:

    for i in {1..10}; do curl "${GATEWAY_EXTERNAL_IP}/version"; echo "";  done

    响应结果:

    version: v1
    version: v1
    version: v1
    version: v1
    version: v1
    version: v1
    version: v1
    version: v1
    version: v1
    version: v1

蓝绿部署

蓝绿部署需要按照服务当前版本所占用的资源状况为服务新版本申请同样的资源规格,部署完毕之后将流量整体切换到服务新版本。

基于容器服务K8s服务发现机制的蓝绿发布

  1. 利用容器服务ACK的声明式API资源部署httpbin服务的新版本v2,副本数同样是3。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin-v2
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: httpbin
          version: v2
      template:
        metadata:
          labels:
            app: httpbin
            version: v2
        spec:
          containers:
          - image: specialyang/spring-cloud-httpbin-k8s:v2
            imagePullPolicy: Always
            name: spring-cloud-httpbin-k8s
            ports:
            - containerPort: 8080
  2. 在httpbin服务的策略配置中添加服务版本v2。

    为云原生API网关添加服务版本的具体操作,请参见管理服务版本

    说明

    需要选择对应的标签来筛选出v2版本的节点,集群中现在v1和v2版本的节点数一致,所以各占50%。

    image

  3. 通过蓝绿发布将流量从v1整体切换至v2,仅需要修改之前创建的路由规则中的目标服务。

    修改云原生API网关路由规则的具体操作,请参见管理路由

    image

  4. 执行以下测试请求命令:

    for i in {1..10}; do curl "${GATEWAY_EXTERNAL_IP}/version"; echo "";  done

    响应结果:

    version: v2
    version: v2
    version: v2
    version: v2
    version: v2
    version: v2
    version: v2
    version: v2
    version: v2
    version: v2

可以发现,访问API资源/version请求的流量已经全部从v1切换至v2。

A/B测试

A/B测试是基于用户请求的元信息将流量路由到新版本,也就是可以根据请求内容来动态路由。在本示例中,希望User-Agent的值为Android的请求 (来自安卓系统的请求)可以访问新版本,其他系统仍然访问旧版本。

基于容器服务K8s服务发现机制的A/B测试

  1. 仍然通过之前实践中部署的httpbin服务v1和v2的应用。同时,需要创建两条路由规则。

    • 匹配Path为/version的请求访问服务版本v1。

    • 匹配Path为/version,且User-Agent头部含有Android的请求访问服务版本v2。

    说明

    version-v2的路由规则中需要增加请求头的匹配规则。

  2. 执行以下测试请求命令(User-Agent中不含有Android):

    curl ${GATEWAY_EXTERNAL_IP}/version

    响应结果:

    version: v1
  3. 执行以下测试请求命令(User-Agent中含有Android):

    curl -H "User-Agent: Mozilla/5.0 (Linux; Android 4.0.3)" ${GATEWAY_EXTERNAL_IP}/version

    响应结果:

    version: v2

可以发现,当前请求会按照来源的操作系统对流量进行分流。

金丝雀发布

金丝雀发布允许引流一小部分流量到新版本,待验证通过后,逐步增加流量,直至完全切换,期间可伴随着新版本的扩容,旧版本的缩容操作,达到资源利用率最大化。

基于容器服务K8s服务发现机制的金丝雀发布

  1. 在金丝雀发布策略中,服务新版本的副本初始部署数无需与原始保持一致。仅需保持资源始终满足灰度流量,所以将新版本的副本数调为1,可以在服务策略中服务版本模块看到当前各版本节点数的占比情况。

    image

  2. 创建一条路由规则,在目标服务中按照权重将流量转发至新旧版本。

    其中,需要配置两个目标服务,httpbin的v1和v2版本,并设置对应的流量比。例如,目标服务为标签路由方式,且v1权重设置为80%,v2权重设置为20%。

  3. 执行以下测试请求命令:

    for i in {1..10}; do curl "${GATEWAY_EXTERNAL_IP}/version"; echo "";  done

    响应结果:

    version: v1
    version: v1
    version: v1
    version: v1
    version: v1
    version: v2
    version: v1
    version: v2
    version: v1
    version: v1

可以发现,10个请求中有2个是访问的新版本v2,其流量比确实符合期望比例。

说明

在真实业务场景中,新版本验证完毕后,就可以继续调大访问新版本的流量权重,期间注意对新版本扩容,按需对旧版本缩容。