Mes R.Pools sont-ils bien configurés ?

Pour rappel, les Resource Pools permettent de donner des priorités CPU et MEM en cas de contention sur les serveurs hôtes (via l’unité Shares) ainsi que de déterminer la réservation et/ou limite pour les VMs qui seront dans ce R.Pool.

De base, les Resource Pool ont des paramétrages par défauts, à savoir Low, Normal et High avec un ratio entre ces paramétrages de 1:2:4

La configuration de base d’un Resource Pool en configuration Normal correspond à une machine avec 4 vCPU et 16 Go de RAM. Par défaut, les Shares associés à ces paramétrages sont donc :

  • Low, CPU=2000, MEM=81920
  • Normal, CPU=4000, MEM=163840
  • High, CPU=8000, MEM=327680

Le problème de se baser uniquement sur ces paramétrages est que cela ne prend pas en compte le nombre/puissance des VMs (la variable la plus fine de calcul étant la somme de la puissance des VMs).

Duncan Epping a fait de très bons articles sur ce sujet en mettant le doigt sur le problème de ne se baser que sur les paramétrages par défauts sans tenir compte de la variable nombre/puissance des VMs : The Resource Pool Priority-Pie Paradox

Pour faire simple, si on prend un exemple avec 2 Resource Pool, un de Production avec un paramétrage en High hébergeant 100 VMs, et un autre Resource Pool Qualification avec un paramétrage en Low hébergeant 10 VMs, chaque VM de production aura (8000/100)=80 Shares CPU alors que chaque machines de qualification aura (2000/10)=200 Shares CPU.

On tombera donc dans un cas où les machines de qualification auront plus de priorités que les machines de production… beau paradoxe ….

On voit bien dans ce cas, que la variable nombre/puissance des VMs est à prendre en compte sérieusement.

Ce qu’il vous faut vérifier si vous utiliser les paramétrages par défauts des Resource Pool va être le ratio du nombre de VMs entre vos R.Pool, afin de vous assurer qu’il ne dépasse pas le ratio des paramétrages (1:2:4). Avec l’exemple ci-dessus (Prod en High et Qualif en Low) si vous avez plus de 4 fois de VMs en production que de VMs en qualification, vous aurez des problèmes lors de contention.

Pour vérifier si vous allez avoir des problèmes de contentions de type Qualif>Prod, nous avons fais un script PowerCLI qui va afficher le paramétrage des Resource Pool de votre vCenter et le paramétrage qu’il devrait y avoir (en respectant le ratio 1:2:4)

Sur la capture d’écran, la partie 1 affiche la configuration réelle de vos cluster (quantité de vCPU et mémoire totales consommées par vos VMs)

Sur la capture d’écran, la partie 2 affiche la configuration des Resource Pool, configuration souhaitée par rapport à la configuration de vos VMs

Function Check-RPool {
<#
.SYNOPSIS
	Check shares for resource pool
.DESCRIPTION
	Calculate "supposed to be" shares on
	a Production/Qualif Resource Pool
	environnement with High/Low type shares
.NOTES
	Authors:	www.cloudydude.fr
.PARAMETER ESXClus
	Name of Cluster to check.
	If null, all clusters are checked
.EXAMPLE
	PS> Check-RPool -ESXClus "ESXClus01"
	PS> Check-RPool
#>

	PARAM(
		[Parameter(Mandatory=$false,HelpMessage="Nom du Cluster ?")] [string[]] $ESXClus
	)

	BEGIN{
		# Pour eviter les retour en warning/error
		$ErrorActionPreference = "SilentlyContinue"
		$WarningPreference = "SilentlyContinue"

		If ((Get-PSSnapin -Name "VMware.VimAutomation.Core" -ErrorAction SilentlyContinue | Measure-Object).count -eq 0) {
			Add-PSSnapin -Name "VMware.VimAutomation.Core"
		}
	}

	PROCESS{
		###
		# Based on the script found on http://www.yellow-bricks.com/2010/02/24/custom-shares-on-a-resource-pools-scripted/
		###
		# Verification des arguments pour la recuperation de la liste de cluster
		if ($ESXClus -ne $null) {
			$ClustersESX = Get-Cluster -Name $ESXClus
			if ($ClusterESX.count -eq 0) {
				Write-Host -ForegroundColor Red "Cluster" $ESXClus "non présent, vérifiez l'orthographe"
				Break
			}
		} else {
			$ClustersESX = Get-Cluster
			if ($ClusterESX.count -eq 0) {
				Write-Host -ForegroundColor Red "Aucun cluster présent"
				Break
			}
		}
		$results = @()
		$compteur = 0 # Variable pour le Write-Progress

		# Parcours du/des cluster(s)
		Foreach ($Cluster in $ClustersESX) {
			$CPUSharesProd = 80 # Production = 80%
			$CPUSharesQualif = 20 # Qualifition = 20%
			$MemSharesProd = 80 # Production = 80%
			$MemSharesQualif = 20 # Qualifition = 20%
			$CPUSharesUpLimit = 8000 # Limite haute de shares CPU = High
			$MEMSharesUpLimit = 327680 # Limite haute de shares MEM = High
			$MinCPUShares = 100 # Limite basse de shares CPU
			$MinMemShares = 100 # Limite basse de shares MEM

			Write-Progress -Activity "Parcours des clusters ESX" -Status "%Effectué:" -PercentComplete (($compteur/$ClustersESX.length)*100)

			# Nomenclature fixe des Resource Pool
			$RP_Prod = "RP_"+$Cluster.Name+"_Prod"
			$RP_Qualif = "RP_"+$Cluster.Name+"_Qualif"

			# Reinitialisation des compteurs
			$NumvCPUsProd = 0
			$NumvCPUsQualif = 0
			$TotalMemoryProd = 0
			$TotalMemoryQualif = 0

			# Parcours du Resource Pool de Production
			$pool = Get-ResourcePool -Name $RP_Prod -location $Cluster.Name
			Foreach ($VM in ($pool |Get-VM | where {$_.PowerState -eq "PoweredOn"})) { # On ne prend que les VM allumées
				$NumvCPUsProd += ($VM).NumCpu
				$TotalMemoryProd += ($VM).MemoryMB
			}

			# Parcours du Resource Pool de Qualification
			$pool = Get-ResourcePool -Name $RP_Qualif -location $Cluster.Name
			Foreach ($VM in ($pool |Get-VM | where {$_.PowerState -eq "PoweredOn"})) { # On ne prend que les VM allumées
				$NumvCPUsQualif += ($VM).NumCpu
				$TotalMemoryQualif += ($VM).MemoryMB
			}

			# Debut de construction de la ligne de resultat
			$lineRes = "" | Select Cluster, vCPUsProd, vCPUQualif, MEMProd, MEMQualif, ProdCPU, ProdMEM, QualifCPU, QualifMEM
			$lineRes.Cluster = $Cluster.Name
			$lineRes.vCPUsProd = $NumvCPUsProd
			$lineRes.MEMProd = $TotalMemoryProd
			$lineRes.vCPUQualif = $NumvCPUsQualif
			$lineRes.MEMQualif = $TotalMemoryQualif

			# Calculs des shares en prennant compte du ratio Production/Qualification
			$MemSharesProd = $MemSharesProd * $TotalMemoryProd
			$MemSharesQualif = $MemSharesQualif * $TotalMemoryQualif
			$CPUSharesProd = $CPUSharesProd * $NumvCPUsProd
			$CPUSharesQualif = $CPUSharesQualif * $NumvCPUsQualif

			# Recuperation du maximum de shares entre Production/Qualification
			$MaxMemShares = If ($MemSharesProd -gt $MemSharesQualif) {$MemSharesProd} else {$MemSharesQualif}
			$MaxCPUShares = If ($CPUSharesProd -gt $CPUSharesQualif) {$CPUSharesProd} else {$CPUSharesQualif}

			if ($MaxCPUShares -gt 0) {
				# On souhaite utiliser la valeur max donnée en paramètre, on se base donc sur un coefficient
				$CPUShareMultiplier = $CPUSharesUpLimit / $MaxCPUShares
				# On utilise ce coefficient pour calculer les shares définitifs
				$CPUSharesProd = $CPUSharesProd * $CPUShareMultiplier
				$CPUSharesQualif = $CPUSharesQualif * $CPUShareMultiplier
			}

			# On utilise la valeur minimale si besoin
			if ($CPUSharesProd -lt $MinCPUShares) {$CPUSharesProd = $MinCPUShares}
			if ($CPUSharesQualif -lt $MinCPUShares) {$CPUSharesQualif = $MinCPUShares}

			# Construction de la ligne de resultat
			$lineRes.ProdCPU = [System.Math]::Round($CPUSharesProd,0)
			$lineRes.QualifCPU = [System.Math]::Round($CPUSharesQualif,0)

			if ($MaxMemShares -gt 0) {
				# On souhaite utiliser la valeur max donnée en paramètre, on se base donc sur un coefficient
				$MemShareMultiplier = $MEMSharesUpLimit / $MaxMemShares
				# On utilise ce coefficient pour calculer les shares définitifs
				$MemSharesProd = $MemSharesProd * $MemShareMultiplier
				$MemSharesQualif = $MemSharesQualif * $MemShareMultiplier
			}

			# On utilise la valeur minimale si besoin
			if ($MemSharesProd -lt $MinMemShares) {$MemSharesProd = $MinMemShares}
			if ($MemSharesQualif -lt $MinMemShares) {$MemSharesQualif = $MinMemShares}

			# Construction de la ligne de resultat
			$lineRes.ProdMEM = [System.Math]::Round($MemSharesProd,0)
			$lineRes.QualifMEM = [System.Math]::Round($MemSharesQualif,0)

			# Ajout de la ligne de resultat dans le tableau global
			$results += $lineRes
			$compteur += 1
		}

		# Affichage des résultats
		# Pour plus de lisibilité, passer par un
		# Check-RPool | Format-Table -AutoSize
		$results
	}
}

8 comments

  1. Pingback: Reconfiguration des R.Pools | Cloudy Dude

    • Bonjour,

      Le script est une fonction, pour que cela fonctionne, vous êtes censé sourcer le fichier .ps1 (via la commande . ./script.ps1) et ensuite utiliser la fonction Check-RPool

  2. Bonjour,
    J’ai bien appeler la appeler la fonction
    Import-module .\script.ps1
    puis j’ai lancé la fonction
    Check-RPool -ESXClus « nom_de_mon_cluster »
    Et j’obtiens le résultat :
    Cluster :
    vCPUsProd : 0
    vCPUQualif : 0
    MEMProd : 0
    MEMQualif : 0
    ProdCPU : 100
    ProdMEM : 100
    QualifCPU : 100
    QualifMEM : 100

    Je ne sais pas comment faire fonctionner la fonction ….?

    • Ce script est basé sur une configuration avec 2 ressources pool, « Prod » et « Qualif », et donc si vous n’êtes pas dans cette situation cela ne peut pas fonctionner.

        • En l’état, si vous n’avez pas une structure avec uniquement 2 ressource pool, ça va être trop compliqué de changer le script.
          Je vais faire une mise à jour du script pour prendre en compte n’importe quel structure de ressource pool.
          Si vous voulez, on peut voir cela directement par mail, ce sera surement plus simple que par commentaires interposés 😉
          (Envoyez moi un mail sur frederic |at| martin.lc et je regarderais ça)

Laisser un commentaire

Required fields are marked *.