チュートリアル: Automation で Webhook を使用して事前イベントと事後イベントを作成する
適用対象: ✔️ Windows VMs ✔️ Linux VM ✔️ オンプレミス環境 ✔️ Azure Arc 対応サーバー。
事前イベントと事後イベント (事前/事後スクリプトとも呼ばれる) は、スケジュールされたパッチ インストールの実行前と実行後にユーザー定義のアクションを実行できるしくみです。 最も一般的なシナリオは、仮想マシン (VM) の起動と停止です。 たとえば、スケジュールされたパッチ適用プロセスの開始前に、事前イベントとして、VM を起動するパッチ適用前スクリプトを実行します。 スケジュール パッチが完了し、サーバーが再起動されたら、パッチ後スクリプトを実行することで VM を安全にシャットダウンできます。
このチュートリアルでは、スケジュールされたパッチ適用ワークフローの中で、Webhook により、VM の起動と停止を行う事前イベントと事後イベントを作成する方法について説明します。
このチュートリアルでは、次の作業を行う方法について説明します。
- 前提条件
- Automation Runbook の作成と発行
- Webhook の追加
- イベント サブスクリプションの作成
前提条件
PowerShell 7.2 Runbook を使用していることを確認します。
マネージド ID にアクセス許可を割り当てます。適切な マネージド ID に対して割り当て操作を実行してください。 Runbook では、Automation アカウントのシステム割り当てマネージド ID またはユーザー割り当てマネージド ID のいずれかを使用できます。
個々の ID に対するアクセス許可の割り当て操作は、以下のようにポータルまたは PowerShell コマンドレットで実行できます。
「Azure portal を使用して Azure ロールを割り当てる」の手順に従ってアクセス許可を割り当てます。
Az.ResourceGraph
モジュールをインポートして、このモジュールを、確実にモジュール バージョン 2.0.3 の ThreadJob に更新します。
Automation Runbook の作成と発行
Azure portal にサインインし、お使いの Azure Automation アカウントに移動します。
従来、Azure Automation Update Management で事前タスクまたは事後タスクに Runbook を使用していた場合は、マシンに予期しない影響が生じることやメンテナンス実行が失敗することを避けるため、以下に示す手順を必ず実行してください。
お使いの Runbook に含まれている Webhook ペイロードを解析し、Microsoft.Maintenance.PreMaintenanceEvent イベントと Microsoft.Maintenance.PostMaintenanceEvent イベント以外ではトリガーされないことを確認します。 設計上、同じエンドポイントに他の任意のイベントが追加されると Webhook は他のサブスクリプション イベントからもトリガーされることに注意する必要があります。
- Azure Event Grid イベント スキーマに関する情報を参照してください。
- メンテナンス構成に特有の Event Grid スキーマに関する情報を参照してください。
- 以下のコードを参照してください。
param ( [Parameter(Mandatory=$false)] [object] $WebhookData ) $notificationPayload = ConvertFrom-Json -InputObject $WebhookData.RequestBody $eventType = $notificationPayload[0].eventType if ($eventType -ne "Microsoft.Maintenance.PreMaintenanceEvent" -and $eventType –ne "Microsoft.Maintenance.PostMaintenanceEvent" ) { Write-Output "Webhook not triggered as part of pre or post patching for maintenance run" return }
SoftwareUpdateConfigurationRunContext パラメーターには更新デプロイの対象となるマシン群の情報が含まれていますが、Automation Webhook を使用して事前イベントまたは事後イベントを処理する際、事前スクリプトまたは事後スクリプトにこのパラメーターは渡されません。 該当するマシンを知るには、Azure Resource Graph に対してクエリを実行する方法や、スクリプト内のコードにマシン一覧を保持しておく方法があります。
- Resource Graph クエリの実行とマシンの起動および停止を確実に実行できるよう、スクリプトで使用するマネージド ID に適切なロールとアクセス許可が付与されていることを確認してください。
- リソース グラフ クエリに関連するアクセス許可の情報を参照してください。
- 仮想マシンの共同作成者ロールに関する情報を参照してください。
- 以下のコードを参照してください。
Webhook ペイロードを確認します。
param ( [Parameter(Mandatory=$false)] [object] $WebhookData ) Connect-AzAccount -Identity # Install the Resource Graph module from PowerShell Gallery # Install-Module -Name Az.ResourceGraph $notificationPayload = ConvertFrom-Json -InputObject $WebhookData.RequestBody $maintenanceRunId = $notificationPayload[0].data.CorrelationId $resourceSubscriptionIds = $notificationPayload[0].data.ResourceSubscriptionIds if ($resourceSubscriptionIds.Count -gt 0) { 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 $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 } }
カスタマイズするには、既存スクリプトを上のように変更して使用するか、以下に示すスクリプトを使用します。
サンプルのスクリプト
param
(
[Parameter(Mandatory=$false)]
[object] $WebhookData
)
Connect-AzAccount -Identity
# Install the Resource Graph module from PowerShell Gallery
# Install-Module -Name Az.ResourceGraph
$notificationPayload = ConvertFrom-Json -InputObject $WebhookData.RequestBody
$eventType = $notificationPayload[0].eventType
if ($eventType -ne "Microsoft.Maintenance.PreMaintenanceEvent") {
Write-Output "Webhook not triggered as part of pre-patching for maintenance run"
return
}
$maintenanceRunId = $notificationPayload[0].data.CorrelationId
$resourceSubscriptionIds = $notificationPayload[0].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
}
}
Webhook の追加
上記の発行済み Runbook に Webhook を追加し、Webhook の URL をコピーします。
Note
Webhook を作成した後は確実に URL をコピーしてください。この URL を再度取得することはできません。
イベント サブスクリプションの作成
Azure portal にサインインし、[Azure Update Manager] に移動します。
[管理] で、[マシン]、[メンテナンス構成] の順に選択します。
[メンテナンス構成] ページで、構成を選択します。
[設定] で、[イベント] を選択します。
[+イベント サブスクリプション] を選択して、メンテナンス前とメンテナンス後のイベントを作成します。
[イベント サブスクリプションの作成] ページで、次の詳細を入力します:
- [イベント サブスクリプションの詳細] セクションで、適切な名前を指定します。
- スキーマは Event Grid スキーマのままにします。
- [イベントの種類] セクションで、[イベントの種類のフィルター] を指定します。
[作成] を選択します
次のステップ
- Azure Update Manager での事前イベントと事後イベントの概要について理解を深める。
- 事前イベントと事後イベントの作成方法について理解を深める
- 事前および事後イベントを管理する方法、またはスケジュール実行をキャンセルする方法については、事前と事後のメンテナンス構成イベントに関する記事を参照してください。
- 「Azure Functions を使用して事前イベントと事後イベントを作成する方法」で詳細を確認する。