当您在线搜索时,您会找到关于Azure DevOps的各种博客文章、文档和教程。所有这些都是有价值的资源,但很少有人能够通过一个真实的场景来引导您。许多人只是简单地浏览安全方面,以便将密码以明文形式留下,要么是为了简单起见,要么是为了最终产品基本上什么都不做。让我们改变这一点。
在这篇文章/教程中,您将从头到尾学习如何构建一个真实的 Azure DevOps 发布流水线,该流水线自动化基础架构。更具体地说,您将学习如何使用 Azure DevOps 构建连续部署流水线以配置 Azure 虚拟机。
通过这个项目的最后,您将拥有一个完全运行的 Azure 流水线。从单个 GitHub 存储库提交开始,它将:
- 构建一个临时的 Azure 资源组
- 通过 ARM 模板配置 Azure VM
- 在 CI/CD 流水线中设置该 ARM 模板
- 在模板发生任何更改时,启动模板验证测试
- 将 ARM 模板部署到 Azure
- 测试已部署的基础结构
- 拆除所有 Azure 资源
让我们立即开始!
项目概览
此项目将分为六个主要部分。它们是:
Azure 资源准备
在本节中,您将学习如何在 Azure 中设置所有先决条件资源。在这里,您将:
- 创建 Azure 服务主体 以执行管道中的各种任务
- 建立一个 Azure Key Vault 并为管道提供所需的秘密
- 设置适当的访问策略以供 ARM 部署和管道使用
Azure DevOps 准备工作
一旦您设置了所有 Azure 资源,就该为您的管道准备 Azure DevOps。 在本节中,您将:
- 在 Azure DevOps 组织中安装 Pester 测试运行程序生成任务
- 创建 服务连接 以为 Azure DevOps 提供所需的资源访问权限
- 创建一个 Azure DevOps 变量组 将密钥库链接到访问 Azure Key Vault 秘密
脚本/模板概述
有各种与该项目相关的工件,包括用于构建服务器的ARM模板和Pester测试。在本节中,我们将简要介绍模板正在提供的内容以及Pester在流水线中具体测试的内容。
流水线创建
在这一部分,真正的乐趣开始了。您将开始设置实际的流水线。在这里,您将学习如何通过单个YAML文件设置整个编排。
您将使用多阶段流水线UI体验构建流水线。截至撰写本文时,此功能处于预览状态。
流水线演示
一旦构建了流水线,您需要看它运行!在这一部分中,您将学习如何触发流水线并简单地观察魔法发生。
清理
最后,由于这只是一次演示,您将获得一个脚本来拆除教程期间构建的所有内容。
听起来很多吗?是的!但不用担心,您将逐步学习,一次攻克一个任务。
如果您想要一个包含用于构建此流水线的所有Azure CLI命令的脚本,您可以在ServerAutomationDemo GitHub存储库中找到,名称为demo.ps1。
先决条件
你将会学到很多,但也需要做好准备。如果你计划跟着做,请确保你有以下内容:
- 一个 Azure DevOps 组织 – 查看 Microsoft 快速入门指南 以了解如何操作。在本文中,你将使用一个名为 ServerAutomationDemo 的项目。
- A GitHub repo – In this article, you’ll be learning from a GitHub repo called ServerAutomationDemo. Sorry, we’re not using Azure repos in this article.
- A GitHub personal access token – Be sure to create the token with the permissions of admin:repo_hook, all repo and all user options.

- Cloud Shell 或 PowerShell 6+(如果在本地运行) – 示例可能在 Windows PowerShell 中运行,但未经测试。所有示例将在本地通过 PowerShell 控制台执行,但 Cloud Shell 也可以正常工作。你将会自动构建流水线。
- 安装 Azure CLI(如果在本地运行) – 你将学习如何使用 Azure CLI 在本文中执行任务。但是,同样的操作也可以通过 Azure 门户、PowerShell 或 Azure SDK 执行。
警告:你即将执行的操作将花费真实的货币,除非你有一些 Azure 信用额度。你将在 Azure 中启动的成本最高的资源是一个虚拟机,但仅是暂时的。
开始之前
在本教程中,你将进行大量的配置。在开始之前,请确保你准备好以下物品。
- 将要部署到的 Azure 订阅资源的名称 – 示例将使用 亚当自动化师。
- 订阅的ID
- Azure AD 租户的Azure AD 租户 ID
- DevOps 组织名称 – 本示例将使用adbertram.
- 放置资源的区域 – 本示例将使用eastus.
- 将临时密钥库放入的 Azure 资源组的名称 – 本示例将使用ServerAutomationDemo.
- A password to assign to the local administrator account on a deployed VM – the examples will use “I like azure.”.
- GitHub 存储库的 URL – 本示例将使用https://github.com/adbertram/ServerAutomationDemo.
使用 Azure CLI 登录
在文章中,您需要大量使用 Azure CLI 进行操作。我喜欢 Azure PowerShell cmdlets,但是 Azure CLI 目前能够执行更多的 DevOps 任务。
您的第一个任务是进入 PowerShell 6+ 控制台。一旦在控制台中,请使用以下命令通过 Azure 进行身份验证:az login
。该命令将打开一个浏览器窗口,并提示您输入帐户信息。
身份验证成功后,请确保将您的订阅设置为默认。将其设置为默认将避免您不断地指定它。
准备 Azure 资源
一旦使用 Azure CLI 登录,就该开始处理业务了。Azure Pipeline 有许多不同的依赖项和各种各样的开关。在这个第一部分中,您将学习如何进行一些设置,并为您的流水线准备环境。
安装 Azure CLI DevOps 扩展
您需要一种使用 Azure CLI 构建各种 Azure DevOps 组件的方法。默认情况下,它不包括该功能。要从 Azure CLI 管理 Azure DevOps,您需要安装 DevOps 扩展。
幸运的是,安装扩展只需要一行命令,如下所示。
安装扩展后,将组织设置为默认值,以防止反复指定它。
创建资源组
尽管管道将创建一个临时资源组,但您也应该为此演示中引入的任何资源创建一个资源组。更具体地说,这个资源组是您将创建 Azure Key Vault 的地方。
创建 Azure 服务主体
下一个任务是创建 Azure 服务主体。您需要一个 Azure 服务主体来进行 Azure 密钥保管库的身份验证。您还将使用此服务主体来验证 服务连接。按照下面的步骤为密钥保管库和最终 ARM 部署创建服务主体。
此时,将
$sp.appId
的值保存在某个地方是个好主意。稍后构建管道时,您会需要它!
您会在示例中看到一些 PowerShell 命令,例如
ConvertFrom-Json
。由于 Azure CLI 仅返回 JSON 字符串,将其转换为 PowerShell 对象后,更容易引用属性。
构建密钥保管库
本教程中的管道需要引用一些密码。与其以明文存储密码,不如用正确的方式处理。所有敏感信息都将存储在 Azure 密钥保管库中。
要创建密钥保管库,请使用如下所示的 az keyvault create
命令。此命令在之前创建的资源组中创建密钥保管库。还请注意 enabled-for-template-deployment
开关。这会更改密钥保管库访问策略,允许未来的 ARM 部署访问密钥保管库。

创建密钥保管库密码
一旦密钥保管库创建完成,就是创建密码的时候了。在此演示中,请创建两个名为ServerAutomationDemo-AppPw和StandardVmAdminPassword的密码。AppPw密码是服务主体的密码。VM密码将被分配给在VM上部署的本地管理员账户。
请注意,在此示例中,您正在使用先前定义的PowerShell变量。在这里,您提供服务主体密码(
$sp.password
)。
允许流水线访问密钥保管库
接下来,流水线需要权限访问密钥保管库。放宽密钥保管库访问策略一点,为创建的服务主体提供get和list权限来管理密钥保管库的密码。
准备Azure DevOps
现在您已经完成了所有Azure资源的准备工作。是时候在Azure DevOps中做一些准备工作了。
安装Pester扩展
首先要执行的任务是安装PesterRunner Azure DevOps扩展。流水线将运行两组Pester测试,以确保VM ARM部署成功。运行Pester测试的一种简单方法是使用PesterRunner扩展。
使用下面的命令安装扩展。
创建Azure DevOps项目
现在是创建项目的时候,流水线将在其中创建。使用 Azure CLI 创建 Azure DevOps pipeline 非常简单。只需运行下面的命令来创建项目并将项目设置为默认项目。
创建服务连接
您的流水线需要对两个服务进行身份验证 – ARM 和您的 GitHub 存储库。为此,必须创建两个服务连接。
首先,创建 ARM 服务终结点。下面的命令将提示输入服务主体密码。确保首先在控制台上显示它并将其复制到剪贴板。
确保填入您的订阅 ID、租户 ID,并替换下面的订阅名称。
接下来,为 GitHub 创建一个服务连接。由于流水线将通过 Git 提交触发,它需要能够读取存储库。
此时 GitHub 个人访问令牌就派上用场了。下面您还需要再次粘贴服务主体密码。您将为两个服务连接使用相同的服务主体。
创建变量组
管道将引用两个密码的关键保管库密码。要安全地执行此操作,您必须创建一个变量组并将其链接到关键保管库。
首先,按照下面的步骤创建变量组。
注意
foo=bar
变量?虽然没有使用,但是需要一个单一的变量来创建变量组。
将变量组链接到关键保管库
此时,您不幸地需要转到 Azure DevOps 门户。截至本文撰写时,Azure CLI 尚无法将关键保管库链接到变量组。
导航至 Azure DevOps 项目,然后单击库。然后,您应该看到如下所示的ServerAutomationDemo变量组。单击ServerAutomationDemo变量组。

进入变量组后,单击将 Azure 关键保管库的秘密链接为变量。这样做后,您将收到警告,说明您将擦除所有变量,并单击确认。您将看到如何执行此操作。此操作没有问题,因为foo变量始终是临时的。

确认后,选择ARM服务连接和之前创建的ServerAutomationDemo-KV关键保管库,如下所示。然后单击添加。

现在检查如下所示之前创建的两个密码,并单击确定和保存以保存更改。

项目文件概览
如果你已经走到这一步,恭喜!你现在已经准备好开始构建流水线了。但等等……还有更多!
为了使Azure Pipeline在现实世界中发挥作用,本教程构建了一个包含“单元”和“验收”测试的完整流水线。这使得教程更加有趣,但也需要对正在发生的事情进行一些额外解释。
在本教程的GitHub存储库中,你会找到一些文件,如下所示。现在是时候要么克隆这个存储库,要么根据这些文件构建你自己的存储库了。

- azure-pipelines.yml – 最终的YAML流水线
- connect-azure.ps1 – 用于对Azure订阅进行身份验证的PowerShell脚本
- server.infrastructure.tests.ps1 – 一个简单的Pester测试,用于确认VM配置是否良好
- server.json – 用于部署VM的Azure ARM模板
- server.parameters.json – 提供ARM模板参数值的Azure ARM参数模板。
确保在server.parameters.json文件中替换你的订阅ID和密钥保管库名称为密钥保管库IT。
- server.templates.tests.ps1 – 用于确认ARM模板是否有效的Pester“单元”测试
稍后你将看到这些文件如何在流水线中相互配合。
创建管道
假设您已克隆了我的 GitHub 仓库或自己建立了一个,现在是创建管道的时候了!要做到这一点,请运行az pipelines create
命令。下面的命令将使用提供的 GitHub 仓库作为触发器创建一个名为ServerAutomationDemo的管道。它将查看master分支并使用之前构建的服务连接。
根据您的 GitHub 仓库中是否有azure-pipelines.yml文件,您可能会或可能不会收到类似以下的反馈。无论哪种方式,您的控制台都会看起来类似。请确保您的 GitHub 个人访问令牌已准备就绪!

YAML 管道审阅
此时,您的管道已准备就绪,但首先了解 YAML 管道非常重要。请查看azure-pipelines.yml文件。当使用多阶段 YAML 管道功能时,该文件是管道。
让我们分解组成此 YAML 管道的各个组件。
触发器
由于您正在构建自动运行的 CI 管道,因此您需要一个触发器。以下触发器指示管道在 Git 主分支中检测到提交时运行。
请注意paths
部分。默认情况下,在CI构建中,如果您不明确包含或排除文件或目录,则当在任何文件上提交时,流水线将运行。由于这个项目完全围绕一个ARM模板构建,所以如果例如您对Pester测试进行了微调,您就不希望运行流水线。
池
每个构建都需要一个代理。每个构建代理需要在虚拟机上运行。在这种情况下,虚拟机使用的是ubuntu-latest
虚拟机映像。这个映像是在构建最初创建时定义的默认映像。由于这个流水线的“简单性”,它没有被更改。
变量
接下来,我们有所有的变量和变量组。此流水线中的各种任务需要读取诸如Azure订阅ID、租户ID和服务主体的应用程序ID等值。与在每个任务中复制静态值不同,它们被定义为变量。
还请注意group
元素。此元素引用了您之前创建的变量组。请务必在此时替换subscription_id
和tenant_id
。
请记住,在创建Azure服务主体部分,您被提醒要将$sp.appId
的值保存在某个地方。这就是您需要它的地方。将该服务主体应用程序ID的值分配给application_id
,如下所示。
注意
azure_resource_group_name
变量的值。在该值中,您会看到$(Build.BuildId)
。这是一个系统变量,代表当前作业的构建ID。在这个上下文中,它被用来确保创建的临时资源组是唯一的。
PowerShell 准备任务
接下来的一系列任务调用 PowerShell 代码。这个管道示例使用 PowerShell 来创建和移除一个用于测试目的的临时资源组。在这些部署任务中,您将看到两个调用 PowerShell 代码的示例。
第一个任务调用一个存在于 GitHub 仓库中的脚本connect-azure.ps1。这个任务用于认证 Azure 订阅,以便后续的 Azure PowerShell 命令能够运行。
这个 Azure PowerShell 连接任务通过调用脚本,并传递一个密钥库秘密值(ServerAutomationDemo-AppPw
)以及管道变量subscription_id
、application_id
和 tenant_id
。
第二个任务运行的 PowerShell 代码inline,意味着脚本并不存在。相反,PowerShell 代码在管道 YAML 本身中使用azure_resource_group_name
管道变量的值定义。
Pester 模板测试
接下来我们有第一个 Pester 测试。在这样一个 CI/CD 管道中,拥有几个不同层次的测试是非常重要的。如果您正在为一个软件项目创建一个管道,您可能会创建各种单元测试。
由于这个示例管道是围绕单个 ARM VM 部署构建的,因此首先要进行的“单元”测试是测试 JSON 模板的有效性。您可以在 server.templates.tests.ps1 文件中添加尽可能多的针对 ARM 模板文件本身的不同测试。
请注意下面,管道正在使用各种 系统变量。这些变量引用了文件一旦传送到构建代理后的文件位置。
PesterRunner 任务将测试结果发送到一个 XML 文件,稍后管道将读取该文件。
ARM VM 部署
我们现在来到了 ARM 部署阶段。由于整个管道都是围绕部署 VM 的能力构建的,因此这一步非常重要!该任务部署 ARM 模板,并提供了使其发生的所有必需属性。
请注意 deploymentOutputs: arm_output
属性。在下一步中,需要一个任务连接到已部署的 VM。通过 ARM 部署返回 DNS 名称或 IP 地址是获取此 VM 的一种好方法。 deploymentOutputs
选项创建了一个可以在其他任务中引用的管道变量。
Pester “接受” 测试
VM 部署完成后,您需要确保它已经通过“集成”或“接受”测试正确部署。这个 PesterRunner 任务正在调用 Pester,并运行另一组与基础设施相关的测试,以确保 VM 已成功部署。
请注意,我们通过 ArmDeploymentJsonOutput
参数传入 ARM 部署的输出值。Pester 测试脚本文件定义了一个参数,该参数接受该值并读取 VM 的 DNS 主机名。
您可以看到下面的 PowerShell 脚本文件server.infrastructure.tests.ps1的样子。请注意,它正在读取 VM 的 DNS 主机名,然后运行简单的开放端口检查。
“验收”测试清理
流水线部署基础结构的唯一原因是测试 ARM 模板的有效性。因为这个基础设施是暂时的,所以需要清理。在最后一个 PowerShell 任务中,流水线正在移除早期创建的资源组及其中的所有内容。
Pester 测试发布
最后,我们来到了最后一组任务。Azure 流水线有一个名为 发布测试结果 的任务。此任务会在构建代理上读取 XML 文件,并在 Azure DevOps 中显示测试结果。这是一种方便的方式,可以轻松查看所有运行的测试结果。

使用 Azure DevOps 流水线
最后,我们准备运行流水线并查看其工作原理。在 Azure DevOps Web UI 中,请确保您在 ServerAutomationDemo 项目中。一旦在这里,请点击 管道,然后您应该会看到 ServerAutomationDemo 管道。
运行流水线的一种方式是点击右侧的三个点,如下所示。然后,点击 运行管道。这将启动自动化过程。

流水线将继续运行,并按照指示执行每个任务。到最后,您应该看到作业执行的每个任务的所有绿色复选标记,如下所示。

清理
一旦您在流水线中摆弄过,并且您在这里完成了所有任务,您应该清理一下。毕竟,这只是一个教程,不是一个生产任务!
以下是一些命令,用于清理本文中构建的所有内容。此代码会移除服务主体、Azure AD 应用程序、资源组及其中的所有内容以及 Azure DevOps 项目。
总结
本教程旨在让您了解构建真实 Azure DevOps 基础设施自动化流水线的一瞥。尽管有无数其他构建此类流水线的方法,但您在本教程中学到的技能应该能帮助您完成许多不同的配置。
现在去吧,开始更多自动化吧!