使用 Canary 部署策略

本文档介绍如何配置和使用 Canary 部署策略。

什么是 Canary 部署?

Canary 部署是应用的渐进式发布,在已部署的版本和新版本之间拆分流量,先将其发布给一部分用户,然后再全面发布。

支持的目标类型

Cloud Deploy 中的 Canary 部署支持所有目标类型,包括以下各项:

Canary 还支持多目标

为何使用 Canary 部署策略?

Canary 部署可让您有机会部分发布应用。通过这种方式,您可以确保新版本的应用可靠,然后再将其提供给所有用户。

例如,如果您要部署到 GKE 或 GKE Enterprise,则需要将应用的新版本部署到有限数量的 Pod。旧版本将继续运行,但更多流量会发送到新 Pod。

如果您要部署到 Cloud Run,则 Cloud Run 本身会根据您配置的百分比在旧修订版本和新修订版本之间拆分流量。

Canary 类型

通过 Cloud Deploy,您可以配置以下类型的 Canary 部署:

  • 自动

    通过 自动 Canary 部署,您可以对 Cloud Deploy 进行配置,指定一系列表示渐进式部署的百分比。Cloud Deploy 会代表您执行额外的操作,以便在新旧版本之间分配流量百分比。

  • 自定义自动化

    对于自定义自动化 Canary,您可以提供以下内容:

    • 阶段名称
    • 百分比目标
    • 要用于该阶段的 Skaffold 配置文件
    • 是否包含验证作业

    但是,您无需提供流量平衡信息;Cloud Deploy 会创建必要的资源,如此处所述。

  • 自定义

    通过自定义 Canary,您可以单独配置每个 Canary 阶段,其中包括:

    • 阶段名称
    • 百分比目标
    • 要用于该阶段的 Skaffold 配置文件
    • 是否包含验证作业

    此外,对于完全自定义的 Canary 版,您需要提供所有流量平衡配置,如此处所述。

Canary 部署的各个阶段

当您为 Canary 部署创建版本时,系统会为每个 Canary 增量创建一个发布阶段,并为每个 Canary 增量创建一个阶段,最后创建一个 stable 阶段(针对 100% 部署)。

例如,如果您为某个 Canary 配置了 25%、50% 和 75% 的增量,则发布将分为以下阶段:

  • canary-25
  • canary-50
  • canary-75
  • stable

如需详细了解发布阶段、作业和作业运行,请参阅管理发布

在自动或自定义自动化 Canary 期间会发生什么

为了支持您的 Canary 部署,Cloud Deploy 在呈现 Kubernetes 清单或 Cloud Run 服务配置时包含特殊的处理步骤:

GKE/GKE Enterprise(网络)

下面介绍了 Cloud Deploy 在基于网络的 GKE 和 GKE Enterprise 中执行 Canary 部署的方式:

  1. 您需要提供 Deployment 资源和 Service 资源的名称。

  2. Cloud Deploy 创建一个额外的 Deployment 资源,其中使用当前 Deployment 的名称加 -canary

  3. Cloud Deploy 会修改 Service 以调整选择器,以选择当前 Deployment 和 Canary Pod 中的 Pod。

    Cloud Deploy 根据此处所述的计算方法计算要用于 Canary 的 Pod 数量。该计算方法因您启用或停用 Pod 超额预配而异。

    如果我们正在跳到 stable 阶段,Cloud Deploy 会添加要用于匹配 Pod 的标签,以便这些标签可用于后续的 Canary 运行。

    Cloud Deploy 会创建一个 Deployment,其中包含特定阶段的 Pod 百分比,并针对每个阶段更新此百分比。方法是将 Pod 数量计算为原始 Pod 数量的百分比。这可能会导致流量分配不精确。如果您需要精确的流量分配,可以使用 Gateway API 来实现。

    此外,系统还会复制 Secret 和 ConfigMap,并使用 -canary 对其进行重命名。

  4. stable 阶段,-canary Deployment 会缩减到零,原始 Deployment 会被新的 Deployment 所替换。

    stable 阶段之前,Cloud Deploy 不会修改原始 Deployment。

Cloud Deploy 会预配 Pod,以尽可能接近请求的 Canary 百分比。此费用基于 Pod 的数量,而不是通向 Pod 的流量。如果您希望 Canary 基于流量,则需要使用 Gateway API

对于 GKE 基于网络的 Canary 版,您可以启用或停用 Pod 超额预配。以下部分介绍了 Cloud Deploy 如何计算每个 Canary 阶段为 Canary 部署预配的 Pod 数量。

启用了超额预配的 Pod 预配

启用超额预配 (disablePodOverprovisioning: false) 后,Cloud Deploy 能够创建足够多的额外 Pod,根据运行现有部署的 Pod 数量来运行所需的 Canary 百分比。以下公式展示了在启用 Pod 超额预配的情况下,Cloud Deploy 如何计算每个 Canary 阶段要预配的 Pod 数:

math.Ceil( percentage * ReplicaCountOfDeploymentOnCluster / (100-percentage))

使用此公式,当前副本计数(即您在此 Canary 版之前已拥有的 Pod 数)乘以该阶段的 Canary 百分比,然后除以(100 减去该百分比)所得的结果。

例如,如果有 4 个 Pod,而 Canary 阶段为 50%,则 Canary Pod 的数量为 4。(100-percentage 的结果用作百分比:100-50=50,被视为 .50。)

Pod 超额预配是默认行为。

停用了超额预配的 Pod 预配

您可以停用超额预配 (disablePodOverprovisioning: true),以确保 Cloud Deploy 不会增加副本数量。

以下公式展示了在停用 Pod 超额预配的情况下,Cloud Deploy 如何为每个 Canary 阶段计算 Canary 部署的 Pod 预配:

math.Ceil( (ReplicaCountOfDeploymentOnCluster + ReplicaCountOfCanaryDeploymentOnCluster) * percentage)

在此公式中,仅当已经存在 Canary 阶段时,ReplicaCountOfCanaryDeploymentOnCluster 才存在。如果这是第一个 Canary 阶段,则不存在 ReplicaCountOfCanaryDeploymentOnCluster

如果您从 4 个 Pod 开始,则该数字将乘以 Canary 百分比(例如 50%,或 .5)得到 2。因此,原始部署现已缩减为 2,并为 Canary 部署创建了 2 个新的 Pod。如果您之后有 75% 的 Canary 阶段,则可以使用 2(原始部署)+2(第一个 Canary 阶段)、*.75 来获取运行原始部署的 3 Canary Pod 和 1 Pod。

GKE/GKE Enterprise(网关)

下面展示了 Cloud Deploy 如何使用 Gateway API 在 GKE 和 GKE Enterprise 中执行 Canary 部署:

  1. 除了 Deployment 和 Service 引用外,您还需要提供 HTTPRoute 资源以及引用 Service 的 backendRefs 规则。

  2. Cloud Deploy 会创建一个新的 Deployment(使用原始 Deployment 的名称加上 -canary)以及一项使用原始 Service 名称加上 -canary 的新 Service。

    此外,系统还会复制 Secret、ConfigMap 和横向 Pod 自动扩缩器,并使用 -canary 对其进行重命名。

  3. 对于每个 Canary 阶段,Cloud Deploy 都会修改 HTTPRoute,以根据该阶段的百分比更新原始 Deployment 的 Pod 和 Canary Deployment 的 Pod 之间的权重。

    由于将更改传播到 HTTPRoute 资源会有延迟,因此您可以在配置中添加 routeUpdateWaitTime 属性,以便系统等待指定的时长进行这种传播。

  4. stable 阶段,-canary Deployment 会缩减到零,并且原始 Deployment 会更新以使用新版本的 Deployment。

    此外,HTTPRoute 现在已恢复为您提供的原始网址。

    stable 阶段之前,Cloud Deploy 不会修改原始 Deployment 或 Service。

Cloud Run

Cloud Deploy 为 Cloud Run 执行 Canary 部署,具体如下所示:

  • 对于 Cloud Run 的 Canary 部署,请勿在服务 YAML 中提供 traffic

  • 创建新的 Canary 发布时,Cloud Deploy 会将流量拆分到由 Cloud Deploy 成功部署的上一个修订版本和新修订版本之间。

如果您想要查看 Canary 部署的各个阶段之间的差异,则可以在版本检查器中查看各阶段渲染的清单中的更改。您甚至可以在发布之前执行此操作。此外,如果您使用的是并行部署,还可以检查每个子项呈现的清单。

配置 Canary 部署

本部分介绍如何为 Canary 部署配置交付流水线和目标。

此处的说明仅包含特定于 Canary 配置的内容。部署应用文档提供了有关配置和执行部署流水线的一般说明。

确保您拥有所需的权限

除了使用 Cloud Deploy 所需的其他 Identity and Access Management 权限之外,您还需要以下权限才能执行 Canary 部署所需的其他操作:

  • clouddeploy.rollouts.advance
  • clouddeploy.rollouts.ignoreJob
  • clouddeploy.rollouts.cancel
  • clouddeploy.rollouts.retryJob
  • clouddeploy.jobRuns.get
  • clouddeploy.jobRuns.list
  • clouddeploy.jobRuns.terminate

如需详细了解哪些可用角色包含这些权限,请参阅 IAM 角色和权限

准备您的skaffold.yaml

与标准部署一样,您的 Canary 版需要一个 skaffold.yaml 文件,该文件用于定义清单和服务定义的呈现和部署方式。

除了标准部署的所需要求之外,您为 Canary 部署创建的 skaffold.yaml 没有任何特殊要求。

准备清单或服务定义

与标准部署一样,您的 Canary 需要一个 Kubernetes 清单或 Cloud Run 服务定义。

GKE 和 GKE Enterprise

对于 Canary 版,您的清单必须包含以下内容:

  • Deployment 和 Service。

  • Service 必须定义 app 选择器,且必须选择指定 Deployment 的 Pod。

  • 如果您使用的是基于 Gateway API 的 Canary 版,则清单还必须包含 HTTPRoute

Cloud Run

对于 Cloud Run 上的 Canary 版,使用常规的 Cloud Run 服务定义文件就足够了,但不包含 traffic 节。Cloud Deploy 会为您管理在上次成功的修订版本与新修订版本之间拆分流量的过程。

配置自动化 Canary

以下说明适用于 Cloud Run 和 GKE 以及 GKE Enterprise 基于服务的网络目标。如果您要将 Kubernetes Gateway API 与 GKE 或 GKE Enterprise 搭配使用,请参阅此文档

您可以在交付流水线定义中配置自动化 Canary:

GKE 和 GKE Enterprise

在流水线阶段,请添加 strategy 属性,如下所示:

serialPipeline:
  stages:
  - targetId: prod
    profiles: []
    strategy:
      canary:
        runtimeConfig:
          kubernetes:
            serviceNetworking:
              service: "SERVICE_NAME"
              deployment: "DEPLOYMENT_NAME"
        canaryDeployment:
          percentages: [PERCENTAGES]
          verify: true|false

在此配置中...

  • SERVICE_NAME 是在清单中定义的 Kubernetes Service 的名称。

  • DEPLOYMENT_NAME 是在清单中定义的 Kubernetes Deployment 的名称。

  • PERCENTAGES 是表示 Canary 增量的百分比值列表(以逗号分隔),例如 [5, 25, 50]

    自动化 Canary 最多支持 50 百分比,但不支持更高的百分比。如果您需要高于 50% 的 Canary 阶段,则需要使用 Gateway API 或使用自定义 Canary

    此外,这不包括 100,因为在 Canary 中假定 100% 部署,并且由 stable 阶段处理。

  • 您可以启用部署验证 (verify: true)。如果启用,则每个阶段都会启用一个 verify 作业。

Cloud Run

在流水线阶段,请添加 strategy 属性,如下所示:

serialPipeline:
  stages:
  - targetId: prod
    profiles: []
    strategy:
      canary:
        runtimeConfig:
          cloudRun:
            automaticTrafficControl: true
        canaryDeployment:
          percentages: [PERCENTAGES]
          verify: true|false

在此配置中...

  • PERCENTAGES 是表示 Canary 增量的百分比值列表(以逗号分隔),例如 [25, 50, 75]。请注意,这不包括 100,因为 Canary 中假定 100% 部署,并且由 stable 阶段处理。
  • 您可以启用部署验证 (verify: true)。如果启用,则系统会在每个 Canary 阶段添加一个 verify 作业。

配置自定义 Canary

您可以手动配置 Canary 版,而不是完全依赖 Cloud Deploy 提供的自动化功能。通过自定义 Canary 配置,您可以在交付流水线定义中指定以下内容:

  • 发布阶段名称

    在完全自动化 Canary 中,Cloud Deploy 会为您命名阶段(例如 canary-25canary-75stable)。但是,对于自定义 Canary,您可以为每个阶段指定任何名称,只要该名称在此 Canary 阶段的所有阶段中具有唯一性,并且遵循资源名称限制即可。但是,最终的 (100%) 阶段名称必须为 stable

  • 每个阶段的百分比目标

    按阶段单独指定百分比。

  • 要用于该阶段的 Skaffold 配置文件

    您可以为每个阶段使用单独的 Skaffold 配置文件、使用同一配置文件或任意组合。每个配置文件都可以使用不同的 Kubernetes 清单或 Cloud Run 服务定义。您还可为给定阶段使用多个配置文件。Cloud Deploy 将它们结合起来。

  • 该阶段是否有验证作业

    请注意,如果要启用验证,则还需要configure skaffold.yaml 以进行验证。

自定义 Canary 支持所有目标类型

自定义 Canary 配置元素

以下 YAML 显示了完全自定义 Canary 部署的各个阶段的配置:

strategy:
  canary:
    # Custom configuration for each canary phase
    ​customCanaryDeployment:
      phaseConfigs:
      - phaseId: "PHASE1_NAME"
        percentage: PERCENTAGE1
        profiles: [ "PROFILE_NAME" ]
        verify: true | false
      - …
      - phaseId: "stable"
        percentage: 100
        profiles: [ "LAST_PROFILE_NAME" ]
        verify: true|false

在这个 YAML 中

  • PHASE1_NAME

    是阶段的名称。每个阶段名称都必须是唯一的。

  • [ "PROFILE_NAME" ]

    是用于阶段的配置文件的名称。您可以为每个阶段使用同一配置文件,或为每个阶段使用不同的配置文件,或者任意组合。此外,您还可以指定多个配置文件。Cloud Deploy 会使用您指定的所有配置文件,以及整个阶段使用的配置文件或清单。

  • PERCENTAGE1

    是第一阶段要部署的百分比。每个阶段必须具有唯一的百分比值,并且该值必须是整数百分比(例如,不是 10.5),而且阶段必须按升序排列。

  • verify: true|false

    告知 Cloud Deploy 是否为该阶段添加验证作业。 请注意,对于要使用验证的每个阶段,Skaffold 都会使用同一配置文件来验证为该阶段的渲染和部署指定的配置文件。

  • stable

    最终阶段必须命名为 stable

最后一个阶段的百分比必须为 100。各阶段将按照您在此 ​customCanaryDeployment 节中的配置顺序执行,但如果百分比值并非按升序排列,则注册交付流水线的命令将失败并显示错误。

请注意,自定义 Canary 的配置不包含 runtimeConfig 节。如果您添加 runtimeConfig,则系统会被视为自定义自动化 Canary

配置自定义自动化 Canary

自定义自动化 Canary 与自定义 Canary 类似,因为您指定了单独的 Canary 阶段,包括自定义阶段名称、百分比值、Skaffold 配置文件和验证作业。但是,对于自定义 Canary,您无需提供定义流量分配的配置(Cloud Deploy 会为您执行这项操作),但您仍然提供要用于每个阶段的 Skaffold 配置文件

如需配置自定义自动化 Canary,请添加 runtimeConfig 节(如此处所示),并添加 customCanaryDeployment 节(如此处所示)。

使用 Kubernetes Gateway API 服务网格配置 Canary 部署

虽然您可以使用 Cloud Deploy Canary 部署将应用部署到基于 Kubernetes 服务的网络,但还可以选择使用 Kubernetes Gateway API 服务网格。本部分介绍如何执行此操作。

您可以将 Gateway API 与 Istio 或任何受支持的实现搭配使用。

  1. 设置 Gateway API 资源:

    这些只是示例。

  2. 在创建版本时提供给 Cloud Deploy 的 Kubernetes 清单,添加以下内容:

    • 引用您的网关资源的 HTTPRoute

    • Deployment

    • 服务

  3. 配置交付流水线以及您将进行 Canary 部署的目标:

    • 目标的配置与任何目标的配置相同。

    • 在特定目标的进度序列中,交付流水线配置包括一个 gatewayServiceMesh 节,用于引用您的 Kubernetes Gateway API HTTPRoute 配置以及 Deployment 和服务。

      strategy:
       canary:
         runtimeConfig:
           kubernetes:
             gatewayServiceMesh:
               httpRoute: "ROUTE"
               service: "SERVICE"
               deployment: "DEPLOYMENT"
               routeUpdateWaitTime: "WAIT_TIME"
         canaryDeployment:
           percentages:
           - 50
      

      其中...

      • ROUTE 是您的 httpRoute 配置,用于定义所需的路由行为。

      • SERVICE 是您的 Service 配置,Cloud Deploy 需要该配置才能将 Canary 部署到 GKE 和 GKE Enterprise。

      • DEPLOYMENT 是您的 Deployment 配置,这是 Cloud Deploy 对 GKE 和 GKE Enterprise 进行 Canary 部署时需要用到的配置。

      • WAIT_TIME 是 Cloud Deploy 等待对 HTTPRoute 资源的更改完成传播所需的时间,以避免请求被丢弃。例如:routeUpdateWaitTime: 60s

        如果您在不使用 Istio 的情况下使用 Gateway API 运行 Canary 版,并且 Gateway API 已连接到 Google Cloud 负载均衡器,则在 Canary 版实例缩减时,可能会丢失少量流量。如果您观察到这种行为,可以配置此设置。

将并行部署与 Canary 部署策略结合使用

您可以使用并行部署运行 Canary 部署。 这意味着,您逐步部署到的目标可以包含两个或更多个子目标。例如,您可以同时逐步部署到不同区域中的集群。

并行 Canary 与单目标 Canary 有何不同

  • 与单目标 Canary 部署一样,如果您要部署到 GKE 目标,则需要在清单中提供 Kubernetes Deployment 配置和 Kubernetes Service 配置。

  • 与单目标 Canary 部署一样,您的交付流水线配置必须在适用阶段的阶段定义内包含一个 strategy.canary 节。

  • 此外,您需要配置多目标,并且需要配置该多目标引用的子目标

  • 当您创建版本时,系统会创建控制器发布子发布

    两种发布类型(控制器发布和子级发布)都针对已配置的所有 Canary 百分比都有单独的阶段,而针对 Canary 100% 的发布则有 stable 阶段。

  • 您无法推进子发布。

    您只能推进控制器发布。当您将控制器发布推进到下一阶段时,子发布也会通过 Cloud Deploy 推进。

  • 您无法重试控制器发布中失败的作业。

    您只能在子发布时重试作业。

  • 您无法ignore控制器发布中失败的作业。

    您只能在子发布中忽略失败的作业。

  • 您可以取消控制器发布,但无法取消子发布。

  • 您只能在子发布下终止作业运行,不能在控制器发布下终止。

如果并行发布在 Canary 中失败,该怎么办

当子发布失败时,控制器发布可以转换为不同的状态,具体取决于子发布的情况:

  • 如果一个或多个子发布失败,但至少有一个子发布仍为 IN_PROGRESS,则控制器发布仍为 IN_PROGRESS

  • 如果一个或多个子发布失败,但至少有一个子发布成功,并且当前子发布之后还有更多阶段,则控制器发布为 HALTED

    如果这是 stable 阶段,则控制器发布为 FAILED

    借助 HALTED,您可以ignore重试失败的子发布,或者取消控制器发布并阻止对子发布执行进一步操作。

  • 如果控制器发布因子发布失败而处于 HALTED 状态,并且您忽略了子发布中失败的作业,则控制器发布会还原为 IN_PROGRESS 状态。

执行已配置的 Canary

如需运行 Canary 部署,请执行以下操作:

  1. 注册已配置的交付流水线和目标。

    gcloud deploy apply --file=PIPELINE
    

    交付流水线包含适用于您所选运行时的自动或自定义 Canary 配置。

    此命令假定您的目标已在同一文件中定义,或者已以其他方式注册。否则,请务必注册目标。

  2. 创建版本:

    gcloud deploy releases create RELEASE_NAME \
                                  --delivery-pipeline=PIPELINE_NAME \
                                  --region=REGION
    

    PIPELINE_NAME 标识的交付流水线包含本文档中所述的自动或自定义 Canary 配置。

  3. 推进 Canary 部署:

    gcloud CLI

    gcloud deploy rollouts advance ROLLOUT_NAME \
                                --release=RELEASE_NAME \
                                --delivery-pipeline=PIPELINE_NAME \
                                --region=REGION
    

    其中:

    ROLLOUT_NAME 是要推进到下一阶段的当前发布作业的名称。

    RELEASE_NAME 是此发布所属版本的名称。

    PIPELINE_NAME 是您用于管理此版本部署的交付流水线的名称。

    REGION 是在其中创建版本的区域的名称,例如 us-central1。这是必填项。

    如需详细了解 gcloud deploy rollouts advance 命令,请参阅 Google Cloud SDK 参考文档。

    Google Cloud 控制台

    1. 打开“交付流水线”页面

    2. 点击交付流水线列表中显示的流水线。

      交付流水线详情页面以图形方式展示交付流水线进度。

    3. 发布作业标签页的交付流水线详情下,点击发布作业的名称。

      系统会显示该发布的发布详情页面。

      Google Cloud 控制台中的发布详情

      请注意,在此示例中,发布包含 canary-50 阶段和 stable 阶段。您的发布可能会有多个阶段或不同的阶段。

    4. 点击推进发布

      发布工作已进入下一阶段。

跳过的阶段

如果您已部署 Canary 版,但您的应用尚未部署到该运行时,则 Cloud Deploy 会跳过 Canary 阶段并运行稳定阶段。请参阅第一次跳过阶段,了解发生这种情况的原因。

后续步骤