如何在Azure Pipeline中托管VM镜像,用临时VM替代自托管代理运行任务?
按需创建临时Azure Pipeline自托管代理(基于自定义VM快照)
核心思路
通过Azure Pipeline编排流水线,在触发测试任务时从你的现有快照创建临时VM,自动注册为自托管代理,待测试完成后立即注销代理并销毁VM,彻底规避永久VM的闲置成本。
实施步骤
1. 前置准备
- 拥有Azure订阅的VM创建/删除权限,以及Azure DevOps组织的代理池管理权限。
- 提前在Azure DevOps中创建专属代理池(例如命名为
TempVM-Agents),用于临时代理的注册。 - 确认VM快照处于可用状态,记录快照所在资源组、区域信息。
2. Pipeline YAML实现(全流程)
以下是包含VM创建、代理注册、测试执行、资源清理的完整流水线示例:
trigger: - main pool: vmImage: 'ubuntu-latest' # 用微软托管代理执行VM创建/清理操作 variables: resourceGroupName: '你的资源组名称' snapshotName: '你的快照名称' tempVmName: 'TempTestVM-$(Build.BuildId)' # 用BuildID保证VM名称唯一 vmSize: 'Standard_D2s_v3' location: 'eastus' # 替换为你的快照所在区域 adoAgentPoolName: 'TempVM-Agents' adoOrgUrl: 'https://dev.azure.com/你的组织名称' adoPAT: '$(ADO-PAT)' # 在Pipeline变量中存储有权限注册代理的PAT(设为保密变量) steps: # 步骤1:从快照创建临时VM - task: AzureCLI@2 displayName: '从快照创建临时VM' inputs: azureSubscription: '你的Azure服务连接' scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | # 创建OS磁盘 az disk create \ --resource-group $(resourceGroupName) \ --name $(tempVmName)-osdisk \ --source $(snapshotName) \ --location $(location) # 创建VM(Linux示例,Windows需修改os-type和认证方式) az vm create \ --resource-group $(resourceGroupName) \ --name $(tempVmName) \ --attach-os-disk $(tempVmName)-osdisk \ --os-type Linux \ --size $(vmSize) \ --admin-username azureuser \ --ssh-key-value @~/.ssh/id_rsa.pub # 获取VM公网IP VM_IP=$(az vm show -d -g $(resourceGroupName) -n $(tempVmName) --query publicIps -o tsv) echo "##vso[task.setvariable variable=tempVmIp]$VM_IP" # 步骤2:在VM上安装并注册Azure Pipeline代理 - task: SSH@0 displayName: '在临时VM上注册ADO代理' inputs: sshEndpoint: '$(tempVmIp)' # 提前配置SSH服务连接,或直接用用户名+密钥 runOptions: 'inline' inline: | # 下载代理安装包(版本可从ADO代理池页面获取最新链接) wget https://vstsagentpackage.azureedge.net/agent/2.220.0/vsts-agent-linux-x64-2.220.0.tar.gz mkdir ado-agent && tar zxvf vsts-agent-linux-x64-2.220.0.tar.gz -C ado-agent # 注册代理 cd ado-agent ./config.sh --unattended \ --url $(adoOrgUrl) \ --auth pat \ --token $(adoPAT) \ --pool $(adoAgentPoolName) \ --agent $(tempVmName) \ --replace \ --work '_work' # 启动代理服务 ./svc.sh install ./svc.sh start # 步骤3:在临时代理上运行测试任务 - job: 在临时VM上执行测试 displayName: '在临时VM代理上运行测试' pool: name: $(adoAgentPoolName) demands: - agent.name -equals $(tempVmName) # 指定使用刚创建的代理 steps: - script: | # 替换为你的测试命令,调用镜像中预装的工具 echo "启动测试..." ./your-test-script.sh displayName: '执行测试' # 步骤4:清理资源(无论测试成败都执行) - task: SSH@0 displayName: '注销ADO代理' condition: always() inputs: sshEndpoint: '$(tempVmIp)' runOptions: 'inline' inline: | cd ado-agent ./svc.sh stop ./svc.sh uninstall ./config.sh remove --unattended --token $(adoPAT) - task: AzureCLI@2 displayName: '删除临时VM和磁盘' condition: always() inputs: azureSubscription: '你的Azure服务连接' scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az vm delete --resource-group $(resourceGroupName) --name $(tempVmName) --yes --no-wait az disk delete --resource-group $(resourceGroupName) --name $(tempVmName)-osdisk --yes --no-wait
3. 关键注意事项
- PAT权限:用于注册代理的PAT需拥有
Agent Pools (Read & manage)权限,建议创建最小权限PAT并设为保密变量。 - Windows VM适配:若快照为Windows系统,需将SSH任务替换为PowerShell远程任务,代理注册改用Windows版本的
config.cmd脚本。 - 网络配置:确保临时VM能访问Azure DevOps服务,私有网络环境需配置出站规则允许访问
dev.azure.com。 - 容错处理:清理步骤添加
condition: always()避免资源残留,可给VM创建、代理注册步骤添加重试逻辑。
内容的提问来源于stack exchange,提问作者Mohan Chandran
相关产品推荐
相关产品推荐

