A powershell script which balances the load of Hyper-V VMs across all cluster nodes

A powershell script which balances the load of Hyper-V VMs across all cluster nodes

Rate This
  • Comments 3

Hi everyone,

I run a 2 node cluster with Hyper-V. While debugging and testing, i often have to reboot a node and end up with all my VM's on one node, and find myself moving them arround manually.

So i came up with the below script to automate this.

Let me know how it works for you!

Cheers

Robert

 P.S. I'm happy to see that this found it's way as a feature into SCVMM 2012. It's called Dynamic Optimization (DO)

#
# VmBalancer.ps1 - A powershell script which balances the load of Hyper-V VMs across all cluster nodes
#
# Environment: Windows Server 2008 R2, Hyper-V, Failover cluster
#
# How it works:
#  All cluster nodes are checked for their virtual to logical processor ratio.
#  Then the average of this values is value is calculated for the entire cluster
#  Then the 2 nodes with the maximum and minimum distance to this average are calculated
#  If the minimum distance is greater then the maximum, the least loaded host is very likely capable
#  to take a VM from the maximum loaded host. So the script does LiveMigrate -one- VM per run 
#
# Notes:
#  The script does run standalone, if you set Set-ExecutionPolicy correctly. I run it as a Scheduled Task
#  every 30 minutes on each cluster node. The script checks if it runs on the one node currently owning the
#  Cluster Group, to ensure it is not run simulateneously on multiple nodes.
#  on Each run, only one VM might be moved, to allow for one LiveMigration at a time
#  When a VM is moved, an event from VM Balancer is written to the Application Event log.
#  
#
# Thoughts:
#  Once you reboot a cluster node, by default, the running VM's are migrated to other nodes. When the node comes
#  back online, VM's are not moved back. You may set Prefered Owners and define a failback policy, but this is
#  rather static. In future, the script might make use of VMM's star rating for best placement, but for now it should also run without VMM
#
#  The recommended virtual to logical processer ratio is 8:1. Courtesy of algorithm
#  See:
http://blogs.msdn.com/b/virtual_pc_guy/archive/2010/08/13/using-powershell-to-find-the-virtual-processor-to-logical-processor-ratio-of-hyper-v.aspx
#  It might happen that the destination node is not able to take the VM as it has not enough memory. This should be
#  covered by LiveMigration checks and the VM is then not moved.

# Warning:
#  This script had limited testing, on my 2 identical node cluster. Use at own risk after your own testing.
#
#
# robertvi at microsoft.com
#
# v1.0 101007
#
#
#

Import-Module FailoverClusters  # load cluster cmdlet

$averageload=0
$numberofnodes=0
$maxload = 0
$minload = 1000
$maxloadedhost = 'undefined'
$minloadedhost = 'undefined'


#ensure we run on one node only
$master = Get-ClusterGroup |  ?{ $_.Name -like "Cluster Group" }
$thishost = Get-WmiObject -class win32_computersystem

$master = $master.OwnerNode.Name.ToLower()
$thishost = $thishost.Name.ToLower()

Write-Host "Cluster Group owner:" $master "Script Host:" $thishost "<"

if ( $master -ne $thishost)
{
 Write-Host "Exiting Script as it is not run on the node that owns the Cluster Group"
 exit
}

 

# Get all nodes
$nodes = get-clusternode

foreach ($node in $nodes)
{

 $Hostinfo = Get-WmiObject -class win32_computersystem -computername $node
 Write-Host "Host " $Hostinfo.Name
 $load = (@(gwmi -ns root\virtualization MSVM_Processor -computername $node).count / (@(gwmi Win32_Processor -computername $node) | measure -p NumberOfLogicalProcessors -sum).Sum)  
 Write-Host "Load " $load

 if ($load -ge $maxload)
 {
  $maxload = $load
  $maxloadedhost = $node
 }

 if ($load -le $minload)
 {
  $minload = $load
  $minloadedhost = $node
 }

 

 $averageload += $load
 $numberofnodes += 1
 
}

$averageload /= $numberofnodes
Write-Host "Average Load " $averageload
Write-Host "Max Load " $maxload
Write-Host "Min Load " $minload

#
# Now if the maximum loaded host - minimum loaded host is still above average, push a VM from maximum to minimum.
#


if (($maxload - $averageload) -gt $minload) #is maxload distance to average greater then minloads distance?
{
 Write-Host "Push a VM from" $maxloadedhost "to " $minloadedhost

 #find a running VM on $maxloadedhost and move to $minloadedhost

 $VMGroups = Get-ClusterNode $maxloadedhost.Name | Get-ClusterGroup | ?{ $_ | Get-ClusterResource | ?{ $_.ResourceType -like "Virtual Machine" } }


 foreach ($vm in $VMGroups)
 {

    if ($vm.State -eq 'Online')
    { 
         Write-Host "VM Group to mmigrate" $vm.name
           

  # This is our best candidate. May still not possible to move when destination memory not sufficent.
  # LiveMigration will determine this and abort the migrate.
  # if Quick Migration should be used: Move-ClusterGroup $vm -Node $minloadedhost

  $evtinfo = "Moving " + $vm + " to Node " + $minloadedhost + " Avg load " +$averageload + " maxload " + $maxload + " minload " + $minload
  $evt=new-object System.Diagnostics.EventLog("Application")
  $evt.Source="VM Balancer"
  $infoevent=[System.Diagnostics.EventLogEntryType]::Information
  $evt.WriteEntry($evtinfo,$infoevent,666)


          Move-ClusterVirtualMachineRole $vm -Node $minloadedhost -Wait 0

  break
            
    } 


 }


}
else
{
  Write-Host "No Balancing needed"

 

  • ...as usual, great stuff Robert ;-)

  • What if I have 4 nodes in the cluster? What current script does, is taking ALL VMs from the most loaded and move ALL them to the less loaded, and after that i am getting the less loaded as a most loaded :).... Is it possible to add some extra logic and calculate how many VMs should be loaded from the most loaded node to to other nodes, members of the cluster? Thanks, Misha

  • I created a project on github with a modified version of this scripts to balance in the proper way the virtual machine across all hosts in the cluster to not have much more of difference > 1 ratio between the high and low host. The code is here:

    github.com/.../HypervVMBalance.

Page 1 of 1 (3 items)
Leave a Comment
  • Please add 8 and 5 and type the answer here:
  • Post