2014-10-29 16:27:19 +00:00
|
|
|
|
|
|
|
================================================
|
|
|
|
Testing NUMA related hardware setup with libvirt
|
|
|
|
================================================
|
|
|
|
|
|
|
|
This page describes how to test the libvirt driver's handling
|
|
|
|
of the NUMA placement, large page allocation and CPU pinning
|
|
|
|
features. It relies on setting up a virtual machine as the
|
|
|
|
test environment and requires support for nested virtualization
|
|
|
|
since plain QEMU is not sufficiently functional. The virtual
|
|
|
|
machine will itself be given NUMA topology, so it can then
|
|
|
|
act as a virtual "host" for testing purposes.
|
|
|
|
|
|
|
|
------------------------------------------
|
|
|
|
Provisioning a virtual machine for testing
|
|
|
|
------------------------------------------
|
|
|
|
|
|
|
|
The entire test process will take place inside a large virtual
|
|
|
|
machine running Fedora 21. The instructions should work for any
|
|
|
|
other Linux distribution which includes libvirt >= 1.2.9 and
|
|
|
|
QEMU >= 2.1.2
|
|
|
|
|
|
|
|
The tests will require support for nested KVM, which is not enabled
|
|
|
|
by default on hypervisor hosts. It must be explicitly turned on in
|
|
|
|
the host when loading the kvm-intel/kvm-amd kernel modules.
|
|
|
|
|
|
|
|
On Intel hosts verify it with
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# cat /sys/module/kvm_intel/parameters/nested
|
|
|
|
N
|
|
|
|
|
|
|
|
# rmmod kvm-intel
|
|
|
|
# echo "options kvm-intel nested=y" > /etc/modprobe.d/dist.conf
|
|
|
|
# modprobe kvm-intel
|
|
|
|
|
|
|
|
# cat /sys/module/kvm_intel/parameters/nested
|
|
|
|
Y
|
|
|
|
|
|
|
|
While on AMD hosts verify it with
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# cat /sys/module/kvm_amd/parameters/nested
|
|
|
|
0
|
|
|
|
|
|
|
|
# rmmod kvm-amd
|
|
|
|
# echo "options kvm-amd nested=1" > /etc/modprobe.d/dist.conf
|
|
|
|
# modprobe kvm-amd
|
|
|
|
|
|
|
|
# cat /sys/module/kvm_amd/parameters/nested
|
|
|
|
1
|
|
|
|
|
|
|
|
The virt-install command below shows how to provision a
|
|
|
|
basic Fedora 21 x86_64 guest with 8 virtual CPUs, 8 GB
|
|
|
|
of RAM and 20 GB of disk space:
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# cd /var/lib/libvirt/images
|
|
|
|
# wget http://download.fedoraproject.org/pub/fedora/linux/releases/test/21-Alpha/Server/x86_64/iso/Fedora-Server-netinst-x86_64-21_Alpha.iso
|
|
|
|
|
|
|
|
# virt-install \
|
|
|
|
--name f21x86_64 \
|
|
|
|
--ram 8000 \
|
|
|
|
--vcpus 8 \
|
|
|
|
--file /var/lib/libvirt/images/f21x86_64.img \
|
|
|
|
--file-size 20
|
|
|
|
--cdrom /var/lib/libvirt/images/Fedora-Server-netinst-x86_64-21_Alpha.iso \
|
|
|
|
--os-variant fedora20
|
|
|
|
|
|
|
|
When the virt-viewer application displays the installer, follow
|
|
|
|
the defaults for the installation with a couple of exceptions
|
|
|
|
|
|
|
|
* The automatic disk partition setup can be optionally tweaked to
|
|
|
|
reduce the swap space allocated. No more than 500MB is required,
|
|
|
|
free'ing up an extra 1.5 GB for the root disk.
|
|
|
|
|
|
|
|
* Select "Minimal install" when asked for the installation type
|
|
|
|
since a desktop environment is not required.
|
|
|
|
|
|
|
|
* When creating a user account be sure to select the option
|
|
|
|
"Make this user administrator" so it gets 'sudo' rights
|
|
|
|
|
|
|
|
Once the installation process has completed, the virtual machine
|
|
|
|
will reboot into the final operating system. It is now ready to
|
|
|
|
deploy an OpenStack development environment.
|
|
|
|
|
|
|
|
---------------------------------
|
2015-03-03 16:37:53 -05:00
|
|
|
Setting up a devstack environment
|
2014-10-29 16:27:19 +00:00
|
|
|
---------------------------------
|
|
|
|
|
|
|
|
For later ease of use, copy your SSH public key into the virtual
|
|
|
|
machine
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# ssh-copy-id <IP of VM>
|
|
|
|
|
|
|
|
Now login to the virtual machine
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# ssh <IP of VM>
|
|
|
|
|
|
|
|
We'll install devstack under $HOME/src/cloud/.
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# mkdir -p $HOME/src/cloud
|
|
|
|
# cd $HOME/src/cloud
|
|
|
|
# chmod go+rx $HOME
|
|
|
|
|
|
|
|
The Fedora minimal install does not contain git and only
|
|
|
|
has the crude & old-fashioned "vi" editor.
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# sudo yum -y install git emacs
|
|
|
|
|
|
|
|
At this point a fairly standard devstack setup can be
|
|
|
|
done. The config below is just an example that is
|
|
|
|
convenient to use to place everything in $HOME instead
|
|
|
|
of /opt/stack. Change the IP addresses to something
|
|
|
|
appropriate for your environment of course
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# git clone git://github.com/openstack-dev/devstack.git
|
|
|
|
# cd devstack
|
|
|
|
# cat >>local.conf <<EOF
|
|
|
|
[[local|localrc]]
|
|
|
|
DEST=$HOME/src/cloud
|
|
|
|
DATA_DIR=$DEST/data
|
|
|
|
SERVICE_DIR=$DEST/status
|
|
|
|
|
|
|
|
LOGFILE=$DATA_DIR/logs/stack.log
|
|
|
|
SCREEN_LOGDIR=$DATA_DIR/logs
|
|
|
|
VERBOSE=True
|
|
|
|
|
|
|
|
disable_service neutron
|
|
|
|
|
|
|
|
HOST_IP=192.168.122.50
|
|
|
|
FLAT_INTERFACE=eth0
|
|
|
|
FIXED_RANGE=192.168.128.0/24
|
|
|
|
FIXED_NETWORK_SIZE=256
|
|
|
|
FLOATING_RANGE=192.168.129.0/24
|
|
|
|
|
|
|
|
MYSQL_PASSWORD=123456
|
|
|
|
SERVICE_TOKEN=123456
|
|
|
|
SERVICE_PASSWORD=123456
|
|
|
|
ADMIN_PASSWORD=123456
|
|
|
|
RABBIT_PASSWORD=123456
|
|
|
|
|
2015-03-21 20:03:05 -04:00
|
|
|
IMAGE_URLS="http://download.cirros-cloud.net/0.3.2/cirros-0.3.2-x86_64-uec.tar.gz"
|
2014-10-29 16:27:19 +00:00
|
|
|
EOF
|
|
|
|
|
|
|
|
# FORCE=yes ./stack.sh
|
|
|
|
|
|
|
|
|
|
|
|
Unfortunately while devstack starts various system services and
|
|
|
|
changes various system settings it doesn't make the changes
|
|
|
|
persistent. Fix that now to avoid later surprises after reboots
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# sudo systemctl enable mysqld.service
|
|
|
|
# sudo systemctl enable rabbitmq-server.service
|
|
|
|
# sudo systemctl enable httpd.service
|
|
|
|
|
|
|
|
# sudo emacs /etc/sysconfig/selinux
|
|
|
|
SELINUX=permissive
|
|
|
|
|
|
|
|
|
|
|
|
----------------------------
|
|
|
|
Testing basis non-NUMA usage
|
|
|
|
----------------------------
|
|
|
|
|
|
|
|
First to confirm we've not done anything unusual to the traditional
|
|
|
|
operation of Nova libvirt guests boot a tiny instance
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
2015-04-29 18:25:11 +01:00
|
|
|
# . openrc admin
|
2015-03-21 20:03:05 -04:00
|
|
|
# nova boot --image cirros-0.3.2-x86_64-uec --flavor m1.tiny cirros1
|
2014-10-29 16:27:19 +00:00
|
|
|
|
|
|
|
The host will be reporting NUMA topology, but there should only
|
|
|
|
be a single NUMA cell this point.
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# mysql -u root -p nova
|
|
|
|
MariaDB [nova]> select numa_topology from compute_nodes;
|
2015-04-29 18:25:11 +01:00
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
| numa_topology |
|
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMATopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cells": [{
|
|
|
|
| "nova_object.name": "NUMACell",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cpu_usage": 0,
|
|
|
|
| "memory_usage": 0,
|
|
|
|
| "cpuset": [0, 1, 2, 3, 4, 5, 6, 7],
|
|
|
|
| "pinned_cpus": [],
|
|
|
|
| "siblings": [],
|
|
|
|
| "memory": 7793,
|
|
|
|
| "mempages": [
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMAPagesTopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "total": 987430,
|
|
|
|
| "used": 0,
|
|
|
|
| "size_kb": 4
|
|
|
|
| },
|
|
|
|
| },
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMAPagesTopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "total": 0,
|
|
|
|
| "used": 0,
|
|
|
|
| "size_kb": 2048
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
| ],
|
|
|
|
| "id": 0
|
|
|
|
| },
|
|
|
|
| },
|
|
|
|
| ]
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
+----------------------------------------------------------------------------+
|
2014-10-29 16:27:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
Meanwhile, the guest instance should not have any NUMA configuration
|
|
|
|
recorded
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
MariaDB [nova]> select numa_topology from instance_extra;
|
|
|
|
+---------------+
|
|
|
|
| numa_topology |
|
|
|
|
+---------------+
|
|
|
|
| NULL |
|
|
|
|
+---------------+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------
|
|
|
|
Reconfiguring the test instance to have NUMA topology
|
|
|
|
-----------------------------------------------------
|
|
|
|
|
|
|
|
Now that devstack is proved operational, it is time to configure some
|
|
|
|
NUMA topology for the test VM, so that it can be used to verify the
|
|
|
|
OpenStack NUMA support. To do the changes, the VM instance that is running
|
|
|
|
devstack must be shut down.
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# sudo shutdown -h now
|
|
|
|
|
|
|
|
And now back on the physical host edit the guest config as root
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# sudo virsh edit f21x86_64
|
|
|
|
|
|
|
|
The first thing is to change the <cpu> block to do passthrough of the
|
|
|
|
host CPU. In particular this exposes the "SVM" or "VMX" feature bits
|
|
|
|
to the guest so that "Nested KVM" can work. At the same time we want
|
|
|
|
to define the NUMA topology of the guest. To make things interesting
|
|
|
|
we're going to give the guest an asymmetric topology with 4 CPUS and
|
|
|
|
4 GBs of RAM in the first NUMA node and 2 CPUs and 2 GB of RAM in
|
|
|
|
the second and third NUMA nodes. So modify the guest XML to include
|
|
|
|
the following CPU XML
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
<cpu mode='host-passthrough'>
|
|
|
|
<numa>
|
|
|
|
<cell id='0' cpus='0-3' memory='4096000'/>
|
|
|
|
<cell id='1' cpus='4-5' memory='2048000'/>
|
|
|
|
<cell id='2' cpus='6-7' memory='2048000'/>
|
|
|
|
</numa>
|
|
|
|
</cpu>
|
|
|
|
|
|
|
|
The guest can now be started again, and ssh back into it
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# virsh start f21x86_64
|
|
|
|
|
|
|
|
...wait for it to finish booting
|
|
|
|
|
|
|
|
# ssh <IP of VM>
|
|
|
|
|
|
|
|
|
2015-03-03 16:37:53 -05:00
|
|
|
Before starting OpenStack services again, it is necessary to
|
2015-07-24 22:57:13 +09:00
|
|
|
reconfigure Nova to enable the NUMA scheduler filter. The libvirt
|
2014-10-29 16:27:19 +00:00
|
|
|
virtualization type must also be explicitly set to KVM, so that
|
|
|
|
guests can take advantage of nested KVM.
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# sudo emacs /etc/nova/nova.conf
|
|
|
|
|
|
|
|
Set the following parameters:
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
[DEFAULT]
|
2015-04-29 18:25:11 +01:00
|
|
|
scheduler_default_filters=RetryFilter, AvailabilityZoneFilter, RamFilter, ComputeFilter, ComputeCapabilitiesFilter, ImagePropertiesFilter, ServerGroupAntiAffinityFilter, ServerGroupAffinityFilter, NUMATopologyFilter
|
2014-10-29 16:27:19 +00:00
|
|
|
|
|
|
|
[libvirt]
|
|
|
|
virt_type = kvm
|
|
|
|
|
|
|
|
|
|
|
|
With that done, OpenStack can be started again
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# cd $HOME/src/cloud/devstack
|
|
|
|
# ./rejoin-stack.sh
|
|
|
|
|
|
|
|
|
|
|
|
The first thing is to check that the compute node picked up the
|
|
|
|
new NUMA topology setup for the guest
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# mysql -u root -p nova
|
|
|
|
MariaDB [nova]> select numa_topology from compute_nodes;
|
2015-04-29 18:25:11 +01:00
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
| numa_topology |
|
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMATopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cells": [{
|
|
|
|
| "nova_object.name": "NUMACell",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cpu_usage": 0,
|
|
|
|
| "memory_usage": 0,
|
|
|
|
| "cpuset": [0, 1, 2, 3],
|
|
|
|
| "pinned_cpus": [],
|
|
|
|
| "siblings": [],
|
|
|
|
| "memory": 3857,
|
|
|
|
| "mempages": [
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMAPagesTopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "total": 987430,
|
|
|
|
| "used": 0,
|
|
|
|
| "size_kb": 4
|
|
|
|
| },
|
|
|
|
| },
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMAPagesTopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "total": 0,
|
|
|
|
| "used": 0,
|
|
|
|
| "size_kb": 2048
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
| ],
|
|
|
|
| "id": 0
|
|
|
|
| },
|
|
|
|
| },
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMACell",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cpu_usage": 0,
|
|
|
|
| "memory_usage": 0,
|
|
|
|
| "cpuset": [4, 5],
|
|
|
|
| "pinned_cpus": [],
|
|
|
|
| "siblings": [],
|
|
|
|
| "memory": 1969,
|
|
|
|
| "mempages": [
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMAPagesTopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "total": 504216,
|
|
|
|
| "used": 0,
|
|
|
|
| "size_kb": 4
|
|
|
|
| },
|
|
|
|
| },
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMAPagesTopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "total": 0,
|
|
|
|
| "used": 0,
|
|
|
|
| "size_kb": 2048
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
| ],
|
|
|
|
| "id": 1
|
|
|
|
| },
|
|
|
|
| },
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMACell",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cpu_usage": 0,
|
|
|
|
| "memory_usage": 0,
|
|
|
|
| "cpuset": [6, 7],
|
|
|
|
| "pinned_cpus": [],
|
|
|
|
| "siblings": [],
|
|
|
|
| "memory": 1967,
|
|
|
|
| "mempages": [
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMAPagesTopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "total": 503575,
|
|
|
|
| "used": 0,
|
|
|
|
| "size_kb": 4
|
|
|
|
| },
|
|
|
|
| },
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "NUMAPagesTopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "total": 0,
|
|
|
|
| "used": 0,
|
|
|
|
| "size_kb": 2048
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
| ],
|
|
|
|
| "id": 2
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
| ]
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
+----------------------------------------------------------------------------+
|
2014-10-29 16:27:19 +00:00
|
|
|
|
|
|
|
This indeed shows that there are now 3 NUMA nodes for the "host"
|
|
|
|
machine, the first with 4 GB of RAM and 4 CPUs, and others with
|
|
|
|
2 GB of RAM and 2 CPUs each.
|
|
|
|
|
|
|
|
|
|
|
|
-----------------------------------------------------
|
|
|
|
Testing instance boot with no NUMA topology requested
|
|
|
|
-----------------------------------------------------
|
|
|
|
|
|
|
|
For the sake of backwards compatibility, if the NUMA filter is
|
|
|
|
enabled, but the flavor/image does not have any NUMA settings
|
|
|
|
requested, it should be assumed that the guest will have a
|
|
|
|
single NUMA node. The guest should be locked to a single host
|
|
|
|
NUMA node too. Boot a guest with the m1.tiny flavor to test
|
|
|
|
this condition
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# . openrc admin admin
|
2015-03-21 20:03:05 -04:00
|
|
|
# nova boot --image cirros-0.3.2-x86_64-uec --flavor m1.tiny cirros1
|
2014-10-29 16:27:19 +00:00
|
|
|
|
|
|
|
Now look at the libvirt guest XML. It should show that the vCPUs are
|
|
|
|
locked to pCPUs within a particular node.
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# virsh -c qemu:///system list
|
|
|
|
....
|
|
|
|
# virsh -c qemu:///system dumpxml instanceXXXXXX
|
|
|
|
...
|
|
|
|
<vcpu placement='static' cpuset='6-7'>1</vcpu>
|
|
|
|
...
|
|
|
|
|
|
|
|
This example shows that the guest has been locked to the 3rd NUMA
|
|
|
|
node (which contains pCPUs 6 and 7). Note that there is no explicit
|
|
|
|
NUMA topology listed in the guest XML.
|
|
|
|
|
|
|
|
------------------------------------------------
|
|
|
|
Testing instance boot with 1 NUMA cell requested
|
|
|
|
------------------------------------------------
|
|
|
|
|
|
|
|
Moving forward a little, explicitly tell Nova that the NUMA topology
|
|
|
|
for the guest should have a single NUMA node. This should operate
|
2015-07-24 22:57:13 +09:00
|
|
|
in an identical manner to the default behavior where no NUMA policy
|
2014-10-29 16:27:19 +00:00
|
|
|
is set. To define the topology we will create a new flavor
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# nova flavor-create m1.numa 999 1024 1 4
|
|
|
|
# nova flavor-key m1.numa set hw:numa_nodes=1
|
|
|
|
# nova flavor-show m1.numa
|
|
|
|
|
|
|
|
Now boot the guest using this new flavor
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
2015-03-21 20:03:05 -04:00
|
|
|
# nova boot --image cirros-0.3.2-x86_64-uec --flavor m1.numa cirros2
|
2014-10-29 16:27:19 +00:00
|
|
|
|
|
|
|
Looking at the resulting guest XML from libvirt
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# virsh -c qemu:///system dumpxml instanceXXXXXX
|
|
|
|
...
|
|
|
|
<vcpu placement='static'>4</vcpu>
|
|
|
|
<cputune>
|
|
|
|
<vcpupin vcpu='0' cpuset='0-3'/>
|
|
|
|
<vcpupin vcpu='1' cpuset='0-3'/>
|
|
|
|
<vcpupin vcpu='2' cpuset='0-3'/>
|
|
|
|
<vcpupin vcpu='3' cpuset='0-3'/>
|
|
|
|
<emulatorpin cpuset='0-3'/>
|
|
|
|
</cputune>
|
|
|
|
...
|
2015-04-29 18:25:11 +01:00
|
|
|
<cpu>
|
|
|
|
<topology sockets='4' cores='1' threads='1'/>
|
|
|
|
<numa>
|
|
|
|
<cell id='0' cpus='0-3' memory='1048576'/>
|
|
|
|
</numa>
|
|
|
|
</cpu>
|
|
|
|
...
|
|
|
|
<numatune>
|
|
|
|
<memory mode='strict' nodeset='0'/>
|
|
|
|
<memnode cellid='0' mode='strict' nodeset='0'/>
|
|
|
|
</numatune>
|
|
|
|
|
|
|
|
The XML shows:
|
|
|
|
|
|
|
|
* Each guest CPU has been pinned to the physical CPUs
|
|
|
|
associated with a particular NUMA node
|
|
|
|
* The emulator threads have been pinned to the union
|
|
|
|
of all physical CPUs in the host NUMA node that
|
|
|
|
the guest is placed on
|
|
|
|
* The guest has been given a virtual NUMA topology
|
|
|
|
with a single node holding all RAM and CPUs
|
|
|
|
* The guest NUMA node has been strictly pinned to
|
|
|
|
a host NUMA node.
|
|
|
|
|
|
|
|
As a further sanity test, check what Nova recorded for the
|
|
|
|
instance in the database. This should match the <numatune>
|
|
|
|
information
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
MariaDB [nova]> select numa_topology from instance_extra;
|
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
| numa_topology |
|
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "InstanceNUMATopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "instance_uuid": "4c2302fe-3f0f-46f1-9f3e-244011f6e03a",
|
|
|
|
| "cells": [
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "InstanceNUMACell",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cpu_topology": null,
|
|
|
|
| "pagesize": null,
|
|
|
|
| "cpuset": [
|
|
|
|
| 0,
|
|
|
|
| 1,
|
|
|
|
| 2,
|
|
|
|
| 3
|
|
|
|
| ],
|
|
|
|
| "memory": 1024,
|
|
|
|
| "cpu_pinning_raw": null,
|
|
|
|
| "id": 0
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
| ]
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
|
|
|
|
-------------------------------------------------
|
|
|
|
Testing instance boot with 2 NUMA cells requested
|
|
|
|
-------------------------------------------------
|
|
|
|
|
|
|
|
Now getting more advanced we tell Nova that the guest will have two
|
|
|
|
NUMA nodes. To define the topology we will change the previously
|
|
|
|
defined flavor
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# nova flavor-key m1.numa set hw:numa_nodes=2
|
|
|
|
# nova flavor-show m1.numa
|
|
|
|
|
|
|
|
Now boot the guest using this changed flavor
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# nova boot --image cirros-0.3.2-x86_64-uec --flavor m1.numa cirros2
|
|
|
|
|
|
|
|
Looking at the resulting guest XML from libvirt
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
# virsh -c qemu:///system dumpxml instanceXXXXXX
|
|
|
|
...
|
|
|
|
<vcpu placement='static'>4</vcpu>
|
|
|
|
<cputune>
|
|
|
|
<vcpupin vcpu='0' cpuset='0-3'/>
|
|
|
|
<vcpupin vcpu='1' cpuset='0-3'/>
|
|
|
|
<vcpupin vcpu='2' cpuset='4-5'/>
|
|
|
|
<vcpupin vcpu='3' cpuset='4-5'/>
|
|
|
|
<emulatorpin cpuset='0-5'/>
|
|
|
|
</cputune>
|
|
|
|
...
|
2014-10-29 16:27:19 +00:00
|
|
|
<cpu>
|
|
|
|
<topology sockets='4' cores='1' threads='1'/>
|
|
|
|
<numa>
|
|
|
|
<cell id='0' cpus='0-1' memory='524288'/>
|
|
|
|
<cell id='1' cpus='2-3' memory='524288'/>
|
|
|
|
</numa>
|
|
|
|
</cpu>
|
|
|
|
...
|
|
|
|
<numatune>
|
|
|
|
<memory mode='strict' nodeset='0-1'/>
|
|
|
|
<memnode cellid='0' mode='strict' nodeset='0'/>
|
2015-04-29 18:25:11 +01:00
|
|
|
<memnode cellid='1' mode='strict' nodeset='1'/>
|
2014-10-29 16:27:19 +00:00
|
|
|
</numatune>
|
|
|
|
|
|
|
|
The XML shows:
|
|
|
|
|
|
|
|
* Each guest CPU has been pinned to the physical CPUs
|
2015-04-29 18:25:11 +01:00
|
|
|
associated with particular NUMA nodes
|
2014-10-29 16:27:19 +00:00
|
|
|
* The emulator threads have been pinned to the union
|
2015-03-03 16:37:53 -05:00
|
|
|
of all physical CPUs in the host NUMA nodes that
|
2014-10-29 16:27:19 +00:00
|
|
|
the guest is placed on
|
|
|
|
* The guest has been given a virtual NUMA topology
|
2015-04-29 18:25:11 +01:00
|
|
|
with two nodes, each holding half the RAM and CPUs
|
|
|
|
* The guest NUMA nodes have been strictly pinned to
|
|
|
|
different host NUMA node.
|
2014-10-29 16:27:19 +00:00
|
|
|
|
|
|
|
As a further sanity test, check what Nova recorded for the
|
|
|
|
instance in the database. This should match the <numatune>
|
|
|
|
information
|
|
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
|
|
MariaDB [nova]> select numa_topology from instance_extra;
|
2015-04-29 18:25:11 +01:00
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
| numa_topology |
|
|
|
|
+----------------------------------------------------------------------------+
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "InstanceNUMATopology",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "instance_uuid": "a14fcd68-567e-4d71-aaa4-a12f23f16d14",
|
|
|
|
| "cells": [
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "InstanceNUMACell",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cpu_topology": null,
|
|
|
|
| "pagesize": null,
|
|
|
|
| "cpuset": [
|
|
|
|
| 0,
|
|
|
|
| 1
|
|
|
|
| ],
|
|
|
|
| "memory": 512,
|
|
|
|
| "cpu_pinning_raw": null,
|
|
|
|
| "id": 0
|
|
|
|
| },
|
|
|
|
| },
|
|
|
|
| {
|
|
|
|
| "nova_object.name": "InstanceNUMACell",
|
|
|
|
| "nova_object.data": {
|
|
|
|
| "cpu_topology": null,
|
|
|
|
| "pagesize": null,
|
|
|
|
| "cpuset": [
|
|
|
|
| 2,
|
|
|
|
| 3
|
|
|
|
| ],
|
|
|
|
| "memory": 512,
|
|
|
|
| "cpu_pinning_raw": null,
|
|
|
|
| "id": 1
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
| ]
|
|
|
|
| },
|
|
|
|
| }
|
|
|
|
|
|
|
|
|
+----------------------------------------------------------------------------+
|