Sockets i Cores w Proxmox - co to naprawdę jest i jak to ustawić

Wstęp

W kreatorze “Create: Virtual Machine” w Proxmox, na zakładce CPU, wpisujesz dwie liczby: Sockets i Cores. Wyglądają jak zwykłe pola formularza, które można wypełnić dowolnie - im więcej, tym VM “mocniejsza”. To błąd, który kosztuje wydajność albo migrację, zanim VM w ogóle wystartuje. Te dwa pola nie są dowolne - są bezpośrednio związane z fizyczną topologią hosta, na którym stawiasz maszynę. Ile masz fizycznych socketów, ile rdzeni na socket, czy host w ogóle jest NUMA - to sprzęt narzuca sensowne wartości w kreatorze, a nie odwrotnie. Wpisanie czegokolwiek “na oko” bez wcześniejszego sprawdzenia lscpu na hoście to jak zamawianie liczby pokoi w hotelu, nie wiedząc ile budynek ma pięter. W tym wpisie tłumaczę, skąd biorą się sensowne wartości tych dwóch pól, jak je wyczytać z własnego sprzętu przed kliknięciem “Create”, oraz kiedy socket ma realne znaczenie (NUMA, licencjonowanie), a kiedy jest czystą kosmetyką.

Co to jest socket i core - fizycznie

Zanim przejdziemy do Proxmoxa, warto rozdzielić te pojęcia na poziomie sprzętu:

  • Socket (gniazdo) - fizyczne miejsce na płycie głównej, w które wpina się procesor. Serwer może mieć jeden socket (typowy desktop, większość homelabów) albo kilka - dwa, cztery, osiem osobnych procesorów na jednej płycie, każdy w swoim gnieździe.
  • Core (rdzeń) - fizyczna jednostka obliczeniowa wewnątrz jednego procesora. Jeden CPU może mieć kilkanaście albo kilkadziesiąt rdzeni.
  • Thread (wątek sprzętowy) - jeśli procesor ma Hyper-Threading (Intel) albo SMT (AMD), każdy fizyczny rdzeń potrafi obsłużyć dwa wątki na raz. System operacyjny widzi wtedy dwa razy więcej “logicznych CPU”, niż jest fizycznych rdzeni.

Na hoście sprawdzisz to jedną komendą:

lscpu

Interesują Cię linijki Socket(s), Core(s) per socket i Thread(s) per core. Na moim głównym hoście homelabowym (Xeon E5-2670 v3) to wygląda tak:

Socket(s):              1
Core(s) per socket:     12
Thread(s) per core:     2

Jeden fizyczny socket, 12 rdzeni, Hyper-Threading włączony - czyli 24 logiczne CPU widoczne dla systemu hosta (nproc pokaże 24). To jest cały budżet, z którego Proxmox rozdziela zasoby między VM.

Jak Proxmox to interpretuje

W konfiguracji VM Proxmox nie ma osobnego pola na thready - to ważna różnica względem np. VMware, gdzie można ręcznie ustawić “cores per socket” łącznie z logiką HT. W Proxmox liczy się tylko iloczyn:

vCPU = Sockets × Cores

Guest OS widzi tyle logicznych CPU, ile wynosi ten iloczyn - i nie ma znaczenia, czy fizyczne wątki hosta pochodzą z HT czy z osobnych rdzeni. Zobaczysz to w configu VM (/etc/pve/qemu-server/<vmid>.conf albo przez qm config <vmid>):

sockets: 1
cores: 4

Cztery vCPU, jeden wirtualny socket. Zmiana przez CLI:

qm set <vmid> --sockets 1 --cores 4

Domyślnie oba pola można zmieniać na żywo w GUI, ale realne dodanie/odjęcie vCPU do już działającej VM wymaga w guście wsparcia dla CPU hotplug (hotplug: cpu w configu) - bez tego zmiana zadziała dopiero po restarcie VM.

ℹ️
Twardy limit: sockets × cores nie może w praktyce przekroczyć liczby logicznych CPU na hoście, bo w danym momencie wszystkie vCPU VM muszą mieć gdzie się zmieścić. Proxmox pozwoli Ci wpisać więcej (overcommit jest legalny, tak jak z RAM-em), ale VM zacznie rywalizować o czas procesora z innymi maszynami i całościowa wydajność spadnie, zamiast wzrosnąć.

Więc po co w ogóle jest pole Sockets?

Skoro vCPU = Sockets × Cores i można to samo osiągnąć samymi Cores, po co grzebać w Sockets? Są dokładnie dwa powody, i żaden z nich nie dotyczy “surowej” wydajności w typowym jednosocketowym homelabie.

1. NUMA - żeby VM wiedziała, jak naprawdę wygląda pamięć

Na hostach z więcej niż jednym fizycznym socketem każdy CPU ma swoją “lokalną” pamięć RAM, podpiętą bezpośrednio do jego kontrolera. Dostęp do pamięci podpiętej pod swój socket jest szybki, dostęp do pamięci podpiętej pod sąsiedni socket (przez połączenie międzyprocesorowe, np. Intel UPI czy AMD Infinity Fabric) jest zauważalnie wolniejszy. To zjawisko nazywa się NUMA (Non-Uniform Memory Access), a każdy socket ze swoją pamięcią to osobny “NUMA node”. Sprawdzisz topologię hosta:

numactl --hardware

Jeśli masz jeden socket (jak ja), zobaczysz jeden node i temat się kończy - cała pamięć jest jednakowo “blisko” wszystkich rdzeni, NUMA fizycznie nie istnieje na Twoim hoście, więc nie ma czego odwzorowywać.

Na hoście z dwoma i więcej socketami sprawa jest inna. Jeśli VM-ce dasz np. 8 rdzeni jako sockets: 1, cores: 8, Proxmox domyślnie nie gwarantuje, że wszystkie 8 vCPU i cała pamięć VM wylądują fizycznie na jednym NUMA node hosta - scheduler może rozrzucić wątki między oboma socketami, a wtedy część dostępów do RAM będzie szła przez wolniejsze połączenie międzysocketowe. Żeby temu zapobiec:

  1. Włącz numa: 1 w opcjach VM (Hardware → Processor → NUMA, albo qm set <vmid> --numa 1).
  2. Ustaw Sockets na liczbę NUMA node’ów hosta (dla typowego dwusocketowego serwera: 2).
  3. Ustaw Cores na łączna liczba rdzeni VM / liczba sockets - bo Cores w Proxmox to rdzenie na jeden socket, nie łącznie.

Przykład: host z dwoma socketami (dwa NUMA node), chcesz dać VM 8 vCPU rozłożone równo po obu node’ach:

qm set <vmid> --sockets 2 --cores 4 --numa 1

Z numa: 1 Proxmox pilnuje, żeby wątki i pamięć konkretnej VM trzymały się jednego NUMA node hosta (o ile się zmieszczą), zamiast błądzić między socketami. Efekt bywa odczuwalny szczególnie przy bazach danych i innych aplikacjach wrażliwych na opóźnienia dostępu do pamięci.

⚠️
Jeśli masz wielosocketowy host, ale ustawisz VM na sockets: 1 z dużą liczbą cores, guest zobaczy fałszywy obraz - jeden “duży” socket, mimo że fizycznie jego wątki mogą być rozrzucone po całym hoście. Aplikacje robiące własną optymalizację pod NUMA (część baz danych, JVM z odpowiednimi flagami) będą podejmować złe decyzje o alokacji pamięci, bo w ogóle nie zobaczą, że powinny się tym przejmować.

2. Licencjonowanie po socketach

Część oprogramowania - najczęściej korporacyjnego - liczy licencje po fizycznych/wirtualnych socketach, a nie po rdzeniach. Klasyczny przykład to starsze modele licencjonowania Windows Server albo niektóre bazy danych, gdzie umowa licencyjna odnosi się wprost do liczby CPU (socketów), niezależnie od tego, ile mają rdzeni.

ℹ️
Uwaga na aktualne modele Microsoftu: licencje Windows Server od dłuższego czasu liczone są per rdzeń fizyczny hosta (z minimum 8 rdzeni na CPU i 16 na host), a nie per socket VM - więc to, co ustawisz w Proxmox jako sockets/cores dla samej VM, nie ma wpływu na wymaganą licencję. Licencja dotyczy fizycznego hosta, na którym VM faktycznie działa, nie konfiguracji wirtualnego CPU. Zawsze sprawdź aktualne warunki licencyjne konkretnego produktu, zanim zaplanujesz infrastrukturę pod kątem “oszczędzania” na licencjach przez zabawę z socketami.

Jeśli trafisz na oprogramowanie, które w warunkach licencji wprost wymaga np. “maksymalnie 2 sockety”, ustaw sockets: 2 i podziel potrzebną liczbę vCPU na cores - to jedyny scenariusz poza NUMA, w którym świadomie manipulujesz tym polem, a nie tylko cores.

Typ procesora ma znaczenie bardziej niż sockets/cores

Osobna, ale często mylona sprawa: pole CPU type (qm set <vmid> --cpu <typ>) w tej samej zakładce. Domyślnie Proxmox ustawia kvm64 - generyczny, maksymalnie kompatybilny zestaw instrukcji, który zadziała bez live-migration błędów na dowolnym hoście w klastrze, ale zostawia na stole realne funkcje Twojego fizycznego CPU (AES-NI, AVX2 i inne). Jeśli VM nigdy nie będzie migrowana na inny, starszy sprzęt, warto ustawić --cpu host - guest dostaje wtedy pełny, nieukryty zestaw instrukcji fizycznego procesora, co potrafi zauważalnie przyspieszyć obciążenia korzystające z tych rozszerzeń (kryptografia, kompresja, część obliczeń AI). To temat na osobny wpis, ale warto wiedzieć, że sockets/cores i CPU type to dwie zupełnie niezależne decyzje - dobre cores z domyślnym kvm64 wciąż zostawia wydajność na stole.

Jak mam to ustawione u siebie

ScenariuszSocketsCoresNUMA
Homelab, jednosocketowy host (mój przypadek)1tyle, ile potrzebuje VMWyłączone - nie ma czego mapować
Hipotetyczny host dwusocketowy, VM ma się zmieścić w jednym node1tyle, ile potrzebuje VM (≤ rdzeni jednego socketu)Włączone - i tak korzystne, bo pilnuje przypięcia do jednego node’a
Hipotetyczny host dwusocketowy, VM potrzebuje więcej vCPU niż ma jeden socket2 (= liczba node’ów)łączne vCPU / 2Włączone - obowiązkowe
Software wymagający konkretnej liczby socketów w licencjityle, ile wymaga licencjareszta potrzebnych vCPUZależnie od hosta

Na co dzień w moim homelabie temat NUMA w ogóle się nie pojawia, bo mam jeden socket - Sockets zawsze zostaje na 1, a jedyne, co realnie zmieniam między VM-kami, to Cores. Gdybym kiedyś dokładał drugi fizyczny procesor albo migrował na serwer dwusocketowy, pierwsza rzecz, którą bym zrobił, to numactl --hardware na nowym hoście i przeliczenie configów VM zgodnie z tabelą wyżej - inaczej część maszyn zacznie po cichu tracić wydajność na crossnode’owych odwołaniach do pamięci, bez żadnego komunikatu błędu, który by na to naprowadził.

Podsumowanie

Sockets i Cores w Proxmox razem dają liczbę vCPU (sockets × cores), ale to nie jest jedno pole podzielone na dwa bez powodu. Cores to Twój domyślny suwak do regulowania mocy VM - w typowym jednosocketowym homelabie to jedyne pole, które w ogóle ruszasz. Sockets zaczyna mieć znaczenie dopiero na hostach z realną topologią NUMA (wtedy w parze z numa: 1 pilnuje, żeby VM nie płaciła kary za odwołania do pamięci przez sąsiedni socket) albo gdy oprogramowanie w środku VM wprost liczy licencje po socketach. Sprawdź lscpu i numactl --hardware na swoim hoście, zanim zaczniesz kombinować z wartością Sockets większą niż 1 - jeśli wynik pokaże jeden node, cały ten wpis sprowadza się do jednego zdania: zostaw Sockets: 1 i reguluj tylko Cores.

Comments powered by Talkyard.