使用 Chocolatey 设置持续部署Set up continuous deployment with Chocolatey

DevOps 领域中有许多工具可帮助你处理持续集成管道中的各个点。In a DevOps world, there are many tools to assist with various points in the continuous integration pipeline. Azure Automation State Configuration 是 DevOps 团队可以采用的新选项。Azure Automation State Configuration is a welcome new addition to the options that DevOps teams can employ.

Azure 自动化是 Azure 中的托管服务,可让你使用 Runbook、节点和共享资源(例如凭据、计划和全局变量)自动完成各种任务。Azure Automation is a managed service in Azure that allows you to automate various tasks using runbooks, nodes, and shared resources, such as credentials, schedules, and global variables. Azure Automation State Configuration 扩展了此自动化功能,以包含 PowerShell Desired State Configuration (DSC) 工具。Azure Automation State Configuration extends this automation capability to include PowerShell Desired State Configuration (DSC) tools. 下面是全面的概述Here's a great overview.

本文演示如何为 Windows 计算机设置持续部署 (CD)。This article demonstrates how to set up Continuous Deployment (CD) for a Windows computer. 可以轻松扩展该技术,在角色(例如网站)中按需要添加更多 Windows 计算机,并从该角色扩展到其他角色。You can easily extend the technique to include as many Windows computers as necessary in the role, for example, a website, and go from there to additional roles.

IaaS VM 的持续部署

概括而言At a high level

此处要处理的事项很多,幸好这些事项可划分成两个主要过程:There's quite a bit going on here, but fortunately it can be broken down into two main processes:

  • 编写并测试代码,针对系统的主要和次要版本创建并发布安装包。Writing code and testing it, then creating and publishing installation packages for major and minor versions of the system.
  • 创建和管理用于安装和执行包中代码的 VM。Creating and managing VMs that install and execute the code in the packages.

完成这两个核心过程后,随着创建和部署新版本,自动更新 VM 上的包很简单。Once both of these core processes are in place, it's easy to automatically update the package on your VMs as new versions are created and deployed.

组件概述Component overview

apt-get 之类的包管理器在 Linux 领域耳熟能详,但在 Windows 领域并不被大家所熟悉。Package managers such as apt-get are well known in the Linux world, but not so much in the Windows world. Chocolatey 就是这样一个工具,Scott Hanselman 有关该工具主题的博客对此工具进行了深入介绍。Chocolatey is such a thing, and Scott Hanselman's blog on the topic is a great introduction. 简单地说,Chocolatey 可让你使用命令行从中央存储库将包安装到 Windows 操作系统。In a nutshell, Chocolatey allows you to use the command line to install packages from a central repository onto a Windows operating system. 可以创建和管理自己的存储库,Chocolatey 可以从指定的任何数量的存储库来安装包。You can create and manage your own repository, and Chocolatey can install packages from any number of repositories that you designate.

PowerShell DSC 是一个 PowerShell 工具,可使用它为计算机声明所需的配置。PowerShell DSC is a PowerShell tool that allows you to declare the configuration that you want for a machine. 例如,如果你想要安装 Chocolatey、安装 IIS、打开端口 80 并安装网站版本 1.0.0,DSC 本地配置管理器 (LCM) 将实现该配置。For example, if you want Chocolatey installed, IIS installed, port 80 opened, and version 1.0.0 of your website installed, the DSC Local Configuration Manager (LCM) implements that configuration. DSC 拉取服务器有一个存储库用于保存计算机的配置。A DSC pull server holds a repository of configurations for your machines. 每台计算机上的 LCM 定期检查计算机的配置是否与存储的配置匹配。The LCM on each machine checks in periodically to see if its configuration matches the stored configuration. 它可以报告状态,也可以尝试让计算机恢复到与存储的配置匹配。It can either report status or attempt to bring the machine back into alignment with the stored configuration. 可以编辑“拉”服务器上存储的配置,使一台计算机或一组计算机与更改的配置匹配。You can edit the stored configuration on the pull server to cause a machine or set of machines to come into alignment with the changed configuration.

DSC 资源是具有特定功能的代码模块,例如管理网络、Active Directory 或 SQL Server。A DSC resource is a module of code that has specific capabilities, such as managing networking, Active Directory, or SQL Server. Chocolatey DSC 资源知道如何访问 NuGet 服务器(以及其他组件)、下载包、安装包,等等。The Chocolatey DSC Resource knows how to access a NuGet Server (among others), download packages, install packages, and so on. PowerShell 库中有许多其他 DSC 资源。There are many other DSC Resources in the PowerShell Gallery. 在 Azure Automation State Configuration 拉取服务器上安装这些模块以供配置使用。You install these modules on your Azure Automation State Configuration pull server for use by your configurations.

Resource Manager 模板以声明方式生成基础结构,例如网络、子网、网络安全性和路由、负载均衡器、NIC、VM,等等。Resource Manager templates provide a declarative way of generating your infrastructure, for example, networks, subnets, network security and routing, load balancers, NICs, VMs, and so on. 这篇文章比较了资源管理器部署模型(声明性)和 Azure 服务管理(ASM 或经典)部署模型(命令性)。Here's an article that compares the Resource Manager deployment model (declarative) with the Azure Service Management (ASM or classic) deployment model (imperative). 本文讨论了核心资源提供程序:计算、存储和网络。This article includes a discussion of the core resource providers: compute, storage, and network.

资源管理器模板的一项主要功能是在预配时将 VM 扩展安装到 VM 中。One key feature of a Resource Manager template is its ability to install a VM extension into the VM as it's provisioned. VM 扩展模块具有特定功能,例如运行自定义脚本、安装防病毒软件或运行 DSC 配置脚本。A VM extension has specific capabilities, such as running a custom script, installing anti-virus software, and running a DSC configuration script. 有许多其他类型的 VM 扩展。There are many other types of VM extensions.

示意图速览Quick trip around the diagram

首先,需要编写、生成和测试代码,然后创建安装包。Starting at the top, you write your code, build it, test it, then create an installation package. Chocolatey 可以处理各种类型的安装包,例如 MSI、MSU、ZIP。Chocolatey can handle various types of installation packages, such as MSI, MSU, ZIP. 如果 Chocolatey 的本机功能不足以满足需要,还有 PowerShell 的完整功能可执行实际安装。And you have the full power of PowerShell to do the actual installation if Chocolatey's native capabilities aren't up to it. 将包放入可访问的位置 - 包存储库。Put the package into some place reachable – a package repository. 本用例使用 Azure Blob 存储帐户中的公共文件夹,但它可以位于任何位置。This usage example uses a public folder in an Azure blob storage account, but it can be anywhere. Chocolatey 原生可配合 NuGet 服务器和其他某些工具一起管理包元数据。Chocolatey works natively with NuGet servers and a few others for management of package metadata. 本文介绍了相应的选项。This article describes the options. 本用例使用 NuGet。The usage example uses NuGet. Nuspec 是包的元数据。A Nuspec is metadata about your packages. Nuspec 信息编译到 NuPkg 中,并存储在 NuGet 服务器上。The Nuspec information is compiled into a NuPkg and stored on a NuGet server. 当配置按名称请求某个包并引用 NuGet 服务器时,VM 中的 Chocolatey DSC 资源将获取并安装该包。When your configuration requests a package by name and references a NuGet server, the Chocolatey DSC resource on the VM grabs the package and installs it. 也可以请求特定版本的包。You can also request a specific version of a package.

示意图左下方有一个 Azure 资源管理器模板。In the bottom left of the picture, there's an Azure Resource Manager template. 在本用例中,VM 扩展将 VM 注册到 Azure Automation State Configuration 拉取服务器成为一个节点。In this usage example, the VM extension registers the VM with the Azure Automation State Configuration pull server as a node. 此配置存储在拉取服务器中两次:一次以纯文本存储,一次编译为 MOF 文件。The configuration is stored in the pull server twice: once as plain text and once compiled as a MOF file. 在 Azure 门户中,MOF 代表节点配置,而不只是简单配置。In the Azure portal, the MOF represents a node configuration, as opposed to a simple configuration. 它是与节点关联的项目,因而节点知道它的配置。It's the artifact that's associated with a node so the node will know its configuration. 以下详细信息演示如何将节点配置分配给节点。Details below show how to assign the node configuration to the node.

创建和编译 Nuspec 并将其存储在 NuGet 服务器非常简单。Creating the Nuspec, compiling it, and storing it in a NuGet server is a small thing. 此外,你已在管理 VM。And you're already managing VMs.

持续部署的下一步需要设置拉取服务器一次、向它注册节点一次,然后创建初始配置并存储到服务器中。Taking the next step to continuous deployment requires setting up the pull server one time, registering your nodes with it one time, and creating and storing the initial configuration on the server. 当包升级并部署到存储库时,仅需根据需要刷新拉取服务器中的配置和节点配置。As packages are upgraded and deployed to the repository, you only have to refresh the configuration and node configuration on the pull server as needed.

如果不是从资源管理器模板开始,也没关系。If you're not starting with a Resource Manager template, that's fine. 有一些 PowerShell 命令可帮助你向拉取服务器注册 VM。There are PowerShell commands to help you register your VMs with the pull server. 有关详细信息,请参阅登记由 Azure Automation State Configuration 管理的计算机For more information, see Onboarding machines for management by Azure Automation State Configuration.

关于使用示例About the usage example

本文中的用例是从一个来自于 Azure 库的通用 Windows Server 2012 R2 映像的 VM 开始的。The usage example in this article starts with a VM from a generic Windows Server 2012 R2 image from the Azure gallery. 可以从任何存储的映像开始,并使用 DSC 配置对其进行调整。You can start from any stored image and then tweak from there with the DSC configuration. 不过,更改已刻入映像的配置要比使用 DSC 动态更新配置难得多。However, changing configuration that is baked into an image is much harder than dynamically updating the configuration using DSC.

将此技巧运用于 VM 时,不需要使用资源管理器模板和 VM 扩展。You don't have to use a Resource Manager template and the VM extension to use this technique with your VMs. 即使 VM 不在 Azure 上,也能由 CD 管理。And your VMs don't have to be on Azure to be under CD management. 只需在 VM 上安装 Chocolatey 并配置 LCM,以使其知道“拉”服务器的所在位置即可。All that's necessary is that Chocolatey be installed and the LCM configured on the VM so it knows where the pull server is.

在生产环境中的 VM 上更新包时,在安装更新的过程中,需要将 VM 从轮转列表中排除。When you update a package on a VM that's in production, you need to take that VM out of rotation while the update is installed. 具体的操作根据情况而有很大的差异。How you do this varies widely. 例如,如果 VM 在 Azure 负载均衡器后面,则可以添加自定义探测。For example, with a VM behind an Azure Load Balancer, you can add a Custom Probe. 更新 VM 时,让探测终结点返回 400。While updating the VM, have the probe endpoint return a 400. 可在配置中进行所需的调整来造成这种更改,但更新完成时,调整将切换为返回 200。The tweak necessary to cause this change can be inside your configuration, as can the tweak to switch it back to returning a 200 once the update is complete.

GitHub 上的此 Visual Studio 项目中提供了本用例的完整源代码。Full source for this usage example is in this Visual Studio project on GitHub.

步骤 1:设置拉取服务器和自动化帐户Step 1: Set up the pull server and Automation account

在经过身份验证的 (Connect-AzAccount -Environment AzureChinaCloud) PowerShell 命令行中:(如果设置请求服务器,则可能需要几分钟时间)At an authenticated (Connect-AzAccount -Environment AzureChinaCloud) PowerShell command line: (can take a few minutes while the pull server is set up)


步骤 2:使 VM 扩展根据资源管理器模板进行调整Step 2: Make VM extension tweaks to the Resource Manager template

Azure 快速入门模板提供了 VM 注册(使用 PowerShell DSC VM 扩展)的详细信息。Details for VM registration (using the PowerShell DSC VM extension) provided in this Azure Quickstart Template. 此步骤将新的 VM 注册到“拉”服务器的 State Configuration 节点列表中。This step registers your new VM with the pull server in the list of State Configuration Nodes. 此注册的一部分指定要应用到节点的节点配置。Part of this registration is specifying the node configuration to be applied to the node. 此节点配置尚无需存在于拉取服务器中,因此第一次可以在步骤 4 中执行该操作。This node configuration doesn't have to exist yet in the pull server, so it's fine that step 4 is where this is done for the first time. 但在步骤 2 中,需要确定节点名称和配置名称。But here in Step 2 you do need to have decided the name of the node and the name of the configuration. 在本用例中,节点名称为“isvbox”,配置名称为“ISVBoxConfig”。In this usage example, the node is 'isvbox' and the configuration is 'ISVBoxConfig'. 因此,节点配置名称(会在 DeploymentTemplate.json 中指定)为“ISVBoxConfig.isvbox”。So the node configuration name (to be specified in DeploymentTemplate.json) is 'ISVBoxConfig.isvbox'.

步骤 3:将所需的 DSC 资源添加到拉取服务器Step 3: Add required DSC resources to the pull server

还有一种手动方法,但该方法只能对每个资源使用一次,除非以后要升级该资源。There's a manual approach, used only once per resource, unless you want to upgrade it later.


适用于 Windows 计算机的 PowerShell 集成模块的文件夹结构与 Azure 自动化所需的文件夹结构稍有不同。The folder structure of a PowerShell integration module for a Windows computer is a little different from the folder structure expected by the Azure Automation.

  1. 安装 Windows Management Framework v5(对于 Windows 10 不需要安装)。Install Windows Management Framework v5 (not needed for Windows 10).

  2. 安装集成模块。Install the integration module.

    Install-Module –Name MODULE-NAME`    <—grabs the module from the PowerShell Gallery
  3. 将模块文件夹从 c:\Program Files\WindowsPowerShell\Modules\MODULE-NAME 复制到临时文件夹中。Copy the module folder from c:\Program Files\WindowsPowerShell\Modules\MODULE-NAME to a temporary folder.

  4. 删除主文件夹中的示例和文档。Delete samples and documentation from the main folder.

  5. 压缩主文件夹,ZIP 文件应使用该文件夹的名称命名。Zip the main folder, naming the ZIP file with the name of the folder.

  6. 将 ZIP 文件放到可访问的 HTTP 位置,例如 Azure 存储帐户中的 Blob 存储。Put the ZIP file into a reachable HTTP location, such as blob storage in an Azure Storage account.

  7. 运行以下命令。Run the following command.

    New-AzAutomationModule `
      -ResourceGroupName MY-AUTOMATION-RG -AutomationAccountName MY-AUTOMATION-ACCOUNT `

随附的示例针对 cChoco 和 xNetworking 实施了这些步骤。The included example implements these steps for cChoco and xNetworking.

步骤 4:将节点配置添加到拉取服务器Step 4: Add the node configuration to the pull server

首次将配置导入到“拉”服务器并进行编译并没有什么特别之处。There's nothing special about the first time you import your configuration into the pull server and compile. 后续导入或编译相同的配置时,过程完全相同。All later imports or compilations of the same configuration look exactly the same. 每次更新包且需要向外推送到生产环境时,在确保配置文件(包括包的新版本)正确之后,就可以执行此步骤。Each time you update your package and need to push it out to production you do this step after ensuring the configuration file is correct – including the new version of your package. 配置文件 ISVBoxConfig.ps1 如下所示:Here's the configuration file ISVBoxConfig.ps1:

Configuration ISVBoxConfig
    Import-DscResource -ModuleName cChoco
    Import-DscResource -ModuleName xNetworking

    Node 'isvbox' {

        cChocoInstaller installChoco
            InstallDir = 'C:\choco'

        WindowsFeature installIIS
            Ensure = 'Present'
            Name   = 'Web-Server'

        xFirewall WebFirewallRule
            Direction    = 'Inbound'
            Name         = 'Web-Server-TCP-In'
            DisplayName  = 'Web Server (TCP-In)'
            Description  = 'IIS allow incoming web site traffic.'
            Enabled       = 'True'
            Action       = 'Allow'
            Protocol     = 'TCP'
            LocalPort    = '80'
            Ensure       = 'Present'

        cChocoPackageInstaller trivialWeb
            Name      = 'trivialweb'
            Version   = '1.0.0'
            Source    = 'MY-NUGET-V2-SERVER-ADDRESS'
            DependsOn = '[cChocoInstaller]installChoco','[WindowsFeature]installIIS'

下面是 New-ConfigurationScript.ps1 脚本(已修改为使用 Az 模块):Here is the New-ConfigurationScript.ps1 script (modified to use the Az module):

Import-AzAutomationDscConfiguration `
    -ResourceGroupName MY-AUTOMATION-RG –AutomationAccountName MY-AUTOMATION-ACCOUNT `
    -SourcePath C:\temp\AzureAutomationDsc\ISVBoxConfig.ps1 `
    -Published –Force

$jobData = Start-AzAutomationDscCompilationJob `
    -ResourceGroupName MY-AUTOMATION-RG –AutomationAccountName MY-AUTOMATION-ACCOUNT `
    -ConfigurationName ISVBoxConfig

$compilationJobId = $jobData.Id

Get-AzAutomationDscCompilationJob `
    -ResourceGroupName MY-AUTOMATION-RG –AutomationAccountName MY-AUTOMATION-ACCOUNT `
    -Id $compilationJobId

这些步骤会生成要放在拉取服务器上的名为“ISVBoxConfig.isvbox”的新节点配置。These steps result in a new node configuration named ISVBoxConfig.isvbox being placed on the pull server. 生成的节点配置名称为 configurationName.nodeNameThe node configuration name is built as configurationName.nodeName.

步骤 5:创建和维护包元数据Step 5: Create and maintain package metadata

对于放入包存储库中的每一个包,需要使用 Nuspec 来描述它。For each package that you put into the package repository, you need a Nuspec that describes it. 其必须经过编译并存储在 NuGet 服务器中。It must be compiled and stored on your NuGet server. 此处对该过程进行了说明。This process is described here.

可以使用 MyGet.org 作为 NuGet 服务器。You can use MyGet.org as a NuGet server. 你可以购买此服务,但这是免费的入门 SKU。You can buy this service, but thee is a free starter SKU. NuGet 中,可以找到为专用包安装你自己的 NuGet 服务器的说明。At NuGet, you'll find instructions on installing your own NuGet server for your private packages.

步骤 6:将其捆绑在一起Step 6: Tie it all together

每当有某个版本通过 QA 和部署批准时,即会创建包,nuspec 和 nupkg 会更新并部署到 NuGet 服务器。Each time a version passes QA and is approved for deployment, the package is created, and nuspec and nupkg are updated and deployed to the NuGet server. 还必须更新配置(步骤 4)以便与新版本号匹配。The configuration (step 4) must also be updated to agree with the new version number. 随后配置必须发送到拉取服务器并进行编译。It must then be sent to the pull server and compiled.

然后,依赖于该配置的 VM 将提取并安装更新。From that point on, it's up to the VMs that depend on that configuration to pull the update and install it. 其中的每项更新都很简单 - 只需一两行的 PowerShell 即可完成。Each of these updates is simple - just a line or two of PowerShell. 对于 Azure DevOps,有些更新封装在可一起链接到内部版本内的生成任务中。For Azure DevOps, some of them are encapsulated in build tasks that can be chained together in a build. 本文提供更多详细信息。This article provides more details. GitHub 存储库详细介绍了各种可用的生成任务。This GitHub repo details the available build tasks.

后续步骤Next steps