Converting Azure Managed Disks to Unmanaged

Microsoft has introduced the ability to create managed disks in Azure a while ago. This feature takes away the manual management overhead for you to keep track of your storage account limits. Managed disks are not stored in “regular” storage accounts, but Microsoft will take care of the VHD placement and will keep track of any IOPS limitions.

For example, a Standard Size VM allows 500 IOPS per disk. The maximum IOPS for a Standard storage account is 20.000 IOPS. This means that you can host a maximum of 40 disks (OS or Data) in a Standard storage account. When you use unmanaged disks, you’ll need to keep track of this limitation yourself. When using managed disks, Microsoft will make sure the 500 IOPS per disk is available, regardless of the storage account.

The conversion of an unmanaged disk to managed is very easy; Microsoft created the ConvertTo-AzureRmVMManagedDisk CmdLet for this. But if you want to convert back from managed to unmanaged, no CmdLet or function in the Azure portal is available for the conversion (for example Azure Site Recovery; very nice feature of Azure, but it doesn’t support managed disks). Converting back to unmanaged is a bit harder, but still possible.

Converting from managed to unmanaged

Converting a managed disk to an unmanaged disk basically means you need to copy the managed VHD file to one of your storage accounts and create a VM using that copied VM. The step-by-step process to convert back to unmanaged is as follows:

  1. Get the Managed Disk object using Get-AzureRmDisk
  2. Grant Access to the Managed Disks using Grant-AzureRmDiskAccess
  3. Copy the VHD to your storage account using Start-AzureStorageBlobCopy
  4. Detach any Network Interfaces from the original VM
  5. Recreate the VM using the copied VHDs
  6. Attach the Network Interfaces

Copying the VHD to a storage account

First of all, you should retrieve the disk name using the following commands:

$vm = Get-AzureRmVM -ResourceGroupName RESOURCEGROUPNAME -Name VMNAME
$vm.StorageProfile.OsDisk | Where-Object {$_.ManagedDisk -ne $null} | Select-Object Name
$vm.StorageProfile.DataDisks | Where-Object {$_.ManagedDisk -ne $null} | Select-Object Name

This retrieves all the managed disks (both OS and Data) from the defined VM. You should not the names of the disks you need to convert. Next, you have to create a storage context which can later be used to copy the VHDs (you can retrieve the storage account key using the portal, or using Get-AzureRmStorageAccountKey):

$context = New-AzureStorageContext -StorageAccountName STORAGEACCOUNTNAME -StorageAccountKey STORAGEACCOUNTKEY

Once you created the context, you can grant access and start the blob copy. To keep track of the asynchronous copy action, you can pass the output of the Start-AzureStorageBlobCopy cmdlet to a variable and later on check the status using Get-AzureStorageBlobCopyState.

$sas = Grant-AzureRmDiskAccess -ResourceGroupName RESOURCEGROUPNAME -DiskName DISKNAME -Access Read -DurationInSecond (60*60*24)
$blobcopyresult = Start-AzureStorageBlobCopy -AbsoluteUri $sas.AccessSAS -DestinationContainer "vhds" -DestinationBlob "YOURDISKNAME.vhd" -DestinationContext $context

During the copy phase, you can retrieve the status using the following command:

$blobcopyresult | Get-AzureStorageBlobCopyState

Recreating the VM

Once the copy job is done, I’d rename the old VM to eg. VMNAME_old; this way you can always switch back to the old VM if anything goes wrong. To connect the new VM to the same virtual network, you can detach the network interfaces from the old VM, so we can attach them again to the new VM. You should take note of those NICs before detaching them, so we can attach them later easily.

Recreating a VM from the copied VHD can be done using the following commands:

$vmconfig = New-AzureRmVMConfig -VMName VMNAME -VMSize "VMSIZE"
$vm = Add-AzureRmVMNetworkInterface -VM $vmConfig -Id (Get-AzureRmNetworkInterface -Name NICNAME -ResourceGroupName RESOURCEGROUPNAME).Id
$vm = Set-AzureRmVMBootDiagnostics -VM $vm -Enable -ResourceGroupName RESOURCEGROUPNAME-StorageAccountName BOOTDIAGNOSTICSSTORAGEACCOUNTNAME
$vm = Set-AzureRmVMOSDisk -VM $vm -VhdUri (Get-AzureStorageBlob -Context $context -Blob "YOURDISKNAME.vhd" -Container "vhds").ICloudBlob.uri.AbsoluteUri -CreateOption Attach -Name "YOURDISKNAME"
New-AzureRmVM -ResourceGroupName RESOURCEGROUPNAME -Location westeurope -VM $vm

Additional configuration

Note that you is possibly that you need to do some additional configuration. You’ll need to remember the following from your original VM:

  • VM Extensions
  • Availability set
  • Auto-shutdown
  • Configuration (Managed Service Identity and Azure hybrid benefit)

If you need to deploy the VM in an availability set, be sure to include this during re-creation:

$vmconfig = New-AzureRmVMConfig -VMName VMNAME -VMSize "VMSIZE" -AvailabilitySetId AVAILABILITYSETID
I hope this article was useful for you. If you have any questions, please don’t hesitate to leave a comment or contact me over email.

12 thoughts to “Converting Azure Managed Disks to Unmanaged”

  1. Thanks for this!
    One question, I used Azure integrated powershell and the session expires after 20min. How can I get the copy status again?

    1. Hi Bruno,

      You should be able to get the status after restarting the cloud shell by using these commands:

      Set-AzureRmCurrentStorageAccount -ResourceGroupName RESOURCEGROUPNAME -Name STORAGEACCOUNTNAME
      Get-AzureStorageBlobCopyState -Container “vhds” -Blob “NAMEOFYOURDISK.vhd”

      1. Thanks!

        oh, by the way, when you recreate the VM you need to specify the osType and caching.

        vm = Set-AzureRmVMOSDisk -VM $vm -VhdUri (Get-AzureStorageBlob -Context $context -Blob “YOURDISKNAME.vhd” -Container “vhds”).ICloudBlob.uri.AbsoluteUri -CreateOption Attach -Name “YOURDISKNAME” -Windows -Caching ReadWrite

  2. Set-AzureRmVMOSDisk -Windows, otherwise you will get “osDisk.osType” is missing (null). Also missed space in “RESOURCEGROUPNAME-StorageAccountName”. Thank you.

  3. Grant Access command returning null
    $sas = Grant-AzureRmDiskAccess -ResourceGroupName RESOURCEGROUPNAME -DiskName DISKNAME -Access Read -DurationInSecond (60*60*24)

    hence $sas.AccessSAS is null.
    Is there another way to pass the URI or am I missing anything ?

  4. For this,
    $blobcopyresult = Start-AzureStorageBlobCopy -AbsoluteUrl $sas.AccessSAS -DestinationContainer “vhds” -DestinationBlob “TestVM_OsDisk_1_f010ae5b471c461fa86ef2748a7858e1.vhd” -DestinationContext $context

    I’m getting result

    Start-AzureStorageBlobCopy : A parameter cannot be found that matches parameter name ‘AbsoluteUrl’.
    At line:1 char:46
    + $blobcopyresult = Start-AzureStorageBlobCopy -AbsoluteUrl $sas.Access …
    + ~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Start-AzureStorageBlobCopy], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet.StartAzureStorageBlobCopy

    Please help

    1. Hi,

      check what’s inside the $sas variable; if the Grant-AzureRmDiskAccess command failed or returned a value that was not expected, the Start-AzureStorageBlobCopy command will fail.

  5. Hi,

    This command return the following message error:

    $vm = Set-AzureRmVMBootDiagnostics -VM $vm -Enable -ResourceGroupName MYRG -StorageAccountName mystorage04
    Set-AzVMBootDiagnostic : Cannot validate argument on parameter ‘VM’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
    At line:1 char:40
    + $vm = Set-AzureRmVMBootDiagnostics -VM $vm -Enable -ResourceGroupName …
    + ~~~
    + CategoryInfo : InvalidData: (:) [Set-AzVMBootDiagnostic], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Azure.Commands.Compute.SetAzureVMBootDiagnosticsCommand

    Please, i appreciate your help…

  6. Hi Floris,
    I got this error, How can I fix it please?

    PS Azure:\> New-AzureRmVM -ResourceGroupName Aquatech-AZR-Prod -Location CanadaCentral -VM $vm
    New-AzureRmVM : Changing property ‘osDisk.vhd.uri’ is not allowed.
    ErrorCode: PropertyChangeNotAllowed
    ErrorMessage: Changing property ‘osDisk.vhd.uri’ is not allowed.
    ErrorTarget: osDisk.vhd.uri
    StatusCode: 409
    ReasonPhrase: Conflict
    OperationID : 3447fc49-e225-4ff7-b51b-e1e4595ba086
    At line:1 char:1
    + New-AzureRmVM -ResourceGroupName Aquatech-AZR-Prod -Location CanadaCe …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : CloseError: (:) [New-AzVM], ComputeCloudException
    + FullyQualifiedErrorId : Microsoft.Azure.Commands.Compute.NewAzureVMCommand

Leave a Reply

Your email address will not be published. Required fields are marked *

Complete the following sum: * Time limit is exhausted. Please reload CAPTCHA.

This site uses Akismet to reduce spam. Learn how your comment data is processed.