You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure DevOps代理配置:如何让YAML流水线在Microsoft托管代理与自托管代理间自动选择空闲代理运行

配置YAML流水线实现跨代理自动调度

先明确两个关键前提:

  • Microsoft托管代理是Azure Pipelines提供的临时代理(每次运行会创建新实例,用完销毁),属于Azure Pipelines池,你无法“拥有”一个固定的托管代理,而是按需使用微软维护的公共代理池。
  • 自托管代理是你自行部署维护的长期运行代理,属于你创建的自定义代理池。

下面分两种场景给出解决方案:

场景1:两个代理都是自托管(含Azure VM部署的自托管代理)

如果你的“Microsoft托管代理”其实是部署在Azure VM上的自托管代理(而非微软官方托管的临时代理),那最简单的方式是把两个自托管代理加入同一个自定义代理池:

  1. 在Azure DevOps的项目设置 → 代理池中,创建或选择一个自定义池,把两个自托管代理都添加进去。
  2. (可选)给两个代理添加相同的自定义标签(比如shared-runner),用于更精准的代理匹配。
  3. 在YAML流水线中指定这个代理池即可,Azure DevOps会自动在池内的空闲代理上运行任务:
pool:
  name: '你的自定义代理池名称'
  # 可选:如果加了标签,可指定标签进一步筛选
  demands:
    - Agent.Name -equals shared-runner

steps:
- script: echo "任务会自动在池内空闲的代理上执行"
  displayName: '运行测试任务'

场景2:一个是微软官方托管代理,一个是自托管代理

因为微软托管代理和自托管代理分属不同的代理池,Azure DevOps原生不支持跨池自动调度空闲代理,但可以通过动态检测代理状态+条件选择池的方式实现近似效果:

实现步骤:

  1. 启用脚本权限:在流水线编辑页→变量→流水线变量,勾选允许脚本访问OAuth令牌,让脚本能调用Azure DevOps API。
  2. 获取自托管池ID:在Azure DevOps的组织设置→代理池→选择你的自托管池,URL中的数字就是池ID(比如https://dev.azure.com/你的组织/_settings/agentpools?poolId=123中的123)。
  3. 使用以下YAML配置,先检测自托管代理是否空闲,再动态选择对应的池:
variables:
  # 替换为你的自托管代理池ID
  selfHostedPoolId: '123'
  # 替换为你的自托管代理池名称
  selfHostedPoolName: '你的自托管池名称'

jobs:
- job: CheckAgentAvailability
  # 先在微软托管代理上运行检测脚本
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - powershell: |
      # 调用Azure DevOps API获取自托管池的代理状态
      $orgUrl = "$(System.CollectionUri)"
      $pat = "$(System.AccessToken)"
      $headers = @{ Authorization = "Bearer $pat" }
      $agentsUrl = "$orgUrl/_apis/distributedtask/pools/$(selfHostedPoolId)/agents?api-version=7.1-preview.1"
      
      try {
        $agents = Invoke-RestMethod -Uri $agentsUrl -Headers $headers -Method Get
        # 筛选在线且未被占用的代理
        $freeAgents = $agents.value | Where-Object { $_.status -eq 'online' -and $_.assignedRequest -eq $null }
        
        if ($freeAgents.Count -gt 0) {
          Write-Host "检测到空闲的自托管代理,将使用自托管池"
          Write-Host "##vso[task.setvariable variable=targetPool;isOutput=true]$(selfHostedPoolName)"
        } else {
          Write-Host "自托管代理全部忙碌,将使用微软托管代理"
          Write-Host "##vso[task.setvariable variable=targetPool;isOutput=true]AzurePipelines"
        }
      } catch {
        Write-Warning "检测代理状态失败,默认使用微软托管代理"
        Write-Host "##vso[task.setvariable variable=targetPool;isOutput=true]AzurePipelines"
      }
    name: SetTargetPool

- job: RunPipelineTasks
  dependsOn: CheckAgentAvailability
  pool:
    ${{ if eq(dependencies.CheckAgentAvailability.outputs['SetTargetPool.targetPool'], variables.selfHostedPoolName) }}:
      name: $(selfHostedPoolName)
    ${{ else }}:
      vmImage: 'ubuntu-latest' # 可替换为你需要的托管镜像,比如windows-latest
  steps:
  - script: echo "当前运行在:$(Agent.Name),所属池:$(Agent.PoolName)"
    displayName: '显示代理信息'
  # 这里添加你的实际任务步骤
  - script: echo "执行核心任务逻辑"

注意事项:

  • 检测脚本存在微小的时间差,如果检测后自托管代理被其他任务占用,仍会进入排队状态。
  • 默认System.AccessToken有足够的权限读取代理池信息,若遇到权限问题可在组织设置中调整权限。

内容的提问来源于stack exchange,提问作者Rasmus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 02:47:42