Tag Based Affinity Rules
vROPS has a feature called Business Intent, which allows us to control the placement of virtual machines through the use of vSphere tags. Business intent allows us to control the placement of machines on a cluster basis or a host basis, allowing you to optimize the performance and placement of vms in accordance with licensing constraints, performance requirements, replication standards, etc. One downside of this feature is that vROPS does not currently allow you to control both cluster and host based placement at the same time. Today I'll present a way that allows you to leverage cluster based business intent, with a secondary method of controlling host placement within the target clusters.
OVERVIEW
There are two modes for vROPS Business Intent: Cluster Based and Host Based. Cluster based business intent causes vROPS to look at vSphere tags applied to clusters and compares them to tags applied to virtual machines. vROPS will then identify violations of these rules and allow you to remediate them manually, on a schedule or automatically. You are able to build intent rules consuming multiple vSphere tag catagories and tags. Here's an example of what it looks like when configured with an intent violation highlight.
Today, we will be focusing on how to leverage host based intent. We will cover cluster based intent and the potential options for mixing the two in a future post. When using host based intent, vROPS will control placement of VMs within clusters using affinity rules, vROPS is currently only able to consume a single vSphere tag category, and each object can only have a single tag within that category. This can make it a bit limiting, as you are unable to create a scenario of declaring that host A can run windows and MSSQL servers, and host B can run windows servers such as the following scenario
If you do try to assign multiple tags to an object - you'll get a big NOPE from vROPS when you try to configure the rules!
Depening on your requirements you can perform via an approach that is less explicit in the way you declare your desired placement intentions. You can read more about that here.
If that method does not meet your needs, and you don't feel like waiting for a feature request to fix this, you can utilize a script (provided below) to configure host base affinity rules using multiple tags and categories. Be warned, the script provided below doesn't check if your tagged rules would create an affinity/anti-affinity conflict and cause DRS issues.
This method has the downside of pulling the management of the business intent out of vROPS hands from a host base intent perspective, but it allows you to configure cluster based business intent to understand where violations are occuring. We will cover in a future post how you can blend this script with cluster based business intent.
Before using this script, besure to vet it and perform proper testing.
1param (
2[Parameter(Mandatory=$true)][string[]]$vcenterlist,
3[Parameter(Mandatory=$true)][string]$vCUsername,
4[Parameter(Mandatory=$true)][string]$vcPassword,
5[Parameter(Mandatory=$true)][string[]]$tagcategories
6)
7#$cred = Get-Credential
8#$vcenterlist = "lab-comp01-vcenter.int.sentania.net"
9#$tagcategories = "businessIntent"
10
11###CYCLE THROUGH EACH vCENTER
12foreach ($vcenter in $vcenterlist)
13{
14 $vCConn = Connect-VIServer -Server $vcenter -User $vCUsername -Password $vcPassword
15 Write-host "Processing DRS Rules via tags for: $vcenter..."
16
17 ####CYCLE THROUGH EACH TAG CATEGORY
18 foreach ($tagCategory in $tagcategories)
19 {
20 Write-host "Processing tag category: $tagcategory..."
21 $tagcategoryObj = Get-TagCategory -Name $tagCategory -server $vCConn
22 $tagcategoryObj
23
24 ####cycle through each tag in the category
25 $tags = get-tag -Category $tagcategoryObj
26 foreach ($tag in $tags)
27 {
28 Write-host "Processing tag: $tag" -ForegroundColor Yellow
29 ###cycle through each cluster for every tag
30 $clusters = get-cluster -Server $vCConn
31 foreach ($cluster in $clusters)
32 {
33 Write-host "Processing Cluster: $cluster..."
34
35
36 #get all hosts that have this tag
37 $vmhosts = $cluster | get-vmhost -Tag $tag
38 $vms = $cluster | get-vm -Tag $tag
39 $vmgroupName = "$cluster.affinitygroup.vm."+ $tag.category +"." + $tag.name
40 $hostgroupName = "$cluster.affinitygroup.host."+ $tag.category +"." + $tag.name
41 $rulename = "$cluster.affinityRule."+ $tag.category +"." + $tag.name
42 if (($vms.count -gt 0) -and ($vmhosts.count -gt 0))
43 {
44 ###add hosts to host group
45 if (($hostgroup = Get-DrsClusterGroup -name $hostgroupName -ea SilentlyContinue))
46 {
47 Write-host -ForegroundColor Green "Host Group Exists, updating if required..."
48 ###EVALUTE GROUP FOR REMOVED MEMBERS
49 $currentHostMembers = $hostgroupName.member
50 foreach ( $thishost in $currentHostMembers)
51 {
52 $hostMembersToRemove = @()
53 if ($vmhosts -notcontains $thishost)
54 {
55
56 $hostMembersToRemove += $thishost
57 }
58 }
59 if ($hostMembersToRemove.length -gt 0)
60 {
61 Write-host -ForegroundColor Red "Hosts have been removed from the group, updating...."
62 $hostGroup = Set-DrsClusterGroup -DrsClusterGroup $vmgroupName -VMHost $hostMembersToRemove -Remove
63 }
64 ###EVALUTE GROUP FOR MISSING MEMBERS
65 $currentHostMembers = $hostgroup.member
66 foreach ( $thishost in $vmhosts)
67 {
68 $hostMembersToAdd = @()
69 if ($currentHostMembers -notcontains $thishost)
70 {
71
72 $hostMembersToAdd += $thishost
73 }
74 }
75 if ($hostMembersToAdd.Length -gt 0)
76 {
77 Write-host -ForegroundColor Red "Hosts are missing from the group, updating...."
78 $hostGroup = set-DrsClusterGroup -DrsClusterGroup $hostgroup -VMHost $hostMembersToAdd -Add -Confirm:$false
79 }
80 else
81 {
82 Write-host -ForegroundColor Green "Host group membership is up to date"
83 }
84 }
85 else
86 {
87 Write-host -ForegroundColor DarkYellow "Host Group does not exist, creating..."
88 $hostGroup = New-DrsClusterGroup -Name $hostgroupName -VMHost $vmhosts -Cluster $cluster -Confirm:$false
89 }
90
91 if (($vmGroup = Get-DrsClusterGroup -name $vmgroupName -ea SilentlyContinue))
92 {
93 Write-host -ForegroundColor Green "VM Group Exists, updating if required..."
94 ####EVALUATE FOR REMOVED MEMBERS
95 $currentVMMembers = $vmGroup.member
96 foreach ( $vm in $currentVMMembers)
97 {
98 $vmMembersToRemove = @()
99 if ($vms -notcontains $vm)
100 {
101 $vmMembersToRemove += $vm
102 }
103 }
104 if ($vmMembersToRemove.Length -gt 0)
105 {
106 $vmGroup = Set-DrsClusterGroup -DrsClusterGroup $vmgroupName -vm $vmMembersToRemove -Remove -Confirm:$false
107 }
108 ####EVALUATE FOR MISSING MEMBERS
109 $currentVMMembers = $vmGroup.member
110 foreach ( $vm in $vms)
111 {
112 $vmMembersToAdd = @()
113 if ($currentVMMembers -notcontains $vm)
114 {
115 $vmMembersToAdd += $vm
116 }
117 }
118 if ($vmMembersToAdd.Length -gt 0)
119 {
120 $vmGroup = Set-DrsClusterGroup -DrsClusterGroup $vmgroupName -vm $vmMembersToRemove -Add -Confirm:$false
121 }
122 else
123 {
124 Write-host -ForegroundColor Green "VM group membership is up to date"
125 }
126
127 }
128 else
129 {
130 Write-host -ForegroundColor DarkYellow "VM Group does not exist, creating..."
131 $vmGroup = new-DrsClusterGroup -Name $vmgroupName -VM $vms -Cluster $cluster -Confirm:$false
132 }
133
134 if (($vmhostRule = Get-DrsVMHostRule -Name $rulename -Cluster $clusters -ea SilentlyContinue))
135 {
136 Write-Host -ForegroundColor DarkGray "VM Host rule exists - group updates will automatically cascade..."
137 }
138 else
139 {
140 Write-Host -ForegroundColor DarkGray "VM Host RUle does not exist, updating"
141 $vmhostrule = New-DrsVMHostRule -Name $rulename -Enabled $true -VMGroup $vmGroup -VMHostGroup $hostGroup -Cluster $cluster -Type ShouldRunOn -Confirm:$false
142 }
143 }
144 else
145 {
146 ###REMOVE GROUPS NO LONGER TAGGED
147 Write-host "REMOVING UNUSED RULE and GROUPS....."
148 if ($vmGroup = Get-DrsClusterGroup -name $vmgroupName -Cluster $cluster -ErrorAction SilentlyContinue)
149 {
150 Write-host "REMOVING RULE: $vmgroup"
151 Write-host ""
152 Remove-DrsClusterGroup -DrsClusterGroup $vmGroup -Confirm:$false
153 }
154 if ($hostGroup = Get-DrsClusterGroup -name $hostgroupName -Cluster $cluster -ErrorAction SilentlyContinue)
155 {
156 Write-host "REMOVING RULE: $hostgroup"
157 Write-host ""
158 Remove-DrsClusterGroup -DrsClusterGroup $hostgroup -Confirm:$false
159 }
160 if ($drsVMHostRule = Get-DrsVMHostRule -name $rulename -Cluster $cluster -ErrorAction SilentlyContinue)
161 {
162 Write-host "REMOVING RULE: $drsvmhostrule"
163 Write-host ""
164 Remove-DrsVMHostRule -RunAsync $drsVMHostRule -Confirm:$false
165 }
166
167 }
168 }
169 }
170 }
171
172 Disconnect-VIServer -Server $vCConn -Confirm:$false
173 }