部署到环境中的 Linux VM

Azure DevOps Services |Azure DevOps Server |Azure DevOps Server 2022 |Azure DevOps Server 2020

可以在 Azure Pipelines 环境中 将虚拟机添加为资源,并将其作为部署目标。 对于持续集成和持续部署(CI/CD)工作流,环境的部署历史记录为每个 VM 提供可追溯性,返回到触发提交。

本文介绍如何设置 Azure DevOps 管道,以便部署到环境中的多个 Linux 虚拟机(VM)资源 。 这些说明生成并部署 JavaScript 或 Java 应用,但你可以针对发布 Web 部署包的任何应用对其进行调整。

有关部署作业面向的环境和资源的详细信息,请参阅 jobs.deployment.environment YAML 架构定义。 有关部署作业的详细信息,请参阅 jobs.deployment 定义。

先决条件

此外,对于 JavaScript 或 Node.js 应用:

重要

  • 若要部署应用,目标环境 VM 资源必须安装并配置所有必要的软件、依赖项、权限和登录名。
  • 若要使用 GitHub 源代码,需要 GitHub 服务连接。 GitHub 还可能会提示你登录、安装 Azure Pipelines GitHub 应用或授权 Azure Pipelines。 若要完成每个过程,请按照屏幕上的说明进行作。 有关详细信息,请参阅访问 GitHub 存储库

创建环境并添加 Linux VM

在 Azure Pipelines 项目中,按照 “创建环境”中的说明创建环境并添加 VM,将 Linux VM 添加为环境资源。

在每个 VM 上运行复制的代理注册脚本,以在环境中注册它。 还可以通过响应交互式提示将标记分配给各个 VM。

创建并运行生成管道

每当向代码存储库的main分支提交更改时,创建一个 CI 管道以构建和部署您的应用程序。

创建 YAML 管道

  1. 在 Azure DevOps 项目中,选择 “管道>新建管道 ”或 “创建管道”,然后选择 GitHub 作为源代码的位置。
  2. “选择存储库 ”屏幕上,选择分叉示例存储库。
  3. 在“配置管道”屏幕上,选择“入门管道”。
  4. “查看管道 YAML”屏幕上,根据您的运行时环境,将生成的初始代码替换为以下代码。

添加构建作业

Build 作业运行任务来生成和测试项目,并将生成输出上传到某个 drop 位置。 此作业在管道 pool中指定的生成代理上运行,而不是在 Linux 环境 VM 上运行。

以下管道使用 npm 生成并测试 Node.js 项目,然后打包输出并将其上传到放置位置。

trigger:
- main

pool:
  vmImage: ubuntu-latest

jobs:  
- job: Build
  displayName: Build
  steps:
  - task: UseNode@1
    inputs:
      version: '16.x'
    displayName: 'Install Node.js'
  - script: |
      npm install
      npm run build --if-present
      npm run test --if-present
    displayName: 'npm install, build and test'
  - task: ArchiveFiles@2
    displayName: 'Archive files'
    inputs:
      rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
      includeRootFolder: false
      archiveType: tar
      tarCompression: gz
      archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).gz
      replaceExistingArchive: true
  - upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).gz
    artifact: drop

有关详细信息,请查看使用 gulp 构建 Node.js 应用中的构建步骤。

运行管道

若要将 azure-pipelines.yml 文件保存到存储库并启动 CI/CD 管道,请选择“ 保存并运行”,然后选择“ 保存并再次运行 ”。

管道完成后,查看作业 摘要 页以验证生成作业是否成功运行,并且 1 个已发布 的项目显示在 “相关”下。

添加并运行部署作业

部署作业依次执行preDeploydeployrouteTrafficpostRouteTraffic生命周期钩子一次,然后执行on: success或者on: failure。 如果部署到环境 VM,阶段 preDeploy 将在构建代理上运行,而不是在环境 VM 上运行。 所有其他步骤都在环境中的已注册 VM 上运行。

  1. 可选 preDeploy 步骤在部署之前运行。 可以使用此步骤进行业务流程、VM 和项目准备以及运行状况检查。
  2. 此步骤 deploy 将部署对象部署到目标环境 VM。
  3. 可选步骤 routeTraffic 可用于流量切换。
  4. 可选的 postRouteTraffic 步骤可以进行健康检查和通知。
  5. 自定义 on.failureon.success 步骤可以提供通知或恢复。

将部署作业到resourceType: VirtualMachine需要环境虚拟机能够运行所有流水线任务,例如 Bash 或 Azure CLI。 可以使用此步骤 preDeploy 在目标 VM 上安装必要的软件和权限。

例如,如果部署步骤使用 Azure CLI,则代理 VM 必须安装 Azure CLI,并在代理用户的 PATH 上可用。 代理用户必须具有运行 CLI 的权限,并且必须向 Azure 进行身份验证。 可能需要将代理用户添加到 sudoers,或设置环境变量以自动安装。

可以使用 preDeploy 脚本在目标 VM 上安装 Azure CLI。 若要向 Azure 进行身份验证,可以运行az login或自动化,定义服务主体并在步骤az login --service-principal中运行preDeploy

添加部署任务

以下示例部署作业会在 Build 作业成功完成后启动。 若要将作业添加到您的管道,请执行以下操作:

  1. 选择“摘要”页上右上角的“更多作”图标,选择“编辑管道”,并将以下代码添加到管道末尾。 将 <environment-name> 替换为您创建的环境名称。

    (可选)可以通过选择环境中的特定 VM 并使用 tags 参数指定为 VM 定义的 <VMtag>,来接收部署。

    - deployment: VMDeploy
      displayName: Web deploy
      dependsOn: Build
      condition: succeeded()
      environment:
        name: <environment-name>
        resourceType: VirtualMachine
        tags: <VMtag> # VMs to deploy to
    
  2. 向作业添加 a strategydeploymentrunOnce 部署策略是最简单的,如果未指定strategy,则默认运行。 此策略在环境中的每个 VM 上执行一次部署步骤,而无需任何并行度或流量管理。

      strategy:
         runOnce:
           deploy:
              steps:
              - script: echo my first deployment
    
  3. 添加部署作业后,选择“ 验证并保存”,然后选择“ 保存”,选择“ 运行”,然后选择“再次 运行 ”。 每次运行此作业时,部署历史记录都会关联到环境。

    注意

    首次运行使用环境的管道时,必须向管道的所有运行授予访问代理池和环境的权限。 在管道运行摘要屏幕上选择作业旁的“等待”符号,然后选择“允许”授予必要的权限。

滚动部署策略

您可以使用rolling,而不是runOnce部署策略。 滚动部署策略可以协调并行度、运行状况检查和流量路由。 runOnce虽然策略一次在单个 VM 上执行,但滚动部署可以在最多五个目标 VM 的滚动集上并行运行,具体取决于maxParallel设置。

maxParallel 参数设置必须保持可用的 VM 的数量或百分比,确保应用可以处理请求,并减少部署期间的总体停机时间。 此参数还确定部署的成功和失败条件。

有关滚动部署策略的详细信息,请参阅 jobs.deployment.strategy.rolling 架构定义。

部署作业示例

部署到 VM 资源时,VM 需要安装并配置所有必需的应用、依赖项和权限。 必须手动预安装这些要求,或者管道必须安装或实现这些要求。

将 Java 应用部署到 VM 资源更容易实现,因为它是自包含的。 Java 虚拟机(JVM)通常预安装在 VM 代理上,无需担心应用依赖项、权限或包管理。 只需下载 JAR 文件,然后通过 java -jar 运行。

Node.js 应用需要在每个代理 VM 上存在并配置 Node、可能还需要 npm 依赖项,以及像 systemd 这样的服务管理器。 若要自动化,管道部署脚本必须是非交互的,并且能够重启和管理应用的服务。

JavaScript 应用的以下 YAML rolling 部署作业取决于成功完成 Build 阶段。 部署作业假定每个代理 VM 上已预安装或预配置以下要求。 对于完全自动化,可以在 VM 上安装和配置这些应用和服务作为管道的一部分。

  • 已安装 Node.js 16.x,并确保 npm 在构建代理的 PATH 中可用。
  • 系统使用一个 systemd 服务文件(如 /etc/systemd/system/pipelines-javascript.service)来配置服务并启动 Node.js 应用。
  • 对于代理用户的必要命令,可在 NOPASSWD:/etc/sudoers 中设置免密码 sudo。
  • 为代理用户写入 /opt/pipelines-javascript 或其他部署目标的权限。

小窍门

对于大多数 Node.js 应用,请考虑部署到 Azure 应用服务 或使用具有 Microsoft 托管代理的常规管道作业,而不使用部署作业。 此方法更简单,可避免管理 VM 环境的运营开销。 部署到特定 VM 资源最适合需要直接控制 VM 服务器、高级业务流程或旧基础结构的方案。

- stage: Deploy
  displayName: Rolling Deploy to VMs
  dependsOn: Build
  condition: succeeded()
  jobs:
  - deployment: RollingDeploy
    displayName: Rolling deploy to Ubuntu VMs
    environment:
      name: <environment-name>
      resourceType: VirtualMachine
    strategy:
      rolling:
        maxParallel: 1   #or 2 for parallel. For percentages, use x%
        preDeploy:
          steps:
          - download: current
            artifact: drop
          - script: echo "Pre-deploy on $(hostname)"
        deploy:
          steps:
          - script: |
              echo "Unpacking Node.js app on $(hostname)"
              sudo mkdir -p /opt/pipelines-javascript
              sudo tar -xzf $(Pipeline.Workspace)/drop/$(Build.BuildId).tar.gz -C /opt/pipelines-javascript --strip-components=1
              cd /opt/pipelines-javascript
              echo "Installing production dependencies"
              sudo npm ci --only=production
              echo "Restarting Node.js service"
              sudo systemctl restart pipelines-javascript
            displayName: 'Extract, install, and restart Node.js service'
        routeTraffic:
          steps:
          - script: echo "Routing traffic on $(hostname)"
        postRouteTraffic:
          steps:
          - script: echo "Post-route health check on $(hostname)"
        on:
          failure:
            steps:
            - script: echo "Deployment failed on $(hostname)"
          success:
            steps:
            - script: echo "Deployment succeeded on $(hostname)"

在环境中访问管道可追溯性

“环境 部署 ”选项卡提供提交和工作项的完整可跟踪性,以及环境的跨管道部署历史记录。

屏幕截图显示了部署视图。