第9章 仮想ネットワークの SR-IOV サポート

RHEL OpenStack Platform 6 から実装されているシングルルート I/O 仮想化 (SR-IOV) のサポートは、仮想ネットワークにまで拡張されました。SR-IOV により、OpenStack は仮想ブリッジに対する以前の要件を無視して、代わりに物理 NIC の機能を直接インスタンスにまで拡張することができます。また、IEEE 802.1br のサポートにより、仮想 NIC が物理スイッチに統合され、この物理スイッチにより仮想 NIC を管理することができます。

9.1. RHEL OpenStack Platform デプロイメントでの SR-IOV の設定

SR-IOV により、Virtual Function の概念がサポートされます。これは、Physical Function によって提供される 仮想インターフェース で、ハードウェア上では PCI デバイスとして表されます。

本章には、物理 NIC が仮想インスタンスにパススルーできるように、SR-IOV を設定する手順が含まれています。以下の手順では、単一のコントローラーノード、単一の OpenStack Networking (neutron) ノード、複数の Compute (nova) ノードを使用するデプロイメントを前提としています。

注記: SR-IOV の Virtual Function (VF) ポートを使用する仮想マシンのインスタンスと、通常のポート (例: Open vSwitch ブリッジに接続されたポート) を使用する仮想マシンのインスタンスの間では、ネットワーク上での相互通信が可能です。これは、L2 設定 (フラット、VLAN) が適切に行われていることを前提とします。現在制約があるため、SR-IOV ポートを使用するインスタンスと、同じコンピュートノード上に設定されている通常の vSwitch ポートを使用するインスタンスが、ネットワークアダプター上で同じ PF を共有している場合には、それらのインスタンス間では相互通信はできません。

9.2. コンピュートノードでの VF の作成

サポート対象ハードウェアを使用する全コンピュートノードで以下の手順を実行します。

注記: サポート対象のドライバーについての詳しい情報は、この記事 を参照してください。

以下の手順では、システムが Intel 82576 ネットワークデバイスをパススルーするように設定します。また、Virtual Function も作成され、インスタンスがこの Virtual Function を使用して、デバイスに SR-IOV アクセスすることができます。

1. Intel VT-d または AMD IOMMU がお使いのシステムの BIOS で有効になっていることを確認してください。マシンの BIOS 設定メニューまたはメーカーから提供されているその他の手法を参照してください。

2. Intel VT-d または AMD IOMMU がオペレーティングシステムで有効になっているかどうかを確認します。

  • 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. 以下のステップを実行して、コンピュートノードで VF を有効化します。

4a. カーネルモジュールを削除します。これで、カーネルモジュールを次のステップで設定できるようになります。

[root@compute ~]# modprobe -r igb

注記: SRIOV をサポートする NIC が使用するモジュールは、他の NIC の igb ではなく (例: ixgbe または mlx4_core)、ステップ 4 で使用する必要があります。ethtool コマンドを実行して、ドライバーを確認します。この例では、em1 が使用予定の PF (Physical Function) です。

[root@compute ~]# ethtool -i em1 | grep ^driver

4b. max_vfs を 7 (サポートされている最大数以下の値) に設定して、モジュールを開始します。

[root@compute ~]# modprobe igb max_vfs=7

4c. VF を永続化します。

[root@compute ~]# echo "options igb max_vfs=7" >>/etc/modprobe.d/igb.conf

注記: Red Hat Enterprise Linux 7 の場合は、上記の変更を永続化させるために、ステップ 4 の完了後に 「Red Hat Enterprise Linux で、initial ramdisk イメージをリビルドする方法」の記事に記載の手順を実行します。

注記: ステップ 4c. および 4d. の設定の永続化について: modprobe コマンドにより、同じカーネルモジュールを使用するすべての NIC 上で VF が有効化され、システムの再起動後も変更が永続化されるようになります。特定の 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=ptigb.max_vfs=7 のパラメーターをカーネルコマンドラインに追記して、Intel VT-d をアクティブ化します。常にこの方法を使用してカーネルを起動する場合には、現在の設定を変更するか、これらのパラメーターを使用したカスタムメニューエントリーを作成することができます。その場合は、システムはデフォルトでそれらのパラメーターを使用してブートしますが、必要な場合にはそれらのパラメーターを使用せずにもカーネルを起動することも可能です。

現在のカーネルコマンドラインパラメーターを変更するには、以下のコマンドを実行します。

[root@compute ~]# grubby --update-kernel=ALL --args="intel_iommu=pt igb.max_vfs=7"

grubby の使用に関する詳しい情報は、『System Administrator's Guide』の「Making Persistent Changes to a GRUB 2 Menu Using the grubby Tool」のセクションを参照してください。

注記: Dell Power Edge R630 ノードを使用している場合には、intel_iommu=pt の代わりに intel_iommu=on を使用する必要があります。これは、grubby で有効にすることができます。

# grubby --update-kernel=ALL --args="intel_iommu=on"

カスタムのメニューエントリーを作成します。

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. saved_entry の値で始まる、任意の menuentry/boot/grub2/grub.cfg から /etc/grub.d/40_custom にコピーします。このエントリーは「menuentry」で開始し、「}」を含む行で終了します。b. menuentry の後ろのタイトルを変更します。c. linux16 で始まる行の最後に、intel_iommu=pt igb.max_vfs=7 を追加します。

例:

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=pt 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. コンピュートノードの 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. 新しい VF を確認します。lspci を使用して、新規作成された VF を一覧表示します。

[root@compute ~]# lspci | grep 82576

以下のように、結果には、デバイスと VF が含まれて表示されます。

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)

9.3. ネットワークノードでの SR-IOV の設定

OpenStack Networking (neutron) では ML2 メカニズムドライバーを使用して、SR-IOV をサポートします。ネットワークノードで以下のステップを実行して、SR-IOV ドライバーを設定します。この手順では、メカニズムドライバーを追加して、有効なドライバーの中に vlan が含まれていることを確認してから、VLAN の範囲を定義します。

1. /etc/neutron/plugin.ini ファイルで sriovnicswitch を有効化します。たとえば、この設定により、Open vSwitch に加え、SR-IOV メカニズムドライバーが有効化されます。

注記: sriovnicswitch は、DHCP エージェント の現在のインターフェースドライバーをサポートしません。そのため、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 が続きます。

注記: メカニズムドライバーsriovnicswitch は現在 flat および vlan のドライバーのみをサポートしていますが、sriovnicswitch を有効にすると、flat または vlan のテナントネットワークには限定されなくなります。SR-IOV ポートを使用していないインスタンスでは、VXLAN および GRE なども引き続き使用することができます。

2. (オプション) VF のリンク状態と管理状態を管理する必要がある場合には、/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 です。これと異なる場合には、お使いの NIC ベンダーの製品 ID を指定してください。以下に例を示します。

[ml2_sriov]
supported_pci_vendor_devs = 15b3:1004,8086:10ca

4. neutron-server.serviceml2_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

9.4. コントローラーでの SR-IOV の設定

1. SR-IOV デバイスを適切にスケジュールできるように、コンピュートスケジューラーは PciPassthroughFilter フィルターで FilterScheduler を使用する必要があります。コントローラーノードの nova.conf ファイルでこの設定を適用します。以下に例を示します。

scheduler_available_filters=nova.scheduler.filters.all_filters
scheduler_default_filters=RetryFilter,AvailabilityZoneFilter,RamFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,CoreFilter, PciPassthroughFilter

2. コンピュートスケジューラーを再起動して、変更を適用します。

[root@compute ~]# systemctl restart openstack-nova-scheduler.service

9.5. コンピュートの SR-IOV 設定

全コンピュートノード上で、利用可能な VF と各物理ネットワークを関連付けます。

1. nova.conf ファイルでエントリーを定義します。この例では、enp5s0f1 と一致する VF ネットワークを追加して、physical_networkphysnet1 (前の手順で network_vlan_ranges に設定したネットワークラベル) としてタグ付けします。

pci_passthrough_whitelist={"devname": "enp5s0f1", "physical_network":"physnet1"}

この例では、ベンダー ID 8086 と一致する PF ネットワークを追加し、physical_networkphysnet1 としてタグ付けします: ~ pci_passthrough_whitelist = \{"vendor_id": "8086","product_id": "10ac", "physical_network":"physnet1"} ~

PCI パススルーのホワイトリストエントリーは、以下の構文を使用します。

["device_id": "<id>",] ["product_id": "<id>",]
["address": "[[[[<domain>]:]<bus>]:][<slot>][.[<function>]]" |
"devname": "Ethernet Interface Name",]
"physical_network":"Network label string"
  • id: id 設定はワイルドカードの値 (*)、または有効なデバイス/製品 ID を受け入れます。lspci を使用して、有効なデバイス名を一覧表示します。
  • address: address の値は、-s スイッチを使用して lspci で表示されたのと同じ構文を使用します。
  • devname: devname は、有効な PCI デバイス名です。ifconfig -a を使用して、利用可能な名前を一覧表示できます。このエントリーは、仮想 NIC に関連付けた PF または VF の値のいずれかと一致する必要があります。address または devname で定義したデバイスが SR-IOV PF と一致する場合は、PF の配下にある VF もすべてこのエントリーと一致します。エントリーに関連付けることのできるタグ数は 0 個以上です。
  • physical_network: SR-IOV ネットワークを使用する場合には、「physical_network」を使用して、デバイスのアタッチ先の物理ネットワークを定義します。

1 ホストあたりの複数のホワイトリストエントリーを指定する点はすでにサポートされています。device_idproduct_idaddress または devname のフィールドは、libvirt のクエリー結果として返された PCI デバイスと照合されます。

2. nova-compute サービスを再起動して変更を適用します。

[root@compute ~]# systemctl restart openstack-nova-compute

9.6. OpenStack Networking の SR-IOV エージェントの有効化

OpenStack Networking の SR-IOV エージェントにより、admin_state ポートの管理が有効になります。このエージェントを使用してネットワークアダプターを統合することで、管理者は VF の管理状態の up/down を切り替えることができるようになります。

また、OpenStack Networking (neutron) サーバー上で、agent_required=True を設定した場合には、各コンピュートノード上で OpenStack Networking の SR-IOV エージェントを実行する必要があります。

注記: 現在、すべての NIC ベンダーが、このエージェントを使用したポートの状態管理をサポートしているわけではありません。

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 が物理ネットワークで、enp4s0f1 が Physical Function (PF) です。exclude_devices を空白にして、関連付けられたすべての VF を、エージェントが管理できるようにします。

[sriov_nic]
physical_device_mappings = physnet1:enp4s0f1
exclude_devices =

4. (オプション) VF を除外します。エージェントの設定から特定の 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-sriov-nic-agent.serviceml2_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 エージェントを起動します。

[root@network ~]# systemctl enable neutron-sriov-nic-agent.service
[root@network ~]# systemctl start neutron-sriov-nic-agent.service

9.7. 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 ポートを使用するように設定されました。

9.8. allow_unsafe_interrupts 設定のレビュー

割り込み再マッピングのプラットフォームサポートは、割り当てデバイスを持つゲストをホストから完全に分離するために必要です。このサポートがない場合、ホストは悪意のあるゲストからのインジェクション攻撃に対して脆弱になる可能性があります。ゲストが信頼される環境では、管理者は引き続き allow_unsafe_interrupts オプションを使用する PCI デバイスの割り当てを選択することができます。ホストで allow_unsafe_interrupts を有効化する必要があるかどうかを確認します。ホストの IOMMU が割り込み再マッピングをサポートする場合には、この機能を有効にする必要はありません。

1. dmesg を使用して、ホストが IOMMU の割り込み再マッピングをサポートするかどうかを確認します。

[root@compute ~]# dmesg |grep ecap

ecap (0xf020ff → …​1111) のビット 3 が 1 の場合には、IOMMU が割り込み再マッピングをサポートしていることが分かります。

2. IRQ 再マッピングが有効化されているかどうかを確認します。

[root@compute ~]# dmesg |grep "Enabled IRQ"
[    0.033413] Enabled IRQ remapping in x2apic mode

注記: 「IRQ 再マッピング」は grub.confintremap=off を追加することで、手動で無効化できます。

3. ホストの IOMMU が割り込み再マッピングをサポートしない場合には、kvm モジュールで allow_unsafe_assigned_interrupts=1 を有効にする必要があります。

9.9. その他の留意事項

  • 仮想 NIC の種別を選択する場合には、vnic_type=macvtap は現在サポートされていない点にご注意ください。
  • インスタンスに SR-IOV が接続された状態での仮想マシンの移行はサポートされていません。
  • 現在、SR-IOV が有効なポートでは、セキュリティーグループを使用できません。