build 65d0a3ad | content blog-content@c8490fa · 338 posts | profiles 20 · corpus 228 | 0 skipped |
Scripting · 2018-06-05

Admission-Control-Prozentwerte ändern

Ein Kunde wollte wissen, welche Funktionen von vSphere 6.5 für seine Umgebung interessant wären. Eine davon: die automatische Anpassung der Prozentwerte in der HA Admission Control.

2018-06-05Datum
Dario DörflingerAutor
6Min. Lesezeit
1112words
no translation reviewed
Themen capabilities · idf weight Automation automation 1.80
Hersteller vendors · idf weight VMware vmware 0.89

Dieser Beitrag ist von 2018. Er bleibt online, weil er nach wie vor nachgefragt wird, beschreibt aber einen Produktstand von damals.

Ein Kunde bat mich kürzlich, ihm ein paar Funktionen von vSphere 6.5 zu erklären, die für seine Umgebung interessant wären. Ich kannte die Umgebung und konnte einige Dinge nennen, die 6.5 besser macht als das installierte 6.0. Eine davon: die automatische Anpassung des Ressourcen-Prozentwerts in den Einstellungen der HA Admission Control.

Falls du es nicht kennst: vSphere 6.5 passt den Prozentwert selbst an, wenn du einem Cluster Hosts hinzufügst oder wegnimmst. Ein Beispiel: Du hast ein Cluster mit vier Nodes, stellst die HA Admission Control auf Cluster Resource Percentage und willst einen Host-Ausfall tolerieren. vSphere setzt die Werte auf 25 % für CPU und Memory. Fügst du jetzt einen Host hinzu, werden sie automatisch auf 20 % für Memory und CPU angepasst.

Der Kunde wollte diese Funktion, weil er oft Hosts hinzufügt und entfernt, konnte aber aus mehreren Gründen nicht auf 6.5 gehen: Hardware-Kompatibilität, Drittanbietersoftware mit vCenter-Integration und Ähnliches. Also fragte er, ob es die Funktion auch ohne Update gibt. Meine Antwort: «Mit PowerCLI geht alles.»

Kurz gesagt, hier ist das Script, das diese 6.5er Funktion nach 6.0 zurückportiert. Du musst es allerdings jedes Mal aufrufen, wenn sich die Hosts in deinen Clustern ändern, oder du lässt es zweimal täglich laufen. Nicht so elegant wie die Funktion in 6.5, aber nah dran.

Update: Dieses Script liegt inzwischen auf GitHub.

Fast vergessen: Das Script nutzt das Modul PSLogging aus der PowerShell Gallery.


#---------------------------------------------------------[Script Parameters]------------------------------------------------------

Param (
    #Script parameters go here
    [Parameter(Mandatory = $true)][string]$vCenter,
    [Parameter(Mandatory = $true)][string]$cluster,
    [Parameter(Mandatory = $true)][string]$failuresToTolerate
)

#---------------------------------------------------------[Initialisations]--------------------------------------------------------

#Set Error Action to Silently Continue
$ErrorActionPreference = 'SilentlyContinue'

#Import Modules & Snap-ins
Import-Module PSLogging

#----------------------------------------------------------[Declarations]----------------------------------------------------------

#Script Version
$sScriptVersion = '1.0'

#Log File Info
$sLogPath = 'C:\Temp'
$sLogName = 'HA_AdmissionControlLog.log'
$sLogFile = Join-Path -Path $sLogPath -ChildPath $sLogName

#-----------------------------------------------------------[Functions]------------------------------------------------------------

Function Connect-VMwareServer {
    Param ([Parameter(Mandatory = $true)][string]$VMServer)

    Begin {
        Write-LogInfo -LogPath $sLogFile -Message "Connecting to vCenter Server [$VMServer]..."
    }

    Process {
        Try {
            $oCred = Get-Credential -Message 'Enter credentials to connect to vCenter Server'
            Connect-VIServer -Server $VMServer -Credential $oCred -ErrorAction Stop
        }

        Catch {
            Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
            Break
        }
    }

    End {
        If ($?) {
            Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
            Write-LogInfo -LogPath $sLogFile -Message ' '
        }
    }
}

Function checkRAMCompliance {
    Param ([Parameter(Mandatory = $true)][string]$clusterName)
    Begin {
        Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same amount of RAM..."
        $myHostsRAM = @()
    }
    Process {
        Try {
            $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop
            $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop

            foreach ($hostObject in $hostObjects) {

                $HostInfoMEM = "" | Select-Object MEM

                $HostInfoMEM.MEM = $hostObject.MemoryTotalGB

                $myHostsRAM += $HostInfoMEM
            }
            #Check if all values are correct: return true, otherwise return false
            if (@($myHostsRAM | Select-Object -Unique).Count -eq 1) {
                #CPU are the same
                Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is the same"
                return $true
            }
            else {
                Write-LogInfo -LogPath $sLogFile -Message "RAM in the cluster is NOT the same"
                return $false
            }

        }
        Catch {
            Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
            Break
        }
    }
    End {
        If ($?) {
            Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
            Write-LogInfo -LogPath $sLogFile -Message ' '
        }
    }
}

Function checkCPUCompliance {
    Param ([Parameter(Mandatory = $true)][string]$clusterName)
    Begin {
        Write-LogInfo -LogPath $sLogFile -Message "Checking if all hosts in cluster [$clusterName] have the same CPU..."
        $myHostsCPU = @()
    }
    Process {
        Try {
            $clusterObject = Get-Cluster -Name $clusterName -ErrorAction Stop
            $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop

            foreach ($hostObject in $hostObjects) {
                $HostInfoCPU = "" | Select-Object CPU

                $HostInfoCPU.CPU = $hostObject.CpuTotalMhz

                $myHostsCPU += $HostInfoCPU
            }
            #Check if all values are correct: return true, otherwise return false

            if (@($myHostsCPU | Select-Object -Unique).Count -eq 1) {
                Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is the same"
                return $true
            }
            else {
                Write-LogInfo -LogPath $sLogFile -Message "CPU in the cluster is NOT the same"
                return $false
            }

        }
        Catch {
            Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
            Break
        }
    }
    End {
        If ($?) {
            Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
            Write-LogInfo -LogPath $sLogFile -Message ' '
        }
    }
}

Function getBiggestCPUInCluster {
    Param ([Parameter(Mandatory=$true)][string]$clusterName)
    Begin {
      Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest CPU resource in cluster [$clusterName]..."
    }
    Process {
      Try {
        $clusterObject = Get-Cluster $clusterName -ErrorAction Stop
        $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop
        $cpuResources =  @()
        foreach ($hostObject in $hostObjects) {
            $cpuInfo = "" | Select-Object CPU
            $cpuInfo.CPU = $hostObject.CpuTotalMhz

            $cpuResources += $cpuInfo
        }
        return ($cpuResources | Measure-Object -Maximum)

      }
      Catch {
        Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
        Break
      }
    }
    End {
      If ($?) {
        Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
        Write-LogInfo -LogPath $sLogFile -Message ' '
      }
    }
  }

  Function getBiggestRAMInCluster {
    Param ([Parameter(Mandatory=$true)][string]$clusterName)
    Begin {
      Write-LogInfo -LogPath $sLogFile -Message "Trying to get the biggest RAM resource in cluster [$clusterName]..."
    }
    Process {
      Try {
        $clusterObject = Get-Cluster $clusterName -ErrorAction Stop
        $hostObjects = $clusterObject | Get-VMHost -ErrorAction Stop
        $ramResources =  @()
        foreach ($hostObject in $hostObjects) {
            $ramInfo = "" | Select-Object RAM
            $ramInfo.RAM = $hostObject.MemoryTotalGB

            $ramResources += $ramInfo
        }
        return ($ramResources | Measure-Object -Maximum)

      }
      Catch {
        Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
        Break
      }
    }
    End {
      If ($?) {
        Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
        Write-LogInfo -LogPath $sLogFile -Message ' '
      }
    }
  }

Function SetAdmissionControl {
    Param ([Parameter(Mandatory = $true)][string]$clusterName)
    Begin {
        Write-LogInfo -LogPath $sLogFile -Message "Setting the admission policy on cluster [$clusterName].."
    }
    Process {
        Try {
            $RAMCompliance = checkRAMCompliance $clusterName
            $CPUCompliance = checkCPUCompliance $clusterName
            $totalAmountofHostsInCluster = (Get-Cluster -Name $clusterName -ErrorAction Stop | Get-VMHost -ErrorAction Stop).Count
            if (($RAMCompliance -eq $true) -and ($CPUCompliance -eq $true)) {
                #Same hardware. calculation very simple
                [int]$ramPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0)
                [int]$cpuPercentageToReserve = [math]::Round((100 / ($totalAmountofHostsInCluster) * ($failuresToTolerate)), 0)

            }
            if ($CPUCompliance -eq $false) {
                #calculate with different CPU resources but same RAM resources
                #get biggest CPU amount, total amount and number of hosts in cluster
                $biggestCPUValue = getBiggestCPUInCluster $clusterName
                $totalCPUMhz = (Get-Cluster $clusterName).ExtensionData.Summary.TotalCPU

                [int]$cpuPercentageToReserve = [math]::Round(((($biggestCPUValue) * 100) / ($totalCPUMhz)*($failuresToTolerate)),0)
            }
            if ($RAMCompliance -eq $false) {
                #in this case RAM is the decisive factor
                #get biggest RAM amount, total amount and number of hosts in cluster
                $biggestMemoryValue = getBiggestRAMInCluster $clusterName
                $totalMemoryGB = [math]::Round(((Get-Cluster $clusterName).ExtensionData.Summary.TotalMemory /1024 /1024 /1024),0)

                [int]$ramPercentageToReserve = [math]::Round(((($biggestMemoryValue) * 100) / ($totalMemoryGB)*($failuresToTolerate)),0)
            }

            Write-LogInfo -LogPath $sLogFile -Message "CPU Value calculated: [$cpuPercentageToReserve].."
            Write-LogInfo -LogPath $sLogFile -Message "RAM Value calculated: [$ramPercentageToReserve].."

            $spec = New-Object VMware.Vim.ClusterConfigSpecEx
            $spec.dasConfig = New-Object VMware.Vim.ClusterDasConfigInfo
            $spec.dasConfig.AdmissionControlPolicy = New-Object VMware.Vim.ClusterFailoverResourcesAdmissionControlPolicy
            $spec.dasConfig.AdmissionControlEnabled = $true
            $spec.dasConfig.AdmissionControlPolicy.cpuFailoverResourcesPercent = $cpuPercentageToReserve
            $spec.dasConfig.AdmissionControlPolicy.memoryFailoverResourcesPercent = $ramPercentageToReserve

            $clusterObject = Get-Cluster $clusterName
            $clusterView =  Get-View $clusterObject
            $clusterView.ReconfigureComputeResource_Task($spec, $true)

        }
        Catch {
            Write-LogError -LogPath $sLogFile -Message $_.Exception -ExitGracefully
            Break
        }
    }
    End {
        If ($?) {
            Write-LogInfo -LogPath $sLogFile -Message 'Completed Successfully.'
            Write-LogInfo -LogPath $sLogFile -Message ' '
        }
    }
}

#-----------------------------------------------------------[Execution]------------------------------------------------------------

Start-Log -LogPath $sLogPath -LogName $sLogName -ScriptVersion $sScriptVersion
Connect-VMwareServer -VMServer $vCenter
SetAdmissionControl -clusterName $cluster
Stop-Log -LogPath $sLogFile

Passt ausserdem