preloader
5 January 2011 / #Powercli

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)

CheckRPool01

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
    }
}

> Frederic MARTIN