第 7 章 配置带有 NUMA 的 CPU 固定(CPU Pinning)

本章介绍了与 NUMA 拓扑相关的信息,以及如何在支持 NUMA 的系统上配置 OpenStack 环境。在这类设置中,虚拟机实例被固定到专用的 CPU 内核,从而可以通过更加智能的调度来提高客户机的性能。

如需了解 NUMA 的背景信息,请参阅 What is NUMA and how does it work on Linux ?。如需了解使用 libvirt 对 NUMA 进行性能调优的信息,请参阅 Virtualization Tuning and Optimization Guide

7.1. Compute 节点的配置

虽然具体的配置取决于您的主机系统的 NUMA 拓扑,但是,您必须为主机进程在所有 NUMA 节点上保留一些 CPU 内核,并让剩余的 CPU 内核处理客户虚拟机实例。例如,有 8 个 CPU 内核平均分布在 2 个 NUMA 节点上,它的结构可以和以下类似:

NUMA 拓扑示例

┌─────────────────┬─────────────────┬─────────────────┐
│                 │ Node 0          │ Node 1          │
├─────────────────┼────────┬────────┼────────┬────────┤
│ Host processes  │ Core 0 │ Core 1 │ Core 4 │ Core 5 │
├─────────────────┼────────┼────────┼────────┼────────┤
│ Guest processes │ Core 2 │ Core 3 │ Core 6 │ Core 7 │
└─────────────────┴────────┴────────┴────────┴────────┘

注意

为了决定为主机进程保留的内核数量,需要在特定工作负载的情况下对主机性能进行观察。

配置 Compute 节点包括以下几个步骤:

  1. /etc/nova/nova.conf 文件中的 vcpu_pin_set 选项设置成为客户系统进程保留的 CPU 内核列表。对于上面的示例,您可以进行以下设置:

    vcpu_pin_set=2,3,6,7
  2. 把相同文件中的 reserved_host_memory_mb 选项设置成为主机进程保留的 RAM 的数量。如果您需要保留 512 MB 内存,配置如下:

    reserved_host_memory_mb=512
  3. 运行以下命令在 Compute 节点上重启 Compute 服务:

    systemctl restart openstack-nova-compute.service
  4. 在引导选项中,使用 isolcpus 并加上 CPU 列表。这可以把主机进程限制为只能访问列出的 CPU 内核。对于以上的示例,您可以运行:

    grubby --update-kernel=ALL --args="isolcpus=2,3,6,7"
  5. 更新引导记录使这个改变生效:

    grub2-install /dev/device

    使用包括引导记录的设备名替换 device,这个设备名通常是 sda

  6. 重启系统。

7.2. 调度程序配置

  1. 在运行 OpenStack Compute Scheduler 的每个系统上编辑 /etc/nova/nova.conf 文件。找到 scheduler_default_filters 选项,如果它被注释掉,取消它的注释,在过滤器列表中加入 AggregateInstanceExtraSpecFilterNUMATopologyFilter。这个行的内容应该和以下类似:

    scheduler_default_filters=RetryFilter,AvailabilityZoneFilter,RamFilter,
    ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,CoreFilter,
    NUMATopologyFilter,AggregateInstanceExtraSpecsFilter
  2. 重启 openstack-nova-scheduler 服务:

    systemctl restart openstack-nova-scheduler.service

7.3. 集合(Aggregate)和 Flavor 配置

为了把您的 OpenStack 环境中的虚拟机固定在特定资源上运行,在一个系统的 Compute 命令行接口中执行以下步骤:

  1. 加载 admin 身份信息:

    source ~/keystonerc_admin
  2. 创建一个可以接收固定请求的主机集合:

    nova aggregate-create name

    使用适当的名称(如 performancecpu_pinning)替换 name

  3. 编辑集合的元数据来启用固定功能:

    nova aggregate-set-metadata 1 pinned=true

    在这个命令中,数字 1 匹配在前一步中创建的集合 ID。

  4. 为其它主机创建一个集合:

    nova aggregate-create name

    使用适当的名称(如 normal)替换 name

  5. 为这个集合编辑元数据:

    nova aggregate-set-metadata 2 pinned=false

    其中,使用的数字是 2,这是因为它在 1(第一个集合的 ID)之后。

  6. 修改存在的 flavors 设置:

    for i in $(nova flavor-list | cut -f 2 -d ' ' | grep -o '[0-9]*'); do nova flavor-key $i set "aggregate_instance_extra_specs:pinned"="false"; done
  7. 为可以接收固定请求的主机创建一个 flavor:

    nova flavor-create name ID RAM disk vCPUs

    使用适当的名称(如 m1.small.performancepinned.small)替换 name;使用新 flavor 的 ID 替换 ID(如果您有 5 个标准的 flavor,使用 6;如果您需要 nova 来产生 UUID,使用 auto);使用需要的内存数量(以 MB 为单位)替换 RAM;使用需要的磁盘大小(以 GB 为单位)替换 disk;使用需要保留的虚拟 CPU 数量替换 vCPUs

  8. 把 flavor 的 hw:cpu_policy 设置为 dedicated,这将启用 CPU 固定功能:

    nova flavor-key ID set hw:cpu_policy=dedicated

    使用在前一步中创建的 flavor 的 ID 替换 ID

  9. aggregate_instance_extra_specs:pinned 设置为 true,从而确保基于这个 flavor 的实例在它们的元数据中有这个设置:

    nova flavor-key ID set aggregate_instance_extra_specs:pinned=true

    使用 flavor 的 ID 替换 ID

  10. 为新的集合添加以下主机:

    nova aggregate-add-host ID_1 host_1

    使用第一个("performance"/"pinning")集合的 ID 替换 ID_1;把 host_1 替换为需要被加入到这个集合中的主机名。

    nova aggregate-add-host ID_2 host_2

    使用第 2 个("normal")集合的 ID 替换 ID_2;把 host_2 替换为需要被加入到这个集合中的主机名。

运行以下命令使用新 flavor 引导一个实例:

nova boot --image image --flavor flavor server_name

image 替换为保存的 VM 镜像名(请参阅 nova image-list);把 flavor 替换为实际的 flavor 名(m1.small.performancepinned.small 或任何您使用的名称);把 server_name 替换为新服务器的名称。

为了检查新服务器被正确配置,运行以下命令,在输出中检查 OS-EXT-SRV-ATTR:hypervisor_hostname 的值:

nova show server_name