使用 Chocolatey 设置持续部署

注意

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

注意

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

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

Azure 自动化是 Azure 中的托管服务,可让你使用 Runbook、节点和共享资源(例如凭据、计划和全局变量)自动完成各种任务。 Azure Automation 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 Automation 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 Automation State Configuration 拉取服务器成为一个节点。 此配置存储在拉取服务器中两次:一次以纯文本存储,一次编译为 MOF 文件。 在 Azure 门户中,MOF 代表节点配置,而不只是简单配置。

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

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

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

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

关于使用示例

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

将此技巧运用于 VM 时,不需要使用资源管理器模板和 VM 扩展。 即使 VM 不在 Azure 上,也能由 CD 管理。 只需在 VM 上安装 Chocolatey 并配置 LCM,使其知道拉取服务器位于何处即可。

在生产环境中的 VM 上更新包时,在安装更新的过程中,需要将 VM 从轮转列表中排除。 具体的操作根据情况而有很大的差异。 例如,如果 VM 在 Azure 负载均衡器后面,则可以添加自定义探测。 更新 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 扩展根据资源管理器模板进行调整

Azure 快速入门模板提供了 VM 注册(使用 PowerShell DSC VM 扩展)的详细信息。 此步骤将新的 VM 注册到“拉”服务器的 State Configuration 节点列表中。 此注册的一部分指定要应用到节点的节点配置。 此节点配置不一定要存在于拉取服务器中,但你需要选择节点的名称和配置的名称。 在此示例中,节点是 isvbox,配置名称是 ISVBoxConfig。 在 DeploymentTemplate.json 中指定的节点配置名称是 ISVBoxConfig.isvbox

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

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

PowerShell 库示例

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

另外还有一种手动方法,只对每个资源使用一次(除非以后再升级)。 有关创作 PowerShell 集成模块的详细信息,请参阅为Azure自动化创作集成模块

注意

适用于 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 存储库详细介绍了各种可用的生成任务。

后续步骤