Every now and again I get a support case with problems around affinity groups. Affinity Groups are a legacy feature that still exists for Azure Classic deployments. Nowadays there is no real advantage in having an affinity group configured – in fact – there are many disadvantages to using one. So why do these groups exist in the first place? And what were they used for when they first got introduced?

The concept of affinity groups

When you deploy a service to an affinity group in Microsoft Azure, you force it to use the same host machine cluster as all other machines in the affinity group.

The term “service” was specifically picked here, because it is a very broad term. Affinity groups can be used with most services from storage, to virtual machines, to networks.

What was the purpose of affinity groups?

Before Microsoft Azure moved to a flat network topology, keeping resource closely together brought an advantage in terms of the connection speed between these resources. This is now not the case anymore.

Instead of using a network that is restricted to just one affinity group, regional networks can now be used, enabling unrestricted networking of resources across an entire region.

What are the current disadvantages of affinity groups?

As described in the previous two points an affinity group makes sure that services stay on the same cluster. This used to be a benefit in the past but is now more of a disadvantage. If one cluster goes down all your services will be affected, which is far from ideal.

Additionally – because the set of available virtual machines has expanded greatly – you may run into situations where the cluster that your affinity group sits on has not got a certain machine size available.

Finally – as affinity groups are being deprecated in a phased manner – having them in place will require you to use scripts for maintenance tasks that could usually be executed via the portal.

Okay this makes sense. So how do I get rid of my affinity groups?

This depends on what your affinity group is defined on. Earlier in this post, I mentioned that affinity groups were designed so that many different resources could join them. I will cycle through the different scenarios in this part of the post.

Affinity Group defined on a network

If an affinity group is defined on a virtual network level only, then a migration from an affinity group network to a regional network can be executed without any downtime. A slight change needs to be made to the XML config for the virtual network. Further information can be found here: https://azure.microsoft.com/en-us/documentation/articles/virtual-networks-migrate-to-regional-vnet/

Affinity Group defined on a cloud service(s)

This scenario is a bit trickier and we have two options to migrate out of the affinity group in this case.

We can either go to the ARM deployment model and migrate without downtime: https://msdn.microsoft.com/en-us/library/mt786751(v=azure.200).aspx

If this is not an option (we need to stay in Classic) we need to take a hit on the downtime and run a PowerShell script to delete and recreate the cloud service.

You can find a script example below.

$cloudServiceName = "cloud-service-name"
$subscriptionId = "subscription id"
$vnetName = "myVnet"
$location = "West US"
$vmNames = @();
$vmNames += "myVM1"
$vmNames += "myVM2"
$vmNames += "myVM3"

# log in

# select subscription
Select-AzureSubscription -SubscriptionId $subscriptionId

# export all
foreach($vm in $vmNames) {
$vmPath = "C:\" + $vm + ".xml"
Export-AzureVm -ServiceName $cloudServiceName -Name $vm -Path $vmPath

Read-Host "Continue by pressing 'Enter' after verifying that all VMs got exported correctly. Please check the XML files to see if the VM has an instance affinity group assignment. This assignment will have to be removed before you continue. By pressing enter you confirm that the cloud service can be temporarily deleted. Your downtime starts as soon as you hit enter..."

# reserve the current cloud service IP
New-AzureReservedIP -ReservedIPName $cloudServiceName -Location "West US" -ServiceName $cloudServiceName
Remove-AzureReservedIPAssociation -ReservedIPName $cloudServiceName -ServiceName $cloudServiceName -Force

# delete all
foreach($vm in $vmNames) {
Get-AzureVM -ServiceName $cloudServiceName -Name $vm | Stop-AzureVM -Force
Remove-AzureVM -ServiceName $cloudServiceName -Name $vm

# delete service
Remove-AzureService -ServiceName $cloudServiceName -Force

# depending on when your cloud service was first created you may have to set a current storage account at this point

# recreate service outside affinity group
New-AzureService -ServiceName $cloudServiceName -Location $location

# recreate all
foreach($vm in $vmNames) {
$vmPath = "C:\" + $vm + ".xml"
$vmConfig = Import-AzureVM -Path $vmPath
New-AzureVM -ServiceName $cloudServiceName -Location $location -VNetName $vnetName -VMs $vmConfig

# assign ip
Set-AzureReservedIPAssociation -ReservedIPName $cloudServiceName -ServiceName $cloudServiceName


Before running this script the VNet needs to have already been migrated out of its affinity group. (if it had one)

Affinity group defined on a storage account

Again you can migrate to ARM without downtime if this is an option: https://azure.microsoft.com/en-us/documentation/articles/virtual-machines-windows-ps-migration-classic-resource-manager/#next-steps

If you need to stay in the Classic deployment model the recommendation is to create a new storage account that does not have the affinity group association and to copy the content across.

Virtual machine disk assignments need to be redone.

Tools like Storage Explorer can be used to access the new and the old account and copy the content over: http://storageexplorer.com/

You can use the tools provided in the Classic portal to delete and create virtual disk objects. You can also use the PowerShell cmdlets available. https://msdn.microsoft.com/en-us/library/azure/dn495255.aspx https://msdn.microsoft.com/en-us/library/azure/dn495252.aspx

If you would like to combine the script in the previous step with a script to migrate the storage in an automated fashion you would complete this migration once the service and the machines are remove and before they are recreated.

However – in real terms – you may prefer to simply start a new storage account for new deployments to the now affinity-group-less service and VNet. Legacy disks can remain in the affinity group storage account.