次の方法で共有


Azure Automation を使用して DevTest Lab の VM の起動順序を定義する

この記事では、Azure Automation で PowerShell Runbook を使用して、特定の順序で DevTest Labs 仮想マシン (VM) を起動する方法について説明します。 PowerShell スクリプトでは、ラボの VM 上のタグを使用して、スクリプトを変更しなくても起動順序を変更できるようにします。

DevTest Labs の自動起動機能を使用すると、指定した時間にラボの VM が自動的に起動するように構成できます。 ただし、ラボの VM を特定の順序で起動することが必要になる場合があります。 たとえば、ラボ内のジャンプボックス VM が他の VM へのアクセス ポイントである場合、ジャンプボックス VM は他の VM より先に起動する必要があります。

前提条件

  • すべてのラボの VM に StartupOrder というタグを作成して適用します。その際に指定する適切な起動値は 0 から 10 です。 起動する必要のないマシンは -1 に指定します。

  • スタンドアロン Azure Automation アカウントを作成する」の手順に従って、Azure Automation アカウントを作成します。 アカウントを作成するときに、[アカウントとして実行] オプションを選択します。

PowerShell Runbook を作成する

  1. Automation アカウントの [概要] ページで、左側のメニューから [Runbook] を選択します。
  2. [Runbook] ページで、[Runbook の作成] を選択します。
  3. マネージド ID を使用して Automation 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"
    }
}

スクリプトを実行する

  • このスクリプトを毎日実行するには、Automation アカウントでスケジュールを作成し、そのスケジュールを Runbook にリンクします。

  • 複数のラボを持つ複数のサブスクリプションがある企業のシナリオでは、さまざまなラボおよびサブスクリプションのパラメーター情報をファイルに格納できます。 スクリプトには個々のパラメーターではなくファイルを渡します。

  • この例では、Azure Automation を使用して PowerShell スクリプトを実行しますが、ビルドとリリースのパイプラインなどの他のオプションを使用することもできます。

次の手順