Migrate IaaS resources from classic to Azure Resource Manager by using PowerShell
Applies to: ✔️ Linux VMs ✔️ Windows VMs
Important
Today, about 90% of IaaS VMs are using Azure Resource Manager. As of February 28, 2020, classic VMs have been deprecated and will be fully retired on September 6, 2023. Learn more about this deprecation and how it affects you.
These steps show you how to use Azure PowerShell commands to migrate infrastructure as a service (IaaS) resources from the classic deployment model to the Azure Resource Manager deployment model.
If you want, you can also migrate resources by using the Azure CLI.
- For background on supported migration scenarios, see Platform-supported migration of IaaS resources from classic to Azure Resource Manager.
- For detailed guidance and a migration walkthrough, see Technical deep dive on platform-supported migration from classic to Azure Resource Manager.
- Review the most common migration errors.
Here's a flowchart to identify the order in which steps need to be executed during a migration process.
Step 1: Plan for migration
Here are a few best practices that we recommend as you evaluate whether to migrate IaaS resources from classic to Resource Manager:
- Read through the supported and unsupported features and configurations. If you have virtual machines that use unsupported configurations or features, wait for the configuration or feature support to be announced. Alternatively, if it suits your needs, remove that feature or move out of that configuration to enable migration.
- If you have automated scripts that deploy your infrastructure and applications today, try to create a similar test setup by using those scripts for migration. Alternatively, you can set up sample environments by using the Azure portal.
Important
Application gateways aren't currently supported for migration from classic to Resource Manager. To migrate a virtual network with an application gateway, remove the gateway before you run a Prepare operation to move the network. After you complete the migration, reconnect the gateway in Azure Resource Manager.
Azure ExpressRoute gateways that connect to ExpressRoute circuits in another subscription can't be migrated automatically. In such cases, remove the ExpressRoute gateway, migrate the virtual network, and re-create the gateway. For more information, see Migrate ExpressRoute circuits and associated virtual networks from the classic to the Resource Manager deployment model.
Step 2: Install the latest version of PowerShell
There are two main options to install Azure PowerShell: PowerShell Gallery or Web Platform Installer (WebPI). WebPI receives monthly updates. PowerShell Gallery receives updates on a continuous basis. This article is based on Azure PowerShell version 2.1.0.
For installation instructions, see How to install and configure Azure PowerShell.
Step 3: Ensure that you're an administrator for the subscription
To perform this migration, you must be added as a coadministrator for the subscription in the Azure portal.
- Sign in to the Azure portal.
- On the Hub menu, select Subscription. If you don't see it, select All services.
- Find the appropriate subscription entry, and then look at the MY ROLE field. For a coadministrator, the value should be Account admin.
If you're not able to add a co-administrator, contact a service administrator or co-administrator for the subscription to get yourself added.
Step 4: Set your subscription, and sign up for migration
First, start a PowerShell prompt. For migration, set up your environment for both classic and Resource Manager.
Sign in to your account for the Resource Manager model.
Connect-AzAccount
Get the available subscriptions by using the following command:
Get-AzSubscription | Sort Name | Select Name
Set your Azure subscription for the current session. This example sets the default subscription name to My Azure Subscription. Replace the example subscription name with your own.
Select-AzSubscription –SubscriptionName "My Azure Subscription"
Note
Registration is a one-time step, but you must do it once before you attempt migration. Without registering, you see the following error message:
BadRequest : Subscription is not registered for migration.
Register with the migration resource provider by using the following command:
Register-AzResourceProvider -ProviderNamespace Microsoft.ClassicInfrastructureMigrate
Wait five minutes for the registration to finish. Check the status of the approval by using the following command:
Get-AzResourceProvider -ProviderNamespace Microsoft.ClassicInfrastructureMigrate
Make sure that RegistrationState is Registered
before you proceed.
Before switching to the classic deployment model, make sure that you have enough Azure Resource Manager virtual machine vCPUs in the Azure region of your current deployment or virtual network. You can use the following PowerShell command to check the current number of vCPUs you have in Azure Resource Manager. To learn more about vCPU quotas, see Limits and the Azure Resource Manager.
This example checks the availability in the West US region. Replace the example region name with your own.
Get-AzVMUsage -Location "West US"
Now, sign in to your account for the classic deployment model.
Add-AzureAccount
Get the available subscriptions by using the following command:
Get-AzureSubscription | Sort SubscriptionName | Select SubscriptionName
Set your Azure subscription for the current session. This example sets the default subscription to My Azure Subscription. Replace the example subscription name with your own.
Select-AzureSubscription –SubscriptionName "My Azure Subscription"
Step 5: Run commands to migrate your IaaS resources
- Migrate VMs in a cloud service (not in a virtual network)
- Migrate VMs in a virtual network
- Migrate a storage account
Note
All the operations described here are idempotent. If you have a problem other than an unsupported feature or a configuration error, we recommend that you retry the prepare, abort, or commit operation. The platform then tries the action again.
Step 5a: Option 1 - Migrate virtual machines in a cloud service (not in a virtual network)
Get the list of cloud services by using the following command. Then pick the cloud service that you want to migrate. If the VMs in the cloud service are in a virtual network or if they have web or worker roles, the command returns an error message.
Get-AzureService | ft Servicename
Get the deployment name for the cloud service. In this example, the service name is My Service. Replace the example service name with your own service name.
$serviceName = "My Service"
$deployment = Get-AzureDeployment -ServiceName $serviceName
$deploymentName = $deployment.DeploymentName
Prepare the virtual machines in the cloud service for migration. You have two options to choose from.
Option 1: Migrate the VMs to a platform-created virtual network.
First, validate that you can migrate the cloud service by using the following commands:
$validate = Move-AzureService -Validate -ServiceName $serviceName ` -DeploymentName $deploymentName -CreateNewVirtualNetwork $validate.ValidationMessages
The following command displays any warnings and errors that block migration. If validation messages do not contain message of type error, you can move on to the Prepare step.
Move-AzureService -Prepare -ServiceName $serviceName ` -DeploymentName $deploymentName -CreateNewVirtualNetwork
Option 2: Migrate to an existing virtual network in the Resource Manager deployment model.
This example sets the resource group name to myResourceGroup, the virtual network name to myVirtualNetwork, and the subnet name to mySubNet. Replace the names in the example with the names of your own resources.
$existingVnetRGName = "myResourceGroup" $vnetName = "myVirtualNetwork" $subnetName = "mySubNet"
First, validate that you can migrate the virtual network by using the following command:
$validate = Move-AzureService -Validate -ServiceName $serviceName ` -DeploymentName $deploymentName -UseExistingVirtualNetwork -VirtualNetworkResourceGroupName $existingVnetRGName -VirtualNetworkName $vnetName -SubnetName $subnetName $validate.ValidationMessages
The following command displays any warnings and errors that block migration. If validation messages do not contain errors, you can proceed with the following Prepare step:
Move-AzureService -Prepare -ServiceName $serviceName -DeploymentName $deploymentName ` -UseExistingVirtualNetwork -VirtualNetworkResourceGroupName $existingVnetRGName ` -VirtualNetworkName $vnetName -SubnetName $subnetName
After the Prepare operation succeeds with either of the preceding options, query the migration state of the VMs. Ensure that they're in the Prepared
state.
This example sets the VM name to myVM. Replace the example name with your own VM name.
$vmName = "myVM"
$vm = Get-AzureVM -ServiceName $serviceName -Name $vmName
$vm.VM.MigrationState
Check the configuration for the prepared resources by using either PowerShell or the Azure portal. If you're not ready for migration and you want to go back to the old state, use the following command:
Move-AzureService -Abort -ServiceName $serviceName -DeploymentName $deploymentName
If the prepared configuration looks good, you can move forward and commit the resources by using the following command:
Move-AzureService -Commit -ServiceName $serviceName -DeploymentName $deploymentName
Step 5a: Option 2 - Migrate virtual machines in a virtual network
To migrate virtual machines in a virtual network, you migrate the virtual network. The virtual machines automatically migrate with the virtual network. Pick the virtual network that you want to migrate.
Note
Migrate a single virtual machine created using the classic deployment model by creating a new Resource Manager virtual machine with Managed Disks by using the VHD (OS and data) files of the virtual machine.
Note
The virtual network name might be different from what is shown in the new portal. The new Azure portal displays the name as [vnet-name]
, but the actual virtual network name is of type Group [resource-group-name] [vnet-name]
. Before you start the migration, look up the actual virtual network name by using the command Get-AzureVnetSite | Select -Property Name
or view it in the old Azure portal.
This following example sets the virtual network name to Group [resource-group-name] [vnet-name]. Replace the example virtual network name with one that was returned from running the command in the Note section above..
$vnetName = "Group [resource-group-name] [vnet-name]"
Note
If the virtual network contains web or worker roles, or VMs with unsupported configurations, you get a validation error message.
First, validate that you can migrate the virtual network by using the following command:
Move-AzureVirtualNetwork -Validate -VirtualNetworkName $vnetName
The following command displays any warnings and errors that block migration. If validation is successful, you can proceed with the following Prepare step:
Move-AzureVirtualNetwork -Prepare -VirtualNetworkName $vnetName
Check the configuration for the prepared virtual machines by using either Azure PowerShell or the Azure portal. If you're not ready for migration and you want to go back to the old state, use the following command:
Move-AzureVirtualNetwork -Abort -VirtualNetworkName $vnetName
If the prepared configuration looks good, you can move forward and commit the resources by using the following command:
Move-AzureVirtualNetwork -Commit -VirtualNetworkName $vnetName
Step 5b: Migrate a storage account
After you're done migrating the virtual machines, perform the following prerequisite checks before you migrate the storage accounts.
Note
If your storage account has no associated disks or VM data, you can skip directly to the "Validate storage accounts and start migration" section. Also note that deleting the classic disks, VM images or OS images does not remove the source VHD files in the storage account. However, it does break the lease on those VHD files so that they can be reused to create ARM disks or images after migration.
Prerequisite checks if you migrated any VMs or your storage account has disk resources:
Migrate virtual machines whose disks are stored in the storage account.
The following command returns RoleName and DiskName properties of all the VM disks in the storage account. RoleName is the name of the virtual machine to which a disk is attached. If this command returns disks, then ensure that virtual machines to which these disks are attached are migrated before you migrate the storage account.
$storageAccountName = 'yourStorageAccountName' Get-AzureDisk | where-Object {$_.MediaLink.Host.Contains($storageAccountName)} | Select-Object -ExpandProperty AttachedTo -Property ` DiskName | Format-List -Property RoleName, DiskName
Delete unattached VM disks stored in the storage account.
Find unattached VM disks in the storage account by using the following command:
$storageAccountName = 'yourStorageAccountName' Get-AzureDisk | where-Object {$_.MediaLink.Host.Contains($storageAccountName)} | Where-Object -Property AttachedTo -EQ $null | Format-List -Property DiskName
If the previous command returns disks, delete these disks by using the following command:
Remove-AzureDisk -DiskName 'yourDiskName'
Delete VM images stored in the storage account.
The following command returns all the VM images with OS disks stored in the storage account.
Get-AzureVmImage | Where-Object { $_.OSDiskConfiguration.MediaLink -ne $null -and $_.OSDiskConfiguration.MediaLink.Host.Contains($storageAccountName)` } | Select-Object -Property ImageName, ImageLabel
The following command returns all the VM images with data disks stored in the storage account.
Get-AzureVmImage | Where-Object {$_.DataDiskConfigurations -ne $null ` -and ($_.DataDiskConfigurations | Where-Object {$_.MediaLink -ne $null -and $_.MediaLink.Host.Contains($storageAccountName)}).Count -gt 0 ` } | Select-Object -Property ImageName, ImageLabel
Delete all the VM images returned by the previous commands by using this command:
Remove-AzureVMImage -ImageName 'yourImageName'
Validate storage accounts and start migration.
Validate each storage account for migration by using the following command. In this example, the storage account name is myStorageAccount. Replace the example name with the name of your own storage account.
$storageAccountName = "myStorageAccount" Move-AzureStorageAccount -Validate -StorageAccountName $storageAccountName
The next step is to prepare the storage account for migration.
$storageAccountName = "myStorageAccount" Move-AzureStorageAccount -Prepare -StorageAccountName $storageAccountName
Check the configuration for the prepared storage account by using either Azure PowerShell or the Azure portal. If you're not ready for migration and you want to go back to the old state, use the following command:
Move-AzureStorageAccount -Abort -StorageAccountName $storageAccountName
If the prepared configuration looks good, you can move forward and commit the resources by using the following command:
Move-AzureStorageAccount -Commit -StorageAccountName $storageAccountName
Next steps
- Overview of platform-supported migration of IaaS resources from classic to Azure Resource Manager
- Technical deep dive on platform-supported migration from classic to Azure Resource Manager
- Planning for migration of IaaS resources from classic to Azure Resource Manager
- Use CLI to migrate IaaS resources from classic to Azure Resource Manager
- Community tools for assisting with migration of IaaS resources from classic to Azure Resource Manager
- Review most common migration errors
- Review the most frequently asked questions about migrating IaaS resources from classic to Azure Resource Manager