本教程介绍了如何使用 Azure Pipelines、Cloud Run 和 Container Registry 为 ASP.NET MVC Core Web 应用创建持续集成/持续部署 (CI/CD) 流水线。
CI/CD 流水线使用两个 Google Cloud 项目(一个用于开发,一个用于生产),如下图所示。
在流水线的开端,开发者将提交对示例代码库的更改。此操作会触发流水线创建一个发布并将其部署到开发集群中的 Cloud Run。然后,发布管理员要升级版本,使其部署到生产项目中。
本教程适用于开发者和 DevOps 工程师。它假定您具备 .NET、Azure Pipelines、Cloud Run 和 git 的基础知识。要完成本教程,您需要拥有 Azure DevOps 账号的管理员权限。
目标
- 将 Artifact Registry 连接到 Azure Pipelines 以发布 Docker 映像。
- 准备 .NET 示例应用以部署到 Cloud Run 中。
- 设置 Azure Pipelines 和 Google Cloud之间的身份验证。
- 使用 Azure Pipelines 发布管理功能来编排 Cloud Run 部署。
费用
在本文档中,您将使用 Google Cloud的以下收费组件:
如需根据您的预计使用量来估算费用,请使用价格计算器。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
查看 Azure DevOps 价格页面,了解使用 Azure DevOps 时可能需要支付的所有费用。
准备工作
在本教程中,您将使用两个单独的项目,一个用于开发,一个用于生产。使用单独的项目可让您在将发布部署到生产环境之前对其进行测试,还可单独管理身份和访问权限管理 (IAM) 角色和权限。
- 创建一个 Google Cloud 项目用于开发。本教程将此项目称为开发项目。
- 创建一个 Google Cloud 项目用于生产。本教程将此项目称为生产项目。
-
Verify that billing is enabled for your Google Cloud project.
- 确保您拥有 Azure DevOps 账号,并且拥有其管理员权限。如果您还没有 Azure DevOps 账号,可以在 Azure DevOps 首页上注册一个。
创建 Azure DevOps 项目
您可以使用 Azure DevOps 来管理源代码、运行构建和测试并将部署编排到 Cloud Run。首先,您需要在 Azure DevOps 账号中创建一个项目。
- 转到 Azure DevOps 首页 (https://dev.azure.com/YOUR_AZURE_DEVOPS_ACCOUNT_NAME)。
- 点击新建项目。
- 输入项目名称,例如
CloudDemo。 - 将 Visibility 设置为 Private,然后点击 Create project。
- 创建项目后,点击左侧菜单中的存储库。
- 点击导入,从 GitHub 创建
dotnet-docs-samples代码库分支,然后设置以下值:- 代码库类型:
Git - 克隆网址:
https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git
- 代码库类型:
点击导入。
导入流程完成后,您将看到
dotnet-docs-samples代码库的源代码。
将 Azure Pipelines 连接到 Artifact Registry
您必须先将 Azure Pipelines 连接到 Artifact Registry,然后才能为 CloudDemo 应用设置持续集成。此连接允许 Azure Pipelines 将容器映像发布到 Artifact Registry。
设置一个服务账号用于发布映像
在生产项目中创建Google Cloud 服务账号:
- 在 Google Cloud 控制台中,切换到生产项目。
-
In the Google Cloud console, activate Cloud Shell.
初始化以下环境变量:
DEV_PROJECT_ID=DEV_PROJECT_ID PROD_PROJECT_ID=PROD_PROJECT_ID
替换以下内容:
DEV_PROJECT_ID:您的开发项目的 IDPROD_PROJECT_ID:您的生产项目的 ID
在生产项目中启用 Artifact Registry API:
gcloud services enable artifactregistry.googleapis.com \ --project=$PROD_PROJECT_ID创建 Artifact Registry 代码库以存储 Docker 映像:
gcloud artifacts repositories create docker \ --project=$PROD_PROJECT_ID \ --repository-format=docker \ --location REGION将
REGION替换为您的 Artifact Registry 代码库的区域,例如us-central1。创建一个服务账号,供 Azure Pipelines 用于发布 Docker 映像:
gcloud iam service-accounts create azure-pipelines-publisher \ --display-name="Azure Pipelines Publisher" \ --project=$PROD_PROJECT_ID向服务账号授予 Artifact Registry Writer 角色 (
roles/artifactregistry.writer),以允许 Azure Pipelines 推送到 Artifact Registry:AZURE_PIPELINES_PUBLISHER=azure-pipelines-publisher@$PROD_PROJECT_ID.iam.gserviceaccount.com gcloud projects add-iam-policy-binding $PROD_PROJECT_ID \ --member serviceAccount:$AZURE_PIPELINES_PUBLISHER \ --role roles/artifactregistry.writer \ --project=$PROD_PROJECT_ID生成服务账号密钥:
gcloud iam service-accounts keys create azure-pipelines-publisher.json \ --iam-account $AZURE_PIPELINES_PUBLISHER \ --project=$PROD_PROJECT_ID tr -d '\n' < azure-pipelines-publisher.json > azure-pipelines-publisher-oneline.json查看服务账号密钥文件的内容:
echo $(<azure-pipelines-publisher-oneline.json)执行以下步骤之一时,需要用到服务账号密钥。
- 在 Azure DevOps 菜单中,选择项目设置,然后选择管道 > 服务连接。
- 点击 Create service connection。
- 从列表中选择 Docker 注册表,然后点击下一步。
在对话框中,为以下字段输入值:
- Registry type:Others
Docker Registry:
https://REGION-docker.pkg.dev/PROD_PROJECT_ID/docker/替换以下内容:
REGION:您的 Artifact Registry 代码库的区域PROD_PROJECT_ID:您的生产项目的名称
Docker ID:
_json_key密码:粘贴
azure-pipelines-publisher-oneline.json的内容。服务连接名称:
gcr-tutorial
点击保存以创建连接。
- 使用 Visual Studio 或命令行
git客户端克隆新的 Git 代码库。 - 在代码库的根目录中,创建一个名为
azure-pipelines.yml的文件。 将以下代码复制到该文件中:
resources: - repo: self fetchDepth: 1 pool: vmImage: ubuntu-22.04 trigger: - master variables: TargetFramework: 'net6.0' BuildConfiguration: 'Release' DockerImageName: 'PROD_PROJECT_ID/docker/CloudDemo' steps: - task: DotNetCoreCLI@2 displayName: Publish inputs: projects: 'applications/clouddemo/netcore/CloudDemo.MvcCore.sln' publishWebProjects: false command: publish arguments: '--configuration $(BuildConfiguration) --framework=$(TargetFramework)' zipAfterPublish: false modifyOutputPath: false - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact' inputs: PathtoPublish: '$(build.artifactstagingdirectory)' - task: Docker@2 displayName: 'Login to Container Registry' inputs: command: login containerRegistry: 'gcr-tutorial' - task: Docker@2 displayName: 'Build and push image' inputs: Dockerfile: 'applications/clouddemo/netcore/Dockerfile' command: buildAndPush repository: '$(DockerImageName)'
将
PROJECT_ID替换为您的生产项目名称,然后保存该文件。由于 Cloud Run 是基于 Linux 的环境,因此该流水线使用基于 Linux 的构建代理。
提交您的更改并将其推送到 Azure Pipelines。
Visual Studio
- 打开团队资源管理器,然后点击主页图标。
- 点击更改。
- 输入类似
Add pipeline definition的提交消息。 - 点击全部提交并推送。
命令行
暂存所有已修改的文件:
git add -A将更改提交到本地代码库:
git commit -m "Add pipeline definition"将更改推送到 Azure DevOps:
git push
在 Azure DevOps 菜单中,选择流水线,然后点击 创建流水线。
选择 Azure Repos Git。
选择您的代码库。
在查看流水线 YAML页面上,点击运行。
系统会触发新的构建。构建流程可能约两分钟后才能完成。
如需验证映像是否已发布到 Artifact Registry,请在 Google Cloud 控制台中切换到生产项目,选择 Artifact Registry > docker,然后点击 CloudDemo。
这会显示一个映像及其标记。该标记与 Azure Pipelines 中运行的构建的数字 ID 相对应。
- “版本”是指构成应用特定版本的一组工件,通常是构建流程的结果。
- “部署”是指提取一个发布并将其部署到特定环境的流程。
- 一次部署会执行一组“任务”,这些任务可分组为多个“作业”。
- 使用“阶段”可以将流水线分段,并可将部署编排到多个环境,例如开发和测试环境。
打开 Cloud Shell。
初始化以下环境变量:
DEV_PROJECT_ID=DEV_PROJECT_ID PROD_PROJECT_ID=PROD_PROJECT_ID
替换以下内容:
DEV_PROJECT_ID:您的开发项目的 IDPROD_PROJECT_ID:您的生产项目的 ID
在开发和生产项目中启用 Cloud Run API 和 Compute Engine API:
gcloud services enable run.googleapis.com --project=$DEV_PROJECT_ID gcloud services enable run.googleapis.com --project=$PROD_PROJECT_ID启用这些 API 会在项目中创建 Cloud Run 服务代理账号。
在存储 Docker 映像的生产项目中,向两个 Cloud Run 服务代理账号授予访问 Artifact Registry 的权限:
DEV_PROJECT_NUMBER=$(gcloud projects describe $DEV_PROJECT_ID \ --format='value(projectNumber)') PROD_PROJECT_NUMBER=$(gcloud projects describe $PROD_PROJECT_ID \ --format='value(projectNumber)') gcloud projects add-iam-policy-binding $PROD_PROJECT_ID \ --member=serviceAccount:service-$DEV_PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com \ --role roles/artifactregistry.reader gcloud projects add-iam-policy-binding $PROD_PROJECT_ID \ --member=serviceAccount:service-$PROD_PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com \ --role roles/artifactregistry.reader创建名为
CloudDemo-runner的服务账号:gcloud iam service-accounts create clouddemo-runner \ --display-name="CloudDemo Runner" \ --project=$DEV_PROJECT_ID gcloud iam service-accounts create clouddemo-runner \ --display-name="CloudDemo Runner" \ --project=$PROD_PROJECT_ID DEV_CLOUDDEMO_RUNNER=clouddemo-runner@$DEV_PROJECT_ID.iam.gserviceaccount.com PROD_CLOUDDEMO_RUNNER=clouddemo-runner@$PROD_PROJECT_ID.iam.gserviceaccount.com创建名为
azure-pipelines-deployer的服务账号:gcloud iam service-accounts create azure-pipelines-deployer \ --display-name="Azure Pipelines Deployer" \ --project=$PROD_PROJECT_ID AZURE_PIPELINES_DEPLOYER=azure-pipelines-deployer@$PROD_PROJECT_ID.iam.gserviceaccount.com分配所需的 IAM 角色,在开发项目中部署新的 Cloud Run 服务或修订版本:
gcloud projects add-iam-policy-binding $DEV_PROJECT_ID \ --member serviceAccount:$AZURE_PIPELINES_DEPLOYER \ --role roles/run.admin gcloud iam service-accounts add-iam-policy-binding \ $DEV_CLOUDDEMO_RUNNER \ --member=serviceAccount:$AZURE_PIPELINES_DEPLOYER \ --role="roles/iam.serviceAccountUser" \ --project=$DEV_PROJECT_ID为生产项目分配同一组角色:
gcloud projects add-iam-policy-binding $PROD_PROJECT_ID \ --member serviceAccount:$AZURE_PIPELINES_DEPLOYER \ --role roles/run.admin gcloud iam service-accounts add-iam-policy-binding \ $PROD_CLOUDDEMO_RUNNER \ --member=serviceAccount:$AZURE_PIPELINES_DEPLOYER \ --role="roles/iam.serviceAccountUser" \ --project=$PROD_PROJECT_ID生成服务账号密钥:
gcloud iam service-accounts keys create azure-pipelines-deployer.json \ --iam-account=$AZURE_PIPELINES_DEPLOYER \ --project=$PROD_PROJECT_ID cat azure-pipelines-deployer.json | base64 -w 0您可以在配置发布流水线时使用此命令的输出。
- 部署到开发环境。
- 在开始部署到生产环境之前请求手动审批。
- 部署到生产环境。
- 在 Azure DevOps 菜单中,选择管道 > 发布。
- 点击新建管道。
- 从模板列表中,选择 Empty job。
- 当系统提示您输入阶段名称时,请输入
Development。 - 在屏幕顶部,将流水线命名为
CloudDemo。 - 在流水线图中,点击工件旁边的添加。
- 选择构建并添加以下设置:
- 源类型:构建
- 源(构建管道):选择构建定义(应该只有一个选项)
- 默认版本:最新
- 源别名:
build
- 点击添加。
- 在项目框中,点击持续部署触发器(闪电图标)来添加部署触发器。
- 在持续部署触发器下,将开关设置为已启用。
- 点击保存。
如果需要,请输入注释,然后点击确定来进行确认。
该流水线会显示如下内容。
- 在菜单中,切换到任务标签页。
- 点击代理作业。
- 将代理规范设置为 ubuntu-22.04。
- 在 Agent job 旁边,点击 Add a task to agent job 以向阶段添加步骤。
- 选择命令行任务,然后点击添加。
点击新添加的任务并配置以下设置:
- 显示名:
Deploy image to development project 脚本:
gcloud auth activate-service-account \ --quiet \ --key-file <(echo $(ServiceAccountKey) | base64 -d) && \ gcloud run deploy clouddemo \ --quiet \ --service-account=clouddemo-runner@$(CloudRun.ProjectId.Development).iam.gserviceaccount.com \ --allow-unauthenticated \ --image=$(CloudRun.Region)-docker.pkg.dev/$(ContainerRegistry.ProjectId)/docker/clouddemo:$BUILD_BUILDID \ --platform=managed \ --region=$(CloudRun.Region) \ --project=$(CloudRun.ProjectId.Development)此命令会从环境变量获取服务账号密钥,然后使用 gcloud CLI 将应用部署到 Cloud Run。Azure Pipelines 代理默认使用 gcloud CLI。
- 显示名:
切换到变量标签页,然后添加以下变量。
名称 值 Secret ServiceAccountKey之前为 azure-pipelines-deployer创建的服务账号密钥。是 ContainerRegistry.ProjectId您的生产项目的 ID。 CloudRun.Region您之前选择的用于部署 Artifact Registry 资源的地区。 CloudRun.ProjectId.Development您的开发项目的 ID。 CloudRun.ProjectId.Production您的生产项目的 ID。 点击保存。
如果需要,请输入注释,然后点击确定来进行确认。
- 在菜单中,切换到管道标签页。
- 在“阶段”框中,选择添加 > 新阶段。
- 从模板列表中,选择 Empty job。
- 当系统提示您输入阶段名称时,请输入
Production。 - 点击新创建阶段的闪电形图标。
进行以下设置:
- 选择触发器:阶段后
- 阶段:开发
- 部署前审批:(已启用)
- 审批者:选择您的用户名。
流水线会显示如下视图。
切换到任务标签页。
将鼠标悬停在任务标签页上,然后选择任务 > 生产。
点击代理作业。
将代理规范设置为 ubuntu-22.04。
点击 Add a task to agent job 以向阶段添加步骤。
选择命令行任务,然后点击添加。
点击新添加的任务并配置以下设置:
- 显示名:
Deploy image to production project 脚本:
gcloud auth activate-service-account \ --quiet \ --key-file <(echo $(ServiceAccountKey) | base64 -d) && \ gcloud run deploy clouddemo \ --quiet \ --service-account=clouddemo-runner@$(CloudRun.ProjectId.Production).iam.gserviceaccount.com \ --allow-unauthenticated \ --image=$(CloudRun.Region)-docker.pkg.dev/$(ContainerRegistry.ProjectId)/docker/clouddemo:$BUILD_BUILDID \ --platform=managed \ --region=$(CloudRun.Region) \ --project=$(CloudRun.ProjectId.Production)
- 显示名:
点击保存。
如果需要,请输入注释,然后点击确定来进行确认。
- 在本地计算机上,从您之前克隆的 Git 代码库中打开
applications\clouddemo\netcore\CloudDemo.MvcCore\Views\Home\Index.cshtml文件。 - 将
ViewBag.Title的值从Home Page更改为Home Page Cloud Run。 提交您的更改并将其推送到 Azure Pipelines。
Visual Studio
- 打开团队资源管理器,然后点击主页图标。
- 点击更改。
- 输入类似
Change site title的提交消息。 - 点击全部提交并推送。
命令行
暂存所有已修改的文件:
git add -A将更改提交到本地代码库:
git commit -m "Change site title"将更改推送到 Azure Pipelines:
git push
在 Azure DevOps 菜单中,选择管道。系统会触发构建。
构建完成后,选择管道 > 发布。系统会启动发布流程。
点击 Release-1 打开详细信息页面,等待开发阶段的状态切换为已成功。
在 Google Cloud 控制台中,切换到开发项目。
在菜单中,选择计算 > Cloud Run。
clouddemo 服务已成功部署。
点击 clouddemo 以查看更多详细信息。
系统会显示一个网址来说明 Cloud Run 已预配该服务。
在新的浏览器标签页中打开该网址,验证 CloudDemo 应用是否已部署并使用自定义标题。
在 Azure Pipelines 中,点击审批(生产阶段旁),将部署提升到生产环境。
(可选)输入注释。
点击审批进行确认,然后等待生产环境的状态切换为已成功。
在 Google Cloud 控制台中,切换到生产项目。
在菜单中,选择计算 > Cloud Run。
clouddemo 服务将部署到生产项目。
点击 clouddemo 以查看更多详细信息。
系统会显示一个网址来说明 Cloud Run 已预配该服务。
在新的浏览器标签页中打开该网址,验证 CloudDemo 应用是否已部署到生产项目并使用自定义标题。
为 Artifact Registry 创建服务连接
在 Azure Pipelines 中,为 Artifact Registry 创建新的服务连接:
持续构建
您现可使用 Azure Pipelines 来设置持续集成。对于推送到 Git 代码库的每个提交项,Azure Pipelines 都会构建代码并将构建工件打包到 Docker 容器中。随后,容器会被发布到 Artifact Registry。
该代码库已包含以下 Dockerfile:
您现在可以创建使用 YAML 语法的新流水线:
持续部署
现在,Azure Pipelines 会自动构建代码并为每个提交项发布 Docker 映像,因此您可以专注于部署工作。
与其他一些持续集成系统不同,Azure Pipelines 对构建和部署进行了区分,并为所有与部署相关的任务提供了一组标记为“版本管理”的专用工具。
Azure Pipelines 版本管理围绕以下概念构建:
您可以将发布流水线设置为在新构建完成时触发。流水线包括两个阶段:开发和生产。在每个阶段,发布流水线都使用构建流水线生成的 Docker 映像,然后将流水线部署到 Cloud Run。
在将每个 Docker 映像发布到 Artifact Registry 之前,您之前配置的构建流水线会为其添加标记。因此,在发布流水线中,您可以使用 $BUILD_BUILDID 变量来标识要部署的适当的 Docker 映像。
配置 Cloud Run
Cloud Run 是一个全代管式式无服务器环境,因此您无需预配任何基础架构。为了帮助确保 Cloud Run 部署的安全,您需要设置 IAM。
部署和运行 Cloud Run 服务涉及多个身份,如下图所示。
其中每个身份都以服务账号的形式实现,并用于特定用途,如下表所述。
| 服务账号 | 使用者 | 用途 | 所需的角色 |
|---|---|---|---|
| Azure Pipelines 发布者 | 构建流水线 | 将 Docker 映像发布到 Artifact Registry | roles/artifactregistry.writer(仅限生产项目) |
| Azure Pipelines 部署者 | 发布流水线 | 启动 Cloud Run 部署 | roles/run.admin |
| 启动 CloudDemo 服务 | roles/iam.serviceAccountUser |
||
| Cloud Run 服务代理 | Cloud Run | 从 Artifact Registry 中拉取 Docker 映像 | roles/artifactregistry.reader(仅限生产项目) |
| CloudDemo 运行者(运行时服务账号) | CloudDemo 服务 | 访问 Google Cloud上的资源 | 无 |
您已创建并配置 Azure Pipelines 发布者服务账号。在以下部分中,您将创建并配置其余服务账号。
配置 Cloud Run 服务账号
配置 CloudDemo 运行者账号
现在,您可以配置 CloudDemo 运行者账号,这是 CloudDemo 服务的自定义运行时服务账号:
配置 Azure Pipelines 部署者账号
最后,创建并配置 Azure Pipelines 部署者账号,Azure 发布流水线将使用该账号部署到 Cloud Run。
配置发布流水线
现在,您可以返回 Azure Pipelines 来自动执行部署,其中包含以下步骤:
创建发布定义
首先,创建一个发布定义:
部署到开发项目
创建发布定义后,您现可为开发项目配置 Cloud Run 部署。
部署到生产集群
最后,配置生产项目的部署:
运行流水线
现在您已经配置了整个流水线,接下来可通过更改源代码来测试该流水线:
清除数据
学完本教程后,请删除您创建的实体,避免日后再为这些实体付费。
删除 Azure Pipelines 项目
如需删除 Azure Pipelines 项目,请参阅 Azure DevOps Services 文档。删除 Azure Pipelines 项目会导致所有源代码更改丢失。
删除 Google Cloud 开发项目和生产项目
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
后续步骤
- 为您的 Cloud Run 服务配置自定义网域。
- 了解如何改用 Azure Pipelines 将同一应用部署到 Google Kubernetes Engine。
- 详细了解如何在 Google Cloud上部署 .NET 应用。
- 探索有关 Google Cloud 的参考架构、图表和最佳做法。查看我们的 Cloud 架构中心。