Proxmox 9 | Kernel 6.14 Performance Probleme Windows VM

Es ist "nur" ein IIS, aber die Applikationen die darauf laufen sind komplex. Dauert mal eben einen Tag das neu aufzusetzen. Optimistisch gerechnet.
Und auf dem anderen Node läuft es ja aktuell. Ein und dieselbe Maschine, ich habe sie vorhin testweise einmal umgezogen, Proxmox 8.4 mit Kernel 5.15.116.
 
Die CPU des Hosts ist ja nur eine 12Core CPU und du hast 24 Cores der VM zugewiesen.
Was passiert denn, wenn du der VM nur 12 Cores gibst?
Lastet die VM denn die CPU so sehr aus, dass die tatsächlich 24 Cores benötigt?

Ich weiß, dass der CPU Scheduler von KVM beim 6er Kernel etwas überarbeitet wurde, was da geändert wurde, weiß ich nicht, aber das wäre so mein Ansatz, das weiter einzugrenzen.
 
Die Host CPU hat 24 vCores, (12 physische Cores, klar), aktuell habe ich also 48 vCores.
Ich hatte die Maschine auch schon auf 10 vCores reduziert von einem Socket.
Und aktuell läuft die Maschine auch mit 20 vCores auf einem Socket.

Und ja: die VM lastet die CPUs entsprechend aus, 40-60% CPU-Last ist normal. Das haben andere Webserver mit den gleichen Aufgaben in dem Konstrukt auch. Es liegt ja generell nicht an der einen VM, die läuft Ansich prima. Das Problem entsteht, wenn eine bestimmte Art von Workload auf die Kombination mit dem Kernel trifft.
 
Ab Kernel 6.14 wurde der Intel-Scheduler umgebaut (wie @Falk R. schon erwähnte). Bei Dual Xeon führt das zu:
  • Falscher Zuordnung von Threads zu L3-Domains
  • Häufiger Migration zwischen NUMA-Nodes
  • Unnötig viele „wakeups“ auf entfernten Nodes
  • Memory Access über QPI/UPI
Der Kernel macht dann falsches NUMA-Balancing, sobald der Workload viel L3 + viel Websocket/HTTP/Worker-wechselseitigen Traffic erzeugt, was bei Deinem IIS dann der Fall ist. Dieser nutzt Web Core Thread Pools, Request Queues, HTTP.sys Kernel Mode Driver & Worker Processes, welche alle sehr NUMA-"sensitiv" sind. Ebenso abähngig von der L3-Cache-Lokalisierung und zudem anfällig, wenn Threads auf andere NUMA-Nodes migrieren. Wenn der 6.14er falsche balanced, dann führt das zu hoher CPU-Auslastung, vielen L3-Misses, Latenzproblemen, Einbrüche beim Web-Traffic und instabiler Performance. IIS nutzt zudem den "NUMA Node Affinity"-Mechanismus (siehe MS-Link HIER), was normalerweise dafür sorgt, dass jeder Worker-Prozess an einen NUMA-Node gebunden wird und die Verarbeitung der Requests lokal bleibt. Innerhalb der VM funktioniert das nur dann korrekt, wenn der Hypervisor die NUMA-Topo sauber "präsentiert", was wiederum beim 6.14er genau das Gegenteil ist. Dann "denkt" der IIS: "Ich habe 2 NUMA-Nodes!", aber die Zugriffe sind nicht lokal.

Ob NUMA wirklich sauber präsentiert wird, kannst Du mit

Code:
Get-WmiObject Win32_NumaNode

abfragen. Der korrekte Output müsste so aussehen:

Code:
NodeID  MemoryBlockSize  AvailableMemory
------  ----------------  ---------------
0       0                XXXXXXXX
1       0                XXXXXXXX

Bei Dir aber wahrscheinlich so:

Code:
NodeID  MemoryBlockSize  AvailableMemory
------  ----------------  ---------------
0       0                XXXXXXXX
1       0                0

Oder aber auch mehr Nodes, als die VM eigentlich haben dürfte.

Wenn bspw. dieser Befel

Code:
wmic cpu get NumberOfCores, NumberOfLogicalProcessors, DeviceID, NodeNumber

sowas ausgibt:

Code:
DeviceID  NodeNumber  NumberOfCores  NumberOfLogicalProcessors
--------  ----------  -------------  --------------------------
CPU0      0           12             12
CPU1      0           12             12
CPU2      1           0              0
CPU3      1           0              0

ist es offensichtlich. Dann hat NODE1 gar keine CPUs, aber Windows "denkt", sie seien vorhanden.

Ohne WMIC kannst Du das auch mit PS prüfen:

Code:
Write-Host "=== NUMA Topology Diagnosis ===" -ForegroundColor Cyan

# CPU-Infos abrufen
$cpus = Get-WmiObject Win32_Processor | Select-Object DeviceID, NumberOfCores, NumberOfLogicalProcessors, NodeNumber
$numaNodes = Get-WmiObject Win32_NumaNode | Select-Object NodeID, AvailableMemory

Write-Host "`nDetected NUMA Nodes:`n"
$numaNodes | Format-Table

Write-Host "`nDetected CPUs:`n"
$cpus | Format-Table

$errors = @()

# 1. Prüfen: Gibt es mehr als 2 NUMA Nodes?
if ($numaNodes.Count -gt 2) {
    $errors += "Mehr als 2 NUMA-Nodes gefunden – VM-Topologie inkonsistent."
}

# 2. Prüfen: Haben alle Nodes Speicher?
foreach ($node in $numaNodes) {
    if ($node.AvailableMemory -eq 0) {
        $errors += "NUMA Node $($node.NodeID) hat 0 Bytes RAM – fehlerhafte Topologie."
    }
}

# 3. Prüfen: Haben alle Nodes CPUs zugeordnet?
$nodesWithCpus = $cpus | Group-Object NodeNumber | ForEach-Object { $_.Name }
foreach ($node in $numaNodes) {
    if (-not ($nodesWithCpus -contains $node.NodeID)) {
        $errors += "NUMA Node $($node.NodeID) hat keine CPUs – inkonsistent."
    }
}

# 4. Prüfen: Gibt es CPUs, die keinem NUMA-Node zugeordnet sind?
foreach ($cpu in $cpus) {
    if ($cpu.NodeNumber -lt 0 -or $cpu.NodeNumber -ge $numaNodes.Count) {
        $errors += "CPU $($cpu.DeviceID) hat ungültigen NodeNumber-Wert: $($cpu.NodeNumber)."
    }
}

# Ergebnis ausgeben
Write-Host "`n=== Ergebnis ===" -ForegroundColor Cyan
if ($errors.Count -eq 0) {
    Write-Host "NUMA-Topologie ist sauber und konsistent." -ForegroundColor Green
} else {
    Write-Host "FEHLER GEFUNDEN:" -ForegroundColor Red
    $errors | ForEach-Object { Write-Host "- $_" -ForegroundColor Red }
}

Write-Host "`nAnalyse abgeschlossen."

Workarounds für den 6.14 er wären jetzt:

  1. VM auf EINEN Socket setzen (dafür mit allen gewünschten vCores)
  2. Numa: 0 - deaktiviert NUMA in der VM
  3. Die CPU Affinity exakt deklarieren:


  4. Code:
    numa: 1
    sockets: 2
    cores: X
    numa0: cpus=0-11,mem=0
    numa1: cpus=12-23,mem=1
 
Last edited: