简体   繁体   English

Azure DevOps 管道 - 如何通过自托管代理在 docker 容器中执行整个模板阶段

[英]Azure DevOps pipelines - how to execute a whole template stage in a docker container by a self-hosted agent

I have a multi stage Azure DevOps pipeline in yaml. Each stage includes multiple jobs.我在 yaml 中有一个多阶段 Azure DevOps 管道。每个阶段包括多个作业。 The pipeline runs properly by using Azure-hosted agents.管道通过使用 Azure 托管的代理正常运行。 I need to run it by our company's self-hosted agent.我需要通过我们公司的自托管代理来运行它。 The self-hosted agent is a virtual machine scale set (VMSS) which is defined as an agent pool in DevOps, it has been tested and is working properly.自托管代理是一个虚拟机规模集 (VMSS),在 DevOps 中被定义为一个代理池,它已经过测试并且可以正常工作。 Because the self-hosted agent does not have all the capabilities we need, our company's policy is to run the jobs inside docker containers.由于自托管代理不具备我们需要的所有功能,我们公司的政策是在 docker 个容器内运行作业。 The docker images reside in our company's private Azure Container Registy. docker 图像位于我们公司的私有 Azure 容器注册表中。

My question is how can I run a whole template stage in a docker container?我的问题是如何在 docker 容器中运行整个模板阶段? Please note that my question is not about executing a job but all the jobs in a stage template.请注意,我的问题不是关于执行作业,而是关于阶段模板中的所有作业。 This link explains how to execute jobs inside a container. 此链接解释了如何在容器内执行作业。 It doesn't give any examples of how to run all the jobs in a stage in a container, especially when the stage is defined as a template.它没有给出任何示例来说明如何在容器中运行一个阶段中的所有作业,尤其是当该阶段被定义为模板时。

My pipeline in simplified form is as follows:我的简化形式的管道如下:

## Name of self-hosted agent
pool: Platform-VMSS

resources:
  containers:
  - container: base
    image: myazurecontainerregistryname.azurecr.io/platform/myimg:1.0.0
    endpoint: 'serviceconnection-acr'

trigger:
  branches:
    include: 
      - "feature/ORGUS-4810"
    exclude:
      - "main"
      - "release"
  paths:
    include:
      - "usecase-poc/**"

variables:
  pythonVersion: 3.8
  whlPackageName: py_core  
  srcDirectory: usecase-poc/$(whlPackageName)
  ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
    BuildFrom: main
    PackageName: $(whlPackageName)
    versionOption: custom
    deployToDevPipeline: True
    deployToQAPipeline: True
    deployToProdPipeline: True
  ${{ else }}:
    BuildFrom: branch_${{ lower(variables['Build.SourceBranchName'] ) }}
    PackageName: $(whlPackageName)_$(BuildFrom)
    versionOption: patch
    deployToDevPipeline: True
    deployToQAPipeline: False
    deployToProdPipeline: False
    stageName: 'deployToDev'

stages:
  - stage: DownloadArtifact
    displayName: "Download python whl from artifactory"
    jobs: 
    - job: DownloadArtifactJob
      steps:
      - checkout: self

      - task: UniversalPackages@0
        displayName: 'Download Artifact with Universal Packages'
        inputs:
          vstsFeed: 'some-value/00000000-0000-0009-0000-d24300000000'
          vstsFeedPackage: '00000000-0000-0000-0000-0000000'
          vstsPackageVersion: 0.8.4 
          downloadDirectory: $(Build.ArtifactStagingDirectory)

      - task: Bash@3
        name: GetWheelName_Task
        inputs:
          targetType: 'inline'
          script: |
            echo $(Build.ArtifactStagingDirectory)
            find $(Build.ArtifactStagingDirectory) -name '*.whl'
            ArtifactName=$(find $(Build.ArtifactStagingDirectory) -name '*.whl')
            echo "Artifact name value is " $ArtifactName
            echo "##vso[task.setvariable variable=ArtifactName;isOutput=true]$ArtifactName"
        displayName: 'Get downloaded artifact in source directory'
 
      - task: PublishBuildArtifacts@1
        displayName: "Publish downloaded artifact to pipeline's output"
        inputs:
          pathToPublish: $(Build.ArtifactStagingDirectory)
          artifactName: whl

  - stage: ConstructSharedVariablesForAllStages
    displayName: Construct Shared Variables For All Stages
    dependsOn: DownloadArtifact
    variables:
    - group: proj-shared-vg
    - name: ArtifactName
      value:  $[stageDependencies.DownloadArtifact.DownloadArtifactJob.outputs['GetWheelName_Task.ArtifactName']]
    jobs: 

    - job: DownloadArtifact
      container: base
      steps:
      - task: Bash@3
        displayName: "Print variable value"
        inputs:
          targetType: 'inline'
          script: |
            echo $(ArtifactName)

      - task: Bash@3
        name: extractWheelName
        displayName: Extract Wheel Name
        inputs:
          targetType: inline
          script: |
            echo $(ArtifactName) | awk -F"/" '{print $NF}'           
            WhlName="py_core-0.8.4-py3-none-any.whl"
            echo "##vso[task.setvariable variable=WhlName;isOutput=true]$WhlName"


      - task: DownloadPipelineArtifact@2
        displayName: "Download artifact from previous stage"
        inputs:
          buildType: 'current'
          project: 'Project Name'
          buildVersionToDownload: 'latest'
          artifactName: whl
          targetPath: '$(System.ArtifactsDirectory)'


      - pwsh: |
          $whlFile = Get-ChildItem -Filter *.whl -Path "$(System.ArtifactsDirectory)" | ForEach-Object { $_.fullname } | Select-Object -First 1
          Write-Host "##vso[task.setvariable variable=whlFile]$whlFile"
        name: SetVars
        displayName: Get wheel name

  ## This is the section where my question is about. How can I make sure each stage runs in the self-hosted agent pool. The stage contains multiple jobs.
  - template: ../templates/azure-pipeline-stage-template.yaml
    parameters:
      deploy: ${{variables.deployToDevPipeline}}
      variableGroup: databricks-sp-vg-dev
      stageName: DeployToDev
      environment: DBRKS_Dev_WHL
      conditionParameter: deployToDev
      dependsOnStage: ConstructSharedVariablesForAllStages

  - template: ../templates/azure-pipeline-stage-template.yaml
    parameters:
      deploy: ${{variables.deployToQAPipeline}}
      variableGroup: databricks-sp-vg-qa
      stageName: DeployToQA
      environment: DBRKS_QA_WHL
      conditionParameter: deployToQA
      dependsOnStage: DeployToDev

  - template: ../templates/azure-pipeline-stage-template.yaml
    parameters:
      deploy: ${{variables.deployToProdPipeline}}
      variableGroup: databricks-sp-vg-prod
      stageName: DeployToProd
      environment: DBRKS_Prod_WHL
      conditionParameter: deployToProd
      dependsOnStage: DeployToQA

In the code above in resources the container resides in our Azure Container Registry (ACR), the endpoint is our DevOps service connection of type container registry to pull and push images to and from ACR.在上面资源中的代码中,容器位于我们的 Azure 容器注册表 (ACR) 中,端点是我们的容器注册表类型的 DevOps 服务连接,用于向 ACR 拉取和推送图像。 In the code above I have commented where the issue is.在上面的代码中,我已经评论了问题所在。 In templates where I am refering to stage templates, I would like to run them all inside a container where I have defined as a resource at the beginning of the pipeline.在我引用阶段模板的模板中,我想在一个容器内运行它们,我在管道的开头将其定义为资源。 The stage template has multiple jobs.舞台模板有多个作业。 Here is just a sample of stage template when running to emphasize it has multiple jobs:这里只是一个运行时的阶段模板示例,以强调它有多个作业:

舞台模板有多个作业

The highlighted stage is the one created by template:突出显示的阶段是由模板创建的阶段:

  - template: ../templates/azure-pipeline-stage-template.yaml
    parameters:
      deploy: ${{variables.deployToDevPipeline}}
      variableGroup: databricks-sp-vg-dev
      stageName: DeployToDev
      environment: DBRKS_Dev_WHL
      conditionParameter: deployToDev
      dependsOnStage: ConstructSharedVariablesForAllStages

Question is how to enforce all the jobs in the above template run in the docker container defined as resource in our pipeline.问题是如何强制上述模板中的所有作业在我们管道中定义为资源的 docker 容器中运行。 Thank you very much for your valuable input.非常感谢您的宝贵意见。

Add a container field at the job level as shown below.在作业级别添加容器字段,如下所示。 Then all the jobs in the template will be running on specified container.然后模板中的所有作业将运行在指定的容器上。

pool:  
  vmImage: ubuntu-latest  
resources:  
  containers:  
    - container: testcontainer  
      image: ubuntu  
stages:  
  - stage: template01  
    displayName: tempate test  
    jobs:  
      - job: template  
        container: testcontainer  
        steps:  
          - template: templates/template01.yaml  
  - stage: template02  
    displayName: template test  
    jobs:  
      - job: template  
        container: testcontainer  
        steps:  
          - template: templates/template02.yaml

Else, add a step target field to all the required tasks in a template, as referred to in this link Build and Release Tasks - Azure Pipelines |否则,将步骤目标字段添加到模板中的所有必需任务,如链接构建和发布任务 - Azure 中所述Microsoft Learn]( https://learn.microsoft.com/en-us/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml#step-target ) "https://learn.microsoft.com/en-us/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml#step-target)") Microsoft Learn]( https://learn.microsoft.com/en-us/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml#step-target ) "https://learn.microsoft.com /zh-cn/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml#step-target)")

resources:  
containers:  
- container: pycontainer  
image: python:3.11  
 
steps:  
- task: AnotherTask@1  
target: pycontainer  

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM