使用 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 阶段。

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

  • 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 中的 Pod 和 Canary Pod。

    Cloud Deploy 根据此处所述的计算结果,计算要用于 Canary 版的 Pod 数量。具体计算方式取决于您是启用或停用 Pod 超量预配

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

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

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

  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 阶段为 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(其名称为原始 Service 名称加上 -canary)。

    此外,系统还会复制 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 版,您的清单必须包含以下内容:

  • 一项部署和一项服务。

  • 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]

    此外,这不包括 100,因为 100% 部署是在 Canary 中假定的,并由 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,因为 100% 部署是在 Canary 中假定的,并由 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

    • 一个部署

    • 服务

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

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

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

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

      其中...

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

      • SERVICE 是您的 Service 配置,对于 GKE 和 GKE Enterprise 的 Canary 部署,Cloud Deploy 需要使用该配置。

      • DEPLOYMENT 是您的部署配置,对于 GKE 和 GKE Enterprise 的 Canary 部署,Cloud Deploy 需要使用该配置。

      • 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 阶段并运行稳定阶段。如需了解发生这种情况的原因,请参阅第一次跳过阶段

后续步骤