第 8 章 配置 SR-IOV 网络
本章介绍了配置 SR-IOV 来把一个物理 NIC 传递到一个虚拟实例的方法。
8.1. SR-IOV 对虚拟网络的支持
RHEL OpenStack Platform 6 扩展了SR-IOV(single root I/O virtualization - 单引导 I/O 虚拟化)对虚拟机网络的支持。这意味着,OpenStack 可以不再需要虚拟网桥,而是把物理 NIC 的功能直接扩展到实例中。另外,通过对 IEEE 802.1br 的支持,虚拟 NIC 可以与物理交换机进行集成,并由它进行管理。
8.2. 在 RHEL OpenStack Platform 中配置 SR-IOV
这些步骤假设系统包括了一个 Controller 节点、一个 OpenStack Networking(neutron) 节点和多个 Compute(nova)节点。
当已存在了适当的 L2 配置(例如,flat 或 VLAN),使用 SR-IOV 端口的实例与使用普通端口(如连接到 Open vSwitch 网桥)的实例间就可以彼此进行通讯。当前,在相同 Compute 节点上的使用 SR-IOV 端口的实例与使用普通 vSwitch 端口的实例间的通讯有一个限制:如果它们在网卡上共享相同的 PF(Physical Function),则无法进行通讯。
8.3. 在 Compute 节点上创建虚拟功能
在带有支持硬件的全部 Compute 节点上执行这些步骤。它会配置一个系统来传递一个 Intel 82576 网络设备。同时,虚拟功能(Virtual Functions)也会被创建,实例可以使用它们来进行 SR-IOV 到设备的访问。
1. 确认 Intel VT-d 或 AMD IOMMU 已在系统的 BIOS 中启用。请参阅机器的 BIOS 配置菜单,或其它相关信息。
2. 确认 Intel VT-d 或 AMD IOMMU 已在操作系统中启用:
3. 运行 lspci 命令确保网络设备可以被系统识别:
[root@compute ~]# lspci | grep 82576
网络设备包括在结果中:
03:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01) 03:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01)
4. 执行以下步骤来在 Compute 节点上激活 Virtual Functions:4a.删除内核模块。在下一步中会对模块进行重新配置:
[root@compute ~]# modprobe -r igb
在第 4 步中,需要使用支持 SRIOV 的 NIC 所使用的模块,而不是使用其它 NIC 的 igb
(如 ixgbe
或 mlx4_core
)。运行 ethtool 命令来确认驱动。在这个例子中,em1
是我们需要使用的 PF(Physical Function):
[root@compute ~]# ethtool -i em1 | grep ^driver
4b. 启动模块时 max_vfs 的值为 7(或不多于被支持的最多数量)。
[root@compute ~]# modprobe igb max_vfs=7
4c. 使 Virtual Functions 有持久性:
[root@compute ~]# echo "options igb max_vfs=7" >>/etc/modprobe.d/igb.conf
对于 Red Hat Enterprise Linux 7,在执行完第 4 步后,执行 rebuild initramfs 操作。
在 4c. 和 4d. 中进行的设置持久性如下:modprobe
命令在使用相同内核模块的所有 NIC 上启用 Virtual Function,并在系统重新引导后仍然可以保持这个设置。虽然可以只在特定 NIC 上启用 VF,但这可能会造成一些问题。例如,使用以下命令来在 enp4s0f1
接口上启用 VF:
# echo 7 > /sys/class/net/enp4s0f1/device/sriov_numvfs
当系统重启后,这个设备将不会被保留。解决这个问题的一个方法是,把这个设置添加到 rc.local 中,但这个方法仍然有以下限制:
# chmod +x /etc/rc.d/rc.local # echo "echo 7 > /sys/class/net/enp4s0f1/device/sriov_numvfs" >> /etc/rc.local
因为额外的 systemd,Red Hat Enterprise Linux 将会并行启动服务,而不是依次启动它们。这意味着,rc.local 在引导过程中被执行的位置是不固定的。因此,一些不可预见的情况可能会出现,我们不推荐使用这个方法。
4d. 把 intel_iommu=on 和 igb.max_vfs=7 参数添加到 /boot/grub2/grub.cfg 文件的内核项中来在内核中激活 Intel VT-d:
i. 在 grub 中找到默认的项:
[root@compute ~]# grub2-editenv list saved_entry=Red Hat Enterprise Linux Server (3.10.0-123.9.2.el7.x86_64) 7.0 (Maipo)
ii. a. 把所需的 menuentry(以 saved_entry
的值开始)从 /boot/grub2/grub.cfg 复制到 /etc/grub.d/40_custom。它从以 menuentry 开头的行开始,直到包括 }
的行结束。
b. 修改 menuentry
后的标题。
c. 把 intel_iommu=on
添加到以 linux16
开始的行的后面。
例如:
menuentry 'Red Hat Enterprise Linux Server, with Linux 3.10.0-123.el7.x86_64 - SRIOV' --class red --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-123.el7.x86_64-advanced-4718717c-73ad-4f5f-800f-f415adfccd01' { load_video set gfxpayload=keep insmod gzio insmod part_msdos insmod ext2 set root='hd0,msdos2' if [ x$feature_platform_search_hint = xy ]; then search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos2 --hint-efi=hd0,msdos2 --hint-baremetal=ahci0,msdos2 --hint='hd0,msdos2' 5edd1db4-1ebc-465c-8212-552a9c97456e else search --no-floppy --fs-uuid --set=root 5edd1db4-1ebc-465c-8212-552a9c97456e fi linux16 /vmlinuz-3.10.0-123.el7.x86_64 root=UUID=4718717c-73ad-4f5f-800f-f415adfccd01 ro vconsole.font=latarcyrheb-sun16 biosdevname=0 crashkernel=auto vconsole.keymap=us nofb console=ttyS0,115200 LANG=en_US.UTF-8 intel_iommu=on igb.max_vfs=7 initrd16 /initramfs-3.10.0-123.el7.x86_64.img }
iii. 更新 grub.cfg 以使配置文件中的修改生效:
[root@compute ~]# grub2-mkconfig -o /boot/grub2/grub.cfg
iv. 修改默认的项:
[root@compute ~]# grub2-set-default 'Red Hat Enterprise Linux Server, with Linux 3.10.0-123.el7.x86_64 - SRIOV'
v. 创建 dist.conf 配置文件。
在执行这个步骤前,请重新查看描述 allow_unsafe_interrupts 的段落:检查 allow_unsafe_interrupts 的设置。
[root@compute ~]# echo "options vfio_iommu_type1 allow_unsafe_interrupts=1" > /etc/modprobe.d/dist.conf
5. 重启服务器以使新内核参数生效:
[root@compute ~]# systemctl reboot
6. 查看 Compute 节点上的 SR-IOV 内核模块。运行 lsmod 以确认模块已被加载:
[root@compute ~]# lsmod |grep igb
这个经过过滤的结果应该包括所需的模块:
igb 87592 0 dca 6708 1 igb
7. 检查 PCI 的厂商 ID:
记录下您的网卡的 PCI 厂商 ID(格式是 vendor_id:product_id)。运行带有 -nn 选项的 lspci 命令可以得到这个值。例如:
[root@compute ~]# lspci -nn | grep -i 82576 05:00.0 Ethernet controller [0200]: Intel Corporation 82576 Gigabit Network Connection [8086:10c9] (rev 01) 05:00.1 Ethernet controller [0200]: Intel Corporation 82576 Gigabit Network Connection [8086:10c9] (rev 01) 05:10.0 Ethernet controller [0200]: Intel Corporation 82576 Virtual Function [8086:10ca] (rev 01)
根据您的网卡硬件的具体情况,这个参数可能会不同。
8. 检查新的 Virtual Functions:
使用 lspci 列出新创建的 VF:
[root@compute ~]# lspci | grep 82576
这个结果会包括设备和 Virtual Function:
0b:00.0 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection (rev 01) 0b:00.1 Ethernet controller: Intel Corporation 82576 Gigabit Network Connection(rev 01) 0b:10.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:10.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:10.2 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:10.3 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:10.4 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:10.5 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:10.6 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:10.7 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:11.0 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:11.1 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:11.2 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:11.3 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:11.4 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01) 0b:11.5 Ethernet controller: Intel Corporation 82576 Virtual Function (rev 01)
8.4. 在 Network 节点上配置 SR-IOV
OpenStack Networking(neutron)使用 ML2 机制驱动来支持 SR-IOV。在 Network 网络上执行这些步骤来配置 SR-IOV 驱动。
1. 在 /etc/neutron/plugin.ini 文件中启用 sriovnicswitch。例如,这个配置启用了 SR-IOV 机制驱动和 Open vSwitch。
sriovnicswitch 不支持 DHCP Agent 的当前接口驱动,因此在使用 sriovnicswitch 时需要 openvswitch(或其它支持 VLAN 的机制驱动)。
[ml2] tenant_network_types = vlan type_drivers = vlan mechanism_drivers = openvswitch, sriovnicswitch [ml2_type_vlan] network_vlan_ranges = physnet1:15:20
- network_vlan_ranges - 在这个例子中,physnet1 被作为网络标签使用,VLAN 的范围是 15-20。
当前,只有 flat 和 vlan 支持机制驱动 sriovnicswitch。
2. 可选 - 如果您需要 VF 链接状态和 admin 状态管理,而且您的厂商支持这些功能,请在 /etc/neutron/plugins/ml2/ml2_conf_sriov.ini 文件中启用这个选项:
[root@network ~]# openstack-config --set /etc/neutron/plugins/ml2/ml2_conf_sriov.ini ml2_sriov agent_required True
3. 可选 - 支持的 vendor_id/product_id 组合是 15b3:1004, 8086:10ca。如果网卡厂商的产品 ID 和这个不同,则需要指定它们。例如:
[ml2_sriov] supported_pci_vendor_devs = 15b3:1004,8086:10ca
4. 配置 neutron-server.service 来使用 ml2_conf_sriov.ini 文件。例如:
[root@network ~]# vi /usr/lib/systemd/system/neutron-server.service [Service] Type=notify User=neutron ExecStart=/usr/bin/neutron-server --config-file /usr/share/neutron/neutron-dist.conf --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugin.ini --config-file /etc/neutron/plugins/ml2/ml2_conf_sriov.ini --log-file /var/log/neutron/server.log
5. 重启 neutron-server 服务来使配置生效:
[root@network ~]# systemctl restart neutron-server.service
8.5. 在 Controller 节点上配置 SR-IOV
1. 为了适当地调度 SR-IOV 设备,Compute 调度程序需要使用带有 PciPassthroughFilter 过滤的 FilterScheduler。在 Controller 节点上的 nova.conf 文件中应用这个配置。例如:
scheduler_available_filters=nova.scheduler.filters.pci_passthrough_filter.PciPassthroughFilter scheduler_default_filters=RetryFilter,AvailabilityZoneFilter,RamFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,CoreFilter, PciPassthroughFilter
2. 重启 Compute 调度器以使修改生效:
[root@compute ~]# systemctl restart openstack-nova-scheduler.service
8.6. 在 Compute 节点上配置 SR-IOV
在所有 Compute 节点上,为每个物理网络关联有效的 VF:1. 在 nova.conf 文件中定义这些项。在这个例子中,添加了匹配 enp5s0f1、tag physical_network 作为 physnet1,以及以前在 network_vlan_ranges 中配置的网络标签(network label)的 VF 网络。
pci_passthrough_whitelist={"devname": "enp5s0f1", "physical_network":"physnet1"}
在这个例子中,添加了匹配厂商 ID 8086、tag physical_network 的 PF 网络作为 physnet1:
pci_passthrough_whitelist = {"vendor_id": "8086","product_id": "10ac", "physical_network":"physnet1"}
PCI passthrough whitelist 项的格式如下:
["device_id": "<id>",] ["product_id": "<id>",] ["address": "[[[[<domain>]:]<bus>]:][<slot>][.[<function>]]" | "devname": "Ethernet Interface Name",] "physical_network":"Network label string"
- id - id 的值可以是通配符(*),或一个有效的 device/product id。您可以使用 lspci 列出有效的设备名。
- address - address 的格式与使用带有 -s 选项的 lspci 命令输出中的格式相同。
- devname - devname 是一个有效的 PCI 设备名称。您可以使用 ifconfig -a 列出全部有效的名称。这个项需要和与一个 vNIC 相关联的 PF 或 VF 值相对应。如果设备由代表一个 SR-IOV PF 的地址或 devname 来定义,则 PF 下的所有 VF 必须和这个项匹配。另外,可以把 0 个或多个 tag 关联到一个项。
- physical_network - 在使用 SR-IOV 网络时,"physical_network" 被用来指定设备附加到的物理网络。
和以前一样,可以使用多个 whitelist 项。device_id、product_id 和 address 或 devname 的值将会和查询 libvirt 所返回的 PCI 设备进行匹配。
2. 重启 nova-compute 服务以使所做的改变生效:
[root@compute ~]# systemctl restart openstack-nova-compute
8.7. 启用 OpenStack Networking SR-IOV agent
可选的 OpenStack Networking SR-IOV agent 启用了对 admin_state 端口的管理。这个 agent 与网络适配器进行集成,允许管理员打开/关闭 VF 的管理状态。
另外,如果 agent_required=True 已在 OpenStack Networking(neutron)服务器上配置,则需要在每个 Compute 节点上都运行 OpenStack Networking SR-IOV Agent。
当前,不是所有网卡厂商都支持使用这个 agent 管理端口状态。
1. 安装 sriov-nic-agent 软件包以便进行以下步骤:
[root@compute ~]# yum install openstack-neutron-sriov-nic-agent
2. 在 /etc/neutron/plugin.ini 文件中启用 NoopFirewallDriver:
[root@compute ~]# openstack-config --set /etc/neutron/plugin.ini securitygroup firewall_driver neutron.agent.firewall.NoopFirewallDriver
3. 在 /etc/neutron/plugins/ml2/ml2_conf_sriov.ini 文件中添加映射信息。在这个例子中,physnet1 是物理接口、eth1 是 physical function。把 exclude_devices 设为空来允许 agent 管理所有相关的 VF。
[sriov_nic] physical_device_mappings = physnet1:eth1 exclude_devices =
4. 可选 - 排除 VF:
为了在 agent 配置中排除特定的 VF,在 sriov_nic 项中列出要排除的 VF。例如:
exclude_devices = eth1:0000:07:00.2; 0000:07:00.3, eth2:0000:05:00.1; 0000:05:00.2
5. 配置 neutron-server.service 来使用 ml2_conf_sriov.ini 文件。例如:
[root@network ~]# vi /usr/lib/systemd/system/neutron-sriov-nic-agent.service [Service] Type=simple User=neutron ExecStart=/usr/bin/neutron-sriov-nic-agent --config-file /usr/share/neutron/neutron-dist.conf --config-file /etc/neutron/neutron.conf --log-file /var/log/neutron/sriov-nic-agent.log --config-file /etc/neutron/plugins/ml2/ml2_conf_sriov.ini
6. 启动 OpenStack Networking SR-IOV agent:
[root@network ~]# systemctl enable neutron-sriov-nic-agent.service [root@network ~]# systemctl start neutron-sriov-nic-agent.service
8.8. 配置一个实例来使用 SR-IOV 端口
在这个例子中,SR-IOV 端口被添加到 web 网络。
1. 获得有效的网络列表
[root@network ~]# neutron net-list +--------------------------------------+---------+------------------------------------------------------+ | id | name | subnets | +--------------------------------------+---------+------------------------------------------------------+ | 3c97eb09-957d-4ed7-b80e-6f052082b0f9 | corp | 78328449-796b-49cc-96a8-1daba7a910be 172.24.4.224/28 | | 721d555e-c2e8-4988-a66f-f7cbe493afdb | web | 140e936e-0081-4412-a5ef-d05bacf3d1d7 10.0.0.0/24 | +--------------------------------------+---------+------------------------------------------------------+
这个结果列出了已在 OpenStack Networking 中创建的网络,以及子网的详情。
2. 在 web 网络中创建端口
[root@network ~]# neutron port-create web --name sr-iov --binding:vnic-type direct Created a new port: +-----------------------+---------------------------------------------------------------------------------+ | Field | Value | +-----------------------+---------------------------------------------------------------------------------+ | admin_state_up | True | | allowed_address_pairs | | | binding:host_id | | | binding:profile | {} | | binding:vif_details | {} | | binding:vif_type | unbound | | binding:vnic_type | normal | | device_id | | | device_owner | | | fixed_ips | {"subnet_id": "140e936e-0081-4412-a5ef-d05bacf3d1d7", "ip_address": "10.0.0.2"} | | id | a2122b4d-c9a9-4a40-9b67-ca514ea10a1b | | mac_address | fa:16:3e:b1:53:b3 | | name | sr-iov | | network_id | 721d555e-c2e8-4988-a66f-f7cbe493afdb | | security_groups | 3f06b19d-ec28-427b-8ec7-db2699c63e3d | | status | DOWN | | tenant_id | 7981849293f24ed48ed19f3f30e69690 | +-----------------------+---------------------------------------------------------------------------------+
3. 使用新端口创建一个实例:
创建一个名为 webserver01 的新实例,配置它来使用新端口(端口 ID 是前一个输出中的 id 项中的值):
您可以使用 glance image-list 命令来获得有效镜像的列表,以及它们的 UUID。
[root@compute ~]# nova boot --flavor m1.tiny --image 59a66200-45d2-4b21-982b-d06bc26ff2d0 --nic port-id=a2122b4d-c9a9-4a40-9b67-ca514ea10a1b webserver01
您的新实例 webserver01 被创建,并配置为使用 SR-IOV 端口。
8.9. 检查 allow_unsafe_interrupts 设置
为了完全把带有分配设备的客户机与主机分离,需要平台对中断重映射功能的支持。如果不支持这个功能,主机可能会受到来自于恶意客户机上的中断注入攻击(interrupt injection attack)。而在一个客户端可以被完全信任的环境中,管理员可能会允许使用 allow_unsafe_interrupts 选项进行 PCI 设备的分配。您需要根据具体情况检查是否在主机上启用 allow_unsafe_interrupts。如果主机上的 IOMMU 支持中断重映射功能,则不需要启用这个选项。
1. 使用 dmesg 检查您的主机是否支持 IOMMU 中断重映射功能:
[root@compute ~]# dmesg |grep ecap
当 ecap (0xf020ff
2. 确认 IRQ 重映射是否已被启用:
[[root@compute ~]]# dmesg |grep "Enabled IRQ" [ 0.033413] Enabled IRQ remapping in x2apic mode
如需手工禁用 "IRQ remapping",把 intremap=off 添加到 grub.conf 文件中。
3. 如果主机的 IOMMU 不支持中断重映射,您需要在 kvm 模块中启用 allow_unsafe_assigned_interrupts=1。
8.10. 额外需要考虑的因素
- 在选择 vNIC 类型时请注意,当前还不支持 vnic_type=macvtap。
- 不支持带有附加了 SR-IOV 实例的 VM 迁移。
- 当前,安全组不能在启用了 SR-IOV 的端口中使用。