使用 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 递增对应一个阶段,还有一个针对 100% 的最终 stable 阶段。

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

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

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

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

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

GKE/企业版

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

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

  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 阶段为 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/企业版

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

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

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

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

  3. 对于每个 Canary 阶段,Cloud Deploy 都会修改 HTTPRoute,以根据该阶段的百分比更新原始 Deployment 的 Pod 和 Canary 部署的 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,没有 traffic 节即可运行普通的 Cloud Run 服务定义文件。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 类似,因为您可以通过自定义阶段名称、百分比值、Skaffold 配置文件和验证作业来指定单独的 Canary 阶段。但使用自定义 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 和服务。

      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 需要使用该配置才能将 Canary 部署到 GKE 和 GKE Enterprise。

      • 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 百分比的 stable 阶段,以及适用于 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 阶段并运行稳定阶段。如需了解发生这种情况的原因,请参阅首次跳过阶段

后续步骤