Sometimes you just need to move Azure resources between resource groups, subscriptions, or regions. Sometimes it is just to tidy up the resources, moving them as a single resource group to manage them more easily, but sometimes there are more serious reasons that leave you with no other choice but to move the resources across subscriptions or regions. In this post, we will be looking at Azure Resource Mover, a new feature on Azure that allows us to move resources across different regions.

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.

The resources need to be validated once they are added to the collections

The resources need to be validated once they are added to the collections

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.

Once the validation is completed the resources are ready to be prepared

Once the validation is completed the resources are ready to be prepared

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."

The move process will be initiated when the resources are prepared

The move process will be initiated when the resources are prepared

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 is the last step of the whole process

Committing the move is the last step of the whole process

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")
Once the move operation is committed the resources in the source region can be removed optional

Once the move operation is committed the resources in the source region can be removed optional

If everything goes according to plan, we should be able to see the resources in their new resource region.

The resources in their new resource group in the target region

The resources in their new resource group in the target region

If we want, we can delete the resources in the source region.

The source and the target resource group

The source and the target resource group

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.

avatar
0 Comments

Leave a reply

Please enclose code in pre tags

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

*

© 4sysops 2006 - 2021

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account