获取ARM VM状态比以前花费更长的时间

时间:2017-12-19 15:58:30

标签: powershell azure virtual-machine azure-powershell

自上周以来我一直面临着一个问题。当我运行这个powershell命令时,一切正常,除了现在这个命令需要大约12秒才能完成。

(Get-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Name $Vm.ResourceName -Status).Statuses[1].DisplayStatus

直到上周,这个简单的代码还没有完成。我是唯一一个面临这个问题的人吗?

问题是,我在一个更大的脚本中使用这个代码,这个部分(为了获得所有Vm powerstate)现在需要花费50分钟来完成,但是大约需要3分钟。

这里是我使用的代码示例(我刚刚添加了一堆' Measure-Command'来查看发生了什么)

#
# Status des VM
#
Write-Output "VM Status Start"
$TimeToGetVmList = Measure-Command {$VmList = Find-AzureRmResource -TagName "environnement" -TagValue $vmEnv | Where-Object {$_.ResourceType -like "Microsoft.Compute/virtualMachines"}}
Write-Host "`n-Get The VmList $($TimeToGetVmList.Minutes):$($TimeToGetVmList.Seconds):$($TimeToGetVmList.Milliseconds) minutes" -ForegroundColor Cyan
if ($VmList) {
    $indexVMState = 1
    $TimeToAllVmStatus = Measure-Command {
        foreach ($Vm in $VmList) {
            <# debug: limit to 10 #>
            if ($indexVMState -le 10) {
                #Write-Host "`r$indexVMState/$($VmList.Count)" -NoNewline
                $TimeToGetVM = Measure-Command {$VmDetails = (Get-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Name $Vm.ResourceName)}
                Write-Host " -Get VM [$($Vm.ResourceName)/$($vm.ResourceGroupName)] $($TimeToGetVM.Minutes):$($TimeToGetVM.Seconds):$($TimeToGetVM.Milliseconds) minutes" -ForegroundColor Magenta
                $VmListTags = $VmDetails.Tags
                $TimeToGetThePowa = Measure-Command {$PowerState = ((Get-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Name $Vm.ResourceName -Status).Statuses[1].DisplayStatus)}
                Write-Host " -Get Status [$($Vm.ResourceName)/$($vm.ResourceGroupName)] $($TimeToGetThePowa.Minutes):$($TimeToGetThePowa.Seconds):$($TimeToGetThePowa.Milliseconds) minutes" -ForegroundColor Magenta
                <#  Write-Output "avant - $($Vm.ResourceName) - $PowerState" #>
                $OsProfile = $VmDetails |Select-Object @{l = 'OsType'; e = {$_.StorageProfile.osDisk.osType}}
                <#  Write-Output "avant - $($Vm.ResourceName) - $($OsProfile.OsType)" #>
                if ($PowerState -notcontains "VM running") {
                    if ($VmListTags -or $VmListTags.schedule -match "`"$dayToday`":" -or $VmListTags.startmwtf -and $WorkingDays -contains $dayToday) {
                        if ($VmListTags.Projet) {$ProjectName = $VmListTags.Projet}else {$ProjectName = "N.C."}
                        $MyTrashStatus = New-Object PSObject
                        $MyTrashStatus | Add-Member -type NoteProperty -name Environnement -Value $vmEnv
                        $MyTrashStatus | Add-Member -type NoteProperty -name "RG Name" -Value $vm.ResourceGroupName
                        $MyTrashStatus | Add-Member -type NoteProperty -name Serveur -Value $Vm.ResourceName
                        $MyTrashStatus | Add-Member -type NoteProperty -name Projet -Value $ProjectName
                        $MyTrashStatus | Add-Member -type NoteProperty -name Systeme -Value $OsProfile."OsType"
                        $MyTrashStatus | Add-Member -type NoteProperty -name Status -Value $PowerState
                        $vmsPowerState.Add($MyTrashStatus) | Out-Null
                    }
                }
                if ($OsProfile."OsType" -match "Windows") {$OsWin += 1} elseif ($OsProfile."OsType" -match "Linux") {$OsLin += 1}
                $indexVMState++
            }
        }
    }
    Write-Host "`n---Time to Get all VM status [$($indexVMState -1)Vm] $($TimeToAllVmStatus.Minutes):$($TimeToAllVmStatus.Seconds):$($TimeToAllVmStatus.Milliseconds) minutes" -ForegroundColor DarkRed
}
$VmStatusList = "$($VmList.Count) VM IaaS ($OsWin Windows & $OsLin Linux)"
if ($vmsPowerState.Count -ge 1) {
    $vmsPowerStateReport = $vmsPowerState | ConvertTo-HTML -fragment
}
else {
    $vmsPowerStateReport = "`t`tToutes les machines sont en etat RUNNING."
}
Write-Output "VM Status End"

输出,正如我所知,当我请求它的状态时,它需要大约12秒! 〜_〜

ALREADY logged in to Azure...
 User: blabla
 Subscription: blabla

Url Start
Url End
Backup Start
Backup End
VM Status Start

-Get The VmList 0:0:443 minutes
 -Get VM [-] 0:0:328 minutes
 -Get Status [-] 0:12:715 minutes
 -Get VM [-] 0:0:243 minutes
 -Get Status [-] 0:12:30 minutes
 -Get VM [-] 0:0:316 minutes
 -Get Status [-] 0:12:23 minutes
 -Get VM [-] 0:0:140 minutes
 -Get Status [-] 0:12:71 minutes
 -Get VM [-] 0:0:172 minutes
 -Get Status [-] 0:12:58 minutes
 -Get VM [-] 0:0:233 minutes
 -Get Status [-] 0:12:76 minutes
 -Get VM [-] 0:0:154 minutes
 -Get Status [-] 0:12:86 minutes
 -Get VM [-] 0:0:178 minutes
 -Get Status [-] 0:12:42 minutes
 -Get VM [-] 0:0:192 minutes
 -Get Status [-] 0:12:78 minutes
 -Get VM [-] 0:0:185 minutes
 -Get Status [-] 0:12:39 minutes

---Time to Get all VM status [10Vm] 2:3:426 minutes
VM Status End
Automation Start
Automation End
Malware Start
Malware End
AzSQL Start
AzSQL End
WebApps Start
WebApps End
WebAppsBck Start
WebAppsBck End
InfraVmwareASR Start
InfraVmwareASR End

 Email send
你也面对面吗? (抱歉这个loooong帖子,请不要TL:DR :))

3 个答案:

答案 0 :(得分:0)

我得到与您相同的时间 - 每个VM大约12秒用于状态检索。考虑到这一点,并考虑到您的VM计数,我建议将您的代码移动到工作流程中,以便这12秒的呼叫可以同时发生。我刚刚使用我的一个订阅测试了它,它将原来的1m 44s持续时间降低到0m 15s。

为了简单起见,我删除了一些你的代码,但希望它有意义,你可以把它装回去:

<#
.Synopsis
   Gets the status from multiple Azure VMs simultaneously
.EXAMPLE
   Get-VMStatus
#>
function Get-VMStatus
{
    [CmdletBinding()]
    Param ()


    <#
    .Synopsis
       Workflow for getting Azure VM status'
    .DESCRIPTION
       Uses PS Workflow to get Azure VM status' in a concurrent manner, preserving the original code sequence
    .EXAMPLE
       Get-VMStatusWF -VMList (Find-AzureRmResource | Where-Object {$_.ResourceType -like "Microsoft.Compute/virtualMachines")
    #>
    workflow Get-VMDetailsWF
    {
        Param
        (
            # Param1 help description
            $VMList
        )
        foreach -parallel ($Vm in $VmList) {
            sequence {
                $TimeToGetVM = Measure-Command {$VmDetails = (Get-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Name $Vm.ResourceName)}
                Write-Verbose " -Get VM [$($Vm.ResourceName)/$($vm.ResourceGroupName)] $($TimeToGetVM.Minutes):$($TimeToGetVM.Seconds):$($TimeToGetVM.Milliseconds) minutes" -Verbose

                $VmListTags = $VmDetails.Tags
                $TimeToGetThePowa = Measure-Command {$PowerState = ((Get-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Name $Vm.ResourceName -Status).Statuses[1].DisplayStatus)}
                Write-Verbose " -Get Status [$($Vm.ResourceName)/$($vm.ResourceGroupName)] $($TimeToGetThePowa.Minutes):$($TimeToGetThePowa.Seconds):$($TimeToGetThePowa.Milliseconds) minutes" -Verbose
            }
        }
    }

    Write-Host "VM Status Start" -ForegroundColor Blue -BackgroundColor White
    $TimeToGetVmList = Measure-Command {$VmList = Find-AzureRmResource | Where-Object {$_.ResourceType -like "Microsoft.Compute/virtualMachines"}}
    Write-Host "`n-Get The VmList $($TimeToGetVmList.Minutes):$($TimeToGetVmList.Seconds):$($TimeToGetVmList.Milliseconds) minutes" -ForegroundColor Green

    $TimeToAllVmStatus = measure-command {Get-VMDetailsWF -VMList $VmList}
    Write-Host "`n---Time to Get all VM status [$($TimeToAllVmStatus.Minutes):$($TimeToAllVmStatus.Seconds):$($TimeToAllVmStatus.Milliseconds)] minutes" -ForegroundColor Green
}


cls
Get-VMStatus

答案 1 :(得分:0)

Azure Compute团队最近更改了此行为,以防止过度频繁的轮询。

HTH

答案 2 :(得分:0)

这是微软官方发布的消息:

以下是对您的记录的支持请求的摘要:

<强>症状: AzureRm.Compute Cmdlet Get-AzureRmVm执行时间高于预期(10s~)。

<强>原因: Azure Compute团队在API中加入了软件延迟/限制,以减少对相同资源的过度或频繁轮询。

然后我在foreach之前移动我的“Get-AzureRmVM”。就这么简单......

#
# Status des VM
#
Write-Output "[$(get-date -Format T)] VM Status Start"
$VmList = Get-AzureRmVm -Status
if ($VmList) {
    $VmProd = 0
    foreach ($Vm in $VmList) {
        if ($Vm.Tags.environment -like "production") {
            $VmDetails = (Get-AzureRmVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name)
            $VmListTags = $VmDetails.Tags
            $PowerState = $Vm.PowerState
            $OsProfile = $VmDetails |Select-Object @{l = 'OsType'; e = {$_.StorageProfile.osDisk.osType}}
            if ($PowerState -notcontains "VM running") {
                if ($VmListTags -or $VmListTags.schedule -match "`"$dayToday`":" -or $VmListTags.startmwtf -and $WorkingDays -contains $dayToday) {
                    <# Write-Output "match - $($Vm.Name) - $($VmListTags.startmwtf) - $($PowerState)" #>
                    $MyTrashStatus = New-Object PSObject
                    $MyTrashStatus | Add-Member -type NoteProperty -name Environnement -Value $Vm.Tags.environment
                    $MyTrashStatus | Add-Member -type NoteProperty -name "RG Name" -Value $vm.ResourceGroupName
                    $MyTrashStatus | Add-Member -type NoteProperty -name Serveur -Value $Vm.Name
                    $MyTrashStatus | Add-Member -type NoteProperty -name Systeme -Value $OsProfile."OsType"
                    $MyTrashStatus | Add-Member -type NoteProperty -name Status -Value $PowerState
                    $vmsPowerState.Add($MyTrashStatus) | Out-Null
                }
            }
            if ($OsProfile."OsType" -match "Windows") {$OsWin += 1} elseif ($OsProfile."OsType" -match "Linux") {$OsLin += 1}
            $VmProd += 1
        }
    }
}
$VmStatusList = "$VmProd VM IaaS ($OsWin Windows & $OsLin Linux)"
if ($vmsPowerState.Count -ge 1) {
    $vmsPowerStateReport = $vmsPowerState | ConvertTo-HTML -fragment
}
else {
    $vmsPowerStateReport = "`t`tToutes les machines sont en etat RUNNING."
}
Write-Output "[$(get-date -Format T)] VM Status End"

谢谢你们