- Create and manage append blobs with PowerShell - Wed, Oct 12 2022
- Permanently delete a Key Vault in Azure using PowerShell - Fri, Feb 4 2022
- Restore Azure Files with PowerShell - Fri, Jan 28 2022
Why move a resource to another region?
You may want to move resources when:
- There is a new region that better suits you geographically
- A resource is accidentally deployed to the wrong region and needs to be fixed
- There is another region that provides higher resource capacity for a resource type
- You need to use specific Azure services or features that are only available in specific regions
- There are special data sovereignty requirements in your business
Supported resource types
The following resources are currently supported by Azure Resource Mover and can be moved across regions:
- Availability sets
- Azure SQL databases and elastic pools
- Azure virtual networks
- Azure VMs and associated disks
- Internal and public load balancers
- Network security groups (NSGs)
- NICs
- Public IP addresses
How to move resources
Azure Resource Mover uses six phases to accomplish move tasks.
Selecting resources to move
When we select resources to be moved, those resources are added to the move collection, an object that is created automatically. This object stores the configuration of the resources that will be moved.
Validating dependencies
This is where Azure Resource Mover checks for the dependencies. If any dependent resources are found, then those additional resources can also be added to the existing collection.
Preparing resources
Once the validation phase has been completed, Azure Resource Mover starts preparing the resources (depending on the resource type). If the resource is stateful and also needs its data to be moved, then Resource Mover also prepares the resource to replicate the data to the target region. If the resource is stateless, then Resource Mover only creates an ARM template to be used to create resources in the target region.
Initiating the move process
This phase is where the actual deployment occurs in the target region. There might be some down time during the phase when certain resources, such as VMs and SQLs, are moved.
Committing the move
This is the last step to decide whether you want to commit the changes. If you commit the changes, then stateful resources in the source region might become inaccessible as they become available in the target region as expected. You can also discard the move, in which case Azure Resource Mover deletes the resources that are already created in the target region.
Deleting source resources (optional)
Once the move has been verified, you may also want to delete the resources in the source region.
Using Azure Resource Mover with PowerShell
Installation prerequisites
Register-AzResourceProvider -ProviderNamespace Microsoft.Migrate Install-Module -Name Az.ResourceMover -Force
Creating the resource group for metadata
Next, you have to create the resource group for metadata where the move configuration will be stored.
$subscriptionId = "xxxxxxxx-xxxxxxxxxx-xxxxxxxxxxx-xxxxxxxx" $metadataRG = "MoveCollectionMatadataRG" New-AzResourceGroup -Name $metadataRG -Location "East US 2"
Creating a new move collection and granting it access
The following lines of code create a new move collection and grant it access over the subscription.
New-AzResourceMoverMoveCollection -Name "MoveCollection01" -ResourceGroupName $metadataRG -SubscriptionId $subscriptionId -SourceRegion "eastus" -TargetRegion "westus" -Location "East US 2" -IdentityType SystemAssigned $moveCollection = Get-AzResourceMoverMoveCollection -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -Name "MoveCollection01" $identityPrincipalId = $moveCollection.IdentityPrincipalId New-AzRoleAssignment -ObjectId $identityPrincipalId -RoleDefinitionName Contributor -Scope "/subscriptions/$subscriptionId" New-AzRoleAssignment -ObjectId $identityPrincipalId -RoleDefinitionName "User Access Administrator" -Scope "/subscriptions/$subscriptionId"
Adding the resources and the resource group to the move collection
$resourcesToMove = Get-AzResource -ResourceGroupName "ResourcesTobeMoved" $resourcesToMove | foreach { $resID = $psitem.ResourceID $resName = $psitem.Name $resType = $psitem.ResourceType Add-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -SourceId $resID -Name $resName -ResourceSettingResourceType $resType -ResourceSettingTargetResourceName $resName } $rgID = (Get-AzResourceGroup -Name ResourcesTobeMoved).ResourceID Add-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -SourceId $rgID -Name ResourcesTobeMoved -ResourceSettingResourceType "resourcegroups" -ResourceSettingTargetResourceName ResourcesTobeMoved-westUS
Once the resources have been added to the collection, their status will be listed as "Prepare pending." Also, the Validate dependencies button will appear in the portal. To validate the dependencies, we will be using the Resolve-AzResourceMoverMoveCollectionDependency cmdlet.
Resolving dependencies
Resolve-AzResourceMoverMoveCollectionDependency -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01"
After the above command is executed, the Validate dependencies button disappears. We can now go to the next step to prepare the resources for the move.
Preparing the resources
$resourcesInTheCollection = Get-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" | select name, MoveStatusMoveState, ProvisioningState, MoveStatusMessage Invoke-AzResourceMoverPrepare -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource "ResourcesTobeMoved" Do { $resourcesInTheCollection | where { $PSITem.name -ne "ResourcesTobeMoved" } | foreach { Invoke-AzResourceMoverPrepare -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource $PSItem.name } }until((Get-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" | select MoveStatusMoveState).MoveStatusMoveState -notcontains "PreparePending")
The prepared resources have the status of "Initiate move pending."
Initiating the move
Invoke-AzResourceMoverInitiateMove -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource "ResourcesTobeMoved" Do { $resourcesInTheCollection | where { $PSITem.name -ne "ResourcesTobeMoved" } | foreach { Invoke-AzResourceMoverInitiateMove -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource $PSItem.name } }until((Get-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" | select MoveStatusMoveState).MoveStatusMoveState -notcontains "MovePending")
Once the move is initiated for the resources, the last step is to commit or discard the changes.
Committing the move
Invoke-AzResourceMoverCommit -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource "ResourcesTobeMoved" Do { $resourcesInTheCollection | where { $PSITem.name -ne "ResourcesTobeMoved" } | foreach { Invoke-AzResourceMoverCommit -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource $PSItem.name } }until((Get-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" | select MoveStatusMoveState).MoveStatusMoveState -notcontains "CommitPending")
If everything goes according to plan, we should be able to see the resources in their new resource region.
If we want, we can delete the resources in the source region.
Full script
Below is the full PowerShell script for moving Azure resources.
Subscribe to 4sysops newsletter!
# Install prerequisites Register-AzResourceProvider -ProviderNamespace Microsoft.Migrate Install-Module -Name Az.ResourceMover -Force $subscriptionId = "xxxxxxxxx-xxxxxxxxxx-xxxxxxxxx-xxxxxx" $metadataRG = "MoveCollectionMatadataRG" # Create the resource group for metadata New-AzResourceGroup -Name $metadataRG -Location "East US 2" # Creating a new move collection and granting it access over the subscription New-AzResourceMoverMoveCollection -Name "MoveCollection01" -ResourceGroupName $metadataRG -SubscriptionId $subscriptionId -SourceRegion "eastus" -TargetRegion "westus" -Location "East US 2" -IdentityType SystemAssigned $moveCollection = Get-AzResourceMoverMoveCollection -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -Name "MoveCollection01" $identityPrincipalId = $moveCollection.IdentityPrincipalId New-AzRoleAssignment -ObjectId $identityPrincipalId -RoleDefinitionName Contributor -Scope "/subscriptions/$subscriptionId" New-AzRoleAssignment -ObjectId $identityPrincipalId -RoleDefinitionName "User Access Administrator" -Scope "/subscriptions/$subscriptionId" # Add resources to the move collection $resourcesToMove = Get-AzResource -ResourceGroupName "ResourcesTobeMoved" $resourcesToMove | foreach { $resID = $psitem.ResourceID $resName = $psitem.Name $resType = $psitem.ResourceType Add-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -SourceId $resID -Name $resName -ResourceSettingResourceType $resType -ResourceSettingTargetResourceName $resName } $rgID = (Get-AzResourceGroup -Name ResourcesTobeMoved).ResourceID Add-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -SourceId $rgID -Name ResourcesTobeMoved -ResourceSettingResourceType "resourcegroups" -ResourceSettingTargetResourceName ResourcesTobeMoved-westUS # Resolve dependencies Resolve-AzResourceMoverMoveCollectionDependency -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" # Prepare the resources $resourcesInTheCollection = Get-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" | select name, MoveStatusMoveState, ProvisioningState, MoveStatusMessage Invoke-AzResourceMoverPrepare -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource "ResourcesTobeMoved" Do { $resourcesInTheCollection | where { $PSITem.name -ne "ResourcesTobeMoved" } | foreach { Invoke-AzResourceMoverPrepare -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource $PSItem.name } }until((Get-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" | select MoveStatusMoveState).MoveStatusMoveState -notcontains "PreparePending") # Initiate The Move Invoke-AzResourceMoverInitiateMove -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource "ResourcesTobeMoved" Do { $resourcesInTheCollection | where { $PSITem.name -ne "ResourcesTobeMoved" } | foreach { Invoke-AzResourceMoverInitiateMove -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource $PSItem.name } }until((Get-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" | select MoveStatusMoveState).MoveStatusMoveState -notcontains "MovePending") # Commit The Move Invoke-AzResourceMoverCommit -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource "ResourcesTobeMoved" Do { $resourcesInTheCollection | where { $PSITem.name -ne "ResourcesTobeMoved" } | foreach { Invoke-AzResourceMoverCommit -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" -MoveResource $PSItem.name } }until((Get-AzResourceMoverMoveResource -SubscriptionId $subscriptionId -ResourceGroupName $metadataRG -MoveCollectionName "MoveCollection01" | select MoveStatusMoveState).MoveStatusMoveState -notcontains "CommitPending")
Conclusion
Azure Resource Mover is the only tool in Azure that allows us to move resources across regions. With PowerShell, you can make the whole process faster and less complicated. The most critical step of the entire process is to ensure there are no unresolved dependencies before initiating the move. Fortunately, the error messages are pretty clear, and you can see if anything is missing before moving to the next step.