AzureのRecovery Services Vault を安全に削除する手順
はじめに
不要になった Azure のリソースグループを削除しようとしたら、Recovery Services コンテナー(Recovery Services Vault) の削除に失敗して、リソースグループの削除ができませんでした。
そのため、削除できなかった Recovery Services コンテナー(Recovery Services Vault) だけをポータルで削除しようとしましたが、やはり削除に失敗します。
詳しい原因までは突き止められませんでしたが、原因の多くは、バックアップ対象の登録が残っていることのようです。
この記事では、AzureStorage の登録を解除してから Recovery Services コンテナー を削除した手順をまとめています。なお、保護済みデータやソフト削除済みデータが残っている場合は、別の依存関係も解除が必要です。
※ Azure の日本語UIでは、英語の Recovery Services vault が「Recovery Services コンテナー」と翻訳されています。以降は Recovery Services コンテナー と書きます。
前提
今回の対象は以下です。
- サブスクリプション:
00000000-0000-0000-0000-000000000000 - リソースグループ:
rg-example-backup - Recovery Services コンテナー:
vault-example001
手順
全体の流れ
やることは次の 4 ステップです。
- Azure に正しいアカウントでサインインする
- Recovery Services コンテナー に登録されている Storage Container を解除する
- ポータルで Recovery Services コンテナー を削除する
- 削除完了を確認する
1. PowerShell で Azure にサインインする
.ps1 を扱うので、bash や Git Bash ではなく PowerShell (pwsh) で実行します。
Connect-AzAccount
必要ならサブスクリプションを明示的に切り替えます。
Set-AzContext -SubscriptionId "00000000-0000-0000-0000-000000000000"
現在のサブスクリプション確認です。
Get-AzContext
2. Storage Container の登録を解除する
Recovery Services コンテナー が消せない原因になりやすいのが、Backup 用に登録された Storage Container です。
今回は、後述するPowerShellスクリプトを使って解除しました。
ps1スクリプトを実行し、以下のように出れば成功です。
<WorkloadName> UnRegister Completed
All Storage containers unregistered.
今回もこの状態になり、Storage Container の登録解除は完了しました。
なお、Azureにログインしていない状態でこのスクリプトを実行したときは、以下のようなメッセージが出ます。
[Login to Azure] To sign in, use a web browser to open the page
https://login.microsoft.com/device and enter the code H3K9CBPDE to authenticate.
表示されているURLをブラウザで開き、このコードH3K9CBPDEを入れて、Azureにログインします。
複数のサブスクリプションがある場合は、サブスクリプションの選択が表示されますので、該当するサブスクリプションを選択します。
選択すると、本来の削除処理が走ります。
3. ポータルで Recovery Services コンテナー を削除する
Storage Container の登録解除後、Azure Portal から対象 Recovery Services コンテナー を削除します。
ここで大事なのは、Recovery Services コンテナー の削除は非同期 だという点です。
削除ボタンを押しても、その場ですぐ消えるとは限りません。
つまり、
- ポータルで削除操作をした
- でもリソースグループ内にしばらく残って見える
というのは、直後であれば正常なことがあります。
4. 削除完了を確認する
削除要求が通ったかどうかは、Azure Activity Log で確認できます。
Get-AzLog -ResourceId "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-example-backup/providers/Microsoft.RecoveryServices/vaults/vault-example001" | Select-Object EventTimestamp, OperationName, Status, SubStatus | Format-Table -AutoSize
途中では次のような状態になります。
Delete Vault StartedDelete Vault Accepted
この段階では、まだ削除完了ではありません。
その後、しばらくして実際にリソースが消えれば完了です。
存在確認は次でもできます。
Get-AzResource -ResourceGroupName "rg-example-backup" -ResourceType "Microsoft.RecoveryServices/vaults" -Name "vault-example001"
何も返らなければ、コンテナーは削除されています。
今回使用したPowerShellスクリプト
以下に示したスクリプトは記事用のサンプルとして、サブスクリプション、リソースグループ、Vault 名をサンプル値で埋めています。
実行前に読者が置き換える必要があるのは、これらの値と <アカウントID> だけです。
$ErrorActionPreference = 'Stop'
# Vault をクリーンアップする対象の Azure リソースと利用アカウント。
$subscriptionId = '00000000-0000-0000-0000-000000000000'
$resourceGroupName = 'rg-example-backup'
$vaultName = 'vault-example001'
$accountId = '<アカウントID>'
$vaultId = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.RecoveryServices/vaults/$vaultName"
try {
# まず現在の Az コンテキストを確認し、使い回せるログイン状態があるか調べる。
$context = Get-AzContext -ErrorAction SilentlyContinue
$needsLogin = $true
# 既存コンテキストが対象サブスクリプションを向いている場合だけ再利用候補にする。
if ($context -and $context.Subscription.Id -eq $subscriptionId) {
try {
# アクセストークンがまだ有効なら再ログインせず、そのまま処理を続ける。
Get-AzAccessToken -ErrorAction Stop | Out-Null
$needsLogin = $false
}
catch {
# コンテキストが残っていてもトークン期限切れなら再ログインが必要。
$needsLogin = $true
}
}
if ($needsLogin) {
# 必要な場合だけログインし直す。WAM を無効化し古いログイン状態を消してから
# device code 認証で対象アカウントにサインインする。
Update-AzConfig -EnableLoginByWam $false -Scope Process -ErrorAction SilentlyContinue | Out-Null
Disconnect-AzAccount -Scope Process -ErrorAction SilentlyContinue | Out-Null
Clear-AzContext -Scope Process -Force -ErrorAction SilentlyContinue
Write-Host "Signing in as $accountId with device authentication..." -ForegroundColor Cyan
Connect-AzAccount -AccountId $accountId -UseDeviceAuthentication | Out-Null
}
# ログイン後は毎回対象サブスクリプションへ切り替え、安全のため結果も確認する。
Write-Host "Switching to subscription $subscriptionId..." -ForegroundColor Cyan
Set-AzContext -SubscriptionId $subscriptionId | Out-Null
$currentContext = Get-AzContext
if (-not $currentContext -or $currentContext.Subscription.Id -ne $subscriptionId) {
throw "Subscription $subscriptionId is not available for account $accountId."
}
# この登録が残っていると Vault 削除のブロッカーになるため、先に列挙して解除する。
Write-Host "Unregistering Storage containers in vault $vaultId..." -ForegroundColor Yellow
$StorageAccounts = Get-AzRecoveryServicesBackupContainer -ContainerType AzureStorage -VaultId $vaultId
if (-not $StorageAccounts) {
# 解除対象がなければ、このスクリプトでやることは完了。
Write-Host 'No Storage containers found.' -ForegroundColor Yellow
exit 0
}
# 各 Storage コンテナーの登録を解除し、Vault を削除できる状態に近づける。
foreach ($item in $StorageAccounts) {
Write-Host "Unregistering Storage container: $($item.Name)" -ForegroundColor DarkYellow
Unregister-AzRecoveryServicesBackupContainer -Container $item -Force -VaultId $vaultId
}
Write-Host 'All Storage containers unregistered.' -ForegroundColor Green
}
catch {
# 失敗理由をそのまま表示し、呼び出し元が失敗を検知できるよう非ゼロで終了する。
Write-Error $_
exit 1
}
このスクリプトでは、以下のことをやっているために長いコードになってます。
- ログイン済みでない場合は、ログイン処理を行っている
- 誤ったサブスクリプションで削除操作が走るのを防ぐ処理を入れている
- エラーハンドリングを try/catch で囲んでいる
本質的なコードは、以下のコードになります。
$StorageAccounts = Get-AzRecoveryServicesBackupContainer -ContainerType AzureStorage -VaultId $vaultId
foreach ($item in $StorageAccounts) {
Write-Host "Unregistering Storage container: $($item.Name)" -ForegroundColor DarkYellow
Unregister-AzRecoveryServicesBackupContainer -Container $item -Force -VaultId $vaultId
}
まとめ
Recovery Services コンテナー を消すときは、いきなり Recovery Services コンテナー を削除しようとしないのが重要です。
先に依存関係、特に Storage Container の登録解除 を行うと、削除までスムーズに進みます。
今回うまくいった流れをそのまま書くと、次の通りです。
-
pwshで Azure にサインイン -
Set-AzContextで対象サブスクリプションへ切り替え - Storage Containerの登録解除スクリプトを実行
- Storage Containerの
UnRegister Completedを確認 - Azure Portal で Recovery Services コンテナー を削除
- Activity Log で
Delete Vault Started / Acceptedを確認 - 少し待つ
- 最終的に Recovery Services コンテナー がリソースグループから消えたことを確認
この流れで、最終的に削除完了まで到達できました。
Discussion