Hyper-V Series: Configurare il NUMA

Quando si crea un ambiente di virtualizzazione, è necessario saper configurare ogni singolo elemento nel modo più accurato a cominciare dall’utilizzo delle risorse hardware. Come dico ogni volta che parlo di questo mondo, il fatto di aver comprato un server molto potente non significa che al suo interno potrò metterci infinite macchine virtuali sperando che vadano tutte come dei missili.

Questo articolo sarà il primo di una serie, atti a spiegare il funzionamento della configurazione delle macchine virtuali basate su Microsoft Hyper-V, l’obiettivo finale è evitare errori di impostazione. Il primo articolo sarà dedicato al mondo dei processori e nello specifico al NUMA.

NUMA

Il Non-Uniform Memory Access è un’architettura presente nei computer con due o più processori che permette di gestire in modo intelligente la coppia CPU/RAM, facendo in modo che venga sfruttato lo stesso Bus, cosa che porta ad un notevole aumento delle performance.

Ogni “coppia” è definita NUMA Nodes.

Figura 1 – Architettura NUMA

In uno scenario fisico, con anche i software capaci di sfruttare queste potenzialità, viene fatto un partizionamento della RAM in base alla sua appartenenza della CPU. Ad esempio se abbiamo un server con 128GB di RAM e 2 socket, se l’applicativo utilizzerà 64GB di RAM il NUMA farà in modo di dividere l’utilizzo tra i due canali e di usare 32GB da una CPU e 32GB dall’altra CPU. Usare lo stesso canale permette uno scambio più veloce delle informazioni e quindi latenze minori.

NUMA in Hyper-V

In Hyper-V il supporto a NUMA è garantito ma anche gli applicativi devono essere capaci di sfruttare questo tipo di architettura e se la cosa è certa negli applicativi dei grossi vendor (Microsoft, Oracle, etc) non sempre si può dire lo stesso delle piccole software house.

Il funzionamento è molto semplice: quando una macchina virtuale si avvia, viene fatta l’allocazione della pRAM allo stesso canale di appartenenza della pCPU. Questo permette alla macchina virtuale di avere performance prossime ad uno scenario fisico. Tuttavia un’associazione diretta può portare a dei limiti, soprattutto quando la memoria di uno dei canali è inferiore rispetto a quanta richiesta dalla macchina virtuale.

NUMA Spanning

Proprio per far fronte a questo tipo di limite, esiste una modalità che si chiama NUMA Spanning che consente all’hypervisor di fare cross-assignment tra le varie pCPU. In uno scenario di virtualizzazione questa architettura può essere un vantaggio o uno svantaggio, ma a questo ci arriveremo dopo.

In Hyper-V, questa funzionalità è attiva di default ma è gestibile tramite le impostazioni – figura 2.

Figura 2 – Gestione NUMA Spanning

Quando una macchina virtuale viene avviata, nel caso la quantità di memoria richiesta non sia sufficiente nella prima pCPU, la richiesta viene fatta anche alla seconda pCPU e questo consente l’avvio corretto della VM.

Pro e Contro

Vediamo i vantaggi, e gli svantaggi, del NUMA Spanning attivo:

  • PRO – Utilizzo delle risorse tra i vari nodi NUMA
  • PRO – Avvio della macchina virtuale anche in caso di sovradimensionamento dei nodi NUMA
  • CON – L’avvio ed il riavvio delle VM può variare a livello di tempo
  • CON – In caso di sovradimensionamento dei nodi NUMA c’è un pesante decadimento delle performance

Di contro, questi sono i vantaggi, e gli svantaggi, del NUMA Spanning disattivato:

  • PRO – Le applicazioni NUMA Aware danno il massimo delle loro performance
  • PRO – L’avvio ed il riavvio delle VM viene fatto al massimo delle performance
  • CON – L’avvio della VM potrebbe fallire in caso di mancanza di risorse
  • CON – La migrazione della VM, su un altro nodo, potrebbe fallire in caso di mancanza di risorse
  • CON – Dynamic Memory potrebbe non essere sfruttata a pieno in caso di richiesta di maggiore vRAM

Come si può vedere, non esiste una soluzione perfetta ma sicuramente lo scenario NUMA Spanning Enabled è quello più flessibile ed adatto alla maggior parte degli scenari.

Configurazione delle Virtual Machine

Ogni macchina virtuale può essere configurata ad-hoc oppure ci si può affidare ai settaggi di base come mostra la figura 3.

Figura 3 – Configurazione Virtual NUMA

Il numero di processori e memoria è dato dal totale disponibile dall’hypervisor per ogni singolo socket. In caso di modifica manuale è sempre possibile resettare i parametri, cliccando sul pulsante Use Hardware Topology. Ovviamente questa modifica può essere fatta solo a macchina virtuale spenta.

Gestione NUMA

Per poter vedere se il vostro hypervisor supporta NUMA è sufficiente eseguire il comando Get-VMHostNumaNode – il risultato sarà simile a quello della figura 4.

Figura 4 – Nodi NUMA

Come si può notare la memoria disponibile di entrambi i nodi è di circa 10GB e la riprova di questo è nel Task Manager, figura 5, che mostra un totale di 23GB disponibili. Questo mi indica che il mio server è bilanciato.

Figura 5 – Task Manager

Un altro comando PowerShell che ci aiuta a capire il bilanciamento è Get-Counter “\Hyper-V VM VID Partition(*)\*” – figura 6.

Figura 6 – Counter NUMA

I primi tre risultati sono relativi al singolo nodo NUMA mentre gli altri riguardano le macchine virtuali. È fondamentale che il contatore Remote Physical Pages abbia un valore uguale a zero, cosa che indica un allineamento corretto da parte della macchina virtuale. Il valore Physical Pages Allocated ci aiuta a capire l’associazione di memoria tra macchina virtuale e nodo NUMA.

L’ultimo comando utile è in verità uno script che ci aiuta a capire la configurazione della macchina virtuale, con la relativa suddivisione NUMA. Lo script è reperibile all’interno di TechNet (https://technet.microsoft.com/en-us/library/dn282282(v=ws.11).aspx) a cui è utile fare una piccola modifica all’ultima riga con questo pezzo:

$vNodes | Format-Table @(“VmName”, “vNUMANode”, “VMMem”, “PhyNUMANode”, “PhyNUMANodeMemRemaining”)

Questo codice ci aiuta ad visualizzare l’array in modo più chiaro, con un risultato simile a quello della figura 7.

Figura 7 – Script Assegnazione NUMA Node

Virtual NUMA vs Dynamic Memory

La figura mostra da subito che in uno scenario di Dynamic Memory, non risulta attiva la funzione di Virtual NUMA. In questa condizione, la macchina virtuale avrà un solo Virtual NUMA assegnato.

Una macchina virtuale che richiede tanta vRAM dovrebbe essere configurata con memoria statica, questo per sfruttare al meglio ogni nodo NUMA e per non avere un decadimento di performance. Fondamentale è anche configurare la macchina virtuale per usare più nodi NUMA, in modo da dividere il carico tra i vari processori fisici dell’host di virtualizzazione.

Problemi di Performance

Se avete migrato delle macchine virtuali da un vecchio ambiente e notate un rallentamento delle performance globali, ovviamente il Perfomance Monitor del server host può darvi una serie di informazioni utili. Nel caso notiate un pesante carico sulle CPU, senza però riscontrare un reale utilizzo da parte dei server, potrebbe essere che i parametri del NUMA, relativo alle singole VM, potrebbe essere stato modificato verso l’alto. Attenzione perchè non è necessariamente vero che questo avviene a causa di una modifica manuale; personalmente ho riscontrato questo problema in fase di migrazione da Windows Server 2012 R2 a Windows Server 2016.

Conclusione

La configurazione corretta della macchina virtuale passa anche da questi piccoli dettagli che possono compromettere le performance dell’intero server di virtualizzazione. Lasciare i parametri di default è sicuramente la scelta più semplice ma nel caso dobbiate usare applicativi NUMA Aware, con specifiche hardware spinte, ora sapete come comportarvi.