SCOM, gruppi di risorse e performance

I gruppi in System Center Operations Manager sono uno strumento di configurazione dell’ambiente indispensabile, aiutano nel targeting degli override, nella creazione di viste e dashboard. Possono però diventare un’arma a doppio taglio se non si seguono alcune regole fondamentali che evitano che il calcolo della membership possa avere un impatto sul corretto funzionamento del sistema di monitor.

La community ha già scritto in merito al tuning necessario e ai pericoli relativi a gruppi mal progettati:

Se si leggono questi articoli senza entrare nello specifico e nelle intenzioni degli autori, si potrebbe giungere alla conclusione che i gruppi in SCOM sono una causa di cattive performance e che utilizzare regular expression nei gruppi sia da evitarsi come la morte. Nulla di più sbagliato. I gruppi in SCOM sono uno strumento indispensabile, le regular expression non possono essere evitate in quanto qualsiasi confronto tra stringhe che non sia un’uguaglianza viene tradotta dall’SDK di SCOM con una regular expression e perchè i gruppi diventino davvero un problema di performance, bisogna progettarli in modo davvero sbagliato.

Voglio dunque condividere una serie di punti guida “no nonsense” sui gruppi in SCOM:

  • Utilizzare sempre classi il più specifiche possibili come base per le condizioni (ad esempio mai usare System.Entity; se si vuole individuare i computer con SQL Server con alcune caratteristiche, meglio usare Microsoft.SQLServer.DBEngine che Microsoft.Windows.Computer)
  • In caso di relazioni (not)contains/contained, meglio realizzare la query direttamente in un management pack indicando un maxDepth di 1.

<Expression>

<Contains maxDepth=”1″>

<MonitoringClass>$MPElement[Name=”*****”]$</MonitoringClass>

</Contains>

</Expression>

  • Evitare gruppi con “molte” migliaia di membri, in quel caso valutare se definire una classe popolata tramite discovery sui singoli agenti target.

Come anticipato, le regular expression sono difficilmente evitabili, in quanto ogni condizione che non sia di uguaglianza viene tradotta con una regex. Il punto sulle  regular expression è che vengono calcolate per ogni riga ritornata per la classe oggetto della condizione. Si capisce immediatamente che occorra:

  • Usare classi il più selettive possibili, applicare una semplice regular expression a 5.000 entità non è tipicamente un problema, applicarla a 100.000 potrebbe diventarlo
  • Evitare il più possibile regular expression “complicate” per il potenziale impatto di CPU che possono avere

Seguendo le indicazioni di cui sopra dovreste essere in grado di creare gruppi con un impatto trascurabile sulla vostra infrastruttura SCOM. E’ anche vero che non esiste una regola generale che possa stabilire a priori se un gruppo possa o non possa avere un impatto sull’infrastruttura SCOM, i fattori in gioco sono troppi.

Se si ha questo dubbio l’approccio più diretto è misurarne l’impatto tracciandone il tempo di esecuzione.

Per fare questo occorre:

  • Abilitare sul management server che calcolerà la membership del gruppo il trace di “Health Service Core” a livello “Information” (è possibile farlo TraceConfig.exe presente sui management server nella cartella Tools)
  • Attendere l’evento 31410 che indica il ricalcolo del gruppo in questione
  • Fermare il tracing e cercare il guid del gruppo fino a trovare delle entry come quelle riportate di seguito per il gruppo con guid “b8450ef4-9a0d-df63-0e76-53eeea46e4c0”. Il guid del gruppo può essere trovato tramite powershell o nei parametri dell’evento 31410l

[3]2052.11188::10/02/2017-17:15:24.404 [ConfigurationManager] [] [Information] :CMEGroupManager::PrepareComponentsWorkflows{megroupmanager_cpp1450}ConfigManager starts processing entity instance: ‘a8450ef4-9a0d-df63-0e76-53eeea46e4c0’

[3]2052.11188::10/02/2017-17:15:24.405 [ConfigurationManager] [] [Information] :CMEGroupManager::PrepareComponentsWorkflows{megroupmanager_cpp1552}ConfigManager sucessfully processed entity instance: ‘a8450ef4-9a0d-df63-0e76-53eeea46e4c0’

Confrontando i tempi di inizio e fine è possibile individuare il tempo di ricalcolo (nel caso in esempio 1 msec)

Nel caso di più management server nel ”All Management Server Pool”, occorrerà prima individuare quale è il Management Server incaricato del calcolo, questo può essere fatto individuando su quale server viene generato l’evento 31410 per il gruppo specifico (nell’evento viene riportato il “system name” del gruppo)

Gli eventi relativi al calcolo dei gruppi possono essere individuati nel range 31400-31500. In particolare l’evento di inizio calcolo è il 31410. Nel caso si utilizzi OMS Log Analytics per tenere sotto monitor la propria infrastruttura SCOM, questi eventi possono essere estratti con la seguente query:

Event
| where EventLog == "Operations Manager" and Source == "Health Service Modules" and EventID > 31400 and EventID < 31500

Se si volgiono estrarre i tempi di calcolo di tutti i gruppi, una volta che si ha a disposizione il log del management server è possile eseguire poche righe di powershell come ad esempio le seguenti:

param(

[string]$fileName

)

$groups=@{}

$log = Get-Content $fileName

foreach($l in $log) {

if($l-match'::(.*?) \[ConfigurationManager\] .*ConfigManager starts processing entity instance: ''(.*?)''$') {

if(!$groups.ContainsKey($matches[2])) {$groups.Add($matches[2],@())}

$values=$groups[$matches[2]]

$values+=@{start=$matches[1]}

$groups[$matches[2]]=$values

}

if($l-match'::(.*?) \[ConfigurationManager\] .*ConfigManager sucessfully processed entity instance: ''(.*?)''$') {

if(!$groups.ContainsKey($matches[2])) {write-warning('Incomplete log for {0}'-f$l);continue}

$values=$groups[$matches[2]]

$values[$values.Length-1].Add('end',$matches[1])

$groups[$matches[2]]=$values

}

}

foreach($g in $groups.GetEnumerator()) {

$elapsed=@()

foreach($cin$g.Value) {

$t1=[datetime]($c.Start-split'-')[1]

$t2=[datetime]($c.End-split'-')[1]

$elapsed+=($t2-$t1).TotalSeconds

}

write-host('{0} calculated {1} times avg {2} seconds'-f$g.Key,$g.Value.Length,($elapsed|Measure-Object-Average).Average)

}