In the dynamic world of cloud computing, time is often a critical factor, especially when it comes to recovering from disasters like ransomware attacks or rolling back after a problematic security update. Imagine waking up to find your entire set of Azure VMs compromised by ransomware or discovering that a recent security update has left your systems inoperable. The clock starts ticking, and the longer it takes to restore your VMs, the greater the impact on your business.
Azure Backup is a robust solution for protecting your Azure VMs, providing peace of mind with its ability to create and manage backup policies, configure backup schedules, and perform reliable restores. However, the features available for Azure Backup in the Portal UI today only allow you to start the restoration of individual VMs one at a time in a sequence of repeated steps. Restoring many VMs manually through the Azure Portal can be extremely time-consuming and inefficient, especially when you need to restore an entire set of VMs quickly.
Azure Backup offers extensive features for protecting your VMs:
Despite these powerful features, there is always room for improvement. For now, there is currently no feature in the Azure Portal to start a batch restore multiple VMs simultaneously. This limitation becomes a bottleneck in scenarios where speed and efficiency are paramount.
To address this gap, we turn to PowerShell scripting, a versatile and powerful tool for managing Azure resources. Microsoft's Az PowerShell module provides a comprehensive suite of cmdlets to automate and manage Azure tasks, including VM backups and restores.
Here's a practical approach: a PowerShell script that enables the parallel restoration of multiple VMs from Azure Backup. This script leverages Az.RecoveryServices to streamline the recovery process, significantly reducing the time required to get your systems back online.
Below is a summary of how one example script works. You can find the full example here.
$resourceGroup = "rg-webservers"
$recoveryServicesVault = "rsv-vmbackup"
$cacheStorageAccount = "unique626872"
$cacheStorageAccountResourceGroup = "rg-webservers"
$vault = Get-AzRecoveryServicesVault -ResourceGroupName $resourceGroup -Name $recoveryServicesVault
$container = Get-AzRecoveryServicesBackupContainer -ContainerType "AzureVM" -VaultId $vault.ID
foreach ($item in $container)
{
# Write out the Backup Item Name
Write-Host "Backup Item Name: $($item.FriendlyName)"
# Get the Backup Item from the Vault
$backupItem = Get-AzRecoveryServicesBackupItem -BackupManagementType "AzureVM" -WorkloadType "AzureVM" -VaultId $vault.ID -Name $item.Name
# Get the resource group & VM name for this backupItem
$vmResourceGroup = $backupItem.VirtualMachineId.Split('/')[4]
$vmName = $backupItem.VirtualMachineId.Split('/')[8]
# Shut down the protected VM before restoring it
Write-Host "Stopping VM: $vmName in Resource Group: $vmResourceGroup before restoring"
Stop-AzVM -ResourceGroupName $vmResourceGroup -Name $vmName -Force -SkipShutdown -NoWait
# Get the latest recovery point for the backup item from the last 7 days
$recoveryPoints = Get-AzRecoveryServicesBackupRecoveryPoint -Item $backupItem -VaultId $vault.ID -StartDate (Get-Date).AddDays(-7).ToUniversalTime() -EndDate (Get-Date).ToUniversalTime()
# Write details about the latest recovery point
Write-Host "Found $($recoveryPoints.Count) Recovery Points for the Backup Item"
Write-Host "Latest Recovery Point Time: $($recoveryPoints[0].RecoveryPointTime)"
# Extract necessary properties from the recovery point
$recoveryPointId = $recoveryPoints[0].RecoveryPointId
# Restore the Azure VM from the latest recovery point to the original location (replace the source VM)
# To speed up the process we run the VM restores in parallel using PowerShell jobs
Write-Host "Restoring $($item.FriendlyName) to the original location"
$job = Start-Job -ScriptBlock {
param ($recoveryPointId, $backupItemName, $vaultId, $vaultLocation, $cacheStorageAccount, $cacheStorageAccountResourceGroup)
# Retrieve the backup item and recovery point within the job
$vault = Get-AzRecoveryServicesVault -ResourceGroupName $vaultId.ResourceGroupName -Name $vaultId.Name
$backupItem = Get-AzRecoveryServicesBackupItem -BackupManagementType "AzureVM" -WorkloadType "AzureVM" -VaultId $vault.ID -Name $backupItemName
$recoveryPoint = Get-AzRecoveryServicesBackupRecoveryPoint -Item $backupItem -VaultId $vault.ID | Where-Object { $_.RecoveryPointId -eq $recoveryPointId }
Restore-AzRecoveryServicesBackupItem -RecoveryPoint $recoveryPoint -StorageAccountName $cacheStorageAccount -StorageAccountResourceGroupName $cacheStorageAccountResourceGroup -VaultId $vault.ID -VaultLocation $vault.Location
} -ArgumentList $recoveryPointId, $item.Name, $vault, $vault.Location, $cacheStorageAccount, $cacheStorageAccountResourceGroup
# Store the job information
$jobs += $job
# Write out the Job ID
Write-Host "Started Restore Job ID: $($job.Id)"
}
By using this script, you can dramatically reduce the time required to restore multiple VMs, enhancing your ability to recover from critical incidents swiftly.
In this post, we've discussed the limitations in the Azure Portal for handling multiple VM restores and introduced a practical workaround using PowerShell scripting. This solution enables you to restore your VMs in parallel, significantly cutting down recovery time and minimizing business disruption.
We encourage you to modify the sample script, try it out in your test environment and see the benefits for yourself. Your feedback is invaluable, so please share your experiences and let us know your thoughts on this approach. Together, we can continue to improve and innovate in the realm of Azure Business Continuity.
Happy scripting, and may your recoveries be swift and seamless!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.