【Azure】AutomationアカウントでVMの起動/停止を定期的に繰り返すスケジュールを組む(PowerShell編):Tech TIPS
既に作成済みのAzure Automationに対し、新たに何らかの処理を定期的に実行するスケジュールを追加するには、幾つかの手段がある。そのうち、Azure PowerShellを使って定期スケジュールを追加作成する方法を紹介する。
対象:Azure Automation、Azure PowerShell
Tech TIPS「【Azure】AutomationアカウントでVMの起動/停止を定期的に繰り返すスケジュールを組む(ARMテンプレート編)」では、Azure Automationのデプロイ時に、定期的に実行するスケジュールも同時に設定する方法を紹介した。
ただ実際には、既存のAutomationアカウントを再デプロイすることなく、新たな定期実行スケジュールを追加したい、という場合もあるだろう。
そこで本Tech TIPSでは、Azure PowerShellを使って、既存のAutomationアカウントにスケジュールを追加する方法を紹介する。例に挙げるのは、前出のTech TIPSと同じ仮想マシン(VM)の定期的な起動/シャットダウンとする。
Azure PowerShellのインストールについては、Tech TIPS「Azure PowerShellをインストールする【Windows 10/11】」を参照していただきたい。
Automationアカウントを操作する前には、「Set-AzContext」コマンドレットを以下のように実行して、デフォルトのサブスクリプションを適切に選択していただきたい。
Set-AzContext -Subscription <サブスクリプション名>
■執筆時の各種ツール/APIのバージョン
- PowerShellのバージョン: Ver. 7.4.2
- PowerShell向けAzモジュール: Ver. 12.1.0
GitHubで公開されているPowerShellスクリプトをRunbookとして登録する
スケジュールによって定期的に実行したいPowerShellスクリプトを、RunbookとしてAutomationアカウントに登録する。ここでは、PowerShellスクリプトを一から作成するのではなく、GitHubで一般公開されているRunbook用PowerShellスクリプトを直接インポートする。
# ファイル: Import-PSScriptsToRunbooks.ps1
# RunbookにインポートするPowerShellスクリプト
$runbooks = @(
# https://github.com/diecknet/Simple-Azure-VM-Start-Stop
@{
name = 'Simple-Azure-VM-Start-Stop2' # 識別しやすい名称を付ける
description = '指定の仮想マシンを起動またはシャットダウンする。' # 説明
type = 'PowerShell' # これはPowerShell 5.1の場合
# ↑PowerShell 7.2なら「PowerShell72」
uri = "https://raw.githubusercontent.com/diecknet/Simple-Azure-VM-Start-Stop/main/SimpleAzureVMStartStop.ps1"
# ↑スクリプトのダウンロードURL
localPath = "./SimpleAzureVMStartStop.ps1"
}
)
# インポート先のAutomationアカウント
$AAName = "<Automationアカウント名>"
$AARG = "<↑のリソースグループ名>"
# 各Runbookの登録
$runbooks | ForEach-Object {
# PowerShellスクリプトをいったんダウンロードしてローカルファイルに保存
Invoke-WebRequest -Uri $_.uri -OutFile $_.localPath
# ローカルファイルからインポートし、そのまま発行済みにする
Import-AzAutomationRunbook `
-ResourceGroupName $AARG -AutomationAccountName $AAName `
-Name $_.name -Description $_.description `
-Type $_.type `
-Path $_.localPath `
-Published
}
※Microsoftのレファレンス: Invoke-WebRequest、Import-AzAutomationRunbook、ForEach-Object
上記リストでは、配列「$runbooks」にまとめた複数のRunbook用スクリプトを、「ForEach-Object」で1つずつインポートしている。
各スクリプトのダウンロードURLは、$runbooksの各要素のハッシュテーブルにあるキー「uri」に指定する。インポートしたいPowerShellスクリプトのダウンロードURLを調べる方法については、Tech TIPS「【Azure】Automation RunbookにGitHub上のPowerShellスクリプトをインポートする(ARMテンプレート編)」の見出し「インポートしたいPowerShellスクリプトのダウンロードURLを取得する」の説明を参照していただきたい。
PowerShellスクリプトはいったんローカルファイルに保存する必要がある。キー「localPath」には、そのローカルファイルのパスを指定する。
スクリプトをPowerShell 5.1で実行する場合は「runbookType」に「PowerShell」を指定する。PowerShell 7.2が必須なら、代わりに「PowerShell72」を指定すること。
インポート先となるAutomationアカウントの名前およびリソースグループ名も、変数「$AAName」「$AARG」にそれぞれ指定してほしい。
カスタムロールを作成する
次は、VMの起動/シャットダウンなどの許可をまとめたカスタムロールを作成(定義)する。これをAutomationアカウントに割り当てることで、同アカウントにVMを制御させることが可能になる。
# ファイル名: Define-CustomRole.ps1
# 現在のサブスクリプションのGUIDを取得
$subscriptionID = (Get-AzContext).Subscription.Id
# カスタムロール作成時のパラメーター向けに空のオブジェクトを新規作成
$customRole = New-Object -TypeName Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition
# オブジェクトにパラメーターを設定
$customRole.Name = "<カスタムロールに付ける名前>"
$customRole.Description = "仮想マシンの起動/シャットダウンと割り当て解除/再起動ができる。"
$customRole.Actions = @(
# このカスタムロールで許可する権限(アクセス許可)を列挙
'Microsoft.Compute/virtualMachines/read' # VMの情報の読み取り
'Microsoft.Compute/virtualMachines/start/action' # VMの起動
'Microsoft.Compute/virtualMachines/deallocate/action' # VMの割り当て解除
'Microsoft.Compute/virtualMachines/powerOff/action' # VMのシャットダウン
'Microsoft.Compute/virtualMachines/restart/action' # VMの再起動
)
$customRole.AssignableScopes = @(
# このカスタムロールを適用するスコープのIDを列挙
"/subscriptions/$subscriptionID"
)
$customRole.IsCustom = $true # カスタムロールを指定
# カスタムロールを作成
New-AzRoleDefinition -Role $customRole
カスタムロールに付ける名前は、オブジェクト「$customRole」のプロパティ「Name」に指定する。これにはスペースが含まれていてもよい。「Description」の説明文についても同様だ。
アクセス許可はプロパティ「Actions」の配列に列挙する。「Microsoft.」から始まる各アクセス許可の名称については、Microsoft Learn「Azureのアクセス許可」にレファレンスが掲載されている。他の許可を追加する場合は、このページを参照していただきたい。公開されているPowerShellスクリプトの場合は、必要なアクセス許可の一覧がドキュメントに記載されていないか確認しよう(前述のスクリプトの場合、JSONファイルで示されている)。
カスタムロールを適用するスコープは、プロパティ「Actions」の配列にそのIDを列挙する。本記事ではサブスクリプションスコープに適用することを想定している。そのため、サブスクリプションレベルでカスタムロールを作成するための許可(組み込み済みのロールなら「所有者」など)が与えられているユーザーでログインしてから、上記スクリプトを実行する必要がある。
制御するVMのリソースグループにカスタムロールを割り当てる
カスタムロールを作成したら、それを制御対象のVMのリソースグループに割り当てることで、Automationアカウントからアクセスできるように許可に与える。
# ファイル名: Assign-CustomRolesToAA.ps1
$roleNames = @( # 割り当てるロール名を列挙
"<作成したカスタムロールの名前>"
)
$scopes = @( # 上記ロールによるアクセス許可を適用するスコープのIDを列挙
"/subscriptions/<サブスクリプションのGUID>/resourceGroups/<リソースグループ名>"
)
# カスタムロールの割り当て先のAutomationアカウント
$AAName = "<Automationアカウント名>"
$AARG = "<↑のリソースグループ名>"
# Automationアカウントを取得
$automationAccount = Get-AzAutomationAccount -ResourceGroupName $AARG -Name $AAName
if ($null -eq $automationAccount.Identity) {
# マネージドIDが無効なら、ここでシステム割り当てIDをオンにする
$automationAccount = Set-AzAutomationAccount -ResourceGroupName $AARG -Name $AAName -AssignSystemIdentity
}
# システム割り当てIDを取得
$managedID = $automationAccount.Identity.PrincipalId
# 指定の全スコープに対して、Automationアカウントに上記カスタムロールを割り当てる
$scopes | ForEach-Object {
$scope = $_
$roleNames | ForEach-Object {
$roleName = $_
New-AzRoleAssignment -ObjectId $managedID -RoleDefinitionName "$roleName" -Scope $scope
}
}
※Microsoftのレファレンス: Get-AzAutomationAccount、Set-AzAutomationAccount、New-AzRoleAssignment
配列「$roleNames」には、割り当てるロール(カスタムロールを含む)の名前を指定する。また配列「$scopes」には、アクセスを許可するスコープのIDを指定する。上記リストでは、スコープとして仮想マシンのリソースグループを想定している。
上記リストのポイントは、マネージドIDを有効化して、それにアクセス許可を与えていることだ。ここでは手軽な「システム割り当て」を選んでいる(Microsoftは「ユーザー割り当て」を推奨している)。
Automationアカウントに定期実行スケジュールを追加する
最後に、定期的に実行するスケジュールをAutomationアカウントに追加して、インポートして作ったRunbookをひも付ける。
# ファイル: Add-VMStartStopSchedules.ps1
# VMの起動/シャットダウン時刻とそのタイムゾーン
$VMStartTime = "03:00:00" # VM起動時刻。ローカルのタイムゾーンで指定
$VMStopTime = "09:00:00" # VMシャットダウン時刻
# 無期限を表す変数
$neverExpiryTime = Get-Date "9999-12-30T23:59:59.9999999+00:00"
# 制御対象のVM
$VMName = "<起動/シャットダウンさせる仮想マシン名>"
$VMRG = "<↑のリソースグループ名>"
# 定期実行のスケジュール(複数)
$schedules = @(
# スケジュール: VM起動
@{
name = "start-$VMName" # このスケジュールの一意な名前
description = "仮想マシン「$VMName」を毎日$VMStartTimeに起動する"
startTime = (Get-Date $VMStartTime).AddDays(1) # 翌日の指定時刻から始める
expiryTime = $neverExpiryTime # 無期限
dayInterval = 1 # 毎日。2日に1回なら「2」
runbookName = "Simple-Azure-VM-Start-Stop" # 実行するRunbookの名称
runbookParams = @{
# 実行するRunbookに渡すパラメーター(個々のRunbookに依存)
ACTION = "Start" # 「VM起動」を指定
VMNAME = $VMName # 対象VMの名前
RESOURCEGROUPNAME = $VMRG # 対象VMのリソースグループ
}
}
# スケジュール: VMシャットダウン
@{
name = "stop-$VMName" # このスケジュールの一意な名前
description = "仮想マシン「$VMName」を毎日$VMStopTimeにシャットダウン/割り当て解除する"
startTime = (Get-Date $VMStopTime).AddDays(1) # 翌日の指定時刻から始める
expiryTime = $neverExpiryTime # 無期限
dayInterval = 1 # 毎日
runbookName = "Simple-Azure-VM-Start-Stop" # 実行するRunbookの名称
runbookParams = @{
ACTION = "Stop" # 「VMシャットダウン」を指定
VMNAME = $VMName # 対象VMの名前
RESOURCEGROUPNAME = $VMRG # 対象VMのリソースグループ
}
}
)
# スケジュール追加先のAutomationアカウント
$AAName = "<Automationアカウント名>"
$AARG = "<↑のリソースグループ名>"
# 各スケジュールを実際に追加
$schedules | ForEach-Object {
# まずスケジュールを生成
New-AzAutomationSchedule `
-ResourceGroupName $AARG -AutomationAccountName $AAName `
-Name $_.name -Description $_.description `
-StartTime $_.startTime -ExpiryTime $_.expiryTime `
-DayInterval $_.dayInterval `
-TimeZone (Get-TimeZone).Id # ローカルのタイムゾーン
# 生成したスケジュールにRunbookをひも付け
Register-AzAutomationScheduledRunbook `
-ResourceGroupName $AARG -AutomationAccountName $AAName `
-Name $_.runbookName `
-ScheduleName $_.name `
-Parameters $_.runbookParams
}
※Microsoftのレファレンス: Get-Date、New-AzAutomationSchedule、Get-TimeZone、Register-AzAutomationScheduledRunbook
「$VMStartTime」にはVMの起動時刻を、例えば「03:00:00」というように指定する。同様に「$VMStopTime」にはシャットダウン時刻を指定する。いずれもタイムゾーンはローカル、すなわち日本時間(+09:00)を想定している。
また対象のVMについては、その名前とリソースグループ名を「$VMName」「$VMRG」にそれぞれ設定する。
Automationで定期的なスケジュールを組むには、「開始日時」「繰り返す単位」「繰り返す間隔」をそれぞれ指定する必要がある。上記の配列「$schedules」の場合、各要素のハッシュテーブルの「startTime」「frequency」「dayInterval」にそれぞれ該当する。上記リストでは翌日の指定時刻より毎日1回ずつ実行するように設定している。3日に1回実行するのならば、「dayInterval」に「3」を指定すればよい。
ハッシュテーブル「runbookParams」では、スケジュールにひも付けるRunbook(ここではPowerShellスクリプト)のパラメーターを指定している。その内容はRunbookに依存するので、スクリプトの仕様を確認して必要なパラメーター名とその値を列挙すること。
スケジュールの新規作成は「New-AzAutomationSchedule」コマンドレットで、Runbookのひも付けは「Register-AzAutomationScheduledRunbook」コマンドレットでそれぞれ行っている。
日ごとではなく、週ごと、あるいは月ごとにスケジュールしたい場合は、「New-AzAutomationSchedule」コマンドレットで、「-DayInterval」パラメーターの代わりに「-WeekInterval」「- MonthInterval」をそれぞれ指定する必要がある。
■関連リンク
- Azure Automation アカウントのシステム割り当てマネージドIDを使用する(Microsoft Learn)
- Azure PowerShell を使用してAzureカスタムロールを作成または更新する - Azure RBAC(Microsoft Learn)
- Azure PowerShell を使用して Azure ロールを割り当てる - Azure RBAC(Microsoft Learn)
Copyright© Digital Advantage Corp. All Rights Reserved.