Table of Contents
Introduction
Microsoft introduced back in June 2017 a new type of storage account called “Managed Disks“. Managed Disks are an exciting feature from Azure, which is designed to help with the availability, manageability, scalability, and performance of virtual machine disks storage within Azure.
Starting with Azure Stack build 1808, Microsoft announced support for managed disks on Azure Stack as well. This update simplifies disk management for Azure Stack VMs by managing the disk associated with the VM. You only have to specify the type (Premium or Standard) and the size of the disk you need and Azure Stack creates and manages the disk for you. This work will bring more options and simplicity to Azure Stack users when working with VMs. Beginning with the 1811 update, Azure Stack managed disks are enabled by default when creating VMs using the Azure Stack portal. Furthermore, Microsoft strongly recommends converting your standard disks in Azure Stack to managed disks.
Azure Stack managed disks are NOT featured parity with Azure, there are some key differences that you should be aware of. Please make sure to continuous reading Microsoft documentation here to see the differences.
The question is, what if you have an existing Azure Stack VMs with unmanaged standard disks, can I convert them to managed disks? The short answer is, YES!
In this post, I will show you how to automate the conversion of Azure Stack virtual machines from unmanaged to managed disks and remove the extra layer of administrative overhead.
If you still have Azure VMs with unmanaged disks laying around, please check my previous article on how to convert them to Azure managed disks.
Convert Azure Stack VMs To Managed Disks
If you have some virtual machines deployed on Azure Stack before you used managed disks, or you decided to simplify and go from an unmanaged disk configuration to a managed disk configuration. Either way, it’s a long process and it’s completely different than converting Azure VM managed disks.
The Azure PowerShell cmdlets ConvertTo-AzureRmVMManagedDisk and ConvertTo-AzVMManagedDisk can’t be used to convert an unmanaged disk to a managed disk in Azure Stack. Azure Stack doesn’t currently support those cmdlets at the time of this writing. Additionally, the Azure Stack portal cannot be used to convert an unmanaged disk to a managed disk. The only way to convert an Azure Stack VM with unmanaged to managed disk is to delete the VM, detach the disks and then recreate the virtual machine with managed disk as described by Microsoft documentation here.
To convert Azure Stack VM to a managed disk, you need first to remove the VM configuration before you create the new VM with a managed disk. So you’ve to take that into consideration in terms of things like downtime, availability of your applications. But if this is a non-critical VM then it’s not a big deal, you can go ahead and convert it anytime.
In this example, I’ve got a VM named vm-azs-sql0, vm-azs-sql0 uses unmanaged disks. As you can see in the screenshot below, it’s got an operating system OS disk and 2 Data disks.
If I click on the OS disk or any data disks, you can see it’s actually using a storage account. So this is an unmanaged disk.
The VM is also a member of an Availability Set. It has also a public IP address, NIC interface, and Network Security Group configured.
The process of converting an Azure Stack VM from unmanaged to managed disk is as follows:
- Specify the VM that you want to convert and in which Azure Stack subscription is hosted.
- Specify the Resource Group Name.
- Specify the location where the VHDs are located that will be used to create the managed disks. The VHD file(s) can be deleted as soon as the managed disks are created (Step 10).
- Get the network configuration (vNET, vNIC, NSG, Public IP address).
- Get the storage account for the Boot Diagnostics settings.
- If the VM is a member of an availability set, you need to convert the Availability Set from classic to managed.
- Delete the VM only without its disks.
- Create the OS managed disk configuration (Linux / Windows).
- Create the Data managed disk configuration.
- Delete the old VHD file(s).
- Create the network configuration back.
- Add the VM to the availability set.
- Attach the Boot Diagnostics storage account.
- Finally, recreate the virtual machine with it’s managed disks.
As you can see, there are a lot of steps that you want to go through and it’s not a simple task, especially if you have a lot of VMs to convert.
To facilitate this process, I have created a PowerShell tool that will automate the entire process for you.
You can run the script as follows:
.EXAMPLE
.\Convert-AzSManagedDisk.ps1 -rgFQDN [region.FQDN] -AADTenantName [domain.com] -AzSCred [user@domain.com] -VMName [VMName] -Storageacc [StorageAccountName] -Verbose
This example will convert a specified Azure Stack VM from unmanaged to a managed disk, this could be running on Azure Stack Integrated System or on Azure Stack Development Kit, you need to specify the region and the external FQDN of the Azure Stack, as well as the username and the storage account where the VHDs are located. If the VM has multiple data disks attached to it, the tool will convert them all to managed disks.
Here is an example of the output once you run this tool:
Once the VM is recreated, you will see that all disks are created as managed disks now. The whole network configuration will be preserved.
PowerShell Code
The complete script is detailed below to automate the entire process:
<# .SYNOPSIS Convert Azure Stack VMs to managed disks. .DESCRIPTION Convert Azure Stack VMs from Standard (unmanaged) disks to managed disks. .NOTES File Name : Convert-AzSManagedDisk.ps1 Author : Charbel Nemnom Version : 1.0 Date : 08-August-2019 Update : 13-August-2019 Requires : PowerShell Version 5.1 or above Module : Azure Stack Version 1.7.1 and above Version : Azure Stack version 1808 and above Support : Azure Stack Development Kit and Azure Stack Integrated System OS : Convert Windows or Linux VMs .LINK To provide feedback or for further assistance please visit: https://charbelnemnom.com .EXAMPLE .\Convert-AzsManagedDisk.ps1 -rgFqdn -AADTenantName -AzsCred <azs@domain.com> -VMName -storageacc -Verbose This example will convert a specified Azure Stack VM from unmanaged to managed disk, this could be running on Azure Stack Integrated System or Azure Stack Development Kit, you need to specify the region and the external FQDN of the Azure Stack, as well as the username and the storage account where the VHDs are located. #> [CmdletBinding()] Param ( [Parameter(Position=0, Mandatory=$true, HelpMessage = 'Provide the region and external FQDN of the Azure Stack')] [Alias('fqdn')] [String]$rgFqdn, [Parameter(Position=1, Mandatory=$true, HelpMessage = 'Provide the Azure AD (AAD) Tenant Name')] [Alias('AAD')] [String]$AADTenantName, [Parameter(Position=2, Mandatory=$True, HelpMessage ='Provide Azure Stack Credentials')] [Alias('Cred')] [PSCredential]$AzsCred, [Parameter(Position=3, Mandatory=$True, HelpMessage ='Provide the Azure Stack VM Name that you want to convert')] [Alias('VM')] [String]$VMName, [Parameter(Position=4, Mandatory=$true, HelpMessage ='Provide the Azure Stack Storage Account where the VHDs exist')] [Alias('StorageAccount')] [String]$storageacc ) # Azure Stack 1904 or later (only) Function Install-AzureRM { Set-PSRepository -Name PSGallery -Installation Trusted -Verbose:$false Install-Module -Name AzureRM.BootStrapper -Confirm:$false -Verbose:$false } # Azure Stack 1904 or later (only) Function Install-AzureStack { Set-PSRepository -Name PSGallery -Installation Trusted -Verbose:$false Use-AzureRmProfile -Profile 2019-03-01-hybrid -Force -Confirm:$false -Verbose:$false Install-Module -Name AzureStack -RequiredVersion 1.7.2 -Confirm:$false -Verbose:$false } # Install Azure RM AvailabilitySet Function Install-AzureRmAvailabilitySet { Try { Import-Module -Name AzureRm.AvailabilitySetManagement -ErrorAction Stop -Verbose:$false | Out-Null Write-Verbose "Importing Azure RM AvailabilitySet PowerShell Module..." } Catch { Write-Warning "Azure RM AvailabilitySet PowerShell Module is not installed..." Write-Verbose "Installing Azure RM AvailabilitySet Module..." Set-PSRepository -Name PSGallery -Installation Trusted -Verbose:$false Install-Module -Name AzureRm.AvailabilitySetManagement -Confirm:$false -Verbose:$false } } #! Check Azure Stack Connection Try { Write-Verbose "Connecting to Azure Stack..." Add-AzureRmEnvironment –Name ‘AzureStackUser’ -ArmEndpoint "https://management.$rgfqdn" | Out-Null # Set your AAD tenant name $AuthEndpoint = (Get-AzureRmEnvironment -Name "AzureStackUser").ActiveDirectoryAuthority.TrimEnd('/') $TenantId = (invoke-restmethod "$($AuthEndpoint)/$($AADTenantName)/.well-known/openid-configuration").issuer.TrimEnd('/').Split('/')[-1] # Signing into Azure Stack Add-AzureRmAccount -EnvironmentName "AzureStackUser" -Credential $AzsCred -TenantId $TenantId -ErrorAction Stop | Out-Null } Catch { Write-Warning "Cannot connect to Azure Stack environment. Please check your credentials. Exiting!" Break } #! Check AzureRM BootStrapper PowerShell Module Try { Import-Module -Name AzureRM.BootStrapper -ErrorAction Stop -Verbose:$false | Out-Null Write-Verbose "Importing Azure RM BootStrapper PowerShell Module..." } Catch { Write-Verbose "Installing the Azure RM BootStrapper Module..." Install-AzureRM } #! Check Azure Stack PowerShell Module Try { Import-Module -Name AzureStack -RequiredVersion 1.7.2 -ErrorAction Stop -Verbose:$false | Out-Null Write-Verbose "Importing Azure Stack PowerShell Module..." } Catch { Write-Warning "Azure Stack PowerShell Module requires update..." Write-Verbose "Installing Azure Stack PowerShell Module version 1.7.2" Install-AzureStack } # Get all Azure Stack Tenant Subscriptions and look for the VM that you want to convert # The source and target VM will be created Write-Verbose "Get all Azure Stack Tenant Subscriptions..." $azsSubs = Get-AzureRmSubscription Write-Verbose "Locate Azure Stack VM ($VMName)..." $azsVM = $azsSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM | Where-Object {$_.Name -eq $VMName} } If (!$azsVM ) { Write-Warning "Azure Stack virtual machine ($VMName) cannot be found. Please check your virtual machine name. Exiting!" Break } # Set the context to the subscription ID in which the managed disk will be created. Write-Verbose "Set the context to the Azure Stack subscription ID: $($azsVM.Id.Split('/')[2])" Select-AzureRmSubscription -SubscriptionId $azsVM.Id.Split('/')[2] | Out-Null # Get the virtual NIC interface name and details $NicName = $azsVM.NetworkProfile.NetworkInterfaces.Id.Split('/')[-1] $vNic = Get-AzureRmNetworkInterface -Name $NicName -ResourceGroupName $azsVM.ResourceGroupName # Get the public ip address name where the virtual machine will be hosted. If ($VNic.IpConfigurations.publicIPAddress.Id -ne $null) { Write-Verbose "Get the public ip address of the virtual machine..." $PIpName = $VNic.IpConfigurations.publicIPAddress.Id.Split('/')[-1] } # Get the virtual network name where the virtual machine will be hosted. Write-Verbose "Get the virtual network name where the virtual machine will be hosted..." $vnetName = Get-AzureRmVirtualNetwork -ResourceGroupName $azsVM.ResourceGroupName ` | % {if($_.Subnets.IpConfigurations.Id.StartsWith($azsVM.NetworkProfile.NetworkInterfaces.Id)){return $_.Name}} # Get the Boot Diagnostics storage account If ($azsVM.DiagnosticsProfile.BootDiagnostics.Enabled -eq $true) { $azsVMstoragediag = $azsVM.DiagnosticsProfile.BootDiagnostics.StorageUri.Split("//")[2] $azsVMstoragediag = $azsVMstoragediag.Split('.')[0] } # Check if the VM that you want to convert to managed disks is in an availability set If ($azsVM.AvailabilitySetReference.Id -ne $null) { Install-AzureRmAvailabilitySet Write-Verbose "Check if the VM that you want to convert is a member of an AvailabilitySet..." $avSetName = $azsVM.AvailabilitySetReference.Id.Split('/')[-1] Write-Verbose "Convert the availability set ($avSetName) to a managed availability set..." $avSet = Get-AzureRmAvailabilitySet -ResourceGroupName $azsVM.ResourceGroupName -Name $avSetName Update-AzureRmAvailabilitySet -AvailabilitySet $avSet -Sku Aligned | Out-Null } #! Get storage account and Blob VHDs Uri URL. Write-Verbose "Get the storage account and Blob VHDs Uri..." $azsStorage = Get-AzureRmStorageAccount -ResourceGroupName $azsVM.ResourceGroupName -Name $storageacc Set-AzureRmCurrentStorageAccount -Name $storageacc -ResourceGroupName $azsVM.ResourceGroupName | Out-Null $storageContainerName = (Get-AzureStorageContainer).Name $azsdisks = @($azsvm.StorageProfile.OsDisk) if ($azsvm.StorageProfile.DataDisks.Vhd.Uri) { $azsdisks += $azsvm.StorageProfile.DataDisks } # Delete old VM, but keep the OS and data disks. Write-Verbose "Remove Azure Stack VM $($azsVM.Name) configuration, the VM is going offline..." Remove-AzureRmVm -Name $azsVM.Name -ResourceGroupName $azsVM.ResourceGroupName -Force -Confirm:$false | Out-Null foreach ($azsdisk in $azsdisks) { # The size of the new disk in GB. It should be greater than the existing VHD file size. $NewDiskSize = ($azsdisk.DiskSizeGB)+1 # Create the managed disk configuration. $DiskConfig = New-AzureRmDiskConfig -AccountType $azsStorage.Sku.Name -Location $azsVM.Location -DiskSizeGB $NewDiskSize ` -SourceUri $azsdisk.Vhd.Uri -CreateOption Import if ($azsdisk.Name -eq "osdisk") { # Create virtual machine configuration Write-Verbose "Create virtual machine configuration..." If ($avSetName) { Write-Verbose "Add the VMName $($azsVM.Name) to a managed availability set ($avSetName)" $VirtualMachine = New-AzureRmVMConfig -VMName $azsVM.Name -VMSize $azsVM.HardwareProfile.VmSize -AvailabilitySetId $avSet.Id } Else { $VirtualMachine = New-AzureRmVMConfig -VMName $azsVM.Name -VMSize $azsVM.HardwareProfile.VmSize } # Create OS managed disk. Write-Verbose "Create the OS managed disk: $($azsVM.Name)-$($azsdisk.Name)" $OsDisk = New-AzureRmDisk -DiskName "$($azsVM.Name)-$($azsdisk.Name)" -Disk $DiskConfig -ResourceGroupName $azsVM.ResourceGroupName # Use the managed disk resource ID to attach it to the virtual machine. # The OS type will be set according to the exisitng VM (Windows/Linux). If ($azsdisk.ostype -eq "Windows") { $VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -ManagedDiskId $OsDisk.Id -CreateOption Attach -Windows -Caching $azsdisk.Caching } Else { $VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -ManagedDiskId $OsDisk.Id -CreateOption Attach -Linux -Caching $azsdisk.Caching } # Delete the OS disk VHD file Remove-AzureStorageBlob -Container $storageContainerName -Blob "$($azsdisk.Vhd.Uri.Split('/')[-1])" -Force -Confirm:$false } Else { # Create Data managed disks. Write-Verbose "Create the Data managed disk: $($azsdisk.Name)" $DataDisk = New-AzureRmDisk -DiskName $azsdisk.Name -Disk $DiskConfig -ResourceGroupName $azsVM.ResourceGroupName # Create the Data managed disk configuration. $VirtualMachine = Add-AzureRmVMDataDisk -VM $VirtualMachine -ManagedDiskId $DataDisk.Id -CreateOption Attach -Lun $azsdisk.Lun ` -Caching $azsdisk.Caching # Delete the Data disk VHD file Remove-AzureStorageBlob -Container $storageContainerName -Blob "$($azsdisk.Vhd.Uri.Split('/')[-1])" -Force -Confirm:$false } } # Create a public IP for the VM. If ($PIpName) { $PublicIp = Get-AzureRmPublicIpAddress -Name $PIpName -ResourceGroupName $azsVM.ResourceGroupName } # Get the virtual network where the virtual machine will be hosted. $VNet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $azsVM.ResourceGroupName # Create NIC in the first subnet of the virtual network. $Nic = Get-AzureRmNetworkInterface -Name $NicName -ResourceGroupName $azsVM.ResourceGroupName $VirtualMachine = Add-AzureRmVMNetworkInterface -VM $VirtualMachine -Id $Nic.Id # Enable Boot Diagnostics with the appropriate storage account. if ($azsVMstoragediag) { $VirtualMachine = Set-AzureRmVMBootDiagnostics -VM $VirtualMachine -Enable -StorageAccountName $azsVMstoragediag -ResourceGroupName $azsVM.ResourceGroupName } # Create the new virtual machine with managed disks. Write-Verbose "Create the new virtual machine ($($azsVM.Name)) with managed disks..." New-AzureRmVM -VM $VirtualMachine -ResourceGroupName $azsVM.ResourceGroupName -Location $azsVM.Location
Summary
Azure Stack VMs deployed with managed disk simplifies disk management by managing the disk associated with the VM. You only have to specify the type (Premium or Standard) and the size of the disk you need and Azure Stack creates and manages the disk for you. This work will bring more options and simplicity to Azure Stack users when working with VMs. And with this tool, it becomes even faster to convert any VM (test or production, Linux or Windows) from unmanaged to managed disk.
Roadmap
I am planning to improve this tool in the future. This is still version 1.0. If you have any feedback or changes that everyone should receive, please feel free to leave a comment below.
That’s it there you have it. Enjoy Azure Stacking!
__
Thank you for reading my blog.
If you have any questions or feedback, please leave a comment.
-Charbel Nemnom-