本教程介绍了如何使用 Azure Pipelines、Cloud Run 和 Container Registry为 ASP.NET MVC Core Web 应用创建持续集成/持续部署 (CI/CD) 流水线。
CI/CD 流水线使用两个 Google Cloud 项目(一个用于开发,一个用于生产),如下图所示。
在流水线的开端,开发者将提交对示例代码库的更改。此操作会触发流水线创建一个发布并将其部署到开发集群中的 Cloud Run。然后,发布管理员要升级版本,使其部署到生产项目中。
本教程适用于开发者和 DevOps 工程师。它假定您具备 .NET Core、Azure Pipelines、Cloud Run 和 git
的基础知识。要完成本教程,您需要拥有 Azure DevOps 帐号的管理员权限。
目标
- 将 Container Registry 连接到 Azure Pipelines 以发布 Docker 映像。
- 准备 .NET Core 示例应用以部署到 Cloud Run 中。
- 设置 Azure Pipelines 和 Google Cloud 之间的身份验证。
- 使用 Azure Pipelines 发布管理功能来编排 Cloud Run 部署。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
您可使用价格计算器根据您的预计使用情况来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
查看 Azure DevOps 价格页面,了解使用 Azure DevOps 时可能需要支付的所有费用。
准备工作
在本教程中,您将使用两个单独的项目,一个用于开发,一个用于生产。使用单独的项目可让您在将发布部署到生产环境之前对其进行测试,还可单独管理身份和访问权限管理 (IAM) 角色和权限。
- 创建一个 Google Cloud 项目用于开发。本教程将此项目称为开发项目。
- 创建一个用于生产环境的 Google Cloud 项目。本教程将此项目称为生产项目。
-
Make sure 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 连接到 Container Registry
您必须先将 Azure Pipelines 连接到 Container Registry,然后才能为 CloudDemo
应用设置持续集成。此连接允许 Azure Pipelines 将容器映像发布到 Container 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
在生产项目中启用 Container Registry API:
gcloud services enable containerregistry.googleapis.com \ --project=$PROD_PROJECT_ID
创建一个服务帐号,供 Azure Pipelines 用于发布 Docker 映像:
gcloud iam service-accounts create azure-pipelines-publisher \ --display-name="Azure Pipelines Publisher" \ --project=$PROD_PROJECT_ID
向服务帐号授予 Storage Admin IAM 角色 (
roles/storage.admin
),以允许 Azure Pipelines 推送到 Container 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/storage.admin \ --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)
执行以下步骤之一时,需要用到服务帐号密钥。
为 Container Registry 创建服务连接
在 Azure Pipelines 中,为 Container Registry 创建新的服务连接:
- 在 Azure DevOps 菜单中,选择项目设置,然后选择管道 > 服务连接。
- 点击 Create service connection。
- 从列表中选择 Docker 注册表,然后点击下一步。
- 在对话框中,为以下字段输入值:
- 注册表类型:其他
- Docker 注册表:
https://gcr.io/PROD_PROJECT_ID
,请将PROD_PROJECT_ID
替换为您的生产项目名称(例如https://gcr.io/azure-pipelines-test-project-12345
)。 - Docker ID:
_json_key
- 密码:粘贴
azure-pipelines-publisher-oneline.json
的内容。 - 服务连接名称:
gcr-tutorial
- 点击保存以创建连接。
持续构建
您现可使用 Azure Pipelines 来设置持续集成。对于推送到 Git 代码库的每个提交项,Azure Pipelines 都会构建代码并将构建工件打包到 Docker 容器中。随后,容器会被发布到 Container Registry。
该代码库已包含以下 Dockerfile:
您现在可以创建使用 YAML 语法的新流水线:
- 使用 Visual Studio 或命令行
git
客户端克隆新的 Git 代码库。 - 在代码库的根目录中,创建一个名为
azure-pipelines.yml
的文件。 将以下代码复制到该文件中:
resources: - repo: self fetchDepth: 1 queue: name: Hosted Ubuntu 1604 trigger: - master variables: TargetFramework: 'net6.0' BuildConfiguration: 'Release' DockerImageName: 'PROD_PROJECT_ID/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页面上,点击运行。
系统会触发新的构建。构建流程可能约两分钟后才能完成。
如需验证映像是否已发布到 Container Registry,请在 Google Cloud 控制台中切换到生产项目,选择 Container Registry > 映像,然后点击 CloudDemo。
这会显示一个映像及其标记。该标记与 Azure Pipelines 中运行的构建的数字 ID 相对应。
持续部署
现在,Azure Pipelines 会自动构建代码并为每个提交项发布 Docker 映像,因此您可以专注于部署工作。
与其他一些持续集成系统不同,Azure Pipelines 对构建和部署进行了区分,并为所有与部署相关的任务提供了一组标记为“版本管理”的专用工具。
Azure Pipelines 版本管理围绕以下概念构建:
- “版本”是指构成应用特定版本的一组工件,通常是构建流程的结果。
- “部署”是指提取一个发布并将其部署到特定环境的流程。
- 一次部署会执行一组“任务”,这些任务可分组为多个“作业”。
- 使用“阶段”可以将流水线分段,并可将部署编排到多个环境,例如开发和测试环境。
您可以将发布流水线设置为在新构建完成时触发。流水线包括两个阶段:开发和生产。在每个阶段,发布流水线都使用构建流水线生成的 Docker 映像,然后将流水线部署到 Cloud Run。
在将每个 Docker 映像发布到 Container Registry 之前,您之前配置的构建流水线会为其添加标记。因此,在发布流水线中,您可以使用 $BUILD_BUILDID
变量来标识要部署的适当的 Docker 映像。
配置 Cloud Run
Cloud Run 是一个全托管式无服务器环境,因此您无需预配任何基础架构。为了帮助确保 Cloud Run 部署的安全,您需要设置 IAM。
部署和运行 Cloud Run 服务涉及多个身份,如下图所示。
其中每个身份都以服务帐号的形式实现,并用于特定用途,如下表所述。
服务帐号 | 使用者 | 用途 | 所需的角色 |
---|---|---|---|
Azure Pipelines 发布者 | 构建流水线 | 将 Docker 映像发布到 Container Registry | roles/storage.admin (仅限生产项目) |
Azure Pipelines 部署者 | 发布流水线 | 启动 Cloud Run 部署 | roles/run.admin |
启动 CloudDemo 服务 | roles/iam.serviceAccountUser |
||
Cloud Run 服务代理 | Cloud Run | 从 Container Registry 中拉取 Docker 映像 | roles/storage.objectViewer (仅限生产项目) |
CloudDemo 运行者(运行时服务帐号) | CloudDemo 服务 | 访问 Google Cloud 上的资源 | 无 |
您已创建并配置 Azure Pipelines 发布者服务帐号。在以下部分中,您将创建并配置其余服务帐号。
配置 Cloud Run 服务帐号
打开 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 服务代理帐号授予访问 Container 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/storage.objectViewer gcloud projects add-iam-policy-binding $PROD_PROJECT_ID \ --member=serviceAccount:service-$PROD_PROJECT_NUMBER@serverless-robot-prod.iam.gserviceaccount.com \ --role roles/storage.objectViewer
配置 CloudDemo 运行者帐号
现在,您可以配置 CloudDemo 运行者帐号,这是 CloudDemo 服务的自定义运行时服务帐号:
创建名为
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 部署者帐号
最后,创建并配置 Azure Pipelines 部署者帐号,Azure 发布流水线将使用该帐号部署到 Cloud Run。
创建名为
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 Pipelines 来自动执行部署,其中包含以下步骤:
- 部署到开发环境。
- 在开始部署到生产环境之前请求手动审批。
- 部署到生产环境。
创建发布定义
首先,创建一个发布定义:
- 在 Azure DevOps 菜单中,选择管道 > 发布。
- 点击新建管道。
- 从模板列表中,选择 Empty job。
- 当系统提示您输入阶段名称时,请输入
Development
。 - 在屏幕顶部,将流水线命名为
CloudDemo
。 - 在流水线图中,点击工件旁边的添加。
- 选择构建并添加以下设置:
- 源类型:构建
- 源(构建管道):选择构建定义(应该只有一个选项)
- 默认版本:最新
- 源别名:
build
- 点击添加。
- 在项目框中,点击持续部署触发器(闪电图标)来添加部署触发器。
- 在持续部署触发器下,将开关设置为已启用。
- 点击保存。
如果需要,请输入注释,然后点击确定来进行确认。
该流水线会显示如下内容。
部署到开发项目
创建发布定义后,您现可为开发项目配置 Cloud Run 部署。
- 在菜单中,切换到任务标签页。
- 点击代理作业。
- 将代理规范设置为 ubuntu-18.04。
- 在代理作业旁边,点击向代理作业添加任务 ,来向阶段添加步骤。
- 选择命令行任务,然后点击添加。
点击新添加的任务并配置以下设置:
- 显示名:
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=gcr.io/$(ContainerRegistry.ProjectId)/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
您之前选择的用于部署 Cloud Run 资源的地区。 CloudRun.ProjectId.Development
您的开发项目的 ID。 CloudRun.ProjectId.Production
您的生产项目的 ID。 点击保存。
如果需要,请输入注释,然后点击确定来进行确认。
部署到生产集群
最后,配置生产项目的部署:
- 在菜单中,切换到管道标签页。
- 在“阶段”框中,选择添加 > 新阶段。
- 从模板列表中,选择 Empty job。
- 当系统提示您输入阶段名称时,请输入
Production
。 - 点击新创建阶段的闪电形图标。
进行以下设置:
- 选择触发器:阶段后
- 阶段:开发
- 部署前审批:(已启用)
- 审批者:选择您的用户名。
流水线会显示如下视图。
切换到任务标签页。
将鼠标悬停在任务标签页上,然后选择任务 > 生产。
点击代理作业。
将代理规范设置为 ubuntu-18.04。
点击向代理作业添加任务
,来向阶段添加步骤。选择命令行任务,然后点击添加。
点击新添加的任务并配置以下设置:
- 显示名:
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=gcr.io/$(ContainerRegistry.ProjectId)/clouddemo:$BUILD_BUILDID \ --platform=managed \ --region=$(CloudRun.Region) \ --project=$(CloudRun.ProjectId.Production)
- 显示名:
点击保存。
如果需要,请输入注释,然后点击确定来进行确认。
运行流水线
现在您已经配置了整个流水线,接下来可通过更改源代码来测试该流水线:
- 在本地计算机上,从您之前克隆的 Git 代码库中打开
applications\clouddemo\netcore\CloudDemo.MvcCore\Views\Home\Index.cshtml
文件。 - 在第 26 行中,将
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 应用是否已部署到生产项目并使用自定义标题。
清理
学完本教程后,请删除您创建的实体,避免日后再为这些实体付费。
删除 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 Architecture Center。