使用 Spinnaker 在 Google Kubernetes Engine 上执行自动化 Canary 分析

本教程将指导您在 Google Kubernetes Engine (GKE) 上配置 Spinnaker 的自动化 Canary 分析功能。

简介

Spinnaker 是一个由 Netflix 和 Google 领导开发的开源持续交付系统,用于管理不同计算平台上的应用部署,包括 App Engine、GKE、Compute Engine、AWS 和 Azure。使用 Spinnaker,您可以实现各种高级部署方法,包括 Canary 部署。

在 Canary 部署中,您可以在全面部署一个应用新版本之前,将其公开给一小部分生产流量并分析应用的行为。这样可以在将新版本部署到所有用户之前降低风险。如需使用 Canary 部署,您必须准确地对比应用的旧版本和新版本的行为。差异可能并不明显,并且可能需要一些时间才会显现。此外,您可能还需要检查许多不同的指标。如需详细了解 Canary 模式,请参阅应用部署和测试策略

为了解决这些问题,您可以使用 Spinnaker 的自动化 Canary 分析功能。此功能从您的监控系统读取新旧两个版本的指标,并运行统计信息分析进行自动对比。本教程介绍如何对部署在 GKE 上并由 Cloud Monitoring 进行监控的应用进行自动化 Canary 分析。

Spinnaker 是一个高级应用部署和管理平台,适用于具有复杂部署场景的组织,这些组织通常拥有专门的发布工程职能团队。虽然您可以在没有 Spinnaker 经验的情况下运行本教程,但通常情况下,在生产环境中实现自动化 Canary 分析是由拥有 Spinnaker 经验、强大的监控系统以及知道如何确定版本是否安全的团队完成的。

关于本教程

本教程中的应用是一个简单的“Hello World”应用,其错误率使用了环境变量进行配置。本教程为此应用提供了预构的 Docker 映像。如下图所示,此应用公开了 Prometheus 格式的指标。Prometheus 是一种 Kubernetes 社区常用的开源监控系统,与 Cloud Monitoring 兼容。

应用架构

目标

  • 安装适用于 Google Cloud 的 Spinnaker。
  • 在没有 Canary 部署的情况下将应用部署到 GKE。
  • 配置并运行应用的 Canary 部署。
  • 配置自动化 Canary 分析。
  • 测试自动化 Canary 分析。

费用

准备工作

  1. 选择或创建 Google Cloud 项目。

    转到“管理资源”页面

  2. 为您的项目启用结算功能。

    启用结算功能

  3. 创建工作区。

    转到 Monitoring 文档

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

使用 Cloud Shell 部署适用于 Google Cloud 的 Spinnaker

在本部分中,您将配置完成本教程所需的基础架构。请从 Cloud Shell 运行本教程中的所有终端命令。

适用于 Google Cloud 的 Spinnaker 针对 Google Cloud 进行了优化,可让您在支持生产环境的配置中设置和管理 Spinnaker。借助帮助程序和常见工具(如 spinhal),适用于 Google Cloud 的 Spinnaker 可设置在 Google Cloud 中运行 Spinnaker 所需的许多资源(GKE、Memorystore、Cloud Storage 存储分区和服务帐号),将 Spinnaker 与相关服务(如 Cloud Build)集成,并为 Spinnaker 的安装提供基于 Cloud Shell 的管理环境。

  1. 在 Cloud Shell 中,打开适用于 Google Cloud 的 Spinnaker。这会将适用于 Google Cloud 的 Spinnaker 代码库克隆到 Cloud Shell 环境中并启动详细的安装说明。

    转到 Cloud Shell

  2. 安装适用于 Google Cloud 的 Spinnaker:

    PROJECT_ID=${DEVSHELL_PROJECT_ID} ~/cloudshell_open/spinnaker-for-gcp/scripts/install/setup_properties.sh
    ~/cloudshell_open/spinnaker-for-gcp/scripts/install/setup.sh
    
  3. 安装 Monitoring-Prometheus 集成插件

    export KUBE_NAMESPACE=prometheus
    export GCP_PROJECT=$DEVSHELL_PROJECT_ID
    export DATA_DIR=/prometheus/
    export DATA_VOLUME=prometheus-storage-volume
    export SIDECAR_IMAGE_TAG=0.7.0
    export GCP_REGION=us-east1-c
    export KUBE_CLUSTER=spinnaker-1
    
    kubectl create namespace ${KUBE_NAMESPACE}
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/prometheus-stackdriver-gke/master/prometheus-service-account.yaml
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/prometheus-stackdriver-gke/master/prometheus-configmap.yaml
    curl -sS https://raw.githubusercontent.com/GoogleCloudPlatform/prometheus-stackdriver-gke/master/gke-prometheus-deployment.yaml | \
      envsubst | \
      kubectl apply -f -
    
  4. 重启 Cloud Shell 以加载新的环境设置。

    Cloud Shell 重启菜单选项。

  5. 连接到 Spinnaker:

    ~/cloudshell_open/spinnaker-for-gcp/scripts/manage/connect_unsecured.sh
    
  6. 在 Cloud Shell 中,选择网页预览图标,然后选择在端口 8080 上预览

    菜单中的 Cloud Shell 重启选项

使用 Spinnaker 部署应用

在本部分中,您将配置 Spinnaker 以在 GKE 集群中部署应用。

创建 Spinnaker 应用

部署之前,请创建 Spinnaker 应用。

  1. 在 Spinnaker 中,选择操作,然后选择创建应用

    创建应用下拉菜单

  2. 新建应用对话框中,输入以下值:

    • 名称sampleapp
    • 所有者电子邮件[example@example.com]

  3. 选择创建

您现在位于 Spinnaker 的 sampleapp 中。它尚未配置,因此大多数标签页都是空的。

创建并运行部署流水线

在本部分中,您首先使用简单的 Spinnaker 流水线部署应用,该流水线会使用 successRate 参数创建具有四个 pod 的 GKE 部署。这些 pod 以与 successRate 参数对应的速率随机抛出错误。在本教程中,它们以 100 - successRate 的速率抛出 500 个错误。

  1. 在 Cloud Shell 中,使用提供的 JSON 文件创建流水线。以下命令将流水线的 JSON 定义直接发布到 Spinnaker API。

    cd ~
    wget https://raw.githubusercontent.com/spinnaker/spinnaker/master/solutions/kayenta/pipelines/simple-deploy.json
    sed "s/my-kubernetes-account/spinnaker-install-account/g" simple-deploy.json > updated-simple-deploy.json
    spin pipeline save --file updated-simple-deploy.json
    
  2. 在 Spinnaker 的“流水线”部分中,会出现一个名为 Simple deploy 的流水线。如果您没有看到此流水线,请重新加载页面。选择开始手动执行

    开始手动执行 Simple deploy 流水线

  3. 确认执行窗口中,将成功率选择为 70,然后选择运行。几秒钟后,流水线会成功部署应用和四个 pod 的配置。

  4. 在 Cloud Shell 中,创建一个在教程结束前向新应用发出请求的 pod。

    kubectl -n default run injector --generator=run-pod/v1 --image=alpine:3.10 -- \
        /bin/sh -c "apk add --no-cache curl; \
        while true; do curl -sS --max-time 3 \
        http://sampleapp:8080/; done"
    

检查注入器日志

  1. 如需查看应用的行为,请检查注入器日志:

    kubectl -n default logs -f \
        $(kubectl -n default get pods -l run=injector \
        -o=jsonpath='{.items[0].metadata.name}')
    
  2. 日志中会显示大量内部服务器错误消息。如需停止关注注入器日志,请按 Ctrl+C

检查应用的运行状况

在您的应用已部署并服务流量后,请查看它是否正常运行。当然,在本教程中,您已经知道它不会正常运行,因为您部署应用时设置的成功率仅为 70%。

该应用公开一个 /metrics 端点,其中包含 Prometheus 格式的指标,这些指标由 Monitoring 提取。在本部分中,您可以在 Monitoring 中可视化这些指标。

  1. 在 Google Cloud Console 中,转到 Monitoring

    转至 Monitoring

  2. 如果导航窗格中显示 Metrics Explorer,请选择 Metrics Explorer。否则,请选择 资源,然后选择 Metrics Explorer

  3. 确保所选标签页为指标

  4. 选中标有查找资源类型和指标的框,然后输入 external.googleapis.com/prometheus/requests

  5. 如需优化图表,请在分组依据字段中输入 http_code

    在下图中,应用应答的 HTTP 请求率按 HTTP 状态代码分组:

    应用响应的 HTTP 请求图表

    如果 Monitoring 中没有您的任何数据,或者您找不到 external.googleapis.com/prometheus/requests 指标,请等待几分钟再重新加载 Metrics Explorer,以便 Monitoring 提取数据。

    如图表所示,应用目前具有不可接受的错误率(约 30%),这与预期相同。本教程的其余部分将指导您完成 Canary 部署流水线的设置和自动化分析,以防止将来部署具有如此高错误率的应用。

创建 Canary 部署

在本部分中,您将创建一个不含自动化分析的 Canary 部署流水线,从而在将应用完全部署到生产环境之前测试该应用的新版本。为简单起见,您在本部分创建的流水线依赖于 Kubernetes 负载平衡来将流量发送到 Canary 版本。因此,您无法选择将哪部分流量路由到 Canary 版本。要实现高级流量路由政策,您可以使用 Istio

下图展示了此流水线的不同阶段:

Canary 部署流水线的阶段图示

  • 步骤 0:与“Simple Deploy”流水线一样,此流水线将“Success Rate”参数作为输入。这个新流水线使用此参数来模拟不同的成功率。这是此流水线的配置

  • 步骤 1:“Find Baseline Version”阶段从最新执行的“Simple Deploy”流水线中检索生产环境中运行的应用的当前版本。在本教程中,它将检索当前部署的应用的成功率。

    在“Find Baseline Version”阶段的同时,“Deploy Canary Config”阶段为应用的 Canary 版本部署新的成功率配置

  • 步骤 2:“Deploy Canary”和“Deploy Baseline”阶段会部署新的 Canary 版本和基准版本这两个版本以进行对比。 Canary 版本使用“Deploy Canary Config”阶段创建的配置,而基准版本使用正式版本使用的配置

  • 步骤 3:“Manual Judgment”阶段将停止流水线,直到您选择继续。在此阶段,您可以检查 Canary 版本是否正常运行。

  • 步骤 4:当完成“Manual Judgment”阶段并选择继续时,“Delete Canary”和“Delete Baseline”阶段均会清理基础架构。

    在清理的同时,“Deploy to Production”阶段将会启动并使用您最初提供的“Success Rate”参数触发“Simple Deploy”流水线。您在 Canary 中测试的应用的同一版本将部署到生产环境中。

    只有在“Manual Judgement”阶段选择“Continue”,才会触发“Deploy to Production”阶段。

  • 步骤 5:最后,“Successful Deployment”阶段将验证整个流水线是否成功。它会检查您是否在“Manual Judgement”阶段中选择了继续,并且仅在“Deploy to Production”、“Delete Canary”和“Delete Baseline”阶段均成功执行时才会执行

现在,您可以创建并运行“Canary Deploy”流水线。

  1. 如需创建“Canary Deploy”流水线,请运行以下命令以获取“Simple deploy”流水线的 ID 并将其注入“Canary Deploy”流水线:

    cd ~
    wget https://raw.githubusercontent.com/spinnaker/spinnaker/master/solutions/kayenta/pipelines/canary-deploy.json
    export PIPELINE_ID=$(spin pipeline get -a sampleapp -n 'Simple deploy' | jq -r '.id')
    jq '(.stages[] | select(.refId == "9") | .pipeline) |= env.PIPELINE_ID | (.stages[] | select(.refId == "8") | .pipeline) |= env.PIPELINE_ID' canary-deploy.json | \
        sed "s/my-kubernetes-account/spinnaker-install-account/g" > updated-canary-deploy.json
        spin pipeline save --file updated-canary-deploy.json
    
  2. 如果在 Spinnaker 中没有看到“Canary Deploy”流水线,请重新加载 sampleapp 页面,然后点击 Pipelines

  3. 如需启动“Canary Deploy”流水线,请执行以下操作:

    1. 选择开始手动执行
    2. 成功率选为 80
    3. 选择运行
  4. 当流水线到达 Manual Judgment 阶段时,先不要选择继续,因为您需要将 Canary 版本与基准版本进行对比。

    Canary 流水线的 Manual Judgement 阶段

  5. 在 Cloud Shell 中,运行 kubectl -n default get pods 命令以查看标记为 canarybaseline 的新 pod:

    NAME                                READY STATUS  RESTARTS  AGE
    injector-66bd655ffd-9ntwx           1/1   Running 0         30m
    sampleapp-5cdf8f55dd-995rz          1/1   Running 0         28m
    sampleapp-5cdf8f55dd-dqq8n          1/1   Running 0         28m
    sampleapp-5cdf8f55dd-ntq57          1/1   Running 0         28m
    sampleapp-5cdf8f55dd-rlpzp          1/1   Running 0         28m
    sampleapp-baseline-567b8d6849-gsgqr 1/1   Running 0          4m
    sampleapp-canary-54b9759dd6-gmjhc   1/1   Running 0          4m
    
  6. 在 Google Cloud Console 中,转到 Monitoring

    转至 Monitoring

  7. 如果导航窗格中显示 Metrics Explorer,请选择 Metrics Explorer。否则,请选择 资源,然后选择 Metrics Explorer

  8. 确保所选标签页为指标

  9. 如需显示基准和 Canary 的错误率,请指定以下参数:

    1. 指标external.googleapis.com/prometheus/requests
    2. 过滤条件
      1. http_code 等于 500
      2. version 不等于(!=) prod

    如果 Monitoring 缺失某些数据,请等待几分钟以使其显示出来。

  10. 比较 Canary 版本(下图中的紫色部分)与基准版本(下图中的蓝色部分)。请注意,您的图表中的颜色可能有所不同。在本教程中,Canary 版本的错误率低于基准版本。因此,将 Canary 版本完全部署到生产环境中是安全的。如果 Canary 版本没有更低的错误率,您可能希望在此阶段停止部署并对应用进行一些更正。

    Canary 版本与基准版本的错误率对比图表

  11. 在 Spinnaker 的 Manual Judgement 对话框中,选择 Continue

  12. 部署完成后,返回到 Monitoring

    转至 Monitoring

  13. 如果导航窗格中显示 Metrics Explorer,请选择 Metrics Explorer。否则,请选择 资源,然后选择 Metrics Explorer

  14. 确保所选标签页为指标

  15. 选择标有查找资源类型和指标的框,然后从菜单中选择或者输入资源和指标的名称。使用以下信息填写此文本框的各个字段:

    1. 对于指标,请选择或输入 external.googleapis.com/prometheus/requests
    2. 分组依据字段中,输入 http_code

    在下图中,应用的 HTTP 请求响应率按 HTTP 状态代码划分:

    HTTP 请求率对比图表

    此图显示所有 pod 的 HTTP 代码 200 和 500 的代码率,包括生产、基准和 Canary。由于 Canary 版本的错误率较低,因此您将其部署于生产环境中。在部署期间的一小段时间后,请求总数略微降低,您可以看到整体错误率也在降低,这意味着 Canary 版本已正确部署于生产环境中。

自动化 Canary 分析

Canary 部署很有用,但它的当前配置方式是手动过程。在进行全面部署之前,您必须手动检查 Canary 是否符合您的要求,并且 Canary 版本和基准版本之间的差异并不总是那么明显。

自动化 Canary 分析是一个好办法。如此一来,您不必自己动手,并且自动化统计信息分析比人类更适合检测一组指标中的问题。在本部分中,“Manual Judgement”阶段由自动化 Canary 分析代替。

启用 Canary 支持

首先,在 Spinnaker 中,您可以配置名为 Kayenta 的自动化 Canary 分析功能。如需配置 Kayenta,请使用 Halyard,这是配置和部署 Spinnaker 的同一工具。

  1. 配置 Kayenta,将 Monitoring 用作后端:

    hal config canary google enable
    hal config canary google account add kayenta-tutorial --project $DEVSHELL_PROJECT_ID
    hal config canary google edit --stackdriver-enabled=true
    
  2. 应用新配置:

    ~/cloudshell_open/spinnaker-for-gcp/scripts/manage/push_and_apply.sh
    

    部署需要几分钟才能完成。

配置自动化 Canary 分析功能

现在,Kayenta 已启用,请为 sampleapp 配置 Kayenta。

  1. 在 Spinnaker 中,选择配置

  2. 功能部分中,勾选 Canary,然后选择保存更改

    流水线功能的屏幕截图

创建 Canary 配置

在 Spinnaker 中,自动化 Canary 分析针对不同指标运行统计信息测试并输出得分。此得分的范围为 0 到 100,表示通过或未通过基准和 Canary 之间的对比的指标数。您可以通过将指标分为不同的分组,并为每个组分配不同的权重,从而影响得分。根据分析的得分,您可以决定继续部署或停止部署。如果您像本教程中所示一样使用单个指标,则得分只能为 0(未通过)或 100(通过)。

一个应用可以有多个 Canary 配置,并在多个应用之间共享。Canary 配置有两个主要元素:

  • 需要分析的一组指标(可能在不同的组中)。
  • 得分的边界和通过阈值。

在部署流水线中,Canary 配置用于“Canary Analysis”阶段。这个阶段可以包括多次 Canary 运行。如果任意一次运行的得分低于边界阈值,则停止该阶段并且不执行其他运行。最后一次运行的得分需要高于整个阶段的通过阈值才能被视为成功通过。

如需创建 Canary 配置,请按照下列步骤操作:

  1. 现在 Canary 已启用,流水线部分将替换为交付。如果您没有看到交付部分,请重新加载 Spinnaker。在交付部分中,转到 Canary 配置
  2. 选择添加配置
  3. 对于配置名称,输入 kayenta-test
  4. 指标部分中,选择添加指标
  5. 添加指标对话框中,输入以下值,然后选择确定

    • 名称error_rate
    • 失败条件increase
    • 资源类型k8s_container
    • 指标类型external.googleapis.com/prometheus/requests
    • 校准器ALIGN_RATE
    • 过滤器模板:选择新建

      • 对于新过滤器模板的名称,请输入:http_code
      • 对于新过滤器模板的模板,请输入:metric.labels.http_code = "500" AND resource.label.pod_name = starts_with("${scope}")
      • 选择保存
  6. 得分部分中,将群组 1 设置为 100

  7. 选择保存更改

将 Canary 分析阶段添加到流水线中

现在您已经拥有了 Canary 配置,接下来您可以修改现有的部署流水线,用一个使用此配置的“Canary Analysis”阶段替换“Manual Judgement”阶段。

  1. 转到交付 > 流水线,针对 Canary Deploy 流水线,选择配置

    Canary 部署的配置按钮的屏幕截图。

  2. 选择添加阶段

  3. 类型中,选择 Canary 分析

  4. 决定条件部分中,修改新阶段以使其取决于以下选择:

    • 部署 Canary 版本
    • 部署基准版本
  5. 使用以下值填写 Canary 分析配置部分:

    参数名称 定义
    分析类型 实时(手动) 为您创建了 Canary 和基准的自动模式尚不可用于 Kubernetes。
    配置名称 kayenta-test 您之前创建的 Canary 配置的名称。
    生命周期 0 小时 5 分钟 Canary 分析应持续的时长。
    延迟 0 在进行分析之前为应用设置的预热时间。
    间隔时间 5 Kayenta 应使用以进行单个统计信息分析的时间窗口。
    基准 sampleapp-baseline Kayenta 应用作基准的 GKE 部署。
    基准位置 默认 基准所在的 GKE 命名空间。
    Canary sampleapp-canary Kayenta 应用作 Canary 的 GKE 部署。
    Canary 位置 默认 Canary 所在的 GKE 命名空间。
    边界 75 边界 Canary 通过的阈值分数。
    通过 95 总体 Canary 通过的阈值分数。
  6. 执行选项部分中,选择忽略失败。选择忽略失败,是为了即使 Canary 分析失败,您也可以销毁基准版本和 Canary 版本。在本教程的后半部分,您将修改该阶段,以将潜在的 Canary 失败考虑在内。

  7. 在流水线架构中,选择部署到生产环境

    流水线的“部署到生产环境”按钮的屏幕截图

  8. 决定条件部分更改为以下参数:

    1. 添加 Canary Analysis
    2. 移除 Manual Judgement
  9. 如需确保仅在 Canary 分析成功时部署到生产环境,请更改条件表达式参数。

    ${ #stage('Canary Analysis')['status'].toString() == 'SUCCEEDED'}
    
  10. 在流水线架构中,选择删除 Canary,然后将决定条件部分更改为以下参数:

    1. 添加 Canary Analysis
    2. 移除 Manual Judgement
  11. 在流水线架构中,选择删除基准,然后更改决定条件部分:

    1. 添加 Canary Analysis
    2. 移除 Manual Judgement
  12. 如果需要在 Canary 分析失败时确保整个流水线失败,请在流水线架构中选择成功部署,然后在现有前提条件下选择修改图标。

    修改成功部署的现有前提条件

    1. 表达式更改为以下内容:

      ${ #stage('Canary Analysis')['status'].toString() == 'SUCCEEDED'}
      
    2. 选择 Update(更新)。

  13. 完成使用新创建的“Canary Analysis”阶段替换“Manual Judgement”阶段的操作

    1. 在流水线架构中,选择 Manual Judgement
    2. 选择移除阶段
  14. 选择保存更改

    您的流水线现在如下图所示:

    可视化 Canary 分析流水线。

测试新流水线

现在,自动化 Canary 分析已完成配置,接下来您可以测试该流水线以确保其行为符合预期。

  1. 转到交付 > 流水线,针对 Canary Deploy 流水线或自动化 Canary 部署(如果使用 CLI),请选择开始手动执行

  2. 成功率选为 60,然后选择运行

  3. 如需检查 Canary 分析的当前进度,请选择 Canary 分析,然后选择任务状态。几分钟后,Canary Analysis 阶段失败,因为当前生产环境中的成功率为 80。当 Canary Analysis 阶段失败时,请转至此 Canary 分析的报告。

    1. 选择 Canary 分析
    2. 选择 Canary 摘要
    3. 选择报告图标。

      在报告页面上,会发现 Canary 版本的错误率高于基准版本的错误率。

      Canary 分析摘要的报告图标

  4. 重复本部分中的步骤,将成功率选为 90 以实现成功的 Canary 分析。

清理

为避免因本教程中使用的资源而导致您的 Google Cloud Platform 帐号产生费用,请执行以下操作:

  1. 在 Cloud Console 中,转到管理资源页面。

    转到“管理资源”页面

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除资源

如果您希望保留在本教程中使用的 Google Cloud 项目,请删除单个资源:

  1. 删除 GKE 集群。

    gcloud container clusters delete spinnaker-1
    
  2. 当系统提示确认时,键入 Y

后续步骤