Overview
Ubuntu で何らかの形で DPDK を実装したかったのですが、試行錯誤の上、諦めたという話です。
簡単な構成イメージは以下の通りです。
- KVM を使う。
- OVS-DPDK を使う。DPDK を試すにあたり、対応するアプリケーションなどを考えるのが面倒だったので、試すのはこれが簡単そうな気がする。
- vHostUserClient を使う。ソケット通信になるので速そうだし、そんなにハードルも高くなさそう。
- 更なるチャレンジとして、この DPDK ブリッジを Kubernetesの Multus に割り当て、Pod から NFS ストレージへの通信を高速化できると最高。
という構成で環境構築を進めていきます。
IOMMU と HugePage
IOMMU と HugePage は DPDK を実装するにあたり必須です。以下は一般的な手順ですね。
myadmin@ubuntu:~$ sudo mv /etc/default/grub /etc/default/grub.orig
myadmin@ubuntu:~$ sudo tee /etc/default/grub <<"EOF"
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=0
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt default_hugepagesz=1G hugepagesz=1G hugepages=4"
EOF
myadmin@ubuntu:~$ sudo update-grub
myadmin@ubuntu:~$ sudo reboot
再起動後、問題なければ以下のように IOMMU の有効化を確認できます。
myadmin@ubuntu:~$ sudo dmesg | grep -i iommu
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-5.15.0-91-generic root=/dev/mapper/vg0-root ro intel_iommu=on iommu=pt default_hugepagesz=1G hugepagesz=1G hugepages=4
[ 0.063810] Kernel command line: BOOT_IMAGE=/vmlinuz-5.15.0-91-generic root=/dev/mapper/vg0-root ro intel_iommu=on iommu=pt default_hugepagesz=1G hugepagesz=1G hugepages=4
[ 0.063856] DMAR: IOMMU enabled
[ 0.164805] DMAR-IR: IOAPIC id 2 under DRHD base 0xfed91000 IOMMU 1
[ 0.340136] iommu: Default domain type: Passthrough (set via kernel command line)
[ 0.394548] DMAR: IOMMU feature fl1gp_support inconsistent
[ 0.394549] DMAR: IOMMU feature pgsel_inv inconsistent
[ 0.394551] DMAR: IOMMU feature nwfs inconsistent
[ 0.394553] DMAR: IOMMU feature pasid inconsistent
[ 0.394555] DMAR: IOMMU feature eafs inconsistent
[ 0.394557] DMAR: IOMMU feature prs inconsistent
[ 0.394559] DMAR: IOMMU feature nest inconsistent
[ 0.394561] DMAR: IOMMU feature mts inconsistent
[ 0.394563] DMAR: IOMMU feature sc_support inconsistent
[ 0.394565] DMAR: IOMMU feature dev_iotlb_support inconsistent
[ 0.394766] pci 0000:00:00.0: Adding to iommu group 0
[ 0.394779] pci 0000:00:01.0: Adding to iommu group 1
[ 0.394787] pci 0000:00:02.0: Adding to iommu group 2
[ 0.394800] pci 0000:00:14.0: Adding to iommu group 3
[ 0.394808] pci 0000:00:14.2: Adding to iommu group 3
[ 0.394821] pci 0000:00:16.0: Adding to iommu group 4
[ 0.394830] pci 0000:00:17.0: Adding to iommu group 5
[ 0.394840] pci 0000:00:1d.0: Adding to iommu group 6
[ 0.394857] pci 0000:00:1f.0: Adding to iommu group 7
[ 0.394866] pci 0000:00:1f.2: Adding to iommu group 7
[ 0.394874] pci 0000:00:1f.3: Adding to iommu group 7
[ 0.394881] pci 0000:00:1f.4: Adding to iommu group 7
[ 0.394890] pci 0000:00:1f.6: Adding to iommu group 8
[ 0.394895] pci 0000:01:00.0: Adding to iommu group 1
[ 0.394900] pci 0000:01:00.1: Adding to iommu group 1
[ 0.394912] pci 0000:02:00.0: Adding to iommu group 9
[ 0.394922] pci 0000:02:00.1: Adding to iommu group 10
HugePage は以下のように確認できます。
myadmin@ubuntu:~$ cat /proc/meminfo | grep -e Mem -e Huge
MemTotal: 32775256 kB
MemFree: 27857296 kB
MemAvailable: 27850408 kB
AnonHugePages: 0 kB
ShmemHugePages: 0 kB
FileHugePages: 0 kB
HugePages_Total: 4
HugePages_Free: 4
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 1048576 kB
Hugetlb: 4194304 kB
ovs-vswitchd の実行ファイルの切り替え
ovs-vswitchd を実行した際の実体を ovs-vswitchd-dpdk に切り替えます。改めてよく見たら切り替わっていないように見えますね(これが原因?)
myadmin@ubuntu:~$ update-alternatives --query ovs-vswitchd
Name: ovs-vswitchd
Link: /usr/sbin/ovs-vswitchd
Status: manual
Best: /usr/lib/openvswitch-switch/ovs-vswitchd
Value: /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
Alternative: /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
Priority: 50
Alternative: /usr/lib/openvswitch-switch/ovs-vswitchd
Priority: 100
myadmin@ubuntu:~$ sudo update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
myadmin@ubuntu:~$ update-alternatives --query ovs-vswitchd
Name: ovs-vswitchd
Link: /usr/sbin/ovs-vswitchd
Status: manual
Best: /usr/lib/openvswitch-switch/ovs-vswitchd
Value: /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
Alternative: /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk
Priority: 50
Alternative: /usr/lib/openvswitch-switch/ovs-vswitchd
Priority: 100
NIC ドライバーのバインド
今回は、0000:02:00.0, 0000:02:00.1 を vfio-pci にしてカーネルから切り離します。
myadmin@ubuntu:~$ sudo driverctl -v list-devices | grep -i net
0000:00:1f.6 e1000e (Ethernet Connection (2) I219-LM)
0000:02:00.0 igb (82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter))
0000:02:00.1 igb (82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter))
myadmin@ubuntu:~$ sudo driverctl set-override 0000:02:00.0 vfio-pci
myadmin@ubuntu:~$ sudo driverctl set-override 0000:02:00.1 vfio-pci
myadmin@ubuntu:~$ sudo driverctl -v list-devices | grep -i net
0000:00:1f.6 e1000e (Ethernet Connection (2) I219-LM)
0000:02:00.0 vfio-pci [*] (82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter))
0000:02:00.1 vfio-pci [*] (82576 Gigabit Network Connection (Gigabit ET Dual Port Server Adapter))
DPDK の有効化
OVS で DPDK を有効化します。
sudo ovs-vsctl set Open_vSwitch . "other_config:dpdk-init=true"
ブリッジの作成と DPDK ポートの追加
今回は2つのブリッジを作成しています。ストレージ用とサービス用です。
sudo ovs-vsctl add-br storage -- set bridge storage datapath_type=netdev
sudo ovs-vsctl add-port storage dpdk0 -- set Interface dpdk0 type=dpdk "options:dpdk-devargs=0000:02:00.0" mtu_request=9000
sudo ovs-vsctl add-br service -- set bridge service datapath_type=netdev
sudo ovs-vsctl add-port service dpdk1 -- set Interface dpdk1 type=dpdk "options:dpdk-devargs=0000:02:00.1"
vHostUserClient ポート
ソケットファイルを配置するディレクトリを作成します。以下は一例なので好みに合わせてどこでも良いです。
sudo mkdir -p /opt/openvswitch/vhuc
sudo chown -R libvirt-qemu:kvm /opt/openvswitch/vhuc
storage, service のブリッジに dpdkvhostuserclient インターフェイスを接続します。このファイル自体は後述の仮想マシンのインターフェイス設定後の起動のタイミングで自動生成されます。
sudo ovs-vsctl add-port storage storage-vhuc00 \
-- set Interface storage-vhuc00 type=dpdkvhostuserclient options:vhost-server-path=/opt/openvswitch/vhuc/storage-vhuc00
sudo ovs-vsctl add-port service service-vhuc00 \
-- set Interface service-vhuc00 type=dpdkvhostuserclient options:vhost-server-path=/opt/openvswitch/vhuc/service-vhuc00
状態の確認
このタイミングで一旦状態を確認しておきます。
sudo ovs-vsctl show
sudo ovs-vsctl del-br storage
sudo ovs-vsctl del-br service
sudo ovs-vsctl del-port storage storage-vhuc00
sudo ovs-vsctl del-port service service-vhuc00
仮想マシンに vHostUserClient を割り当て
仮想マシンのインターフェイス設定を vHostUserClient に書き換えます。
virsh edit dpdk-test.si1230.com
<interface type='vhostuser'>
<source type='unix' path='/opt/openvswitch/vhuc/storage-vhuc00' mode='server'/>
<model type='virtio'/>
</interface>
<interface type='vhostuser'>
<source type='unix' path='/opt/openvswitch/vhuc/service-vhuc00' mode='server'/>
<model type='virtio'/>
</interface>
まとめ
上記までの設定に大きな問題はないように思ましたが、実際には外部との通信ができず、諦めています。参照していた 1 サイトによると、vHostUserClient を使用する際の KVM は root で実行することが前提などの記載もあり、それが原因なのかもしれません。今回は KVM 上で色々動かすことも目的だったので、早々に諦めましたが、致命的に考え方や設定方針がずれているわけではなさそうなので、折を見てリベンジしようと思います。それにしてももうちょいな気がするのですが。