使用 Chocolatey 设置持续部署

注意

Azure 自动化状态配置将于 2027 年 9 月 30 日停用,请在该日期前迁移到 Azure 计算机配置。 有关详细信息,请参阅博客文章公告。 Azure Machine Configuration 服务结合了 DSC 扩展、Azure 自动化 State Configuration 以及客户反馈中最常请求的功能。 Azure Machine Configuration 还包括通过已启用 Arc 的服务器提供的混合计算机支持。

重要

“添加”“撰写配置”“图库”导航链接将于 2025 年 3 月 31 日从门户中移除。

注意

适用于 Linux 的 Azure 自动化 DSC 已于 2023 年 9 月 30 日停用。

DevOps 领域中有许多工具可帮助你处理持续集成管道中的各个点。 Azure 自动化 State Configuration 是 DevOps 团队可以采用的新选项。

Azure 自动化是 Azure 中的托管服务,可让你使用 Runbook、节点和共享资源(例如凭据、计划和全局变量)自动完成各种任务。 Azure 自动化 State Configuration 扩展了此自动化功能,包含 PowerShell Desired State Configuration (DSC) 工具。 下面是全面的概述

本文演示如何为 Windows 计算机设置持续部署 (CD)。 可以轻松扩展该技术,在角色(例如网站)中按需要添加更多 Windows 计算机,并从该角色扩展到更多角色。

IaaS VM 的持续部署

总体而言

此处要处理的事项很多,幸好这些事项可划分成两个主要过程:

  • 编写并测试代码,针对系统的主要和次要版本创建并发布安装包。
  • 创建和管理用于安装和执行包中代码的 VM。

当这两个核心流程都已建立后,在创建并部署新版本时,就可以轻松地自动更新 VM 上的软件包。

组件概述

apt-get 之类的包管理器在 Linux 领域耳熟能详,但在 Windows 领域并不被大家所熟悉。 Chocolatey 是 Windows 的包管理器。 Scott Hanselman 关于 Chocolatey 的博客文章是一篇很好的介绍。 通过 Chocolatey,你可使用命令行从中央存储库将包安装到 Windows 操作系统。 可以创建和管理自己的存储库,Chocolatey 可以从指定的任何数量的存储库来安装包。

PowerShell DSC 是一个 PowerShell 工具,可使用它为计算机声明所需的配置。 例如,如果你想要安装 Chocolatey、安装 IIS、打开端口 80 并安装网站版本 1.0.0,DSC 本地配置管理器 (LCM) 将实现该配置。 DSC 拉取服务器托管一个供你的计算机使用的配置存储库。 每台计算机上的 LCM 定期检查计算机的配置是否与存储的配置匹配。 它可以报告状态,也可以尝试让计算机恢复到与存储的配置匹配。 您可以编辑拉取服务器上存储的配置,从而使一台或一组计算机与已更改的配置保持一致。

DSC 资源是具有特定功能的代码模块,例如管理网络、Active Directory 或 SQL Server。 Chocolatey DSC 资源知道如何访问 NuGet 服务器、下载包、安装包以及执行其他任务。 PowerShell 库 中有许多其他 DSC 资源。 你需要将这些模块安装到 Azure 自动化 State Configuration 拉取服务器上,以供你的配置使用。

资源管理器模板提供了一种声明性方法来为基础结构生成资源,例如:

  • 网络和子网
  • 网络安全
  • 路由,
  • 负载均衡器,
  • NIC、VM 等

有关资源管理器部署模型(声明性)和 Azure 经典部署模型(命令性)的比较情况,请参阅 Azure 资源管理器与经典部署。 本文讨论了核心资源提供程序:计算、存储和网络。

资源管理器模板的一项主要功能是能够在 VM 预配期间安装 VM 扩展。 VM 扩展模块具有特定功能,例如运行自定义脚本、安装防病毒软件或运行 DSC 配置脚本。 有许多其他类型的 VM 扩展。

示意图速览

从最开始,你要编写代码、构建代码并进行测试,然后创建安装包。 Chocolatey 可以处理各种类型的安装包,例如 MSI、MSU、ZIP。 如果 Chocolatey 的原生功能不够用,你还可以借助 PowerShell 的全部功能来执行实际安装操作。 将包放入可访问的位置,即包存储库。 本用例使用 Azure Blob 存储帐户中的公共文件夹,但它可以位于任何位置。 Chocolatey 原生支持与 NuGet 服务器及其他少数几个服务器配合使用,以管理包元数据。 本文介绍了相应的选项。 本用例使用 NuGet。 Nuspec 是用于描述你的包的元数据。 Nuspec 信息编译到 NuPkg 中,并存储在 NuGet 服务器上。 当配置按名称请求某个包并引用 NuGet 服务器时,VM 中的 Chocolatey DSC 资源将获取并安装该包。 也可以请求特定版本的包。

示意图左下方有一个 Azure 资源管理器模板。 在此使用示例中,VM 扩展将该 VM 作为节点注册到 Azure 自动化 State Configuration 拉取服务器。 此配置存储在拉取服务器中两次:一次以纯文本存储,一次编译为 MOF 文件。 在 Azure 门户中,MOF 代表节点配置,而不只是简单配置。

创建 Nuspec、编译它并将其存储在 NuGet 服务器中相对简单。 持续部署的下一步要求执行下列一次性任务:

  • 设置拉取服务器
  • 将节点注册到服务器
  • 在服务器上创建初始配置

将包升级并部署到存储库时,只需要刷新拉取服务器中的配置和节点配置。

如果不是从资源管理器模板开始,有 PowerShell 命令来帮助你将 VM 注册到拉取服务器。 有关详细信息,请参阅将计算机加入 Azure 自动化 State Configuration 管理

使用示例说明

本文中的用例是从一个来自于 Azure 库的通用 Windows Server 2012 R2 映像的 VM 开始的。 可以从任何存储的映像开始,并使用 DSC 配置对其进行调整。 不过,更改已刻入映像的配置要比使用 DSC 动态更新配置难得多。

将此技巧运用于 VM 时,不需要使用资源管理器模板和 VM 扩展。 而且,您的虚拟机不必位于 Azure 上,也可以纳入 CD 管理。 只需在 VM 上安装 Chocolatey 并配置 LCM,使其知道拉取服务器位于何处即可。

在生产环境中的 VM 上更新软件包时,需要在安装更新期间将该 VM 从轮换中移除。 具体的操作根据情况而有很大的差异。 例如,对于位于 Azure 负载均衡器后面的 VM,可以添加自定义探测。 更新 VM 时,使探测端点返回 400。实现这一更改所需的调整可以在配置中进行;更新完成后,也可以通过在配置中进行相应调整,将其切换回返回 200。

GitHub 上的此 Visual Studio 项目中提供了本用例的完整源代码。

步骤 1:设置拉取服务器和自动化帐户

在经过身份验证的 (Connect-AzAccount -Environment AzureChinaCloud) PowerShell 会话中运行以下命令:

New-AzResourceGroup -Name MY-AUTOMATION-RG -Location MY-RG-LOCATION-IN-QUOTES
$newAzAutomationAccountSplat = @{
    ResourceGroupName = 'MY-AUTOMATION-RG'
    Location = 'MY-RG-LOCATION-IN-QUOTES'
    Name = 'MY-AUTOMATION-ACCOUNT'
}
New-AzAutomationAccount @newAzAutomationAccountSplat

步骤 2:对资源管理器模板中的 VM 扩展进行调整

虚拟机注册详情(使用PowerShell DSC VM扩展)见此[Azure Quickstart Template][12]。 此步骤将在状态配置节点列表中向拉取服务器注册您的新虚拟机。 注册过程的一部分是指定将应用于该节点的节点配置。 此节点配置不一定要存在于拉取服务器中,但你需要选择节点的名称和配置的名称。 在此示例中,节点是 isvbox,配置名称是 ISVBoxConfig。 在 DeploymentTemplate.json 中指定的节点配置名称是 ISVBoxConfig.isvbox

步骤 3:将所需的 DSC 资源添加到拉取服务器

PowerShell 库可以将 DSC 资源安装到 Azure 自动化帐户中。 导航到所需的资源,然后选择“部署到 Azure 自动化”。

PowerShell 库示例

Azure 门户最近添加的另一种技术允许提取新模块或更新现有模块。 然后选择 浏览库 图标以查看库中的模块列表、深入查看详细信息,并将其导入到自动化帐户中。 可以使用此过程使模块保持最新。 此外,导入功能会检查与其他模块的依赖性,以确保所有模块都保持同步。

另外还有一种手动方法,只对每个资源使用一次(除非以后再升级)。 有关编写PowerShell集成模块的更多信息,请参见[Authoring Integration Modules for Azure 自动化][11]。

注意

适用于 Windows 计算机的 PowerShell 集成模块的文件夹结构与 Azure 自动化所需的文件夹结构稍有不同。

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

  2. 安装集成模块。

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

  4. 删除主文件夹中的示例和文档。

  5. 压缩主文件夹,ZIP 文件应使用该文件夹的名称命名。

  6. 将 ZIP 文件放到可访问的 HTTP 位置,例如 Azure 存储帐户中的 Blob 存储。

  7. 运行以下命令。

    $newAzAutomationModuleSplat = @{
        ResourceGroupName = 'MY-AUTOMATION-RG'
        AutomationAccountName = 'MY-AUTOMATION-ACCOUNT'
        Name = 'MODULE-NAME'
        ContentLinkUri = 'https://STORAGE-URI/CONTAINERNAME/MODULE-NAME.zip'
    }
    New-AzAutomationModule @newAzAutomationModuleSplat
    

随附的示例针对 cChoco 和 xNetworking 实施了这些步骤。

步骤 4:将节点配置添加到拉取服务器

第一次将配置导入拉取服务器并编译时,并没有什么特别之处。 后续导入或编译相同的配置时,过程完全相同。 每次更新包且需要向外推送到生产环境时,在确保配置文件(包括包的新版本)正确之后,就可以执行此步骤。 下面是配置文件 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 PowerShell 模块:

$importAzAutomationDscConfigurationSplat = @{
    ResourceGroupName = 'MY-AUTOMATION-RG'
    AutomationAccountName = 'MY-AUTOMATION-ACCOUNT'
    SourcePath = 'C:\temp\AzureAutomationDsc\ISVBoxConfig.ps1'
    Published = -Published
    Force = -Force
}
Import-AzAutomationDscConfiguration @importAzAutomationDscConfigurationSplat

$startAzAutomationDscCompilationJobSplat = @{
    ResourceGroupName = 'MY-AUTOMATION-RG'
    AutomationAccountName = 'MY-AUTOMATION-ACCOUNT'
    ConfigurationName = 'ISVBoxConfig'
}
$jobData = Start-AzAutomationDscCompilationJob @startAzAutomationDscCompilationJobSplat

$compilationJobId = $jobData.Id

$getAzAutomationDscCompilationJobSplat = @{
    ResourceGroupName = 'MY-AUTOMATION-RG'
    AutomationAccountName = 'MY-AUTOMATION-ACCOUNT'
    Id = $compilationJobId
}
Get-AzAutomationDscCompilationJob @getAzAutomationDscCompilationJobSplat

步骤 5:创建和维护包元数据

对于放入包存储库中的每一个包,需要使用 Nuspec 来描述它。 其必须经过编译并存储在 NuGet 服务器中。 有关详细信息,请参阅[使用 nuget.exe CLI 创建 NuGet 包]

可以使用 MyGet.org 作为 NuGet 服务器。 你可以购买此服务,但也有一个免费的入门 SKU。 有关为专用包安装你自己的 NuGet 服务器的说明,请查看 Nuget.org 上的文档。

步骤 6:将其捆绑在一起

每当有某个版本通过 QA 和部署批准时,即会创建包,nuspec 和 nupkg 会更新并部署到 NuGet 服务器。 必须使用新的版本号更新配置(步骤 4)。 然后,将其发送到拉取服务器并对其进行编译。

然后,依赖于该配置的 VM 将提取并安装更新。 其中的每项更新都很简单 - 只需一两行的 PowerShell 即可完成。 对于 Azure DevOps,其中一些被封装在生成任务中,你可以在一次生成中将这些链接在一起。 本文提供更多详细信息。 此 GitHub 存储库详细介绍了各种可用的生成任务。

后续步骤