チュートリアル: Azure Functions を使用してメンテナンス前イベントとメンテナンス後イベントを作成する

適用対象: ✔️ Windows VMs ✔️ Linux VM ✔️ オンプレミス環境 ✔️ Azure Arc 対応サーバー。

このチュートリアルでは、Azure Functions を使用して、スケジュールされたパッチ ワークフローで仮想マシン (VM) を開始および停止するためのメンテナンス前イベントとメンテナンス後イベントを作成する方法について説明します。

このチュートリアルでは、次の作業を行う方法について説明します。

  • 関数アプリを作成します。
  • 関数を作成します。
  • イベント サブスクリプションを作成します。

前提条件

  1. PowerShell 7.4 Runbook を使用していることを確認します。

  2. 適切なマネージド ID にアクセス許可を割り当てます。 Runbook では、Automation アカウントのシステム割り当てマネージド ID またはユーザー割り当てマネージド ID を使用できます。

    次のスクリプトの例 (VM の起動と停止) には、仮想マシン共同作成者ロールまたはこれらの特定のアクセス許可を持つカスタム ロールが必要です。

    • Microsoft.Compute/virtualMachines/start/action
    • Microsoft.Compute/virtualMachines/deallocate/action
    • Microsoft.Compute/virtualMachines/restart/action (仮想マシンの再起動アクション)
    • Microsoft.Compute/virtualMachines/powerOff/action

    Azure portal または Azure PowerShell コマンドレットを使用して、各 ID にアクセス許可を割り当てることができます。

    アクセス許可を割り当てるには、「 Azure portal を使用して Azure ロールを割り当てる」の手順に従います。


  1. Az.ResourceGraph モジュールをインポートします。 モジュールバージョン 2.0.3 でモジュールが ThreadJob に更新されていることを確認します。

Function App を作成する

  1. 関数アプリを作成する手順に従います。

  2. リソースに移動し、次の手順を使用して依存関係を読み込みます。

    注

    依存関係を初めて読み込む必要があります。 PowerShell の依存関係が読み込みに失敗している場合は、最新バージョンの Az と Az.ResourceGraphを確認してください。

    1. 関数アプリの場合は、[アプリ ファイル] を選択します。

    2. host.jsonで、ManagedDependecy を True に設定し、requirements.psd1 を選択します。

    3. requirements.psd1 の下に、次のコードを貼り付けます。

      @{
      'Az'='12.*' 
      'Az.ResourceGraph'='1.0.0' 
      'Az.Resources'='6.*' 
      'ThreadJob' = '2.*'
      }
      
    4. [保存] を選択します。

  3. [概要] タブから関数アプリを再起動して、requirements.psd1 ファイルに記述されている依存関係を読み込みます。

関数を作成する

  1. 関数アプリを作成したら、リソースに移動し、[ 概要] に移動し、[ Azure portal で作成] を選択します。

  2. [ 関数の作成 ] ウィンドウで、次の項目を選択します。

    1. [開発環境の選択] の [開発環境]で、[ポータルで開発] を選択します。

    2. [ テンプレートの選択] で、 イベント グリッドを選択します。

    3. [ テンプレートの詳細] の [ 新しい関数] で、名前を選択します。 次に、[ 作成] を選択します。

      関数を作成するための選択を示すスクリーンショット。

  3. [イベント グリッド関数] ウィンドウで、左側のメニューから [コード + テスト] を選択します。 次のコードを貼り付けて、[ 保存] を選択します。

    # Make sure that you're using eventGridEvent for parameter binding in the Azure function.
    param($eventGridEvent, $TriggerMetadata)
    
    Connect-AzAccount -Identity
    
    # Install the Resource Graph module from PowerShell Gallery
    # Install-Module -Name Az.ResourceGraph
    
    $maintenanceRunId = $eventGridEvent.data.CorrelationId
    $resourceSubscriptionIds = $eventGridEvent.data.ResourceSubscriptionIds
    
    if ($resourceSubscriptionIds.Count -eq 0) {
        Write-Output "Resource subscriptions are not present."
        break
    }
    
    Write-Output "Querying ARG to get machine details [MaintenanceRunId=$maintenanceRunId][ResourceSubscriptionIdsCount=$($resourceSubscriptionIds.Count)]"
    
    $argQuery = @"
        maintenanceresources 
        | where type =~ 'microsoft.maintenance/applyupdates'
        | where properties.correlationId =~ '$($maintenanceRunId)'
        | where id has '/providers/microsoft.compute/virtualmachines/'
        | project id, resourceId = tostring(properties.resourceId)
        | order by id asc
    "@
    
    Write-Output "Arg Query Used: $argQuery"
    
    $allMachines = [System.Collections.ArrayList]@()
    $skipToken = $null
    
    do
    {
        $res = Search-AzGraph -Query $argQuery -First 1000 -SkipToken $skipToken -Subscription $resourceSubscriptionIds
        $skipToken = $res.SkipToken
        $allMachines.AddRange($res.Data)
    } while ($skipToken -ne $null -and $skipToken.Length -ne 0)
    if ($allMachines.Count -eq 0) {
        Write-Output "No Machines were found."
        break
    }
    
    $jobIDs= New-Object System.Collections.Generic.List[System.Object]
    $startableStates = "stopped" , "stopping", "deallocated", "deallocating"
    
    $allMachines | ForEach-Object {
        $vmId =  $_.resourceId
    
        $split = $vmId -split "/";
        $subscriptionId = $split[2]; 
        $rg = $split[4];
        $name = $split[8];
    
        Write-Output ("Subscription Id: " + $subscriptionId)
    
        $mute = Set-AzContext -Subscription $subscriptionId
        $vm = Get-AzVM -ResourceGroupName $rg -Name $name -Status -DefaultProfile $mute
    
        $state = ($vm.Statuses[1].DisplayStatus -split " ")[1]
        if($state -in $startableStates) {
            Write-Output "Starting '$($name)' ..."
    
            $newJob = Start-ThreadJob -ScriptBlock { param($resource, $vmname, $sub) $context = Set-AzContext -Subscription $sub; Start-AzVM -ResourceGroupName $resource -Name $vmname -DefaultProfile $context} -ArgumentList $rg, $name, $subscriptionId
            $jobIDs.Add($newJob.Id)
        } else {
            Write-Output ($name + ": no action taken. State: " + $state) 
        }
    }
    
    $jobsList = $jobIDs.ToArray()
    if ($jobsList)
    {
        Write-Output "Waiting for machines to finish starting..."
        Wait-Job -Id $jobsList
    }
    
    foreach($id in $jobsList)
    {
        $job = Get-Job -Id $id
        if ($job.Error)
        {
            Write-Output $job.Error
        }
    }
    
  4. 左側のメニューで、[ 統合] を選択します。 [トリガー] に、イベント トリガーパラメーター名の値を入力します。 [コードとテスト] ウィンドウで指定したのと同じパラメーター名を使用します。 この例では、パラメーターは eventGridEvent。

    イベント トリガーのパラメーター名のエントリを示すスクリーンショット。

  5. [保存] を選択します。

イベント サブスクリプションの作成

  1. Azure portal にサインインし、[Azure Update Manager] に移動します。

  2. [ 管理] で、[ マシン>メンテナンス構成] を選択します。

  3. [ メンテナンス構成 ] ウィンドウで、構成を選択します。

  4. [設定] で、[イベント] を選択します。

  5. [+イベント サブスクリプション] を選択して、メンテナンス前またはメンテナンス後のイベントを作成します。

  6. [ イベント サブスクリプションの作成 ] ウィンドウの [ イベント サブスクリプションの詳細 ] セクションで、適切な名前を指定します。 スキーマは Event Grid スキーマのままにします。

  7. [ イベントの種類] セクションの [ フィルターからイベントの種類] で、[ メンテナンス前イベント ] または [ メンテナンス後イベント] を選択します。

  8. [ エンドポイントの詳細] セクションで、 Azure 関数 エンドポイントを選択し、[ エンドポイントの構成] を選択します。

  9. イベントをトリガーするリソース グループや関数アプリなど、適切な詳細を指定します。

  10. [作成] を選択します

Azure Storage アカウントとイベント ハブを使用して、イベントを格納、送信、受信することもできます。 詳細については、 Azure Storage でのキューの作成と、Azure portal を使用した イベント ハブの作成 に関するクイックスタートを参照してください。