使用 Azure 自動化定義 DevTest Lab VM 的啟動順序
本文說明如何使用 Azure 自動化中的 PowerShell Runbook,以特定順序啟動 DevTest Labs 虛擬機器 (VM)。 PowerShell 指令碼會使用實驗室 VM 上的標籤,因此您可以變更啟動順序,而不需要變更指令碼。
DevTest Labs 自動啟動功能可以設定實驗室 VM,以在指定的時間自動啟動。 然而,有時候您可能會想要讓實驗室 VM 以特定順序啟動。 例如,若實驗室中的 Jumpbox VM 是其他 VM 的存取點,則該 Jumpbox VM 就必須在其他 VM 之前啟動。
必要條件
建立名為 StartupOrder 的標籤,並將其套用至具有適當啟動值 (0 到 10) 的所有實驗室 VM。 指定不需要啟動為 -1 的任何機器。
遵循建立獨立 Azure 自動化帳戶中的指示,建立 Azure 自動化帳戶。 當您建立帳戶時,請選擇 [執行身分帳戶] 選項。
建立 PowerShell Runbook
- 在自動化帳戶的 [概觀] 頁面上,從左側功能表中選取 [Runbook]。
- 在 [Runbook] 頁面上,選取 [建立 Runbook]。
- 遵循使用受控識別建立自動化 PowerShell Runbook 中的指示,建立 PowerShell Runbook。 使用下列 PowerShell 指令碼填入 Runbook。
準備 PowerShell 指令碼
下列指令碼會採用訂閱名稱與實驗室名稱作為參數。 指令碼會取得實驗室中的所有 VM,並剖析其標籤資訊,以建立 VM 名稱與其啟動順序的清單。 指令碼會依序逐步解說清單並啟動 VM。
若特定順序號碼中有多部 VM,則這些 VM 會使用 PowerShell 作業以非同步方式啟動。 沒有標籤的 VM 會將其啟動值設定為 10,且根據預設為最後一個啟動。 指令碼會忽略具有 0 到 10 以外之標記值的任何 VM。
#Requires -Version 3.0
#Requires -Module AzureRM.Resources
param
(
[Parameter(Mandatory=$false, HelpMessage="Name of the subscription that has the lab")]
[string] $SubscriptionName,
[Parameter(Mandatory=$false, HelpMessage="Lab name")]
[string] $LabName
)
# Connect and add the appropriate subscription
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Add-AzureRMAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationID $Conn.ApplicationId -Subscription $SubscriptionName -CertificateThumbprint $Conn.CertificateThumbprint
# Find the lab
$dtLab = Find-AzResource -ResourceType 'Microsoft.DevTestLab/labs' -ResourceNameEquals $LabName
# Get the VMs
$dtlAllVms = New-Object System.Collections.ArrayList
$AllVMs = Get-AzResource -ResourceId "$($dtLab.ResourceId)/virtualmachines" -ApiVersion 2016-05-15
# Get the StartupOrder tag. If missing, set to start up last (10).
ForEach ($vm in $AllVMs) {
if ($vm.Tags) {
if ($vm.Tags['StartupOrder']) {
$startupValue = $vm.Tags['StartupOrder']
} else {
$startupValue = 10
}
} else {
$startupValue = 10
}
$dtlAllVms.Add(@{$vm.Name = $startupValue}) > $null
}
# Setup for the async multiple vm start
# Save profile
$profilePath = Join-Path $env:Temp "profile.json"
If (Test-Path $profilePath){
Remove-Item $profilePath
}
Save-AzContext -Path $profilePath
# Job to start VMs asynch
$startVMBlock = {
Param($devTestLab,$vmToStart,$profilePath)
Import-AzContext -Path ($profilePath)
Invoke-AzResourceAction `
-ResourceId "$($devTestLab.ResourceId)/virtualmachines/$vmToStart" `
-Action Start `
-Force
Write-Output "Started: $vmToStart"
}
$current = 0
# Start in order from 0 to 10
While ($current -le 10) {
# Get the VMs in the current stage
$tobeStarted = $null
$tobeStarted = $dtlAllVms | Where-Object { $_.Values -eq $current}
if ($tobeStarted.Count -eq 1) {
# Run sync – jobs not necessary for a single VM
$returnStatus = Invoke-AzResourceAction `
-ResourceId "$($dtLab.ResourceId)/virtualmachines/$($tobeStarted.Keys)" `
-Action Start `
-Force
Write-Output "$($tobeStarted.Keys) status: $($returnStatus.status)"
} elseif ($tobeStarted.Count -gt 1) {
# Start multiple VMs async
$jobs = @()
Write-Output "Start Jobs start: $(Get-Date)"
# Jobs
$jobs += Start-Job -ScriptBlock $startVMBlock -ArgumentList $dtLab, $($singlevm.Keys), $profilePath
Write-Output "Start Jobs end: $(Get-Date)"
}
# Get results from all jobs
if($jobs.Count -ne 0) {
Write-Output "Receive Jobs start: $(Get-Date)"
foreach ($job in $jobs){
$jobResult = Receive-Job -Job $job -Wait | Write-Output
}
Remove-Job -Job $jobs -Force
}
else
{
Write-Output "Information: No jobs available"
}
}
執行指令碼
若要每日執行此指令碼,請在自動化帳戶中建立排程,並將排程連結至 Runbook。
在具有多個實驗室之數個訂閱的企業案例中,您可以將不同實驗室與訂閱的參數資訊儲存於檔案中。 將檔案傳遞給指令碼,而不是傳遞個別參數。
此範例會使用 Azure 自動化來執行 PowerShell 指令碼,但您也可以使用其他選項,例如組建/發行管線。