场景 - 使用带有 DPDK 的 Open vSwitch

概述

操作员可以选择使用 DPDK 加速的 Open vSwitch,而不是未加速的 Open vSwitch 或 Linux 网桥,作为 Neutron 虚拟网络基础设施。这种架构最适合 NFV 工作负载,在实施之前需要仔细考虑和规划。本文档概述了如何在您的环境中进行设置。

警告

OpenStack-Ansible 中 DPDK 的当前实现是实验性的,尚未达到生产就绪状态。不同版本之间不保证可升级性或向后兼容性。

先决条件

要在 Linux 平台上启用 DPDK,请确保为 Intel 处理器启用了 VT-d/VT-x,并为 AMD 处理器启用了 AMD-V/AMD-Vi。这些功能通常在 BIOS 中启用。

在 Intel 平台上,需要以下内核参数,可以将其添加到 GRUB 配置中

GRUB_CMDLINE_LINUX="... iommu=pt intel_iommu=on"

在 AMD 平台上,请使用以下参数代替

GRUB_CMDLINE_LINUX="... iommu=pt amd_iommu=on"

更新 GRUB 并重新启动主机。

DPDK 需要巨页。利用 DPDK 加速的 Open vSwitch 的实例必须配置为通过 flavor 属性使用巨页。这些属性和巨页的配置在本指南中描述。

为了获得最佳性能,应将 CPU 频率设置为最大值。许多硬件供应商在 BIOS 中设置了节能属性,可能需要修改。建议使用 cpufreq 或类似工具将 CPU 频率从 ondemand 更改为 performance

注意

当前 playbook 仅支持 DPDK 的单个 NIC 接口。每个 NIC 的多个端口尚未支持,但将来可能会支持。本指南假定 NIC 绑定到 NUMA 节点 0,但可以修改说明以用于绑定到其他 NUMA 节点的 NIC。

NUMA 拓扑

非统一内存访问 (NUMA) 是一种用于多处理的计算机内存设计。本指南无法深入探讨 NUMA 架构。但是,有一些配置需要进行,这些配置依赖于操作员了解使用 DPDK 加速的 Open vSwitch 的计算节点上的 NUMA 特性。

要查看特定系统的 NUMA 拓扑,请使用此处显示的 numactl 命令

root@compute1:~# numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23
node 0 size: 48329 MB
node 0 free: 31798 MB
node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31
node 1 size: 48379 MB
node 1 free: 25995 MB
node distances:
node   0   1
  0:  10  20
  1:  20  10

这里呈现的 NUMA 拓扑对应于具有 2 个 Intel Xeon 2450L 处理器和 96GB 总 RAM 的主机。RAM 在两个 NUMA 节点之间平均分配。每个 CPU 有 8 个核心。启用超线程后,每个 CPU 有 16 个线程,操作系统总共呈现 32 个线程或核心。碰巧这个双插槽系统每个插槽有一个 NUMA 节点,但并非总是如此。请参阅您的系统文档以获取特定于您系统的相关信息。

给定 NUMA 节点列表中的前八个核心/cpu 可以被认为是 CPU 中的物理核心。对于 NUMA 节点 0,这将是核心 0-7。其他八个核心,16-23,被认为是虚拟兄弟核心,并在启用超线程时呈现。可以使用以下命令确定物理到虚拟的映射

root@compute1:~# for cpu in {0..7}; do cat /sys/devices/system/cpu/"cpu"$cpu/topology/thread_siblings_list; done
0,16
1,17
2,18
3,19
4,20
5,21
6,22
7,23

root@compute1:~# for cpu in {8..15}; do cat /sys/devices/system/cpu/"cpu"$cpu/topology/thread_siblings_list; done
8,24
9,25
10,26
11,27
12,28
13,29
14,30
15,31

PCI 插槽通常对应于单个 NUMA 节点。为了获得最佳性能,DPDK NIC 和使用该 NIC 的任何实例应限制在同一 NUMA 节点及其各自的内存中。确保这种行为需要使用 flavor、主机聚合和特殊的内核参数以及 Open vSwitch/DPDK 配置设置。

在此示例中,安装在 PCI 插槽 2 中的单个 10G NIC 绑定到 NUMA 节点 0。理想情况下,使用该 NIC 的任何实例都应限制为与 NUMA 节点 0 关联的核心和内存。这意味着核心 0-7 和 16-23,以及最多 48GB 的 RAM。实际上,但是,一些核心和 RAM 来自 NUMA 节点 0 将被保留并对实例不可用。此外,与 NUMA 节点 1 关联的核心 8-15 和 24-31 应使实例不可用。稍后在本指南中将介绍进行此配置的方法。

通常的做法是为正常的(非 DPDK)操作系统功能保留每个 NUMA 节点的一个物理核心及其各自的虚拟兄弟核心。此外,即使 NIC 绑定到单个 NUMA 节点,也应为每个 NUMA 节点的 DPDK 轮询模式驱动程序 (PMD) 功能保留至少一个物理核心(和兄弟核心)。剩余的核心可以保留给虚拟机实例。

在此示例中,细分将类似于以下内容

` | 保留的核心         | 用途               | node0     | node1 | | ---------------------- | --------------------- | --------- | ----- | | 0,8,16,24              | 主机操作系统 | 0,16      | 8,24  | | 1,9,17,25              | DPDK PMD          | 1,17      | 9,25  | | 2-7,18-23              | 虚拟机      | 2-7,18-23 | N/A   | `

用于定义此配置的变量将在以下部分中讨论。

巨页配置

DPDK 需要巨页的配置,这是一种 Linux 内核可以超出基本页面单元(4096 字节)对更大数量的内存进行分区和寻址的机制。巨页通常以 2MB 和 1G 的大小出现,是连续内存块。用于 2MB 页面页表适合管理多个千兆字节的内存,而 1GB 页面页表更适合扩展到太字节的内存。DPDK 需要使用 1GB 页面。

典型的 x86 系统将具有 2048 kBytes (2MB) 的巨页大小。可以通过查看 /proc/meminfo 的输出来找到默认巨页大小

# cat /proc/meminfo | grep Hugepagesize
Hugepagesize: 2048 kB

可以通过修改 /proc/sys/vm/nr_hugepages 或使用 sysctl 命令在运行时分配巨页的数量。

要使用 /proc 条目查看当前设置

# cat /proc/sys/vm/nr_hugepages
0

要使用 sysctl 命令查看当前设置

# sysctl vm.nr_hugepages
vm.nr_hugepages = 0

要使用 /proc 条目设置巨页数量

# echo 5 > /proc/sys/vm/nr_hugepages

要使用 sysctl 设置巨页数量

# sysctl -w vm.nr_hugepages=5
vm.nr_hugepages = 5

可能需要重新启动才能分配所需的巨页数量。这是因为巨页需要大面积的连续物理内存。

当使用 1G 巨页时,必须在启动时对其进行配置。应创建的 1G 巨页数量将根据几个因素而变化,包括

  • 系统中可用的总 RAM 量

  • 计划的实例所需的 RAM 量

  • 将使用的 NUMA 节点数量

这里呈现的 NUMA 拓扑对应于具有 2 个 Intel Xeon 2450L 处理器和 96GB 总 RAM 的主机。RAM 在两个 NUMA 节点之间平均分配。DPDK NIC 将与单个 NUMA 节点关联,为了获得最佳性能,使用 DPDK NIC 的任何实例都应限制为与 NUMA 节点关联的相同核心和内存。在此示例系统中,DPDK 和实例都可以仅使用与 NUMA 节点 0 关联的 48GB RAM,尽管其中一些 RAM 将被操作系统和其他任务使用。

在 NUMA 节点 0 上可用的 48GB RAM 中,32GB 将保留给 DPDK PMD 和实例使用的 1GB 巨页。使用内核参数配置巨页会导致定义的巨页数量在 NUMA 节点之间平均分配。使用以下内核参数,每个 NUMA 节点将被分配 32 个 1G 巨页

GRUB_CMDLINE_LINUX="... hugepagesz=1G hugepages=64"

如果需要,可以调整巨页,但这样做不在本指南的范围内。

OpenStack-Ansible 变量和覆盖

将实例固定到特定核心的能力不是新的,可以使用此处看到的 vcpu_pin_set 覆盖来实现

nova_nova_conf_overrides:
  DEFAULT:
    vcpu_pin_set: 2-7,18-23

此更改可以添加到 user_overrides.yml 文件以进行全局实施,也可以添加到 openstack_user_config.yml 文件中的各个节点中,如下所示

compute_hosts:
  compute01:
    ip: 172.29.236.200
    container_vars:
      ...
      nova_nova_conf_overrides:
        DEFAULT:
          vcpu_pin_set: 2-7,18-23

为主机操作系统功能(非 DPDK)保留的核心必须转换为十六进制掩码,并使用 ovs_dpdk_lcore_mask 覆盖进行定义。要转换为十六进制掩码,必须首先使用以下表格建立所选核心的二进制掩码

` | 31 | 30 | . | 24 | 23 | . | 17 | 16 | 15 | . | 9  | 8  | 7  | . | 1  | 0  | | -- | -- | - | -- | -- | - | -- | -- | -- | - | -- | -- | -- | - | -- | -- | | 0  | 0  | . | 1  | 0  | . | 0  | 1  | 0  | . | 0  | 1  | 0  | . | 0  | 1  | `

省略号表示未显示的内核。核心 0、8、16、24 的二进制掩码可以这样确定

00000001000000010000000100000001

该二进制值的十六进制表示形式为 0x1010101。相应地在 user_variables.yml 文件或 openstack_user_config.yml 中设置 ovs_dpdk_lcore_mask 覆盖

ovs_dpdk_lcore_mask: 1010101

可以以类似的方式确定为 DPDK PMD 保留的核心 1、9、17、25 的掩码。该表将类似于以下内容

` | 31 | 30 | . | 25 | 24 | . | 17 | 16 | 15 | . | 9  | 8  | 7  | . | 1  | 0  | | -- | -- | - | -- | -- | - | -- | -- | -- | - | -- | -- | -- | - | -- | -- | | 0  | 0  | . | 1  | 0  | . | 1  | 0  | 0  | . | 1  | 0  | 0  | . | 1  | 0  | `

省略号表示未显示的内核。核心 1、9、17、254 的二进制掩码可以这样确定

00000010000000100000001000000010

该二进制值的十六进制表示形式为 0x2020202。相应地在 user_variables.yml 文件或 openstack_user_config.yml 中设置 ovs_dpdk_pmd_cpu_mask 覆盖

ovs_dpdk_pmd_cpu_mask: 2020202

应设置其他变量,包括

  • ovs_dpdk_driver

  • ovs_dpdk_pci_addresses

  • ovs_dpdk_socket_mem

ovs_dpdk_driver 的默认值为 vfio-pci。覆盖可以全局设置或逐主机设置。

注意

请参阅 DPDK 网络接口控制器驱动程序 文档,以获取有关 DPDK 支持的网络驱动程序的更多信息。

ovs_dpdk_pci_addresses 的值是与 DPDK NIC 关联的 NIC 端口的 PCI 总线地址。在此示例中,DPDK NIC 被标识为地址 0000:03:00。各个接口是 0000:03:00.00000:03:00.1。变量 ovs_dpdk_pci_addresses 是一个列表,可以这样定义这两个值

ovs_dpdk_pci_addresses:
  - 0000:03:00.0
  - 0000:03:00.1

ovs_dpdk_socket_mem 的值将根据 NUMA 节点的数量、每个 NUMA 节点的 NIC 数量以及 MTU 而变化。默认值假定单个 NUMA 节点并关联一个 1G 巨页到 DPDK,该巨页可以处理 1500 MTU。当有多个 NUMA 节点可用时,即使只有一个 NIC,也应设置以下内容

ovs_dpdk_socket_mem: "1024,1024"

对于使用单个 NUMA 节点的双 NUMA 系统和 9000 MTU,可以设置以下内容

ovs_dpdk_socket_mem: "3072,1024"

确定所需的套接字内存涉及超出本指南范围的计算。

Flavor 配置

连接到 DPDK 加速 Open vSwitch 的实例必须配置为通过自定义 flavor 属性使用大页(1G)。

可以将 hw:mem_page_size 属性设置为新的或现有的 flavor,以启用此功能。

openstack flavor set m1.small --property hw:mem_page_size=large

注意:如果使用小页大小,或者未设置页大小,则接口可能会出现在实例中,但将无法正常工作。

OpenStack-Ansible 用户变量

为您的网络主机创建 group var 文件 /etc/openstack_deploy/group_vars/network_hosts。它必须包含

# Ensure the openvswitch kernel module is loaded
openstack_host_specific_kernel_modules:
  - name: "openvswitch"
    pattern: "CONFIG_OPENVSWITCH"

在您的 /etc/openstack_deploy/openstack_user_config.yml 中指定 provider 网络定义,这些定义定义一个或多个 Neutron provider bridge 以及相关配置。

注意

此处指定的 bridge 将自动创建。如果定义了 *network_interface*,则该接口将自动放置到 bridge 中,作为 *DPDK 加速* 接口。

- network:
    container_bridge: "br-provider"
    container_type: "veth"
    type: "vlan"
    range: "101:200,301:400"
    net_name: "physnet1"
    network_interface: "eno49"
    group_binds:
      - neutron_openvswitch_agent

可以通过使用 network_bond_interfaces 指定成员接口列表来创建 *DPDK 加速* bond 接口。bond 端口将自动创建并添加到 OVS 中的相应 bridge 中。

- network:
    container_bridge: "br-provider"
    container_type: "veth"
    type: "vlan"
    range: "101:200,301:400"
    net_name: "physnet1"
    network_bond_interfaces:
      - "0000:04:00.0"
      - "0000:04:00.1"
    group_binds:
      - neutron_openvswitch_agent

可以使用以下键指定额外的 OVS bond 参数

  • bond_mode(默认值:active-backup)

  • lacp(默认值:off)

  • bond_downdelay(默认值:100)

  • bond_updelay(默认值:100)

- network:
    container_bridge: "br-provider"
    container_type: "veth"
    type: "vlan"
    range: "101:200,301:400"
    net_name: "physnet1"
    network_bond_interfaces:
      - "0000:04:00.0"
      - "0000:04:00.1"
    bond_mode: balance-tcp
    lacp: active
    bond_downdelay: 200
    bond_updelay: 200
    group_binds:
      - neutron_openvswitch_agent

有关可能值的更多信息,请访问:https://docs.ansible.org.cn/ansible/2025.2/collections/openvswitch/openvswitch/openvswitch_bond_module.html

在您的 /etc/openstack_deploy/user_variables.yml 中设置以下用户变量,以启用 Open vSwitch 驱动程序和 DPDK 支持。

neutron_plugin_type: ml2.ovs
neutron_ml2_drivers_type: "vlan"
neutron_plugin_base:
  - router
  - metering

# Enable DPDK support
ovs_dpdk_support: True

# Add these overrides or set on per-host basis in openstack_user_config.yml
ovs_dpdk_pci_addresses:
  - "0000:04:00.0"
  - "0000:04:00.1"
ovs_dpdk_lcore_mask: 1010101
ovs_dpdk_pmd_cpu_mask: 2020202
ovs_dpdk_socket_mem: "1024,1024"

注意

目前,DPDK 启用节点不支持叠加网络。

安装后

运行 playbook 并配置 OVS/DPDK 后,如果未定义 network_interfacenetwork_bond_interfaces,则可能需要在网络完全建立之前将物理接口添加到 provider bridge。

在计算节点上,可以使用以下命令将 NIC 端口 0000:04:00.0 附加到 provider bridge br-provider

ovs-vsctl add-port br-provider 0000:04:00.0 -- set interface 0000:04:00.0 type=dpdk options:dpdk-devargs=0000:04:00.0

此外,可能需要对接口队列或其他参数进行安装后调整,以避免 Open vSwitch 中的错误。

ovs-vsctl set interface 0000:04:00.0 options:n_txq=5
ovs-vsctl set interface 0000:04:00.0 options:n_rxq=5

可以根据您的配置调整命令。

警告

除非配置了 bonding,否则将多个端口添加到 bridge 可能会导致桥接环路。