Azure Automationを使用してAzure仮想マシンのディスクのスナップショットを自動取得する

#背景
　諸事象によりAzure Backupで正常にバックアップを取得することが出来ない仮想マシンが有ったため、Azure Backupの代替策としてスナップショット取得の自動化(Azure Automation)を検証しました。

#前提条件
　Azure サブスクリプションにて以下のリソースが作成済みであることを前提に説明します。
・Azure Automation アカウント
・Azure 仮想マシン(検証の為OSディスクの他にデータディスクを2本接続済み)

#スクリプトの概説

1.パラメーター指定

　今回の処理で指定すべきパラメータは以下の4つです。

```
$resourceGroupName = "<仮想マシンが存在するリソースグループ名>" 
$location = "<仮想マシンのリージョン>" 
$vmName = "<仮想マシンの名前>"
$retentionPeriod = <スナップショットを保持する日数> 
```

2.Azure へログイン

　既定のAzure Automation 実行アカウントを使用してAzure へログインします。Runbookに以下の内容を記載します。

```
$connectionName = "AzureRunAsConnection"
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         

Login-AzAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 
```

3.VMの指定

　スナップショットを取得する仮想マシンを指定します。

```
$vm = Get-AzureRmVM -ResourceGroupName $resourceGroupName -Name $vmName
```

4.Snapshot作成(OSディスク)

　スナップショットを作成する際スナップショットの名前を指定する必要が有ります。どのOSディスクのスナップショットであるか判別できるように、今回はディスク名をスナップショットの名称に含めます。1日に複数回取得する可能性も考慮して、スナップショット取得時のタイムスタンプもスナップショットの名称に含めます。更にスナップショットリソースであることを示すために「snapshot」の文言も含めます。また、Azure AutomationのタイムゾーンはUTCであるため日本時間になるようタイムスタンプ取得時に9時間加算しています。

```
$date = (Get-Date).AddHours(9).ToString("yyyyMMddHHmmss")
$snapshotName = $vm.StorageProfile.OsDisk.Name + "-snapshot-" + $date
$snapshot =  New-AzureRmSnapshotConfig -SourceUri $vm.StorageProfile.OsDisk.ManagedDisk.Id -Location $location -CreateOption copy
New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName -ResourceGroupName $resourceGroupName
```

5.Snapshot作成(データディスク)

　OSディスクと同様の方針でデータディスクのスナップショットを作成します。OSディスクと異なりデータディスクは仮想マシン毎に複数存在する為、for文を使用して全てのディスクでスナップショットを作成します。

```
for ($i=0; $i -lt $vm.StorageProfile.DataDisks.Count ; $i++){
$date = (Get-Date).AddHours(9).ToString("yyyyMMddHHmmss")
$snapshotName = $vm.StorageProfile.DataDisks[$i].Name + "-snapshot-" + $date
$snapshot =  New-AzureRmSnapshotConfig -SourceUri $vm.StorageProfile.DataDisks[$i].ManagedDisk.Id -Location $location -CreateOption copy
New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName -ResourceGroupName $resourceGroupName
}
```

6.古いSnapshotの削除

　スナップショットはAzure Backupとは異なり自動削除されない為、古くなったスナップショットを削除する処理も加えます。すべてのスナップショットを取得し、スナップショットのタイムスタンプと現在時刻を比較して、一定日数を過ぎたスナップショットは削除します。

```
$Snapshots = Get-AzureRmSnapshot -ResourceGroupName $resourceGroupName
for ($i=0; $i -lt $Snapshots.Count; $i++){
 if ($Snapshots[$i].TimeCreated -lt (Get-Date).AddDays((-1)*$retentionPeriod)) {
 Remove-AzureRmSnapshot -ResourceGroupName proxy-demo -SnapshotName $Snapshots[$i].Name -Force    
 }
}
```

#Runbookに記載するスクリプト
　
　以上の内容を合わせて、Runbookに記載する内容は以下です。

```
##パラメーター指定
$resourceGroupName = "<仮想マシンが存在するリソースグループ名>" 
$location = "<仮想マシンのリージョン>" 
$vmName = "<仮想マシンの名前>"
$retentionPeriod = <スナップショットを保持する日数> 


##Azure へログイン
$connectionName = "AzureRunAsConnection"
$servicePrincipalConnection=Get-AutomationConnection -Name $connectionName         

Login-AzAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 

##VMの指定
$vm = Get-AzureRmVM -ResourceGroupName $resourceGroupName -Name $vmName

##Snapshot作成(OSディスク)
$date = (Get-Date).AddHours(9).ToString("yyyyMMddHHmmss")
$snapshotName = $vm.StorageProfile.OsDisk.Name + "-snapshot-" + $date
$snapshot =  New-AzureRmSnapshotConfig -SourceUri $vm.StorageProfile.OsDisk.ManagedDisk.Id -Location $location -CreateOption copy
New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName -ResourceGroupName $resourceGroupName

##Snapshot作成(データディスク)
for ($i=0; $i -lt $vm.StorageProfile.DataDisks.Count ; $i++){
$date = (Get-Date).AddHours(9).ToString("yyyyMMddHHmmss")
$snapshotName = $vm.StorageProfile.DataDisks[$i].Name + "-snapshot-" + $date
$snapshot =  New-AzureRmSnapshotConfig -SourceUri $vm.StorageProfile.DataDisks[$i].ManagedDisk.Id -Location $location -CreateOption copy
New-AzureRmSnapshot -Snapshot $snapshot -SnapshotName $snapshotName -ResourceGroupName $resourceGroupName
}

##古いSnapshotの削除
$Snapshots = Get-AzureRmSnapshot -ResourceGroupName $resourceGroupName
for ($i=0; $i -lt $Snapshots.Count; $i++){
 if ($Snapshots[$i].TimeCreated -lt (Get-Date).AddDays((-1)*$retentionPeriod)) {
 Remove-AzureRmSnapshot -ResourceGroupName proxy-demo -SnapshotName $Snapshots[$i].Name -Force    
 }
}
```

#動作確認
　RunbookにAzure Automationのスケジュールを関連付け、Azure Automationのジョブが実行されるまで待機します。ジョブ完了後以下のように想定通りの名称のスナップショットが作成されていることを確認します。また、数日後に古いスナップショットが削除されていることも併せて確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531201/3cd63945-b7b6-debe-68da-44ef9252d979.png)