In this blog post we will learn how to clone a Windows virtual machine in Azure. It is important to know that there are two choices when it comes to cloning Azure VM:

  • You can generalize the existing VM using sysprep and create a new virtual machine from this image.
  • You can copy the existing OS disk image to a new storage account and create a new virtual machine with this disk.

Today we will cover the second option. Its upside is that you will get an exact copy of an existing VM. The downside is that you will need to copy a 130 GB disk image.

First of all, you will need Azure Powershell tools installed. You will also need to download and install AzCopy — a tool to copy Azure storage blobs. After you've done all that, just save the following script to your hard drive and run it in PowerShell:

$name = Read-Host -Prompt "Resource name prefix"
$location = Read-Host -Prompt "Location"
$rgName = $name + "-RG"
Write-Host "Creating Resource Group..."
New-AzureRmResourceGroup -Name $rgName -Location $location

$rnd = Get-Random
$storageName = $name.ToLower() + "storage" + $rnd
$storageName = $storageName.Substring(0, [math]::min($storageName.Length, 23))

Write-Host "Creating Storage Account..."
New-AzureRmStorageAccount -ResourceGroupName $rgName -AccountName $storageName -Type "Standard_LRS" -Location $location
$keys = Get-AzureRmStorageAccountKey -ResourceGroupName $rgName -Name $storageName;
$ctx = New-AzureStorageContext -StorageAccountName $storageName -StorageAccountKey $keys[0].Value;

Write-Host "Creating Blob Container..."
$container = New-AzureStorageContainer -Context $ctx -Name vhds;
$blob = $container.CloudBlobContainer
$dstUrl = $blob.Uri.AbsoluteUri

Write-Host "Copying OS image to destination url: $dstUrl"
$srcUrl = Read-Host -Prompt 'Source VHD url'
$srcKey = Read-Host -Prompt 'Source Storage key'
$dstKey = $keys[0].Value
&"c:\Program Files (x86)\Microsoft SDKs\Azure\AzCopy\azcopy.exe" /source:$srcUrl /dest:$dstUrl /sourcekey:$srcKey /destkey:$dstKey /s

Write-Host "Creating VM and resources"
$subnetName = $name + "Net"
$singleSubnet = New-AzureRmVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix
$vnetName = $name +  "Vnet"
$vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $location -AddressPrefix -Subnet $singleSubnet
$ipName = $name + "IP"
$pip = New-AzureRmPublicIpAddress -Name $ipName -ResourceGroupName $rgName -Location $location -AllocationMethod Dynamic
$nicName = $name + "Nic"
$nic = New-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $rgName -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id
$nsgName = $name + "Nsg"
$rdpRule = New-AzureRmNetworkSecurityRuleConfig -Name myRdpRule -Description "Allow RDP" -Access Allow -Protocol Tcp -Direction Inbound -Priority 110 -SourceAddressPrefix Internet -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 3389
$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName $rgName -Location $location -Name $nsgName -SecurityRules $rdpRule
$vmName = $name + "VM"
$vmSize = Read-Host -Prompt "VM size"
$vmConfig = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize
$vm = Add-AzureRmVMNetworkInterface -VM $vmConfig -Id $nic.Id
$vhd = Get-AzureStorageBlob -Container $container.Name -Context $ctx
$osDiskUri = $vhd.ICloudBlob.uri.AbsoluteUri
$osDiskName = $vmName + "osDisk" 
$vm = Set-AzureRmVMOSDisk -VM $vm -Name $osDiskName -VhdUri $osDiskUri -CreateOption attach -Windows
New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vm

The script will ask for various bits of information. The most important are an Uri for the source OS disk and storage account key. You can get both by navigating to your existing VM's storage account in Azure portal. First, open up a Keys pane and copy the Key1 value. Then open the Overview pane, select Blobs, click the vhds container and choose Properties. Now you can copy the container Uri.

Note that the process of copying the OS disk image can take a very long time as all the VMs are created with the fixed-size disks of 130 GB. After the script finishes, you can go to your Azure portal and play with your new virtual machine.