使用API在K8s集群中金丝雀发布应用

本文介绍如何使用EDAS提供的Java SDK调用API在K8s集群中进行金丝雀发布应用(JAR包、WAR包和镜像)。

准备工作

金丝雀发布应用前,您必须提前完成以下准备工作:

  • 确定应用部署地域,假设为cn-hangzhou
  • 在EDAS K8s环境中创建应用。目前支持多种创建应用的方式,请根据实际需求选择:

    如果已经创建应用,您可以调用ListApplication接口查询应用列表,获取目标应用的AppId,假设为6bbc57a2-a017-4bec-b521-49a15bd3****

  • 已将应用升级部署包(JAR包、WAR包和镜像)上传至目标地址。
    • JAR包或WAR包:本示例以OSS存储路径为例,假设为https:doc***.oss-cn-hangzhou.aliyuncs.com/sc-****-D-0.0.2-SNAPSHOT.jar
    • 镜像:假设镜像仓库为image-demo-project,镜像地址为registry-vpc.cn-hangzhou.aliyuncs.com/image-demo-project/provider:2.0

背景信息

使用API金丝雀发布应用,在首批灰度发布后,您必须手动确认继续剩余批次的发布。在确认剩余批次发布前,您可以进行小规模验证,验证后,再继续剩余批次的发布,即将应用全量升级到新版本。

使用API金丝雀发布应用,设置剩余批次(除首批灰度发布外)的发布方式时推荐选用自动分批发布。如果您选用手动分批发布方式,则还需要调用ContinuePipeline接口手动确认执行下一批发布。

此处提供两种金丝雀发布策略示例,请根据您的实际场景选择并修改策略。

  • 首批灰度发布2个Pod实例+剩余Pod实例分2批发布+自动分批+分批间隔1分钟。

    {"type":"GrayBatchUpdate","batchUpdate":{"batch":2,"releaseType":"auto","batchWaitTime":1},"grayUpdate":{"gray":2}}
  • 首批灰度发布2个Pod实例+剩余Pod实例分2批发布+手动分批。

    {"type":"GrayBatchUpdate","batchUpdate":{"batch":2,"releaseType":"manual"},"grayUpdate":{"gray":2}}

使用JAR包或WAR包金丝雀发布应用

  1. 运行以下示例代码,使用JAR包或WAR包金丝雀发布应用。

    以下代码适用于在EDAS K8s集群中金丝雀发布应用(JAR包)。代码中未设置调度规则、启动命令、环境变量等高级参数,如需了解更多API参数信息,请参见DeployK8sApplication

    说明

    如果您需要使用WAR包金丝雀应用,请根据需要在示例代码中增加以下两个参数:

    //部署包依赖的Tomcat版本。适用于通过WAR包部署的Spring Cloud和Dubbo应用。
    request.setWebContainer("apache-tomcat-7.0.91");  
    //部署包依赖的EDAS Container版本。适用于通过WAR包部署的HSF应用。     
    request.setEdasContainerVersion("3.5.9");
    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.exceptions.ServerException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.edas.model.v20170801.DeployK8sApplicationRequest;
    import com.aliyuncs.edas.model.v20170801.DeployK8sApplicationResponse;
    
    public class DeployK8sApplication {
    
        public static void main(String[] args)  {
            // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
            // 此处以把AccessKey和AccessKeySecret保存在环境变量为例说明。您可以根据业务需要,保存到配置文件里。
            // 强烈建议不要把AccessKey和AccessKeySecret保存到代码里,会存在密钥泄漏风险。
            String aliyun_user_ak = System.getenv("ACCESS_KEY_ID");
            String aliyun_user_sk = System.getenv("ACCESS_KEY_SECRET");
            //应用所在地域ID。
            String region_id = "cn-hangzhou";
    
            DefaultProfile defaultProfile = DefaultProfile.getProfile(region_id, aliyun_user_ak, aliyun_user_sk);
            DefaultAcsClient client = new DefaultAcsClient(defaultProfile);
    
            //创建API请求,并设置参数。
            DeployK8sApplicationRequest request = new DeployK8sApplicationRequest();
            //应用ID。
            request.setAppId("6bbc57a2-a017-4bec-b521-49a15bd3****");
            //JAR包或者WAR包地址、版本。
            request.setPackageUrl("https:doc***.oss-cn-hangzhou.aliyuncs.com/sc-****-D-0.0.2-SNAPSHOT.jar");
            request.setPackageVersion("2021-04-15 16:41:52");
            //部署包依赖的JDK版本。可选的参数值为Open JDK 7和Open JDK 8。
            request.setJDK("Open JDK 8");
            //自定义分批发布策略。此处示例值代表“首批灰度发布2个Pod实例+剩余Pod实例分2批发布+自动分批+分批间隔1分钟”。
            request.setUpdateStrategy("{\"type\":\"GrayBatchUpdate\",\"batchUpdate\":{\"batch\":2,\"releaseType\":\"auto\",\"batchWaitTime\":1},\"grayUpdate\":{\"gray\":2}}");
            //灰度发布流量控制策略。示例策略表示:50%的流量会被转发到灰度分组。
            request.setTrafficControlStrategy("{\"http\":{\"rules\":[{\"conditionType\":\"percent\",\"percent\":50}]}}");
            //应用实例数。
            request.setReplicas(4);
            //应用运行过程中,应用实例的CPU限额、内存限额等,0表示不限制。
            request.setCpuLimit(0);
            request.setMemoryLimit(0);
            request.setCpuRequest(0);
            request.setMemoryRequest(0);
            //CPU最小资源需求,单位:核数。0表示不限制。
            request.setMcpuRequest(0);
            //CPU能使用的最大值,单位:核数。0表示不限制。
            request.setMcpuLimit(0);
            //变更记录描述。
            request.setChangeOrderDesc("金丝雀发布(JAR包)");
    
            try {
                DeployK8sApplicationResponse response = client.getAcsResponse(request);
                System.out.println("ChangeOrderId=" + response.getChangeOrderId() + "\nMessage=" + response.getMessage());
            } catch (ServerException e) {
                e.printStackTrace();
            } catch (ClientException e) {
                e.printStackTrace();
            }
        }
    }

    运行程序,返回的执行结果如下:

    ChangeOrderId=5886e6f9-05b1-42f0-a3d4-5d90558e****
    Message=success
  2. 调用GetChangeOrderInfo接口,获取金丝雀发布应用变更的相关批次的流程ID(PipelineId)。

    调用GetChangeOrderInfo接口,返回结果如下:

    {
      "Message": "success",
      "RequestId": "19C54DC3-C66C-40D0-AEED-8D5A1F00F3BA",
      "Code": 200,
      "changeOrderInfo": {
        "Status": 8,
        "Desc": "金丝雀发布(JAR包)",
        "PipelineInfoList": {
          "PipelineInfo": [
            {
              "PipelineStatus": 2,
              "PipelineName": "Canary Change",
              ......
              "PipelineId": "ca7221a6-2c39-40b5-b40a-53fd3d99****"
              ......
              "PipelineId": "e228e628-f722-43bc-9c2b-45076c3a****"
              ......
              "PipelineId": "d6dcb857-2ff0-4db9-90fa-a2d9db7b****"
              ......
              //此处未罗列全部执行结果,仅供参考。
    说明

    示例代码中使用的是首批灰度发布2个Pod实例+剩余Pod实例分2批发布+自动分批+分批间隔1分钟的金丝雀发布策略,在首批灰度发布2个Pod实例流程运行完以后,需要手动确认继续剩余批次的发布。在调用GetChangeOrderInfo接口返回结果中出现3个流程ID(PipelineId),第二次出现的流程ID(PipelineId)代表需要手动确认继续剩余批次的发布。

    剩余批次的策略是剩余Pod实例分2批发布+自动分批+分批间隔1分钟,则无需手动确认,系统自动完成剩余批次的发布。

  3. 调用ContinuePipeline接口,手动确认继续剩余批次的发布。

    返回结果如下:

    {
      "Message": "success",
      "RequestId": "050392EE-959D-4144-AA02-3A1E7CE2F736",
      "Code": 200
    }

使用镜像金丝雀发布应用

  1. 运行程序,使用镜像金丝雀发布应用。

    以下代码适用于在EDAS K8s集群中金丝雀发布应用(镜像)。代码中未设置调度规则、启动命令、环境变量等高级参数,如需了解更多API参数信息,请参见DeployK8sApplication

    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.exceptions.ServerException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.edas.model.v20170801.DeployK8sApplicationRequest;
    import com.aliyuncs.edas.model.v20170801.DeployK8sApplicationResponse;
    
    public class DeployK8sApplication {
    
        public static void main(String[] args)  {
            // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
            // 此处以把AccessKey和AccessKeySecret保存在环境变量为例说明。您可以根据业务需要,保存到配置文件里。
            // 强烈建议不要把AccessKey和AccessKeySecret保存到代码里,会存在密钥泄漏风险。
            String aliyun_user_ak = System.getenv("ACCESS_KEY_ID");
            String aliyun_user_sk = System.getenv("ACCESS_KEY_SECRET");
            //应用所在地域ID。
            String region_id = "cn-hangzhou";
    
            DefaultProfile defaultProfile = DefaultProfile.getProfile(region_id, aliyun_user_ak, aliyun_user_sk);
            DefaultAcsClient client = new DefaultAcsClient(defaultProfile);
    
            //创建API请求,并设置参数。
            DeployK8sApplicationRequest request = new DeployK8sApplicationRequest();
            //应用ID。
            request.setAppId("6bbc57a2-a017-4bec-b521-49a15bd3****");
            //镜像地址。
            request.setImage("registry-vpc.cn-hangzhou.aliyuncs.com/image-demo-project/provider:2.0");
            //自定义金丝雀发布策略。此处示例值代表“首批灰度发布2个Pod实例+剩余Pod实例分2批发布+手动分批”。
            request.setUpdateStrategy("{\"type\":\"GrayBatchUpdate\",\"batchUpdate\":{\"batch\":2,\"releaseType\":\"manual\"},\"grayUpdate\":{\"gray\":2}}");
            //灰度发布流量控制策略。示例策略表示:50%的流量会被转发到灰度分组。
            request.setTrafficControlStrategy("{\"http\":{\"rules\":[{\"conditionType\":\"percent\",\"percent\":50}]}}");
            //应用实例数。
            request.setReplicas(4);
            //应用运行过程中,应用实例的CPU限额、内存限额等,0表示不限制。
            request.setCpuLimit(0);
            request.setMemoryLimit(0);
            request.setCpuRequest(0);
            request.setMemoryRequest(0);
            //CPU最小资源需求,单位:核数。0表示不限制。
            request.setMcpuRequest(0);
            //CPU能使用的最大值,单位:核数。0表示不限制。
            request.setMcpuLimit(0);
            //变更记录描述。
            request.setChangeOrderDesc("金丝雀发布(镜像)");
    
            try {
                DeployK8sApplicationResponse response = client.getAcsResponse(request);
                System.out.println("ChangeOrderId=" + response.getChangeOrderId() + "\nMessage=" + response.getMessage());
            } catch (ServerException e) {
                e.printStackTrace();
            } catch (ClientException e) {
                e.printStackTrace();
            }
        }
    }

    运行程序,返回的执行结果如下:

    ChangeOrderId=a7431f9e-7e05-4590-aef8-17088f0****
    Message=success
  2. 调用GetChangeOrderInfo接口,获取金丝雀发布应用变更的相关批次的流程ID(PipelineId)。

    调用GetChangeOrderInfo接口,返回结果如下:

    {
      "Message": "success",
      "RequestId": "1B1127FB-251C-4946-AA20-D4FF5DF4788F",
      "Code": 200,
      "changeOrderInfo": {
        "Status": 8,
        "Desc": "金丝雀发布(镜像)",
        "PipelineInfoList": {
          "PipelineInfo": [
            {
              "PipelineStatus": 2,
              "PipelineName": "Canary Change",
              ......
              "PipelineId": "09e7d9aa-e79d-49ef-99b9-5405532d****"
              ......
              "PipelineId": "1ea53844-2c60-46f1-b46d-df3b34d0****"
              ......
              "PipelineId": "d99da075-b87d-4fe7-bbb6-ae1c6c26****"
              ......
              //此处未罗列全部执行结果,仅供参考。
    说明

    示例代码中使用的是首批灰度发布2台+剩余分2批发布+手动分批的金丝雀发布策略,在首批灰度发布2个Pod实例流程运行完以后,需要手动确认继续剩余批次的发布。在调用GetChangeOrderInfo接口返回结果中出现3个流程ID(PipelineId),第二次出现的流程ID(PipelineId)代表需要手动确认继续剩余批次的发布,第三次出现的流程ID(PipelineId)代表剩余批次中第一批完成后需要手动确认继续下一批次的发布。

  3. 调用ContinuePipeline接口,手动确认继续剩余批次发布。

    返回结果如下:

    {
      "Message": "success",
      "RequestId": "B8ECF6F7-672D-40E9-91DD-1C33F06D4FD8",
      "Code": 200
    }
  4. 调用ContinuePipeline接口,手动确认下一批发布。

    返回结果如下:

    {
      "Message": "success",
      "RequestId": "7BB4F043-7C28-4A0E-B6A5-D4023EB24388",
      "Code": 200
    }
    说明

    示例代码中使用的是首批灰度发布2个Pod实例+剩余Pod实例分2批发布+手动分批的金丝雀发布策略,运行到剩余批次发布过程,只需要手动确认一批。如果您是剩余批次需要手动确认多批的场景,请选择正确批次的流程ID(PipelineId)并重复执行此步骤。

    重复执行此步骤时,请等待批次内部署间隔时长,默认10秒。

结果验证

您在金丝雀发布应用后,可以调用GetChangeOrderInfo接口查看变更流程详情,获取金丝雀发布应用的变更状态。具体API参数详情,请参见GetChangeOrderInfo

调用GetChangeOrderInfo接口查看变更流程详情,返回的执行结果如下:

{
    "Message": "success",
    "RequestId": "10DA427D-AF74-4ECE-BB0A-EECC0EBF7548",
    "Code": 200,
    "changeOrderInfo": {
        "Status": 2,
        "Desc": "金丝雀发布(***)",
        "PipelineInfoList": {
            "PipelineInfo": [
                {
                   ......
                   //此处未罗列全部执行结果,仅供参考。

请查看上述执行结果中的changeOrderInfo.Status参数值,通过该值判断金丝雀发布应用的变更是否成功。changeOrderInfo.Status的取值如下:

  • 0:准备

  • 1:执行中

  • 2:执行成功

  • 3:执行失败

  • 6:终止

  • 8:手动分批发布模式下,等待手工确认执行下一批。

  • 9:自动分批发布模式下,等待下一批执行中。

  • 10:系统异常执行失败