CentOS8によるovs(Open vSwitch)+DPDKのビルドとネットワーク設定方法について記載しました。
基本的にはCentOS7と同様ですが、CentOS8の場合はdpdkのパッケージがあるため、比較的楽に導入出来ます。
1.構成
1-1.環境
筐体 : ProLiant DL360e Gen8 System ROM : P73 01/22/2018 NIC : Intel X540-AT2 OS : CentOS8.0(1905) Kernel : 4.18.0-80.el8.x86_64 Installed Environment Groups : @^graphical-server-environment @container-management @development @virtualization-client @virtualization-hypervisor @virtualization-tools ovs : 2.12.90 DPDK : 18.11.3
1-2.全体の流れ
事前準備
DPDKインストール
OvSソースビルド
OvS+DPDKのネットワーク設定
仮想マシンのvirsh edit
2.事前準備
2-1.qemu-kvmの実行ユーザをrootへ変更
qemu-kvmの実行ユーザをqemu→rootに変更します。
vi /etc/libvirt/qemu.conf user = "root" #コメントを外す group = "root" #コメントを外す
2-2.必要なパッケージのインストール
sed -i -e s/enabled=0/enabled=1/g /etc/yum.repos.d/CentOS-PowerTools.repo dnf -y install libpcap-devel elfutils-libelf-devel numactl-devel libmnl-devel clang
2-3.HugePageとIOMMUの有効化
sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ default_hugepagesz=1G hugepagesz=1G hugepages=16\"/g" /etc/default/grub sed -i -e "/GRUB_CMDLINE_LINUX=/s/\"$/ intel_iommu=on iommu=pt pci=realloc\"/g" /etc/default/grub grub2-mkconfig -o /etc/grub2.cfg reboot
2-4.HugePageの確認とマウント
grep Huge /proc/meminfo 出力例 # grep Huge /proc/meminfo AnonHugePages: 135168 kB HugePages_Total: 16 HugePages_Free: 16 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 1048576 kB vi /etc/fstab 最終行に以下を追記 nodev /mnt/huge_1GB hugetlbfs pagesize=1GB 0 0
HugePageの割り当て状況確認
HugePageの永続化マウント
3.DPDKインストール
3-1.インストール
dnf -y install dpdk dpdk-devel dpdk-doc dpdk-tools
4.OvSソースビルド
4-1.ビルド環境準備
ビルド環境の準備をします。
cd /usr/src git clone https://github.com/openvswitch/ovs.git
ディレクトリ移動
git cloneにてソースのダウンロード
4-2.ビルド
ソースからビルドします。
export DPDK_BUILD=/usr/share/dpdk/x86_64-default-linuxapp-gcc && \ cd /usr/src/ovs && \ ./boot.sh && \ ./configure --with-dpdk=$DPDK_BUILD CC=clang && \ make && \ make install
dpdk-develへのパスを指定
ディレクトリ移動
boot.sh実行
configure実行*2
ビルド
インストール
多少時間は掛かりますが、最後の方は以下のような出力がでれば正常にビルドが完了しています。
onitor-ipsec vtep/ovs-vtep '/usr/local/share/openvswitch/scripts' make[3]: Leaving directory '/usr/src/ovs' make[2]: Leaving directory '/usr/src/ovs' make[1]: Leaving directory '/usr/src/ovs'
5.OvS+DPDKのネットワーク設定
5-1.全体構成
前回記事の構成図と比較してください。
グレーアウト&斜体文字になっているのが前回設定した箇所です。
今回は(1)~(6)の黒文字になっている箇所を設定していきます。
5-2.全体の流れ ~概要~
- DPDKにバインド:(1)(2)
- Bridge作成:(3)
- Bond作成:(4)
- vHostUserClientポート作成:(5)
- 仮想マシンの設定:(6)
5-3.コマンド投入前準備1
コマンド投入前には以下のようにパスを通しておいてください。*3
vi /root/.bash_profile PATH=$PATH:$HOME/bin:/usr/local/share/openvswitch/scripts export PATH
5-4.コマンド投入前準備2
OvSを起動後、DPDK周りの詳細設定を追加しておきます。
ovs-ctl --system-id=random start ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem=1024,1024 ovs-vsctl --no-wait set Open_vSwitch . other_config:vhost-iommu-support=true ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0x33 ovs-vsctl --no-wait get Open_vSwitch . other_config
OvSサービスの開始
DPDKの初期化
NUMA毎のメモリ設定(単位MB)
PMD-CPUマスクの設定
設定内容の確認
上記のうち、dpdk-init=true以外はチューニングパラメータなので、設定しなくてもとりあえずは動きます。
5-5.全体の流れ ~コマンドのみ~
以下のコマンドを投入していきます。
やりたいことが既に決まっている方は、構成図とコマンドの内容を見るだけでもよいと思います。
1.DPDKにバインド (1) dpdk-devbind --status dpdk-devbind --bind=vfio-pci ens1f0 (2) dpdk-devbind --bind=vfio-pci ens1f1 dpdk-devbind --status 2.Bridge作成 (3) ovs-ctl --system-id=random stop ovs-ctl --system-id=random start ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev 3.Bond作成 (4) ovs-vsctl add-bond ovsbr0 bond0 dpdk0 dpdk1 \ vlan_mode=trunk trunks=11,300-304 \ bond_mode=balance-tcp lacp=active other_config:lacp-time=fast \ -- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:08:00.0 \ -- set Interface dpdk1 type=dpdk options:dpdk-devargs=0000:08:00.1 4.vHostUserClientポート作成 (5) mkdir -p /usr/local/openvswitch/ touch /usr/local/openvswitch/vhuc0 ovs-vsctl add-port ovsbr0 vhuc0 \ vlan_mode=access tag=300 \ -- set Interface vhuc0 type=dpdkvhostuserclient \ options:vhost-server-path=/usr/local/openvswitch/vhuc0 5.仮想マシンの設定 (6) virsh edit Guest3 <currentMemory unit='KiB'>1048576</currentMemory> <memoryBacking> <hugepages> <page size='1048576' unit='KiB' nodeset='0'/> </hugepages> </memoryBacking> <cpu mode='host-passthrough' check='none'> <numa> <cell id='0' cpus='0' memory='1048576' unit='KiB' memAccess='shared'/> </numa> </cpu> <interface type='vhostuser'> <source type='unix' path='/usr/local/openvswitch/vhuc0' mode='server'/> <model type='virtio'/> </interface> ※ 青=追記,緑=置換
6.DPDKにバインド
Kernel上で動作しているX540をDPDK上で動作されるようにバインドします。*4
(1)
dpdk-devbind --status
dpdk-devbind --bind=vfio-pci ens1f0
(2)
dpdk-devbind --bind=vfio-pci ens1f1
dpdk-devbind --status
[root@c80gmas ~]# dpdk-devbind --status Network devices using kernel driver =================================== 0000:02:00.0 'I350 Gigabit Network Connection 1521' if=eno1 drv=igb unused=vfio-pci,uio_pci_generic *Active* 0000:02:00.1 'I350 Gigabit Network Connection 1521' if=eno2 drv=igb unused=vfio-pci,uio_pci_generic 0000:02:00.2 'I350 Gigabit Network Connection 1521' if=eno3 drv=igb unused=vfio-pci,uio_pci_generic 0000:02:00.3 'I350 Gigabit Network Connection 1521' if=eno4 drv=igb unused=vfio-pci,uio_pci_generic 0000:08:00.0 'Ethernet Controller 10-Gigabit X540-AT2 1528' if=ens1f0 drv=ixgbe unused=vfio-pci,uio_pci_generic 0000:08:00.1 'Ethernet Controller 10-Gigabit X540-AT2 1528' if=ens1f1 drv=ixgbe unused=vfio-pci,uio_pci_generic [root@c80gmas ~]# dpdk-devbind.py --bind=vfio-pci ens1f0 [root@c80gmas ~]# dpdk-devbind.py --bind=vfio-pci ens1f1 [root@c80gmas ~]# dpdk-devbind.py --status Network devices using DPDK-compatible driver ============================================ 0000:08:00.0 'Ethernet Controller 10-Gigabit X540-AT2 1528' drv=vfio-pci unused=ixgbe,uio_pci_generic 0000:08:00.1 'Ethernet Controller 10-Gigabit X540-AT2 1528' drv=vfio-pci unused=ixgbe,uio_pci_generic Network devices using kernel driver =================================== 0000:02:00.0 'I350 Gigabit Network Connection 1521' if=eno1 drv=igb unused=vfio-pci,uio_pci_generic *Active* 0000:02:00.1 'I350 Gigabit Network Connection 1521' if=eno2 drv=igb unused=vfio-pci,uio_pci_generic 0000:02:00.2 'I350 Gigabit Network Connection 1521' if=eno3 drv=igb unused=vfio-pci,uio_pci_generic 0000:02:00.3 'I350 Gigabit Network Connection 1521' if=eno4 drv=igb unused=vfio-pci,uio_pci_generic
バインドされると、X540がNetwork devices using DPDK-compatible driverに表示されます。
今回利用するドライバはvfio-pciですが、uio_pci_genericでも利用可能です。
利用したい場合は、以下のように変更すればOKです。
dpdk-devbind --bind=uio_pci_generic ens1f0
また、vfio-pciを利用するにあたり、ProLiant DL360G8を使用している方はRMRR設定が必要になる場合があります。
以下のサイトを参考にしてみてください。
DPDK and RMRR Compatibility Issues on the HP Proliant DL360e G8 | www.jimmdenton.com
https://support.hpe.com/hpsc/doc/public/display?sp4ts.oid=7271259&docId=emr_na-c04781229&docLocale=ja_JP
7.Bridge作成
念のため、ovsの再起動をした後、Bridge作成を行ってください。
(3)
ovs-ctl --system-id=random stop
ovs-ctl --system-id=random start
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
[root@c80gmas ~]# ovs-ctl --system-id=random stop Exiting ovs-vswitchd (20081) [ OK ] Exiting ovsdb-server (20063) [ OK ] [root@c80gmas ~]# ovs-ctl --system-id=random start Starting ovsdb-server [ OK ] Configuring Open vSwitch system IDs [ OK ] Enabling remote OVSDB managers [ OK ] [root@c80gmas ~]# ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
正常にBridgeが作成されると上記のような出力となります。
8.Bond作成
ovsbr0上にアップリンクポート*5を追加し、Bondを組みます。また、TrunkとLACPの設定も同時に追加します。
(4)
ovs-vsctl add-bond ovsbr0 bond0 dpdk0 dpdk1 \
vlan_mode=trunk trunks=11,300-304 \
bond_mode=balance-tcp lacp=active other_config:lacp-time=fast \
-- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:08:00.0 \
-- set Interface dpdk1 type=dpdk options:dpdk-devargs=0000:08:00.1
ovs-vsctl show
[root@c80gmas ~]# ovs-vsctl add-bond ovsbr0 bond0 dpdk0 dpdk1 \ > vlan_mode=trunk trunks=11,300-304 \ > bond_mode=balance-tcp lacp=active other_config:lacp-time=fast \ > -- set Interface dpdk0 type=dpdk options:dpdk-devargs=0000:08:00.0 \ > -- set Interface dpdk1 type=dpdk options:dpdk-devargs=0000:08:00.1 [root@c80gmas ~]# ovs-vsctl show 8daaa733-f6ef-4b67-a1a9-581875f33420 Bridge "ovsbr0" Port "ovsbr0" Interface "ovsbr0" type: internal Port "bond0" trunks: [11, 300, 301, 302, 303, 304] Interface "dpdk0" type: dpdk options: {dpdk-devargs="0000:08:00.0"} Interface "dpdk1" type: dpdk options: {dpdk-devargs="0000:08:00.1"} ovs_version: "2.12.90" [root@c80gmas ~]#
上記のように追加されていればOKです。
FullTrunkにしたい場合は、以下の行を削除してください。
vlan_mode=trunk trunks=11,300-304 \
スイッチ側の仕様でLACPが組めない場合、以下のように修正してください。
bond_mode=balance-tcp lacp=active other_config:lacp-time=fast \ ↓ bond_mode=balance-slb \
9.vHostUserClientポート作成
ovsbr0上にダウンリンクポート*6を追加します。
先にSocketファイルとなるvhuc0を作成し、その後ovsbr0にポートを追加します。
(5)
mkdir -p /usr/local/openvswitch/
touch /usr/local/openvswitch/vhuc0
ovs-vsctl add-port ovsbr0 vhuc0 \
vlan_mode=access tag=300 \
-- set Interface vhuc0 type=dpdkvhostuserclient \
options:vhost-server-path=/usr/local/openvswitch/vhuc0
ovs-vsctl show
[root@c80gmas ~]# mkdir -p /usr/local/openvswitch/ [root@c80gmas ~]# touch /usr/local/openvswitch/vhuc0 [root@c80gmas ~]# ovs-vsctl add-port ovsbr0 vhuc0 \ > vlan_mode=access tag=300 \ > -- set Interface vhuc0 type=dpdkvhostuserclient \ > options:vhost-server-path=/usr/local/openvswitch/vhuc0 [root@c80gmas ~]# ovs-vsctl show 8daaa733-f6ef-4b67-a1a9-581875f33420 Bridge "ovsbr0" Port "ovsbr0" Interface "ovsbr0" type: internal Port "bond0" trunks: [11, 300, 301, 302, 303, 304] Interface "dpdk1" type: dpdk options: {dpdk-devargs="0000:08:00.1"} Interface "dpdk0" type: dpdk options: {dpdk-devargs="0000:08:00.0"} Port "vhuc0" tag: 300 Interface "vhuc0" type: dpdkvhostuserclient options: {vhost-server-path="/usr/local/openvswitch/vhuc0"} ovs_version: "2.12.90"
上記のように追加されていればOKです。
ちなみに、vlan_mode=access tag=300としましたが、tag=300のみでも自動的にaccessポートにしてくれます。
また、trunkポートにしたい場合は、Bond設定で投入した「vlan_mode=trunk trunks=11,300-304」を参考に置換してください。
10.仮想マシンの設定
virshで仮想マシンの設定を編集します。
これにより、以下3点を実施します。
・仮想マシン上でHugePageを利用可能にする
・仮想マシンに対してCPUのパススルー機能を有効化する
・vHostUserにてNICを追加する
(6)
virsh edit Guest3
<currentMemory unit='KiB'>1048576</currentMemory>
<memoryBacking>
<hugepages>
<page size='1048576' unit='KiB' nodeset='0'/>
</hugepages>
</memoryBacking>
<cpu mode='host-passthrough' check='none'>
<numa>
<cell id='0' cpus='0' memory='1048576' unit='KiB' memAccess='shared'/>
</numa>
</cpu>
<interface type='vhostuser'>
<source type='unix' path='/usr/local/openvswitch/vhuc0' mode='server'/>
<model type='virtio'/>
</interface>
※
青=追記,緑=置換
[root@c80gmas ~]# virsh edit Guest3 <currentMemory unit='KiB'>1048576</currentMemory> <memoryBacking> <hugepages> <page size='1048576' unit='KiB' nodeset='0'/> </hugepages> </memoryBacking> <cpu mode='host-passthrough' check='none'> <numa> <cell id='0' cpus='0' memory='1048576' unit='KiB' memAccess='shared'/> </numa> </cpu> <interface type='vhostuser'> <source type='unix' path='/usr/local/openvswitch/vhuc0' mode='server'/> <model type='virtio'/> </interface> ※ 青=追記,緑=置換
xmlファイルのため、virsh editで開くと、最初はどこを編集していいか探したり、迷ったりすると思いますが、通常のviエディタと同様に編集可能なため、「cpu mode」などで検索すればすぐに見つかると思います。
あと、vhostuserですが、mode=serverとなっています。以前はmode=clientだったのですが、現在はmode=serverが推奨されています。*7
11.仮想マシンの起動
仮想マシンを起動し、新規に追加されたインターフェースにIP設定後、疎通確認を行ってみてください。
virsh start Guest3
起動時にPermission Denyなどのエラーが出力される場合があります。
その場合、「2-2.qemu-kvmの実行ユーザをrootへ変更」を参照し、Qemuの実行ユーザが確実にrootとなっていることを確認してください。
その上で、
systemctl restart libvirtd.service
を実行し、それでもダメなら、ホストOSを再起動してみてください。
以上です。
12.最後に
CentOS7からの改編となります。
大きく変わっている点は、
といったあたりです。
一度勘所がわかると、いくらでも応用が効くようになるので、その積み重ねが大切なのかなと思います。
CentOS8にてopenstackはまだ各種パッケージなどが準備されていないようですが、ovs-dpdkは実装できたので諸々移行できそうです。
LinuxBridge&ovsにて、それぞれsriov&dpdkが使用できれば、概ねやりたいことはできるので。
また、nmcliコマンドはCentOS7でも8でも共通なので、そのまま転用可能です。
ちなみに、元々の動機はCentOS8でこれ↓がやりたかったので、CentOS8でもovs-dpdkを実装してみました。
github.com
これができれば、dpdk+dockerやk8sも包含されるため、現段階における仮想化されたネットワークの様々アーキテクチャは網羅されるかな、と考えています。
さらにその次のステップとして、SRv6によるネットワークスライシングなどにも踏み込めれば、楽しそうだなと考えています。
*1:IOMMUについては、DL360G8特有の設定(RMRRの設定)があるため、途中で補足を入れます。
*2:CentOS7のときは、gccを使用していましたが、今回はclangを使用しています。理由はコンパイル時間の短縮です。x86_64アーキテクチャのみの環境であれば、clang/llvmの方が早かったので。ちなみにgccでも問題ありませんが、3倍以上の時間を要しました、また、Warningメッセージが出まくるので少々不安になるかもしれません。
*3:.bash_profileに追記した場合は、ログアウト&ログインを忘れずに。またCentOS7のときとは異なり、dnfコマンドにてdpdkをインストールしているため、dpdk関連コマンドへのパス通しは不要となりました。
*4:CentOS7とは異なり、.pyの拡張子が無くなっています。.pyを入力してしまうと、No such a file or diretory~が出力されます。
*5:DPDK上で稼働しているX540のens1f0とens1f1
*7:詳細は、 Data Plane Development Kit vHost User Client Mode with Open vSwitch* | Intel® Softwareに記載されています。
*8:CentOS8の場合、ver2.12となっているため
*9:dnfコマンドでインストールが可能なため