Azure虚拟机规模集:可靠分配、运行程序与释放方案问询
批量运行计算密集型模型的云环境问题
需求背景
需要批量运行多个计算密集型模型,目标是创建100台虚拟机,运行指定模型后关闭。由于每次运行的模型不同,不希望虚拟机开机自动运行程序,而是由外部指定要运行的程序。
当前方案
计划使用Azure文件共享(Azure fileshare)和Azure虚拟机规模集(VM Scale Set):已编译为EXE的各类程序、模型数据与输出文件都存储在文件共享中。全程通过.NET(F#代码)控制流程,不使用PowerShell或Azure门户,方便其他工具自动触发虚拟机操作。
尝试通过Azure.ResourceManager API实现以下流程:
- 启动虚拟机
- 通过RunCommand执行脚本,映射文件共享至驱动器并启动目标EXE
- 关闭并释放虚拟机
遇到的问题
方案可运行但可靠性极低:
- 调度不稳定:从所有VMSS实例处于Deallocated状态启动时,多数实例成功启动,但有相当数量的实例长时间卡在“Updating (Running)”状态(30分钟内未完成),严重影响运行效率。
- 状态留存异常:成功启动的虚拟机似乎会自动运行之前的脚本(可看到模型输出),但代码逻辑是等所有虚拟机启动后才会尝试执行脚本。看起来虚拟机在关机并释放后,仍会保留之前的脚本状态,原本以为分配后会从初始镜像全新启动。
核心问题
- 是否存在可靠的虚拟机分配、运行程序与释放的实现方式?
- 虚拟机分配/开机后的状态是“全新状态”,还是会保留释放前的状态?
- 考虑过其他方案(如Azure Batch),但希望尽可能简化,因Azure文档较难理解,当前方案看似复杂度最低。
控制程序代码示例
let vmss = resourceGroup.GetVirtualMachineScaleSet("myScaleSet").Value let powerOn = vmss.PowerOn(Azure.WaitUntil.Completed) let vms = vmss.GetVirtualMachineScaleSetVms() |> Seq.cast<VirtualMachineScaleSetVmResource> |> List.ofSeq let scripts = vms |> List.map (fun vm -> let name = vm.Id.Name let command = Models.RunCommandInput("RunPowerShellScript") command.Script.Add(@"net use S: /delete") command.Script.Add(@"Net use S: \fileshare etc.") command.Script.Add(@"& S:\MyModel.exe "+name) Console.WriteLine(" "+vm.Id.Name+" starting script") vm.RunCommand(Azure.WaitUntil.Started, command) ) Console.Write("Waiting for scripts to complete... ") let results = scripts |> List.map (fun op -> op.WaitForCompletionResponse()) // Some code to check for when the model has run let powerOff = vms |> List.map (fun vm -> let data = vm.Data Console.WriteLine(" "+vm.Id.Name+" powering off") vm.PowerOff(Azure.WaitUntil.Started) ) Console.Write("Waiting for power off... ") powerOff |> List.iter (fun op -> op.WaitForCompletionResponse() |> ignore) Console.WriteLine("completed") Console.Write("Deallocating VMs... ") vmss.Deallocate(Azure.WaitUntil.Completed) |> ignore
问题解答
1. 虚拟机分配/开机后的状态说明
虚拟机从Deallocated状态启动时,默认会保留上次释放前的磁盘状态(包括系统盘和数据盘),不会从初始镜像全新启动。只有执行**重新部署(Redeploy)**操作,或者在VMSS配置中结合overprovision与deleteVMOnScaleDown实例删除策略,才会得到近似“全新状态”的实例。你遇到的脚本自动运行问题,大概率是系统盘保留了上次运行的脚本残留(比如RunCommand历史执行记录被误触发,或脚本在系统中留下开机自启配置)。
2. 可靠的虚拟机分配、运行与释放实现方式
针对你的场景,优化现有VMSS方案可提升可靠性,具体调整如下:
- 分批启动实例:一次性启动100台会触发Azure调度限流,导致部分实例卡顿。建议分批次启动(如每批20台),每批启动完成后再执行RunCommand,避免资源竞争。
- 用Redeploy替代简单PowerOn:启动前对Deallocated状态的实例执行
Redeploy,强制Azure将实例迁移到新宿主机并从镜像重新初始化系统盘,确保实例处于干净状态。 - 优化RunCommand脚本:
- 避免用
net use映射驱动器,改用UNC路径直接访问文件共享(\\fileshare\path\MyModel.exe),减少驱动器冲突。 - 脚本开头添加状态重置逻辑,比如删除上次运行的输出文件,避免残留干扰。
- 使用
Start-Process -Wait确保EXE执行完成后再退出脚本,避免RunCommand提前结束导致流程误判。
- 避免用
- 完善状态检查逻辑:不要仅依赖VM的“Running”状态,需确认实例
ProvisioningState为Succeeded且PowerState为VM running后,再执行脚本。 - 调整释放顺序:先确保所有EXE执行完成,再逐个关闭实例,最后执行VMSS的Deallocate操作,避免批量操作导致任务未完成就终止。
3. 关于Azure Batch的简化方案
如果希望进一步简化流程,Azure Batch更适合批量计算场景:
- Batch会自动管理虚拟机的创建、调度、运行和销毁,无需手动处理VMSS的启动/释放逻辑。
- 可直接将任务提交到Batch池,系统自动分发任务到空闲节点,任务完成后可自动缩放池大小(甚至缩至0)。
- 支持通过.NET SDK(包括F#)完全控制流程,无需手动编写RunCommand脚本,只需指定任务的执行命令和资源文件位置。
- 虽然文档看似复杂,但针对你的场景,只需创建Batch池(配置虚拟机规格和数量)并提交任务(指定EXE和参数)即可实现自动化,长期来看比VMSS方案更可靠、维护成本更低。
内容的提问来源于stack exchange,提问作者Paul Whiting
相关产品推荐
相关产品推荐

