![QEMU Tips- NIC에 NUMA 할당하기](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlMbK0%2FbtsHO5e5PMv%2FG4sFoaZmw7aG1lfKkoakW1%2Fimg.png)
VM을 가장 간단한 방법으로 생성해서 실행하면 QEMU는 기본적으로 NUMA를 할당 하지 않습니다.
기존에 생성된 PCIe 정보들 확인
처음 xml 파일
<domain type="kvm">
<name>ubuntu22.04-2</name>
<uuid>0cdefc01-40ed-42a1-84d1-e2c7aa398110</uuid>
<metadata>
<libosinfo:libosinfo xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0">
<libosinfo:os id="http://ubuntu.com/ubuntu/22.04"/>
</libosinfo:libosinfo>
</metadata>
<memory unit="KiB">4194304</memory>
<currentMemory unit="KiB">4194304</currentMemory>
<vcpu placement="static">4</vcpu>
<os firmware="efi">
<type arch="x86_64" machine="pc-q35-6.2">hvm</type>
<firmware>
<feature enabled="yes" name="enrolled-keys"/>
<feature enabled="yes" name="secure-boot"/>
</firmware>
<loader readonly="yes" secure="yes" type="pflash">/usr/share/OVMF/OVMF_CODE_4M.ms.fd</loader>
<nvram template="/usr/share/OVMF/OVMF_VARS_4M.ms.fd">/var/lib/libvirt/qemu/nvram/ubuntu22.04-2_VARS.fd</nvram>
<boot dev="hd"/>
</os>
<features>
<acpi/>
<apic/>
<vmport state="off"/>
<smm state="on"/>
</features>
<cpu mode="custom" match="exact" check="partial">
<model fallback="allow">EPYC-Rome</model>
<numa>
<cell id="0" cpus="0-1" memory="2097152" unit="KiB"/>
<cell id="1" cpus="2-3" memory="2097152" unit="KiB"/>
</numa>
</cpu>
<clock offset="utc">
<timer name="rtc" tickpolicy="catchup"/>
<timer name="pit" tickpolicy="delay"/>
<timer name="hpet" present="no"/>
</clock>
<on_poweroff>destroy</on_poweroff>
<on_reboot>restart</on_reboot>
<on_crash>destroy</on_crash>
<pm>
<suspend-to-mem enabled="no"/>
<suspend-to-disk enabled="no"/>
</pm>
<devices>
<emulator>/usr/bin/qemu-system-x86_64</emulator>
<disk type="file" device="disk">
<driver name="qemu" type="qcow2"/>
<source file="/home/sh/sh/packer-qemu-template/output/ubuntu"/>
<target dev="vda" bus="virtio"/>
<address type="pci" domain="0x0000" bus="0x04" slot="0x00" function="0x0"/>
</disk>
<controller type="usb" index="0" model="qemu-xhci" ports="15">
<address type="pci" domain="0x0000" bus="0x02" slot="0x00" function="0x0"/>
</controller>
<controller type="pci" index="0" model="pcie-root"/>
<controller type="pci" index="1" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="1" port="0x10"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="2" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="2" port="0x11"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x1"/>
</controller>
<controller type="pci" index="3" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="3" port="0x12"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x2"/>
</controller>
<controller type="pci" index="4" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="4" port="0x13"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x3"/>
</controller>
<controller type="pci" index="5" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="5" port="0x14"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x4"/>
</controller>
<controller type="pci" index="6" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="6" port="0x15"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x5"/>
</controller>
<controller type="pci" index="7" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="7" port="0x16"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x6"/>
</controller>
<controller type="pci" index="8" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="8" port="0x17"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x02" function="0x7"/>
</controller>
<controller type="pci" index="9" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="9" port="0x18"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x0" multifunction="on"/>
</controller>
<controller type="pci" index="10" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="10" port="0x19"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x1"/>
</controller>
<controller type="pci" index="11" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="11" port="0x1a"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x2"/>
</controller>
<controller type="pci" index="12" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="12" port="0x1b"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x3"/>
</controller>
<controller type="pci" index="13" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="13" port="0x1c"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x4"/>
</controller>
<controller type="pci" index="14" model="pcie-root-port">
<model name="pcie-root-port"/>
<target chassis="14" port="0x1d"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x03" function="0x5"/>
</controller>
<controller type="sata" index="0">
<address type="pci" domain="0x0000" bus="0x00" slot="0x1f" function="0x2"/>
</controller>
<controller type="virtio-serial" index="0">
<address type="pci" domain="0x0000" bus="0x03" slot="0x00" function="0x0"/>
</controller>
<interface type="network">
<mac address="52:54:00:74:74:82"/>
<source network="default"/>
<model type="virtio"/>
<address type="pci" domain="0x0000" bus="0x01" slot="0x00" function="0x0"/>
</interface>
<serial type="pty">
<target type="isa-serial" port="0">
<model name="isa-serial"/>
</target>
</serial>
<console type="pty">
<target type="serial" port="0"/>
</console>
<channel type="unix">
<target type="virtio" name="org.qemu.guest_agent.0"/>
<address type="virtio-serial" controller="0" bus="0" port="1"/>
</channel>
<channel type="spicevmc">
<target type="virtio" name="com.redhat.spice.0"/>
<address type="virtio-serial" controller="0" bus="0" port="2"/>
</channel>
<input type="tablet" bus="usb">
<address type="usb" bus="0" port="1"/>
</input>
<input type="mouse" bus="ps2"/>
<input type="keyboard" bus="ps2"/>
<graphics type="spice" autoport="yes">
<listen type="address"/>
<image compression="off"/>
</graphics>
<sound model="ich9">
<address type="pci" domain="0x0000" bus="0x00" slot="0x1b" function="0x0"/>
</sound>
<audio id="1" type="spice"/>
<video>
<model type="qxl" ram="65536" vram="65536" vgamem="16384" heads="1" primary="yes"/>
<address type="pci" domain="0x0000" bus="0x00" slot="0x01" function="0x0"/>
</video>
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="2"/>
</redirdev>
<redirdev bus="usb" type="spicevmc">
<address type="usb" bus="0" port="3"/>
</redirdev>
<watchdog model="itco" action="reset"/>
<memballoon model="virtio">
<address type="pci" domain="0x0000" bus="0x05" slot="0x00" function="0x0"/>
</memballoon>
<rng model="virtio">
<backend model="random">/dev/urandom</backend>
<address type="pci" domain="0x0000" bus="0x06" slot="0x00" function="0x0"/>
</rng>
</devices>
</domain>
위의 PCIe 정보들을 미리 보는 이유는 PCIe 번호들이 겹치면 안되어서 입니다.
이제 NIC에 NUMA 번호를 할당하는 여정을 떠나보겠습니다.
1. QEMU의 CPU에 NUMA 할당이 필요합니다.
virt-manager의 xml파일을 열어보면 이런식으로 되어 있을것입니다.
이 중에서 cpu 부분에 아래와 같이 numa 내용을 추가할 수 있습니다.
<cpu mode="custom" match="exact" check="partial">
<model fallback="allow">EPYC-Rome</model>
<numa>
<cell id="0" cpus="0-1" memory="2097152" unit="KiB"/>
<cell id="1" cpus="2-3" memory="2097152" unit="KiB"/>
</numa>
</cpu>
cell id 0 과 1이 각각 NUMA 번호라고 생각하면 되고 거기에 할당할 cpu 들을 나열하고, 메모리도 할당하는것이죠.
예시에서는 제가 생성한 VM의 cpu 개수가 4개라서 2개씩 할당했고 메모리가 4GB 니 2GB씩 나눠서 할당했습니다.
2. PCIe-expander-bus와 pcie-root-port를 추가해야합니다.
기존 xml에 정의 되어있던 pci 10번부터 14번까지의 pcie-root-port는 필요없는 정보라 지웁니다.
그리고 아래 내용을 추가합니다.
추가 위치는 controller들이 정의되어 있는 위치 밑에 그냥 추가하시면 됩니다.
<controller type="pci" index="10" model="pcie-expander-bus">
<model name="pxb-pcie"/>
<target busNr="180">
<node>0</node>
</target>
<address type="pci" domain="0x0000" bus="0x00" slot="0x04" function="0x0"/>
</controller>
<controller type="pci" index="11" model="pcie-root-port">
<model name="ioh3420"/>
<target chassis="11" port="0x10"/>
<address type="pci" domain="0x0000" bus="0x0a" slot="0x00" function="0x0"/>
</controller>
pcie 10번 인덱스에 pcie-expander-bus를 달고 거기에 pcie-root-port를 연결해 두는식입니다.
모양은 아래와 같은 느낌으로 생각을 하시면 될것 같네요.
기존
pcie-root (index == 0)
|
+- pcie-root-port (index == 1)
|
+ - Virtual NIC (virtio network)
변경
pcie-root (index == 0)
|
+- pcie-expander-bus (index == 10, numa node == 0)
|
+- pcie-root-port (index == 11)
|
+ - Virtual NIC (virtio network)
저도 PCIe 스펙을 정확하게 아는건 아니라서 이게 항상 맞는말인지는 잘 모르겠습니다.
1. pcie-root (index=0) : 얘는 PCIe 를 QEMU 혹은 커널에서 구성하는데 반드시 필요한 요소로 보입니다.
2. pcie-expander-bus : NUMA 할당을 위해서 추가 된 부분입니다.
3. pcie-root-port : NIC에 pcie 정보를 부여하기 위해서 필수인 부분입니다.
정도로 생각 가능 할 것 같습니다.
3. 할당한 pcie-root-port를 NIC과 연결해줍니다.
pcie-root (index == 0)
|
+- pcie-expander-bus (index == 10, numa node == 0)
|
+- pcie-root-port (index == 11)
|
+ - Virtual NIC (virtio network)
위에서 보여드린 그림에서 pcie-root-port의 index가 11입니다.
따라서, 할당하고자 하는 nic의 pcie address를 그 index로 연결해 주어야합니다.
기본적으로는 아마 bus가 01로 되어있습니다. 그것을 11로 변경해주면 됩니다.
아래와 같이 bus="0x0b" (16진수로 11이죠) 로 할당하면 됩니다.
결과
Virtio network device에 numa가 0번으로 할당된 것을 알 수 있습니다.
또한, 같은 방법으로 QEMU에 붙이는 NVMe drive에도 numa를 할당할 수 있습니다.
추후에 여유가 된다면 포스트를 작성하도록 하겠습니다.
참조
Daniel P. Berrangé » Blog Archive » Setting up a nested KVM guest for developing & testing PCI device assignment with NUMA
Over the past few years OpenStack Nova project has gained support for managing VM usage of NUMA, huge pages and PCI device assignment. One of the more challenging aspects of this is availability of hardware to develop and test against. In the ideal world i
www.berrange.com
'DevOps > QEMU' 카테고리의 다른 글
개발 및 IT 관련 포스팅을 작성 하는 블로그입니다.
IT 기술 및 개인 개발에 대한 내용을 작성하는 블로그입니다. 많은 분들과 소통하며 의견을 나누고 싶습니다.