[PSH] HA AutoSlotSize – MAJ

MAJ 21.02.2013 : Ajout de filtres pour les hosts vide afin d’éviter les divisions par 0.

MAJ 06.02.2013 : Debug des scripts.

MAJ 22.11.2012 : Nous avons oublié de préciser que pour que le script fonctionne correctement, le “statistic level” pour l’intervale de 5 minutes doit être à 2 minimum :

MAJ 23.10.2012 : Ajout d’un filtre dans les scripts pour ne modifier le(s) cluster que si nécéssaire.

Suite au post de Frank “distributed” Denneman traitant du sujet délicat des HA slot size “HA admission control is not a capacity management tool“, nous avons dépoussiéré une vieille idée de script de configuration automatique des “slot size” (mémoire et cpu) d’un cluster HA pour en faire un bon petit oneliner. L’idée est forcer le “slot size” à une valeur reflétant une vm moyenne du cluster afin de savoir approximativement la “place” restante dans le cluster et surtout pouvoir vraiment tirer parti de l’alarme “insufficient resources to satisfy HA failover level

Nous avons fais nos tests sur un cluster de 6 ESXi 4.1 (4×4 cores 2.3Ghz & 64Go de RAM) contenant environ 150 VM sans réservations. Par défaut, voici ce qu’HA remonte comme information dans le vCenter :

Ces informations sont totalement erronés étant donné que le cluster est presque plein (en tenant compte du N-1 pour HA) mais c’est le comportement attendu d’HA lorsque les VM n’ont pas de réservations (l’overhead est pris en compte). On notera que le nombre de vcpu correspond à la plus grosse vm.

Voici ce qu’HA remonte après avoir passé notre script :

On est nettement plus proche de la vérité. Le calcul pour le cpu est la moyenne d’utilisation journalière par vm démarrée, idem pour les vcpu mais pour la ram nous avons du faire un choix pas trop optimiste (active memory) ni trop optimiste (consumed memory). Nous avons donc choisi de prendre la valeur médiane entre active et consumed (moyene journalière). Voici le résultat sur une journée de stat sur notre cluster de test :

Idéalement, ce script est donc à lancée une fois par jour. Voici la version pour vSphere 4.x (filtré par cluster où HA est activé) :

foreach ($cluster in (get-view -viewtype ClusterComputeResource -property Host,ConfigurationEx|?{$_.ConfigurationEx.DasConfig.Enabled})) {,($cluster.host|%{get-view $_ -property runtime,vm}|?{$_.Runtime.ConnectionState -match "^connected$"}|?{($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})}|select @{n="mem";e={(($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "mem"}|?{$_.nameinfo.key -match "active$"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count/1kb}) + ($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "mem"}|?{$_.nameinfo.key -match "consumed$"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count/1kb}))/2}}, @{n="cpu";e={($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "cpu"}|?{$_.nameinfo.key -match "usagemhz"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count})}}, @{n="vcpu";e={(($_.vm|%{get-view $_ -property Runtime,Config}|?{$_.Runtime.PowerState -eq "poweredon"})|%{$_.Config.Hardware.NumCpu}|measure -average).average}}|measure -average -property mem,cpu,vcpu|%{[math]::round($_.average,0)})|%{if (($_|measure -Sum).sum -ne ($cluster.ConfigurationEx.DasConfig.Option|?{$_.key -match "das.slotCpuInMhz|das.slotMemInMB"}|measure -Sum -Property value).sum) {$cluster.ReconfigureComputeResource((New-Object VMware.Vim.ClusterConfigSpecEx -property @{dasConfig=(New-Object VMware.Vim.ClusterDasConfigInfo -property @{option=@((New-Object VMware.Vim.OptionValue -property @{key="das.vmMemoryMinMB";value=$_[0].tostring()});(New-Object VMware.Vim.OptionValue -property @{key="das.vmCpuMinMHz";value=$_[1].tostring()});(New-Object VMware.Vim.OptionValue -property @{key="das.slotMemInMB";value=$_[0].tostring()});(New-Object VMware.Vim.OptionValue -property @{key="das.slotCpuInMhz";value=$_[1].tostring()});(New-Object VMware.Vim.OptionValue -property @{key="das.SlotNumVCpus";value=$_[2].tostring()}))})}),$true)}}}

Pour vSphere 5.0, le nombre de vcpu ne rentre plus en comptre pour le calcul du slot size, nous avons donc adapté le script en conséquence :

foreach ($cluster in (get-view -viewtype ClusterComputeResource -property Host,ConfigurationEx|?{$_.ConfigurationEx.DasConfig.Enabled})) {,($cluster.host|%{get-view $_ -property runtime,vm}|?{$_.Runtime.ConnectionState -match "^connected$"}|?{($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})}|select @{n="mem";e={(($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "mem"}|?{$_.nameinfo.key -match "active$"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count/1kb}) + ($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "mem"}|?{$_.nameinfo.key -match "consumed$"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count/1kb}))/2}}, @{n="cpu";e={($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "cpu"}|?{$_.nameinfo.key -match "usagemhz"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count})}}|measure -average -property mem,cpu|%{[math]::round($_.average,0)})|%{if (($_|measure -Sum).sum -ne ($cluster.ConfigurationEx.DasConfig.Option|?{$_.key -match "das.slotCpuInMhz|das.slotMemInMB"}|measure -Sum -Property value).sum) {$cluster.ReconfigureComputeResource((New-Object VMware.Vim.ClusterConfigSpecEx -property @{dasConfig=(New-Object VMware.Vim.ClusterDasConfigInfo -property @{option=@((New-Object VMware.Vim.OptionValue -property @{key="das.vmMemoryMinMB";value=$_[0].tostring()});(New-Object VMware.Vim.OptionValue -property @{key="das.vmCpuMinMHz";value=$_[1].tostring()});(New-Object VMware.Vim.OptionValue -property @{key="das.slotMemInMB";value=$_[0].tostring()});(New-Object VMware.Vim.OptionValue -property @{key="das.slotCpuInMhz";value=$_[1].tostring()}))})}),$true)}}}

As of vSphere API 5.0, the number of vcpus is no longer used for slot calculations

Pour vSphere 5.1, le slot size est maintenant configurable dans via la GUI du web client (et donc de nouvelles propriétés sont disponibles) mais on va le faire en PowerCLI quand même :)

foreach ($cluster in (get-view -viewtype ClusterComputeResource -property Host,ConfigurationEx|?{$_.ConfigurationEx.DasConfig.Enabled})) {,($cluster.host|%{get-view $_ -property runtime,vm}|?{$_.Runtime.ConnectionState -match "^connected$"}|?{($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})}|select @{n="mem";e={(($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "mem"}|?{$_.nameinfo.key -match "active$"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count/1kb}) + ($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "mem"}|?{$_.nameinfo.key -match "consumed$"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count/1kb}))/2}}, @{n="cpu";e={($_|%{((get-view (Get-View ServiceInstance).content.PerfManager).QueryPerf((New-Object VMware.Vim.PerfQuerySpec -property @{entity = $_.moref;format = "normal";IntervalId = "300";MetricId = (New-Object VMware.Vim.PerfMetricId -property @{instance = "";counterId = (((Get-View (Get-View ServiceINstance).Content.PerfManager).PerfCounter|?{$_.groupinfo.key -match "cpu"}|?{$_.nameinfo.key -match "usagemhz"}|?{$_.RollupType -match "average"}).key)})}))|%{$_.value}|%{$_.value}|measure -Average).average/(($_.vm|%{get-view $_ -property Runtime}|?{$_.Runtime.PowerState -eq "poweredon"})|measure).count})}}|measure -average -property mem,cpu|%{[math]::round($_.average,0)})|%{if (($_|measure -Sum).sum -ne (@($cluster.ConfigurationEx.DasConfig.AdmissionControlPolicy.SlotPolicy.Memory, $cluster.ConfigurationEx.DasConfig.AdmissionControlPolicy.SlotPolicy.Cpu)|measure -Sum).sum) {$cluster.ReconfigureComputeResource((New-Object VMware.Vim.ClusterConfigSpecEx -property @{dasConfig=((New-Object VMware.Vim.ClusterDasConfigInfo -property @{admissionControlPolicy=((New-Object VMware.Vim.ClusterFailoverLevelAdmissionControlPolicy -property @{slotPolicy=(New-Object VMware.Vim.ClusterFixedSizeSlotPolicy -property @{cpu = $_[1];memory = $_[0]});FailoverLevel = $cluster.ConfigurationEx.DasConfig.AdmissionControlPolicy.FailoverLevel}))}))}),$true)}}}

Ceux qui ont l’oeil auront certainement remarqué l’usage d’une “multidimensional array” (aka nested array) dans nos oneliner pour faire passer des tableaux au travers d’un pipe sans en changer le type.

Pour plus d’information sur HA, nous vous conseillons vivement la lecture de la série “Clustering Deepdive” de Duncan et Frank.

Tags: , , , ,

3 Responses to “[PSH] HA AutoSlotSize – MAJ”

  1. MrPochpoch Says:
    October 26th, 2012 at 10:12

    C’est Retour vers le futur ta date de MAJ … ;-)

  2. En effet, thx ;)
    Et sinon t’as testé le script ?

  3. [...] plusieurs mois maintenant, nous utilisons notre script HA AutoSlotSize sur un environnement composé de plusieurs gros cluster comme celui-ci [...]

Leave a Reply