jeudi 6 mars 2014

VMWare/Powershell - Tirer des rapports de l'utilisation CPU/RAM/Disk/Network d'une machine virtuelle minute par minute et sans agrégation d'unité de temps

Bonjour à tous,

L'objectif de départ est de réaliser des mesures de l'activité de machines virtuelles hébergées sur une infrastructure à base d’hyperviseur ESXi à intervalle de temps d'une minute sur une période de 24h.

Le problème principal est que notre outil habituel de mesure, Veeam One, applique une agrégation des unités de temps pour maîtriser l'espace que sa base de données prend sur le disque ainsi que pour accélérer la génération des rapports et graphiques.

En effet, Veeam, malgré la configuration réalisée au niveau de l'hyperviseur VMWare même, applique ces règles :
  • Raw data (data with 20-second resolution) is stored for 1 hour.
  • After 1 hour, raw data is aggregated to 5-minute resolution data.
  • After 1 week, data with 5-minute resolution is aggregated to 2-hour resolution data. Data with this level of detail is stored in the database for up to 1 year.

Nous avons donc ouvert un ticket chez Veeam afin de déterminer avec eux s'il existait une possibilité de modifier ce comportement et de répondre, ainsi, à notre besoin. Voici le point central de leur réponse :
  • Veeam One Reporter is not able to send out reports with the discression of 1 minute
  • Veeam One Monitor does not send out reports

Bad news :-(

Let's go to script ^^

La première étape, si ce n'est déjà fait, est de télécharger VMware vSphere PowerCLI : 


Chargeons le snapin qui va nous permettre d'utiliser les cmdlets proposés par VMWare dans le cadre de tâches d'automatisation et de gestion de votre infrastructure virtualisée :
Add-PSSnapin VMware.VimAutomation.Core

Connectons-nous à notre VCenter :
Connect-VIServer –Server VotreServeurVcenter

Récupérons, par exemple les valeurs en pourcentage du CPU, minute par minute, de la journée d'hier :
$statCPU = Get-Stat -Entity $vmToQuery -Stat cpu.usage.average -Start $start -Finish $stop | where{$_.Instance -eq ""}

Vous pouvez également utiliser la version simplifiée qui fait la même chose :
$statCPU = Get-Stat -Entity $vmToQuery -CPU -Start $start -Finish $stop | where{$_.Instance -eq ""}

Nous obtenons donc un tableau comprenant toutes les valeurs du CPU en pourcentage minute par minute selon l’intervalle que vous avez défini.
Par exemple, pour la journée d’hier sur une période de 24h, voici ce que j’utilise dans le script comme valeur de début et de fin :
$start = (Get-Date -Hour 0 -Minute 0 -Second 0).AddDays(-1)
$stop = (Get-Date -Hour 23 -Minute 59 -Second 0).AddDays(-1)

L’idée est donc d’exploiter ce tableau pour générer un fichier Excel reprenant les valeurs en pourcentage ainsi que le timestamp de cette valeur. La seconde idée est de générer un graphique traçant les courbes selon ces données.

Pour réaliser des graphes, nous allons nous servir de l’excellente librairie proposée par .Net 3.5 ou supérieur : 
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms.DataVisualization")

Et on commence par créer le chart et le chartarea :
$chart = new-object System.Windows.Forms.DataVisualization.Charting.Chart
$chartarea = new-object system.windows.forms.datavisualization.charting.chartarea

On donne les dimensions voulues :
$chart.width = 1500
$chart.Height = 600
$chart.Left = 40
$chart.top = 30

Gestion du titre qui sera present sur l’image :  
$titlefont=new-object system.drawing.font("ARIAL",12,[system.drawing.fontstyle]::bold)
$title =New-Object System.Windows.Forms.DataVisualization.Charting.title
$chart.titles.add($title)
$chart.titles[0].text = "CPU/Ram - " + $vmToQuery + " (" + $reportDate + ")"
$chart.titles[0].font = $titlefont
$chart.titles[0].forecolor = "Black"
$chart.Name = $vmToQuery
$chart.BackColor = [System.Drawing.Color]::White

Pour donner de la couleur au chartarea (N’hésitez pas à regarder la liste disponible ici ;-) http://msdn.microsoft.com/fr-fr/library/system.drawing.color_properties(v=vs.90).aspx) :
$chartarea.BackColor = [System.Drawing.Color]::FloralWhite

On ajoute le chartarea au chart : 
$chart.ChartAreas.Add($chartarea)

$legend = New-Object system.Windows.Forms.DataVisualization.Charting.Legend
$chart.Legends.Add($legend)

On positionne la légende de l’axe des X de manière vertical et selon un intervalle de 15 minutes (chaque point est dessiné selon une minute, mais la légende n’indique qu’un intervalle toutes les 1( minutes, pour garantir la lisibilité) : 
$chartarea.AxisX.LabelStyle.Angle = -90
$chartarea.AxisX.Interval = 15 

Les lignes suivantes vont nous permettre de gérer le tracé de la série que nous avons, rappelez-vous, dans notre tableau :
$chart.Series.Add("CPU")
$chart.Series["CPU"].ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Line
$chart.Series["CPU"].color = "blue"

Et voici la partie du code qui va nous permettre d’exploiter tout ce que nous venons de préparer précédemment. On parcourt notre tableau, pour ajouter son contenu à un objet de type psobject (http://msdn.microsoft.com/en-us/library/system.management.automation.psobject(v=vs.85).aspx)   
Ensuite, on transforme notre timestamp en un string acceptable pour la lisibilité et la lecture et on ajoute nos points les uns après les autres grâce à la ligne $chart.Series["CPU"].Points.AddXY($dtToString, $t.Value :

 foreach($t in $statCPU) {  
    $out = new-object psobject

    $out | Add-Member noteproperty timeStampCPU $t.Timestamp
    $out | Add-Member noteproperty valueCPU $t.Value
   
    $dtToString = $t.Timestamp
    [string]$dtToString = $dtToString -f "hh:mm"

    $chart.Series["CPU"].Points.AddXY($dtToString, $t.Value)

    $result += $out   

$chartarea.AxisY.Title = $unitCPU

$filename = $logFolder + "\" + $vmToQuery + "_" + $reportDate + ".png"
$chart.SaveImage($filename, "PNG")

L’export CSV (le paramètre –append nécessite Powershell v3.0) :
$result | Export-CSV -path $logFile –append –NoTypeInformation  

J’ai consolidé les informations d’utilisation de RAM et CPU sur le même graphique afin d’obtenir finalement ceci : 


J'ai réalisé la même chose pour l'utilisation des disques et du réseau.

$statRAM = Get-Stat -Entity $vmToQuery -Stat mem.usage.average -Start $start -Finish $stop
$statNetwork = Get-Stat -Entity $vmToQuery -Network -Start $start -Finish $stop
$statDisk = Get-Stat -Entity $vmToQuery -Disk -Start $start -Finish $stop  

Et après traitement, les résultats suivants :




Bon amusement :-)

Aucun commentaire:

Enregistrer un commentaire