使用 Git 分支和 Cloud Build 实现 Cloud Run Canary 部署

Last reviewed 2023-05-26 UTC

本文档介绍如何实现 Cloud Run 的部署流水线,该流水线通过自动执行 Canary 版测试和基于百分比的流量管理来实现从开发者分支到生产环境的一系列代码。该文档适用于负责创建和管理 CI/CD 流水线的平台管理员。本文档假定您对 Git、Cloud Run 和 CI/CD 流水线概念有基本的了解。

借助 Cloud Run,您只需很少的开销或精力即可部署和运行应用。许多组织使用强大的发布流水线将代码投入生产。Cloud Run 提供独特的流量管理功能,可让您轻松地实现高级发布管理技术。

目标

  • 创建 Cloud Run 服务
  • 启用开发者分支
  • 实现 Canary 版测试
  • 安全地部署到生产环境中

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

准备工作

  1. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  2. 确保您的 Google Cloud 项目已启用结算功能

  3. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

    Cloud Shell 会话随即会在 Google Cloud 控制台的底部启动,并显示命令行提示符。Cloud Shell 是一个已安装 Google Cloud CLI 且已为当前项目设置值的 Shell 环境。该会话可能需要几秒钟时间来完成初始化。

准备环境

  1. 在 Cloud Shell 中,创建在本教程中使用的环境变量:

    export PROJECT_ID=$(gcloud config get-value project)
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
    
  2. 启用以下 API:

    • Resource Manager
    • GKE
    • Cloud Build
    • Container Registry
    • Cloud Run
    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        secretmanager.googleapis.com \
        cloudbuild.googleapis.com \
        containerregistry.googleapis.com \
        run.googleapis.com
    
  3. 将 Cloud Run Admin 角色 (roles/run.admin) 授予 Cloud Build 服务账号

    gcloud projects add-iam-policy-binding $PROJECT_ID \
      --member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
      --role=roles/run.admin
    
  4. 将 IAM Service Account User 角色 (roles/iam.serviceAccountUser) 授予 Cloud Run 运行时服务账号的 Cloud Build 服务账号

    gcloud iam service-accounts add-iam-policy-binding \
    $PROJECT_NUMBER-compute@developer.gserviceaccount.com \
      --member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
      --role=roles/iam.serviceAccountUser
    

设置 Git 值

如果您以前没有在 Cloud Shell 中使用 Git,请设置要使用的 user.nameuser.email 值:

    git config --global user.email YOUR_EMAIL_ADDRESS
    git config --global user.name YOUR_USERNAME
    git config --global credential.helper store
  • YOUR_EMAIL_ADDRESS:与您的 GitHub 账号搭配使用的电子邮件地址
  • YOUR_USERNAME:您的 GitHub 用户 ID

如果您将 MFA 与 GitHub 搭配使用,请创建个人访问令牌,并在通过命令行与 GitHub 交互时将其用作密码。

将 GitHub 用户 ID 存储在环境变量中,以便于访问:

export GH_USER=YOUR_GITHUB_ID

克隆项目代码库

如需创建您自己的可写版本的实验代码库,请通过 GitHub 界面将示例代码库克隆到 GitHub 账号中。

克隆示例代码库

克隆并准备示例代码库:

git clone https://github.com/$GH_USER/software-delivery-workshop.git cloudrun-progression

cd cloudrun-progression/labs/cloudrun-progression

连接您的 Git 代码库。

借助 Cloud Build,您可以使用 Google Cloud 控制台创建和管理与源代码库的连接。您可以使用第一代或第二代 Cloud Build 代码库创建和管理连接。本教程使用第二代 Cloud Build 代码库。

授予所需的权限

如需连接您的 GitHub 主机,请将 Cloud Build Connection Admin (roles/cloudbuild.connectionAdmin) 角色授予您的用户账号:

PN=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")
CLOUD_BUILD_SERVICE_AGENT="service-${PN}@gcp-sa-cloudbuild.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
 --member="serviceAccount:${CLOUD_BUILD_SERVICE_AGENT}" \
 --role="roles/secretmanager.admin"

创建主机连接

  1. 配置 Cloud Build 代码库连接:

    gcloud alpha builds connections create github $GH_USER --region=us-central1
    
  2. 点击输出中提供的链接,然后按照屏幕上的说明完成连接。

  3. 验证 GitHub 连接的安装:

    gcloud alpha builds connections describe $GH_USER --region=us-central1
    

使用您刚刚配置的主机连接,关联您克隆的示例代码库:

 gcloud alpha builds repositories create cloudrun-progression \
     --remote-uri=https://github.com/$GH_USER/software-delivery-workshop.git \
     --connection=$GH_USER \
     --region=us-central1

设置代码库名称变量

存储代码库名称以备后用:

export REPO_NAME=projects/$PROJECT_ID/locations/us-central1/connections/$GH_USER/repositories/cloudrun-progression

部署 Cloud Run 服务

在本部分中,您将构建和部署在本教程中使用的初始生产应用。

部署该服务

  • 在 Cloud Shell 中,构建和部署应用,包括需要身份验证的服务。如需提供公共服务,请使用 --allow-unauthenticated 标志

        gcloud builds submit --tag gcr.io/$PROJECT_ID/hello-cloudrun
    
        gcloud run deploy hello-cloudrun \
          --image gcr.io/$PROJECT_ID/hello-cloudrun \
          --platform managed \
          --region us-central1 \
          --tag=prod -q
    

    输出如下所示:

    Deploying container to Cloud Run service [hello-cloudrun] in project [sdw-mvp6] region [us-central1]
    ✓ Deploying new service... Done.
      ✓ Creating Revision...
      ✓ Routing traffic...
    Done.
    Service [hello-cloudrun] revision [hello-cloudrun-00001-tar] has been deployed and is serving 100 percent of traffic.
    Service URL: https://hello-cloudrun-apwaaxltma-uc.a.run.app
    The revision can be reached directly at https://prod---hello-cloudrun-apwaaxltma-uc.a.run.app
    

输出包括服务网址和修订版本的唯一网址。您的值将与此处所示的值略有不同。

验证部署

  1. 部署完成后,在 Cloud 控制台中的修订版本页面上查看新部署的服务。

  2. 在 Cloud Shell 中,查看经过身份验证的服务响应:

    PROD_URL=$(gcloud run services describe hello-cloudrun --platform managed --region us-central1 --format=json | jq --raw-output ".status.url")
    
    echo $PROD_URL
    
    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $PROD_URL
    

启用分支部署

在本部分中,您将为 Git 中的开发分支启用唯一网址。

设置分支触发器

每个分支都由一个由分支名称标识的网址表示。提交到分支的操作会触发部署,并且可以通过同一网址访问更新。

  1. 在 Cloud Shell 中,设置触发器:

    gcloud alpha builds triggers create github \
    --name=branchtrigger \
    --repository=$REPO_NAME \
    --branch-pattern='[^(?!.*main)].*' \
    --build-config=labs/cloudrun-progression/branch-cloudbuild.yaml \
    --region=us-central1
    
  2. 如需查看触发器,请进入 Cloud 控制台中的 Cloud Build 触发器页面

在分支上创建更改

  1. 在 Cloud Shell 中,创建一个新的分支:

    git checkout -b new-feature-1
    
  2. 使用您喜爱的编辑器或使用 Cloud Shell IDE 打开示例应用:

    edit app.py
    
  3. 在示例应用中,将第 24 行修改为指示 v1.1 而不是 v1.0:

    @app.route('/')
    
    def hello_world():
        return 'Hello World v1.1'
    
    
  4. 如需返回终端,请点击“打开终端”。

执行分支触发器

  1. 在 Cloud Shell 中,提交更改并推送到远程代码库:

    git add . && git commit -m "updated" && git push origin new-feature-1
    
  2. 如需查看正在进行的构建,请前往 Cloud Build 构建记录屏幕

  3. 如需查看新修订版本,请在构建完成后进入 Cloud 控制台中的 Cloud Run 修订版本页面

  4. 在 Cloud Shell 中,获取此分支的唯一网址:

    BRANCH_URL=$(gcloud run services describe hello-cloudrun --platform managed --region us-central1 --format=json | jq --raw-output ".status.traffic[] | select (.tag==\"new-feature-1\")|.url")
    
    echo $BRANCH_URL
    
  5. 访问经过身份验证的网址:

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $BRANCH_URL
    

    更新后的响应输出如下所示:

    Hello World v1.1
    

自动执行 Canary 版测试

在代码发布到生产环境后,通常先将代码发布到一小部分实时流量,然后再将所有流量迁移到新的代码库。

在本部分中,您将实现一个触发器,该触发器会在代码提交到主分支时激活。该触发器会将代码部署到唯一的 Canary 版网址,并且会将所有实时流量的 10% 路由到新修订版本。

  1. 在 Cloud Shell 中,设置分支触发器:

    gcloud alpha builds triggers create github \
      --name=maintrigger \
      --repository=$REPO_NAME \
      --branch-pattern=main \
      --build-config=labs/cloudrun-progression/main-cloudbuild.yaml \
      --region=us-central1
    
  2. 如需查看新触发器,请进入 Cloud 控制台中的 Cloud Build 触发器页面

  3. 在 Cloud Shell 中,将分支合并到主代码行并推送到远程代码库:

    git checkout main
    git merge new-feature-1
    git push origin main
    
  4. 如需查看正在进行的构建,请进入 Cloud Build 构建页面

  5. 构建完成后,如需查看新修订版本,请进入 Cloud 控制台中的 Cloud Run 修订版本页面。请注意,90% 的流量会路由到生产环境,10% 的流量会路由到 Canary,0% 的流量会路由到分支修订版本。

查看用于实现 Canary 部署逻辑的 main-cloudbuild.yaml 的关键行。

第 39-45 行部署新的修订版本,并使用标记标志从唯一的 Canary 版网址路由流量:

gcloud run deploy ${_SERVICE_NAME} \
--platform managed \
--region ${_REGION} \
--image gcr.io/${PROJECT_ID}/${_SERVICE_NAME} \
--tag=canary \
--no-traffic

第 61 行向该修订版本添加静态标记,以记下部署的 Git 短 SHA:

gcloud beta run services update-traffic ${_SERVICE_NAME} --update-tags=sha-$SHORT_SHA=$${CANARY} --platform managed --region ${_REGION}

第 62 行更新了流量,将 90% 路由到生产环境,将 10% 路由到 Canary:

gcloud run services update-traffic ${_SERVICE_NAME} --to-revisions=$${PROD}=90,$${CANARY}=10 --platform managed --region ${_REGION}
  1. 在 Cloud Shell 中,获取 Canary 修订版本的唯一网址:

    CANARY_URL=$(gcloud run services describe hello-cloudrun --platform managed --region us-central1 --format=json | jq --raw-output ".status.traffic[] | select (.tag==\"canary\")|.url")
    
    echo $CANARY_URL
    
  2. 直接查看 Canary 版端点:

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $CANARY_URL
    
  3. 如需查看基于百分比的响应,请发出一系列请求:

    LIVE_URL=$(gcloud run services describe hello-cloudrun --platform managed --region us-central1 --format=json | jq --raw-output ".status.url")
    for i in {0..20};do
      curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $LIVE_URL; echo \n
    done
    

发布到生产环境

使用一小部分流量验证 Canary 部署后,您需要将部署发布到其余实时流量。

在本部分中,您将设置一个触发器,该触发器会在代码库中创建标记时激活。触发器会根据标记的提交 SHA 将 100% 的流量迁移到已部署的修订版本。使用提交 SHA 可确保通过 Canary 流量验证的修订版本是用于其余生产流量的修订版本。

  1. 在 Cloud Shell 中,设置标记触发器:

    gcloud alpha builds triggers create github \
      --name=tagtrigger \
      --repository=$REPO_NAME \
      --tag-pattern=. \
      --build-config=labs/cloudrun-progression/tag-cloudbuild.yaml \
      --region=us-central1
    
  2. 如需查看新触发器,请进入 Cloud 控制台中的 Cloud Build 触发器页面

  3. 在 Cloud Shell 中,创建一个新标记并将其推送到远程代码库:

    git tag 1.1
    git push origin 1.1
    
  4. 如需查看正在进行的构建,请前往 Cloud 控制台中的 Cloud Build 构建记录屏幕

  5. 构建完成后,如需查看新修订版本,请进入 Cloud 控制台中的 Cloud Run 修订版本页面。请注意,修订版本经过更新,指示 prod 标记,并且正在处理 100% 的实时流量。

  6. 在 Cloud Shell 中,如需查看基于百分比的响应,请发出一系列请求:

    LIVE_URL=$(gCloud Run services describe hello-cloudrun --platform managed --region us-central1 --format=json | jq --raw-output ".status.url")
    
    for i in {0..20};do
      curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $LIVE_URL; echo \n
    done
    
  7. 查看用于实现生产部署逻辑的 tag-cloudbuild.yaml 的关键行。

    第 37 行更新 Canary 修订版本,添加了 prod 标记。现在,已部署的修订版本标记为 prod 和 Canary:

    gcloud beta run services update-traffic ${_SERVICE_NAME} --update-tags=prod=$${CANARY} --platform managed --region ${_REGION}
    

    第 39 行更新了基本服务网址的流量,将 100% 的流量路由到标记为 prod 的修订版本:

    gcloud run services update-traffic ${_SERVICE_NAME} --to-revisions=$${NEW_PROD}=100 --platform managed --region ${_REGION}
    

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

  1. 在 Google Cloud 控制台中,进入管理资源页面。

    转到“管理资源”

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

后续步骤