Paginas

18 May 2021

VMware Metro Cluster - DRS Automation with TAGS

 


Hello guys, in this post I will show you a how to use TAGs in VMware to distinguish the Site where the virtual machines are running. In this way,  and using PowerCLI Scripts we are able to allocate the VM to the Host of the respective site with the help of DRS (Distributed Resource Scheduler).
It is possible to make these configurations without using TAGs, but I think that this way it is more flexible, simple and elegant. The only requirement is to have Metro Cluster working properly (it's not in this scope how to configure a vSphere Metro Cluster) and the vSphere Enterprise Plus license on every Host.

This is very useful if you have a Metro Cluster, and you want that VMs that are on Site 1 Storage to run on the Hosts in Site 1 and vice-versa for Site 2. If you don't use this feature, you may end up having VMs on Site 1 Storage running on Site 2 Hosts and vice-versa.

Unfortunately, it's not yet possible to make these settings automatically in the vCenter. (I hope that VMware in future releases will place the option of TAGs directly in the DRS, instead of the name of the VMs). So let's deep dive to the PowerCLI Scripts.


First of all, you will need to TAG all the VMs that are running in Hosts at Site 1 and VMs on Site 2. You can use PowerCLI as well for doing that with Category Location for example.
Then, to check that the TAGs were applied correctly you can run the following script changing the variable Site:

# What VMs have TAG Site1
Get-VM -Tag Site1 | Select Name,VMHost,@{N="Datastore";E={[string]::Join(',',(Get-Datastore -Id $_.DatastoreIdList | Select -ExpandProperty Name))}} | ft -AutoSize


Check which VMs dont' have TAG with Category Location (change the Cluster Name variable):

# What VMs do not have the TAG Location in a specific Cluster
$cat = Get-TagCategory -Name 'Location'
$cluster = Get-Cluster -Name "CLUSTER_NAME"
Get-VM -Location $cluster | Where{!(Get-TagAssignment -Entity $_ -Category $cat)} | Select Name,@{N="Tag";E={(Get-TagAssignment $_.name).tag}} | ft -AutoSize

 
With all VMs tagged with Category Location, we can now run the Script to Create all the DRS Host/VM Groups and Rules accordingly with the TAGs. I'm assing that you have only one cluster with several Hosts in Site1 and Site2 (all identical in CPU and memory). You can run the Script for every cluster that you have.

  • SCRIPT 1 - Remove all the Rules and recreate them accordingly with VM Tags from Location
    • Variables: Cluster Name, Name of the Rules and VM/Host Groups, ESX Hostnames and Site Tags
# Name of the Cluster (add more if you have multiple Clusters within vCenter)
$clusterPRD = "CLUSTER_NAME"

# Remove all the DRS Host Rules (add more if you have more than two sites)
Remove-DrsVMHostRule -DrsMHostRule "NAME_OF_THE_RULE_SITE_1" -Confirm:$false
Remove-DrsVMHostRule -DrsMHostRule "NAME_OF_THE_RULE_SITE_2" -Confirm:$false

# Remove all the DRS Cluster Rules (add more if you have more than two sites)
Remove-DrsClusterGroup -DrsClusterGroup "NAME_OF_THE_RULE_SITE1_VMs" -Confirm:$false
Remove-DrsClusterGroup -DrsClusterGroup "NAME_OF_THE_RULE_SITE2_VMs" -Confirm:$false
Remove-DrsClusterGroup -DrsClusterGroup "NAME_OF_THE_RULE_SITE1_Hosts" -Confirm:$false
Remove-DrsClusterGroup -DrsClusterGroup "NAME_OF_THE_RULE_SITE2_Hosts" -Confirm:$false

# Create new DRS Cluster Rules fos Hosts
New-DrsClusterGroup -Name "NAME_OF_THE_RULE_SITE1_Hosts" -Cluster $clusterPRD -VMHost "HOST_X","HOST_Y","..."
New-DrsClusterGroup -Name "NAME_OF_THE_RULE_SITE2_Hosts" -Cluster $clusterPRD -VMHost "HOST_Z","HOST_W","..."

# Find the Tags in the VMs
$TagSite1 = Get-VM | where {(Get-TagAssignment -Entity $_ | Select -ExpandProperty Tag) -like '*Site1*'}
$TagSite2 = Get-VM | where {(Get-TagAssignment -Entity $_ | Select -ExpandProperty Tag) -like '*Site2*'}
$firstSite1 = 1
$firstSite2 = 1

# For each VM in Site 1, first create a new DRS Cluster Rule for VMs and then add the Following to the same Group
foreach ($VM in $TagSite1) {
   if ($firstSite1){
      New-DrsClusterGroup -Cluster $cluster -VM $VM -Name "NAME_OF_THE_RULE_SITE1_VMs"
      $firstSite1 = 0
   }
   else {
      Set-DrsClusterGroup -DrsClusterGroup "NAME_OF_THE_RULE_SITE1_VMs" -VM $VM Add
   }
}

# For each VM in Site 2, first create a new DRS Cluster Rule for VMs and then add the Following to the same Group
foreach ($VM1 in $TagSite2) {
   if ($firstSite2){
      New-DrsClusterGroup -Cluster $cluster -VM $VM1 -Name "NAME_OF_THE_RULE_SITE2_VMs"
      $firstSite2 = 0
   }
   else {
      Set-DrsClusterGroup -DrsClusterGroup "NAME_OF_THE_RULE_SITE2_VMs" -VM $VM1 Add
   }
}

# Create a rule and add the VMs Group to the Host Group with ShouldRunOn
# (Don't use the MustRunOn because in case of Site failure, the VMs must PowerOn on the remaining Site)
New-DrsVMHostRule -Name "Site1_Rules" -Cluster $clusterPRD -VMGroup "NAME_OF_THE_RULE_SITE1_VMs" -VMHostGroup "NAME_OF_THE_RULE_SITE1_Hosts" -Type ShouldRunOn
New-DrsVMHostRule -Name "Site2_Rules" -Cluster $clusterPRD -VMGroup "NAME_OF_THE_RULE_SITE2_VMs" -VMHostGroup "NAME_OF_THE_RULE_SITE2_Hosts" -Type ShouldRunOn

 
If you have DRS in Fully automated mode, your VMs will migrate to the right nodes after you run the script.

  • SCRIPT 2 - Check if VMs are running in the Right Place (Site/Host/Datastore)
    • Variables: ESX Hostnames and Datastore
    • Notes:
      • You can use wildcards and "like" attribute
      • You can exclude some VMs that are on local datastores
 
I usually run the this script several times a month to guarantee the following:
  1. VMs running in Hosts from Site 1 must be in Datastores from Storage in Site 1
  2. VMs running in Hosts from Site 2 must be in Datastores from Storage in Site 2
# Exclude some VMs for the DRS check
$excludedVM = 'vm1','vm2','...'

# New View with some Virtual Machine Proprieties
$sView = @{
    ViewType = 'VirtualMachine'
    Property = 'Name','Datastore','Runtime.Host','Runtime.PowerState'
    Filter = @{
        'Name' = "^((?!$($excludedVM -join '|')).)*$"
        'Runtime.PowerState' = 'poweredOn'
    }
}

# Get all the ESX Hosts and Datastores from the running VMs and Check if they are correct
Get-View @sView | ForEach-Object -Process {

    # Add more Hosts if you have more Hosts or more Sites (In this case I have two hosts in each Site)
    $esx = Get-View -Id $_.Runtime.Host -Property Name 
    $esx1 = Select-String -Pattern "NAME_ESX_1_SITE1" -InputObject $esx.Name 
    $esx2 = Select-String -Pattern "NAME_ESX_2_SITE1" -InputObject $esx.Name 
    $esx3 = Select-String -Pattern "NAME_ESX_1_SITE2" -InputObject $esx.Name 
    $esx4 = Select-String -Pattern "NAME_ESX_2_SITE2" -InputObject $esx.Name
    # You can parse the name of the datastore like: $esxPre = $esx.Name.Substring(10,1)

    # Get the Datastore for the running VM
    $ds = Get-View -Id $_.Datastore[0] -Property Name 
    $SiteDS1 = Select-String -Pattern "NAME_DATASTORE_SITE1" -InputObject $ds.Name
    $SiteDS2 = Select-String -Pattern "NAME_DATASTORE_SITE2" -InputObject $ds.Name
    # You can parse the name of the datastore like: $dsPre = $ds.Name.Substring(0,3)

    # Check if the VMs on Site 1 are running in Hosts and Datastores from Site 1
    if(($esx1 -ne $null -or $esx2 -ne $null -ne $null) -and $SiteDS2 -ne $null){
        $_ | Select Name,
            @{N='VMHost';E={$esx.Name}},
            @{N='Datastore';E={$ds.Name}}
    }
    # Check if the VMs on Site 2 are running in Hosts and Datastores from Site 2
    if(($esx3 -ne $null -or $esx4 -ne $null -ne $null) -and $SiteDS1 -ne $null){
        $_ | Select Name,
            @{N='VMHost';E={$esx.Name}},
            @{N='Datastore';E={$ds.Name}}
    }
    # If there are some VMs in Site 1 running in Hosts/Datastores Site 2 it will print in the screen
    # If there are some VMs in Site 2 running in Hosts/Datastores Site 1 it will print in the screen
}

If you have no results from the Script, every VM is in the right Site/Host/Datastore. If you have results, you should check if the VM has a TAG and it's correct. Then, you must migrate manually that VM to the right place and re-run the script or wait for DRS to apply (in full automated mode).

You can even use this TAGs for Backups. For instance, with the new Veeam v11 you can use several Tags within a VM, so you can backup to a sepcific repository from the Site where the VM is running.

Tell me if you have any doubts or ideias to improve the scripts.
See you next time!

No comments:

Post a Comment