Azure Automationで祝日を考慮した自動起動/停止を構成する!

こんにちは!パーソルプロセス&テクノロジーの佐藤です。

コストの観点から定期的な仮想マシンの起動/停止を行うために、Azure Automationの自動起動/停止ソリューションを使用されているお客様は多いかと思います。

しかし、通常のソリューションではタスク実行スケジュールの設定を指定の日あるいは曜日で行うため、仮想マシンを使用しない祝日にも起動ジョブが走り、余計なコストがかかってしまう恐れがあります。

そこで今回は、国の定める祝日を反映させた仮想マシン自動起動/停止を構成するシンプルな方法をご紹介します。

 

※本記事で紹介するAutomation RunbookではPowershell Azモジュールを使用します。構成をお試しになる場合、新規にAutomationアカウントを作成してAzモジュールをインポートすることをお勧めします。

参考:

Azure AutomationのPowerShell RunbookでAzモジュールを使用することはできますか?(https://cloudsteady.jp/post/10046/

 

概要

  1. 内閣府ホームページからダウンロードした祝日一覧をAutomation変数に格納します。
  2. 作成した変数を用いて祝日判定を行い、平日にのみ自動起動スクリプトを実行します。なお、自動停止スクリプトについては祝日判定を行わず毎日定時に実行する構成を取っていますが、自動起動スクリプトと同様の手順で祝日除外の構成をすることも可能です。

今回はAzure Automationの基礎の習熟も兼ね、祝日取得と祝日判定、自動起動のRunbookをPowershellで作成し、それらをグラフィカルRunbookで繋ぐ構成をとります。グラフィカルRunbookが面倒に感じたらひとつのPowershell Runbookで構成することも可能です。

前提条件

  • AutomationアカウントにAzモジュールがインポートされ、Azコマンドが実行可能な状態であること
  • Automation実行アカウントが利用可能な状態であること

Automation変数の作成

以下の3つの変数を作成します。

  • Target_ResourceGroup(文字列):自動起動/停止の対象となる仮想マシンが存在するリソースグループ名を格納します。半角カンマ(,)で区切ることで複数指定も可能です。なお、複数のリソースグループを指定する場合、仮想マシン名はそれらのリソースグループ間で一意にする必要があります。
  • ExcludeVMs(文字列):Target_ResourceGroupに入力するリソースグループ内で自動起動・停止の対象から除外する仮想マシン名を入力します。半角カンマで区切ることで複数指定が可能です。
  • Japanese_Holidays(文字列):Webから取得する日本の祝日リストが格納されます。

Runbookの作成

以下5つのRunbookを作成します。

  • AddHolidays:年に一度、内閣府HPから日本の祝日一覧(振替休日あり)を取得し、今年度の休日リストを作成して変数に格納します。
  • IsitHoliday:月曜日から金曜日にかけて毎日決まった時間に休日判定を行います。
  • StartVMs:決まった時間に対象の仮想マシンを起動します。
  • StopVMs:決まった時間に対象の仮想マシンを停止します。
  • HolidayAutomation:IsitHolidayとStartVMsをリンクさせます。

※HolidayAutomationはグラフィックRunbookで作成し、その他のRunbookはPowershell Runbookで作成します。

Powershell Runbookのソースコードは以下の通りです。

Runbook:AddHolidays

#内閣府HPから休日csvをインポート
$uri="https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv"
$importLoc=".\syukujitsu.csv"
Invoke-WebRequest -Uri $uri -OutFile $importLoc 
$HolidaysCsv= Import-Csv $importLoc -Encoding Default -Header "date","name" |Where-Object -FilterScript{$_.date -ne "国民の祝日・休日月日"}
#年末年始休暇を追加
$thisyear =(get-date).Tostring("yyyy")
$aditionalHolidays =@("/1/2","/1/3","/12/29","/12/30","/12/31")
foreach($addition in $aditionalHolidays){
    $addition= $thisyear+$addition
    $HolidaysCsv += New-Object PsObject -Property @{ date = $addition ; name = '年末年始休暇' }
}
#来年の休日をソートして抜き出し
$thisyearsHolidays= $HolidaysCsv |Where-Object -FilterScript{$_.date -ge $thisyear+"/1/1"}|sort {[datetime]$_.date} 
$thisyearsHolidays|export-csv -path $importLoc -Encoding Default -NoTypeInformation
#休日を文字列として結合
$content=""
$lastholiday=$thisyearsHolidays[-1]
$thisyearsHolidays|ForEach-Object{
    $content+=[string]$_.date
    if($_.date -ne $lastholiday.date){
    $content+=","
    }
}
#変数に追加
Set-AutomationVariable -Name 'Japanese_Holidays' -Value $content

Runbook:IsitHoliday

#変数の休日取得
$Holidays = (Get-AutomationVariable -Name 'Japanese_Holidays')-split(",")
#今日の日付
$Today= Get-Date -format d
#休日判定
$IsitHoliday= $Holidays.contains($Today)
Write-Output $IsitHoliday

Runbook:StartVMs

$servicePrincipalConnection=Get-AutomationConnection -Name "AzureRunAsConnection"      
        Add-AzAccount `
            -ServicePrincipal `
            -TenantId $servicePrincipalConnection.TenantId `
            -ApplicationId $servicePrincipalConnection.ApplicationId `
            -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
  
#対象リソースグループ取得
$TargetResourceGroup= (Get-AutomationVariable -Name 'Target_ResourceGroup')-split(",")
#対象リソースグループ所属VMリスト取得
$VMList= @()
ForEach($rg in $TargetResourceGroup){
    $VMList += (get-azVM -ResourceGroupName $rg).Name
}
#除外VMリスト取得
$ExcludeVMs =(Get-AutomationVariable -Name 'ExcludeVMs')-split(",")
#対象VM取得
$TargetVMs= Compare-Object -ReferenceObject $VMList -DifferenceObject $ExcludeVMs -PassThru
#対象VM起動
$TargetVMs|ForEach-Object{
    Start-AzVM -ResourceGroupName (get-azVM -Name $_).ResourceGroupName -Name $_
}

Runbook:StopVMs

$servicePrincipalConnection=Get-AutomationConnection -Name "AzureRunAsConnection"      
        Add-AzAccount `
            -ServicePrincipal `
            -TenantId $servicePrincipalConnection.TenantId `
            -ApplicationId $servicePrincipalConnection.ApplicationId `
            -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
#対象リソースグループ取得
$TargetResourceGroup= (Get-AutomationVariable -Name 'Target_ResourceGroup')-split(",")
#対象リソースグループ所属VMリスト取得
$VMList= @()
$TargetResourceGroup|ForEach-Object{
    $VMList += (get-azVM -ResourceGroupName $_).Name
}
#除外VMリスト取得
$ExcludeVMs =(Get-AutomationVariable -Name 'ExcludeVMs')-split(",")
#対象VM取得
$TargetVMs= Compare-Object -ReferenceObject $VMList -DifferenceObject $ExcludeVMs -PassThru
#対象VM停止
$TargetVMs|ForEach-Object{
    Stop-AzVM -ResourceGroupName (get-azVM -Name $_).ResourceGroupName -Name $_ -force
}

Runbook:HolidayAutomation

Powershell Runbookを作成したら、仮想マシン自動起動に休日条件を適用するため、下画像のようにIsitHolidayとStartVMsを条件付きシーケンスで繋いだグラフィックRunbookを作成します。

条件式にはRunbook:IsitHolidayで出力する変数を

$ActivityOutput['IsitHoliday']

としてBoolean型を返す式を入力することができます。

$ActivityOutputはAzure Automationの規定の書式であり、オブジェクト型の変数を格納することが可能です。

(参考:Azure Automationでのグラフィカル作成

スケジュール設定

AddHolidays・HolidayAutomation・StopVMsのRunbookに対してそれぞれのスケジュールを作成し、割り当てを行います。

なお、Azure AutomationではRunbookの実行時間が課金単位となります。

よってスケジュールを細かく設定するほど課金額は大きくなるので、任意でStopVMsのスケジュールを週単位に設定してください。

(本当はStartVMs・StopVMsのRunbookの中で次回スケジュールを設定できれば良いのですが、スケジュールの時刻変更を行うPowershellコマンドは未だ無いようです…)

AddHolidays

HolidayAutomation

StopVMs

割り当て

まとめ

長文おつきあいいただきありがとうございます。

csvファイルを取得して変数に格納し、それによって毎日の休日判定を行うといった愚直な構成のソリューションですが、

本記事が皆様の運用の改善ないしAzure Automation理解のお役に立てれば幸いです。

 

いいね (この記事が参考になった人の数:16)
(↑参考になった場合はハートマークを押して評価お願いします)
読み込み中...

注意事項・免責事項

※技術情報につきましては投稿日時点の情報となります。投稿日以降に仕様等が変更されていることがありますのでご了承ください。

※公式な技術情報の紹介の他、当社による検証結果および経験に基づく独自の見解が含まれている場合がございます。

※これらの技術情報によって被ったいかなる損害についても、当社は一切責任を負わないものといたします。十分な確認・検証の上、ご活用お願いたします。

※当サイトはマイクロソフト社によるサポートページではございません。パーソルプロセス&テクノロジー株式会社が運営しているサイトのため、マイクロソフト社によるサポートを希望される方は適切な問い合わせ先にご確認ください。
 【重要】マイクロソフト社のサポートをお求めの方は、問い合わせ窓口をご確認ください