Azure Pipeline代理分配优化配置问询:避免跨构建抢占
Azure Pipeline 配置问题解决指南
术语定义
- Pipeline - 流水线(包含Automation、Fast、Slow类型)
- Build - 针对特定提交的流水线单次运行实例
- Job - 构建的组成步骤
- Task - 作业的组成步骤
- Agent - 运行作业的服务器
核心需求
- 当某台Agent启动某个Build后,在该Build完成前不再承接其他Build的Job
- 单个Build最多使用3台Agent
- 优先让尽可能多的Agent同时处理同一个Build
- 每个Build可使用1台或多台Agent
当前问题
Agent会在不同Build间切换,导致部分Build无人处理,现有YAML配置如下:
trigger: tags: include: - 2.* parameters: - name: 'tests' type: object default: - "test_1" - "test_2" - "test_3" - "test_4" - "test_5" - "test_6" - "test_7" - "test_8" - "test_9" stages: - stage: RunTests displayName: 'Run Tests' jobs: - job: ui timeoutInMinutes: 120 pool: name: Nightly demands: - Cmd - DotNetFramework strategy: maxParallel: 3 matrix: ${{ each test_case in parameters.tests }}: ${{ test_case }}: test: ${{ test_case }} steps: - task: DeleteFiles@1 displayName: 'Delete past session artifacts' inputs: sourceFolder: 'C:/dev' contents: | /files/**/* /temp/**/* condition: always() - task: DeleteFiles@1 displayName: 'Delete past session captures' inputs: sourceFolder: 'C:/test_capture' contents: | **/* condition: always() - task: BatchScript@1 displayName: 'configure z' inputs: filename: 'scripts\configure_z.bat' modifyEnvironment: false timeoutInMinutes: 20 - template: build_env.yaml - task: BatchScript@1 displayName: 'Run script automation/run_tests.bat ' inputs: filename: 'automation/run_tests.bat' arguments: $(test) modifyEnvironment: false condition: and(succeeded(), ne(variables['Agent.JobStatus'], 'Canceled')) - task: PublishPipelineArtifact@1 displayName: 'Publish Pipeline Artifact' inputs: artifactName: Automation logs $(Agent.JobName) Attemp $(System.JobAttempt) targetPath: 'c:\test_capture' condition: always() - template: publish_test_results.yaml - stage: WrapUp displayName: 'Wrap Up' dependsOn: RunTests jobs: - job: PublishCompiledLogs displayName: 'Publish Compiled Logs' timeoutInMinutes: 20 pool: name: Nightly demands: - Cmd - DotNetFramework steps: - task: DownloadPipelineArtifact@2 inputs: patterns: '**/nosetest-*.xml' path: './tests-xml' condition: always() - task: CmdLine@1 displayName: 'Combine Logs' inputs: filename: python arguments: 'scripts/merge_nosetest_logs.py --directory tests-xml --output tests-xml/nosetest-automation.xml --remove' continueOnError: true condition: always() - task: PublishPipelineArtifact@1 displayName: 'Publish All Tests Artifact' inputs: artifactName: All Automatic Tests Logs targetPath: './tests-xml' condition: always()
解决方案
1. 实现Agent独占Build(解决跨Build切换问题)
在Job的pool配置中添加lockBehavior: exclusive,确保Agent被当前Build的Job独占,直到该Build所有作业完成:
pool: name: Nightly demands: - Cmd - DotNetFramework lockBehavior: exclusive # 锁定Agent为当前Build专属
同时进入Azure DevOps代理池管理页面(组织设置→代理池→Nightly),将每个Agent的最大并行作业数设为1,彻底避免Agent同时处理多个Job。
2. 保持单Build最大Agent数限制
你现有配置中的strategy: maxParallel: 3已经实现了单个Build最多使用3台Agent的需求,无需修改。
3. 强化同Build作业优先分配逻辑
在Azure DevOps代理池的作业队列设置中(组织设置→代理池→Nightly→作业队列),开启“同一流水线的作业优先”选项,确保可用Agent优先分配给当前正在运行的Build作业。
4. 支持动态Agent数量
现有矩阵策略会根据测试用例数量自动调整并行Agent数(测试用例≤3时使用对应数量的Agent),完全满足“Build可使用1台或多台Agent”的需求,无需额外配置。
调整后的完整YAML配置
trigger: tags: include: - 2.* parameters: - name: 'tests' type: object default: - "test_1" - "test_2" - "test_3" - "test_4" - "test_5" - "test_6" - "test_7" - "test_8" - "test_9" stages: - stage: RunTests displayName: '运行测试' jobs: - job: ui timeoutInMinutes: 120 pool: name: Nightly demands: - Cmd - DotNetFramework lockBehavior: exclusive strategy: maxParallel: 3 matrix: ${{ each test_case in parameters.tests }}: ${{ test_case }}: test: ${{ test_case }} steps: - task: DeleteFiles@1 displayName: '删除历史会话产物' inputs: sourceFolder: 'C:/dev' contents: | /files/**/* /temp/**/* condition: always() - task: DeleteFiles@1 displayName: '删除历史会话捕获文件' inputs: sourceFolder: 'C:/test_capture' contents: | **/* condition: always() - task: BatchScript@1 displayName: '配置环境Z' inputs: filename: 'scripts\configure_z.bat' modifyEnvironment: false timeoutInMinutes: 20 - template: build_env.yaml - task: BatchScript@1 displayName: '运行自动化测试脚本 run_tests.bat' inputs: filename: 'automation/run_tests.bat' arguments: $(test) modifyEnvironment: false condition: and(succeeded(), ne(variables['Agent.JobStatus'], 'Canceled')) - task: PublishPipelineArtifact@1 displayName: '发布流水线产物' inputs: artifactName: 自动化日志_$(Agent.JobName)_尝试_$(System.JobAttempt) targetPath: 'c:\test_capture' condition: always() - template: publish_test_results.yaml - stage: WrapUp displayName: '收尾处理' dependsOn: RunTests jobs: - job: PublishCompiledLogs displayName: '发布合并后的测试日志' timeoutInMinutes: 20 pool: name: Nightly demands: - Cmd - DotNetFramework lockBehavior: exclusive steps: - task: DownloadPipelineArtifact@2 inputs: patterns: '**/nosetest-*.xml' path: './tests-xml' condition: always() - task: CmdLine@1 displayName: '合并测试日志' inputs: filename: python arguments: 'scripts/merge_nosetest_logs.py --directory tests-xml --output tests-xml/nosetest-automation.xml --remove' continueOnError: true condition: always() - task: PublishPipelineArtifact@1 displayName: '发布所有测试日志产物' inputs: artifactName: 所有自动化测试日志 targetPath: './tests-xml' condition: always()
内容的提问来源于stack exchange,提问作者bimBamBom
相关产品推荐
相关产品推荐

