Azure Automation による Azure のサービスおよび外部システムの監視
このポストは、11 月 17 日に投稿された Monitoring Azure Services and External Systems with Azure Automation の翻訳です。
今回の記事では、特定のイベントが発生した場合に対処できるように、Azure Automation をセットアップして Azure または外部システムのサービスを監視する方法を手順を追って説明します。Azure Automation を利用してこれを実現するにあたってお客様と多くの議論を重ねてきましたので、ここでは、ほとんどのシナリオで有効と思われるアプローチを説明します。
処理をトリガーする他のシステムのイベントを監視するのに Automation がよく利用されます。外部システムに変更を加える必要がなく、イベントへの対処のロジックを一元化できることが、広く利用される理由です。
監視を行うにはポーリングのしくみが必要です。これについては後ほど説明します。ポーリングのしくみには Azure Automation のスケジュール機能とワークフロー機能を利用しており、実際に実行する時間を最小限に抑え、リソースとコストを節減します。
基本的な監視
まず始めに、Azure のサービスの監視が必要なシナリオから見ていきましょう。Azure 環境で Virtual Machines をいくつかデプロイしており、イベント ログを監視して特定のイベント ID をチェックしたいとします。たとえば、証明書の有効期限が迫っている場合に、証明書を更新し、その旨を電子メールで知らせるようにします。
VM のイベントを監視する Runbook は下図のようになります。
有効期限が迫っている証明書のシナリオでの手順は次のようになります。
- Azure の VM を監視して、直近 24 時間に発生したイベント ID 64 (証明書の有効期限が迫っている) を探します。
- イベント ID が検出されたら、組織が定める手続きに従って証明書を更新する Runbook ジョブを新たに起動します。
- 証明書が更新されたら電子メールを送信します。
- 有効期限が迫っている証明書 (イベント ID 64) がないか VM の監視を継続します。
この処理をすべての VM を対象に毎日 1 回実行しなければならないとします。この場合、Cloud Services の VM にコールして、このイベント ID が見つかったかどうかを判断する Runbook を作成するとよいでしょう。見つかった場合は、子 Runbook を呼び出して証明書を更新します。
このシナリオの要件は有効期限が迫っている証明書を 1 日 1 回チェックすることなので、スリープや継続的なポーリングは不要です。代わりに Azure Automation のスケジューリング機能を利用して簡単にスケジュール設定できます。
開始時刻を毎晩 11:55 に設定して、その日のすべてのイベントを対象に 5 分間または午前 0 時になるまで実行させます。
高度な監視
基本的な監視ソリューションを導入できたので、ポーリングの頻度を高める方法を見ていきましょう。
Azure Automation では Runbook を 1 時間おきに実行するよう設定できます。基本的な監視と同じ手法で、実行間隔を 1 時間に短くすることができますが、ここでは 15 分おきにポーリングしたいとします。15 分ずつずらして実行する 4 つのスケジュールを作成して Watch-EventID という Runbook に関連付けます。
下の [NEXT RUN] 列に見えるとおり、この Runbook は 15 分おきに実行されます。
状態管理による監視
前述のアプローチは、Runbook の監視ニーズをほぼ満たすものの、2 つの欠点があります。それは、各 Runbook にスケジュールを設定しなければならないことと、Runbook の外部 (たとえば Automation 変数) で状態を管理し重複したイベントがトリガーされないようにしなければならないことです。有効期限が迫っている証明書のイベント ログのシナリオでもう一度考えてみましょう。15 分前に実行したジョブが証明書の有効期限切れイベントを基に既に証明書を再発行しているのですが、それ以降の Runbook ジョブはそのことを判断できないので新しい証明書を発行しようとします。
この問題を解決するには、あらかじめ定義した間隔で監視 Runbook を実行するよう設定した別の Runbook を用意し、スケジュール設定します。この Runbook を “Manage-MonitorRunbook” と呼ぶことにしましょう。この Runbook では特定のタグが関連付けられている監視 Runbook を起動します。この手法は、Runbook ごとにスケジュールを設定しないで済むという利点があり、必要に応じて簡単に監視を停止できます。
状態管理の欠点の対応策として、PowerShell ワークフローの Suspend-Workflow (英語) アクティビティを利用できます。監視 Runbook でポーリングを 1 回実行して完了とするのではなく、監視 Runbook が継続してループしながら、監視対象システムのポーリングを 1 回実行したら自ら中断するようにします。その後、Manage-MonitorRunbook が Resume-AzureAutomationJob コマンドレットで監視 Runbook のジョブを再開します。
1 つの監視 Runbook のジョブでポーリング間の状態を管理できるだけでなく、Runbook ジョブを連続実行しないで済むという利点があります。したがって、処理を行ってない間はコストも発生しません。これは、現在 Suspend-Workflow で中断するのではなく Start-Sleep でスリープ状態にして Runbook を使用している場合に効果的な対策です。中断状態のワークフローは料金は発生しませんが、スリープ状態のワークフローは実行状態なのでランニング コストが発生します。
この手法を前述の Watch-EventID Runbook に応用すると以下のようになります。以下のワークフローでは、Runbook 内で状態を管理して新しいイベントを探し始める時刻を指定し、イベントを見つけるたびに、その値を更新して以降のポーリングが同じイベントに対してトリガーしないようにします。
<#
.SYNOPSIS
Azure VM の特定のイベント ID をチェックするサンプル Runbook
.DESCRIPTION
この Runbook は Azure VM で特定のイベント ID を探し、
そのイベントが発生するとアクションを実行します。
Manage-MonitorRunbook ユーティリティ Runbook と併用して、
Manage-MonitorRunbook のスケジュールで定義された特定の間隔で
再開されるよう設計されています。この Runbook には
Manage-MonitorRunbook によって再開されることを示すタグを設定する必要があります。
この Runbook はギャラリーから入手可能な Connect-AzureVM ユーティリティ Runbook に依存します。
.PARAMETER ServiceName
VM が存在する Azure Cloud Services の名前。
.PARAMETER VMName
Azure VM の名前。
.PARAMETER AzureCredentialSetting
組織 Id のユーザー名 / パスワードを格納し、この Azure サブスクリプションへのアクセス権を持つ資格情報アセット名。
.PARAMETER SubscriptionName
Azure サブスクリプションの名前。
.PARAMETER EventID
検出対象のイベント ID。このサンプルではこのイベント ID を探します。
.PARAMETER LogName
イベント ログの名前。Example System。
.PARAMETER Source
イベント ログのソース。Example EventLog。
.PARAMETER VMCredentialSetting
Azure VM へのアクセス権を持つ資格情報アセット名。
.EXAMPLE
Watch-EventID -ServiceName "Finance" -VMName 'FinanceWeb1' -AzureCredentialSetting 'FinanceOrgID' -SubscriptionName "Visual Studio Ultimate with MSDN" -EventID "63" -LogName "System" -Source "EventLog" -VMCredentialSetting "FinanceVMCredential"
#>
workflow Watch-EventID
{
Param (
[String] $ServiceName,
[String] $VMName,
[String] $AzureCredentialSetting,
[String] $SubscriptionName,
[String] $EventID,
[String] $LogName,
[String] $Source,
[String] $VMCredentialSetting
)
# 開始時刻を指定して、この時刻以降のイベントのみを探す。
# これは、他の監視 Runbook で共通のパターンとして利用できる。
$StartTime = Get-Date
Try
{
While (1)
{
$OrgIDCredential = Get-AutomationPSCredential -Name $AzureCredentialSetting
if ($OrgIDCredential -eq $null)
{
throw "Could not retrieve '$AzureCredentialSetting' credential asset.Check that you created this first in the Automation service."
}
$Credential = Get-AutomationPSCredential -Name $VMCredentialSetting
if ($Credential -eq $null)
{
throw "Could not retrieve '$VMCredential' credential asset.Check that you created this first in the Automation service."
}
# Connect-AzureVM ユーティリティ Runbook を呼び出して、接続先の Azure VM の URI を取得。
$Uri = Connect-AzureVM `
-AzureOrgIdCredential $OrgIDCredential `
-AzureSubscriptionName $SubscriptionName `
-ServiceName $ServiceName `
-VMName $VMName
# リモート VM で実行する、イベント ID を探すスクリプト。
$ScriptBlock = {Param($EventID, $StartTime,$LogName,$Source) Get-EventLog -LogName $LogName -Source $Source -InstanceID $EventID -After $StartTime -Newest 1}
# この ScirptBlock をリモート VM で実行。
$EventResult = InlineScript {
Invoke-command -ConnectionUri $Using:Uri -Credential $Using:Credential -ScriptBlock $Using:ScriptBlock -ArgumentList $Using:EventID, $Using:StartTime, $Using:LogName, $Using:Source
}
if ($EventResult)
{
# 新しい開始時刻をこのイベント以降に設定。新しいイベントのみ探す。
$StartTime = $EventResult.TimeGenerated
# このイベントが発生した場合に必要なアクションを実行。
# Start-AzureAutomationRunbook コマンドレットを使用して新しい Runbook を非同期でトリガーし、
# この Runbook がすぐに処理を返し、Manage-MonitorRunbook からの
# 次のコールで再開されるまで自ら中断できるようにする。
# Start-AzureAutomationRunbook -AutomationAccountName <System.String> -Name <System.String> [-Parameters <System.Collections.IDictionary>]
Write-Output "Event ID found... Taking action"
}
# ワークフローを中断して Automation の利用を停止。
# このワークフローは別の監視管理 Runbook (Manage-MonitorRunbook) により特定のスケジュールで再開される。
Write-Verbose "Suspending workflow..."
# 現在、資格情報は中断状態では保持されないため、消去。
$Credential = $Null
$OrgIDCredential = $Null
Suspend-Workflow
}
}
Catch
{
# この Runbook はエラーが発生した場合にも、監視管理 Runbook により
# 再開されてしまうので中断させないこと。監視 Runbook が不適切なタイミングで一時停止してしまうので、
# Erroractionpreference = stop と設定しないこと。
# この場合、エラーを出力。
Write-Error ($_)
}
}
Manage-MonitorRunbook により上記の Runbook を特定の間隔で再開させて、その間隔でポーリングできるようにします。下はその例です。この Runbook をそのまま使用して、お客様の環境で監視を管理できます。
<#
.SYNOPSIS
監視 Runbook が特定の間隔で実行されるよう制御するユーティリティ Runbook。
.DESCRIPTION
この Runbook は指定された間隔で実行し、
中断されている特定のタグを持つ監視 Runbook を再開します。
.PARAMETER AccountName
Azure Automation アカウント名。
.PARAMETER AzureCredentialSetting
組織 Id のユーザー名 / パスワードを格納し、この Azure サブスクリプションへのアクセス権を持つ資格情報アセット名。
.PARAMETER Tag
再開する監視 Runbook のタグの値。他の中断状態の Runbook を再開しないように
監視 Runbook にはこのタグを設定する。
.PARAMETER SubscriptionName
Azure サブスクリプションの名前。オプションのパラメーター。指定しない場合は、既定のサブスクリプションを使用。
.EXAMPLE
Manage-MonitorRunbook -AccountName "Finance" -AzureCredentialSetting 'FinanceOrgID' -Tag "Monitor" -SubscriptionName "Visual Studio Ultimate with MSDN"
#>
workflow Manage-MonitorRunbook
{
Param (
[Parameter(Mandatory=$true)]
[String] $AccountName,
[Parameter(Mandatory=$true)]
[String] $AzureCredentialSetting,
[Parameter(Mandatory=$true)]
[String] $Tag,
[Parameter(Mandatory=$false)]
[String] $SubscriptionName
)
$AzureCred = Get-AutomationPSCredential -Name $AzureCredentialSetting
if ($AzureCred -eq $null)
{
throw "Could not retrieve '$AzureCredentialSetting' credential asset.Check that you created this first in the Automation service."
}
# 使用する Azure サブスクリプションを設定。
$Null = Add-AzureAccount -Credential $AzureCred
# 渡された場合は特定のサブスクリプションを選択、そうでない場合は既定のサブスクリプションを使用。
if ($SubscriptionName -ne $Null)
{
$Null = Select-AzureSubscription -SubscriptionName $SubscriptionName
}
# 指定のタグを持つ Runbook のリストを取得。
$MonitorRunbooks = Get-AzureAutomationRunbook -AutomationAccountName $AccountName | where -FilterScript {$_.Tags -match $Tag}
foreach ($Runbook in $MonitorRunbooks)
{
Write-Verbose ("Checking " + $Runbook.Name + " for suspended jobs to resume")
# この Runbook ID を持つ次の中断状態のジョブを取得。
$SuspendedJobs = Get-AzureAutomationJob -AutomationAccountName $AccountName `
-RunbookName $Runbook.Name | Where -FilterScript {$_.Status -eq "Suspended"}
if ($SuspendedJobs.Count -gt 1)
{
Write-Error ("There are multiple jobs for " + $Runbook.Name + " running. This shouldn't happen for monitor runbooks")
# 一番古いジョブを選択して再開。
$SuspendedJobs = $SuspendedJobs | Sort-Object -Property CreationTime | Select-Object -First 1
}
if ($SuspendedJobs)
{
Write-Verbose ("Resuming the next suspended job: " + $SuspendedJobs.Id)
Resume-AzureAutomationJob -AutomationAccountName $AccountName -Id $SuspendedJobs.Id
}
}
}
上記の Runbook は、監視 Runbook であることを示すタグが設定されている Runbook を探してそれを再開します。監視 Runbook はチェックを行った後、再び中断します。下を見ると、Runbook が 30 分おきに実行するようスケジュール設定されているのがわかります。
監視管理 Runbook のスケジュールのパラメーターを見ると、Tag パラメーターに “monitor” の値が設定されており、このタグを持つ中断状態の Runbook が再開されるのがわかります。このシナリオでは、構成ページで “monitor” タグを Watch-EventID Runbook に追加して、監視管理 Runbook によって 30 分おきに呼び出されるようにします。
このソリューションを拡張してさまざまな時間間隔で監視を行うことができます。監視管理 Runbook をさまざまなスケジュールで構成して、Runbook に適切な時刻間隔のタグを付けます。たとえば、Runbook を 15 分おきに実行するよう設定して “monitor15” タグを持つ監視 Runbook を起動したり、5 分おきに実行するよう設定して Tag パラメーターに “monitor5” を使用したりすることができます。
上記の Runbook を Azure Automation の Runbook ギャラリーで提供しています。独自の監視 Runbook を作成し、監視管理 Runbook を使用して各種システムに統合し、運用タスクをまとめて自動化することができます。
Automation の詳細や利用を開始する方法については、Automation のページをご覧ください。