End-to-End BCDR with Azure ASR: From Setup to Failover and Back

In my experience, many companies viewed implementing Business Continuity and Disaster Recovery (BCDR) as too technically complex and financially unfeasible, resulting in it becoming more of an academic exercise than an attainable, predictable, measurable, and verifiable business process.

Sample Solution Architecture (Source: Microsoft Cloud Workshop)

With Azure Recovery Services, I have found this perception no longer accurate.

In a recent demonstration, I used the Microsoft Cloud Workshop to showcase Azure BCDR with step-by-step guidance to

  • Configure a DR plan for a database app in Azure West US 3 region
  • Drill/rehearse the plan to failover the app to Azure East US region is a DR scenario
  • Execute a failover to mimic conducting a DR episode
  • Commit the failover upon verifying the plan executed with expected results

Later

  • Follow a series of steps for reversing and falling back the app to its original region, West US 3
  • Reenable the protection, i.e., DR pan, and ensure readiness for future DR needs

The following slide deck includes screen captures of relevant processes and resource settings, serves as a reference for context and expected results. While the deck is not intended to replace the workshop instructions and despite inconsistent resource names in some sections, the process flows with expected resource states are accurately depicted. One may find it handy for realizing the how and what of executing the workshop exercises and tasks.

References

Creating Azure Usage and Quota Report Using PowerShell


write-host "

This script, based on the original script published in the article,

Report Azure resource usage with PowerShell
https://4sysops.com/archives/report-azure-resource-usage-with-powershell/,

displays interactively the Azure compute, storage, 
and network quota and usage of an examined region relevant to 
an Azure subscription. It also generates a text file accordingly. 

© 2020 Yung Chou. All Rights Reserved.

"

#region [Customization]

$region="uksouth"

#endregion

Connect-AzAccount

#region [Needed only if an account owns multiple subscriptions]

# Set the context for subsequent operations
$context = (Get-AzSubscription | Out-GridView -Title 'Set subscription context' -PassThru)
Set-AzContext -Subscription $context | Out-Null
write-host "Azure context set for the subscription, `n$((Get-AzContext).Name)" -f green

#endregion

#region [DO NOT CHANGE]

($vm = Get-AzVMUsage -Location $region `
| select @{label='ResourceType';expression={$_.name.LocalizedValue}}, currentvalue, limit) `
| Out-GridView -Title "Azure $region Region Compute Quota & Usage"

($storage = Get-AzStorageUsage -Location $region `
| select @{label='ResourceType';expression={$_.name}}, currentvalue, limit) `
| Out-GridView -Title "Azure $region Region Storage Account Quota & Usage"

($network = Get-AzNetworkUsage -Location $region `
| select @{label='ResourceType';expression={$_.resourcetype}}, currentvalue, limit) `
| Out-GridView -Title "Azure $region Network Quota & Usage"

$when=get-date -format 'yyyyMMdd-hhmm'

($usage = @("Azure $region Region Quota and usage, as of $when",$vm,"`n",$storage,"`n",$network) | ft) `
>> "usage-$region-$when.txt"

#endregion [DO NTO CHANGE]

Creating Azure VM with Snapshot Using PowerShell

#region [CREATE VM FROM SNAPSHOT]

Write-host "
------------------------------------------------------------

This script is based on the following reference and for 
learning Azure and PowerShell. I have made changes to the 
original scrtip for clarity and portability.

Ref: Create a virtual machine from a snapshot with PowerShell
https://docs.microsoft.com/en-us/azure/virtual-machines/scripts/virtual-machines-windows-powershell-sample-create-vm-from-snapshot

Assuming a snapshot is in place, to test the script simply 
validate the customization part, followed by manually running
the script statement by statement in cloud shell.
Upon completing the deployment, stopwatch will display the 
deployment statistics. 

© 2020 Yung Chou. All Rights Reserved.

------------------------------------------------------------
"

#region [Customization]

#region [Needed only if an account owns multiple subscriptions]

Get-AzSubscription | Out-GridView  # Copy the target subscription name

# Set the context for subsequent operations
$context = (Get-AzSubscription | Out-GridView -Title 'Set subscription context' -PassThru)
Set-AzContext -Subscription $context | Out-Null
write-host "Azure context set for the subscription, `n$((Get-AzContext).Name)" -f green

#endregion

$snapshotName   = 'mySnapshot'
$snapshotRgName = 'mySnapshotRgName'

#endregion [Customization]

#region [Deployment Preping]

$tag = get-date -format 'mmss'

$vmRgName       = "vm-$tag"
$vmName         = "vm-$tag"
$vmSize         = 'Standard_B2ms'
$vmOsDiskName   = "osDisk-$tag"
$rdpPort        = 3389

$vnetName       = "vnet-$tag"
$vnetAddSpace   = '192.168.0.0/16'
$subnetAddSpace = '192.168.1.0/24'

($snapshot = Get-AzSnapshot `
    -ResourceGroupName $snapshotRgName `
    -SnapshotName $snapshotName)

$loc = $snapshot.Location

if (($existingRG = (Get-AzResourceGroup | Where {$_.ResourceGroupName -eq $vmRgName})) -eq $Null) { 
    write-host "Resource group, $vmRgName, not found, creating it" -f y
    New-AzResourceGroup -Name $vmRgName -Location $loc
} else {
    write-host "Using this resource group, $vmRgName, for the vm, $vmName" -f y
}
# Remove-AzResourceGroup -Name $vmRgName -AsJob

# Create a subnet configuration
$subnetConfig = `
New-AzVirtualNetworkSubnetConfig `
    -Name 'default' `
    -AddressPrefix $subnetAddSpace `
    -WarningAction 'SilentlyContinue'

# Create a virtual network
$vnet = `
New-AzVirtualNetwork `
    -ResourceGroupName $vmRgName `
    -Location $loc `
    -Name "$vmRgName-vnet" `
    -AddressPrefix $vnetAddSpace `
    -Subnet $subnetConfig

# Create a public IP address and specify a DNS name
$pip = `
New-AzPublicIpAddress `
    -ResourceGroupName $vmRgName `
    -Location $loc `
    -Name "$vmName-pip" `
    -AllocationMethod Static `
    -IdleTimeoutInMinutes 4

# Create an inbound network security group rule for port 3389
$nsgRuleRDP = `
New-AzNetworkSecurityRuleConfig `
    -Name "$vmName-rdp"  `
    -Protocol Tcp `
    -Direction Inbound `
    -Priority 1000 `
    -SourceAddressPrefix * `
    -SourcePortRange * `
    -DestinationAddressPrefix * `
    -DestinationPortRange $rdpPort `
    -Access Allow

# Create an inbound network security group rule for port 80,443
$nsgRuleHTTP = `
New-AzNetworkSecurityRuleConfig `
    -Name "$vmName-http"  -Protocol Tcp `
    -Direction Inbound `
    -Priority 1010 `
    -SourceAddressPrefix * `
    -SourcePortRange * `
    -DestinationAddressPrefix * `
    -DestinationPortRange 80,443 `
    -Access Allow

$nsg= `
New-AzNetworkSecurityGroup `
    -ResourceGroupName $vmRgName `
    -Location $loc `
    -Name "$vmName-nsg" `
    -SecurityRules $nsgRuleRDP, $nsgRuleHTTP `
    -Force

# Create a virtual network card and associate with public IP address and NSG
$nic = `
New-AzNetworkInterface `
    -Name "$vmName-nic" `
    -ResourceGroupName $vmRgName `
    -Location $loc `
    -SubnetId $vnet.Subnets[0].Id `
    -PublicIpAddressId $pip.Id `
    -NetworkSecurityGroupId $nsg.Id

$vmConfig = `
New-AzVMConfig `
    -VMName $vmName `
    -VMSize $vmSize `
| Add-AzVMNetworkInterface `
    -Id $nic.Id 

$diskConfig = New-AzDiskConfig `
    -Location $snapshot.Location `
    -SourceResourceId $snapshot.Id `
    -CreateOption Copy

$disk = New-AzDisk `
    -Disk $diskConfig `
    -ResourceGroupName $vmRgName `
    -DiskName $vmOsDiskName

$vmConfig = Set-AzVMOSDisk `
    -VM $vmConfig `
    -ManagedDiskId $disk.Id `
    -CreateOption Attach `
    -Windows

#endregion

#region [Deploying]

$StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch; $stopwatch.start()
write-host "`nDeploying the vm, $vmName, to $loc...`n" -f y

$vmStatus = `
New-AzVM `
    -ResourceGroupName $vmRgName `
    -Location $loc `
    -VM       $vmConfig `
    -WarningAction 'SilentlyContinue' `
    -Verbose

Set-AzVMBgInfoExtension `
    -ResourceGroupName $vmRgName `
    -VMName $vmName `
    -Name 'bginfo' `
    -Verbose

write-host '[Deployment Elapsed Time]' -f y
$stopwatch.stop(); $stopwatch.elapsed

#endregion

#region [Clean up]
# Remove-AzResourceGroup -Name $vmRgName -Force -AsJob 
#endregion

#endregion

Creating Azure Managed Disk with VHD Using PowerShell


#region [CREATE MANAGED DISK WITH VHD]

write-host "
------------------------------------------------------------

This script is based on the following reference and for
learning Azure and PowerShell. I have made changes to the
original scrtip for clarity and portability.

Ref: Create a managed disk from a VHD file
https://docs.microsoft.com/en-us/azure/virtual-machines/scripts/virtual-machines-windows-powershell-sample-create-managed-disk-from-vhd

Recommend manually running the script statement by
statement in cloud shell.

© 2020 Yung Chou. All Rights Reserved.

------------------------------------------------------------
"

#region [CUSTOMIZATION]

#region [Needed only if an account owns multiple subscriptions]

Get-AzSubscription | Out-GridView  # Copy the target subscription name

# Set the context for subsequent operations
$context = (Get-AzSubscription | Out-GridView -Title 'Set subscription context' -PassThru)
Set-AzContext -Subscription $context | Out-Null
write-host "Azure context set for the subscription, `n$((Get-AzContext).Name)" -f green

#endregion

$sourceVhdStorageAccountResourceId = '/subscriptions/…/StorageAccounts/'
$sourceVhdUri = 'https://.../.vhd'

#Get-AzLocation
$sourceVhdLoc = 'centralus'

$mngedDiskRgName ="da-mnged-$(get-date -format 'mmss')"
#$mngedDiskRgName ='dnd-mnged'

#Provide the name of a to-be-created Managed Disk
$mngedDiskName = 'myMngedDisk'
$mngedStorageType = 'Premium_LRS' # Premium_LRS,Standard_LRS,Standard_ZRS
$mngedDiskSize = '128' # In GB greater than the source VHD file size

#endregion

if (($existingRG = (Get-AzResourceGroup | Where {$_.ResourceGroupName -eq $mngedDiskRgName})) -eq $Null) {
write-host "Resource group, $mngedDiskRgName, not found, creating it" -f y
New-AzResourceGroup -Name $mngedDiskRgName -Location $mngedDiskLoc
} else {
write-host "Using this resource group, $mngedDiskRgName, for the managed disk, $mngedDiskName" -f y
}

$diskConfig = New-AzDiskConfig `
-AccountType $mngedStorageType `
-Location $sourceVhdLoc `
-CreateOption Import `
-StorageAccountId $sourceVhdStorageAccountResourceId `
-SourceUri $sourceVhdUri

New-AzDisk `
-Disk $diskConfig `
-ResourceGroupName $mngedDiskRgName `
-DiskName $mngedDiskName `
-Verbose

#endregion [CREATE MANAGED DISK WITH VHD]

#region [CLean up]
# Remove-AzResourceGroup -Name $mngedDiskRgName -Force -AsJob
#endregion

What Is and What Is Not Cloud Computing and Why Do I as an IT Pro Care

This was a presentation which I delivered at Stratford University in PDF format. My focus was on bringing clarity of cloud computing to the audiences so we can better articulate the business values of cloud computing and why cloud is or perhaps is not the solution for a business problem.

Additional resources is available at http://aka.ms/selected.