仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

Ubuntu Xenial (16.04) でOpen vSwitch+DPDKな環境を作る(vHost User Clientモード編)

以前、UbuntuでOpen vSwitch+DPDKを導入してKVMで利用する手順をここで書かせていただきました。

tech.virtualtech.jp

tech.virtualtech.jp

tech.virtualtech.jp

以前取り上げた方法は全てvHost User Serverモードによって動かす手順です。vHost User ServerモードはOVS-DPDKがリセットされるとソケットが破棄されるため、OVSとQEMUを再起動するまでVMとの接続が再確立されませんでした。

これでは不便だよねということでそのあと開発されたのがvHost User Clientモードです。vHost User ClientモードはOVS-DPDKはvHostクライアントとして動作し、QEMUがサーバーとして動作します。この構成では、Open vSwitchがクラッシュしたとしても、ソケットはQEMUによって管理されるため、vHost User Serverモードよりも接続の復旧が容易になります。

詳細はこちらをご覧ください。

software.intel.com

OpenStackでDPDKを使う場合も、Ocata以降ではvHost User Clientモードをサポートしているので、デフォルトではこちらのモードで動作します。vHost User Clientモードを利用するにはOVS 2.6、QEMU 2.7以降が必要です。ただし、RHEL7の場合はqemu-kvm-rhev-2.6.0-23.el7以降のバージョンにバックポートされています。CentOS 7ではバージョン7.3以上で同バージョンのqemu-kvm-evを利用可能です。

vHost User Clientモードに切り替える

以降、これまで紹介した手順でDPDK、OVS、QEMUがインストールされていることを前提に、vHost User Clientモードに切り替える方法をご紹介します。

sockディレクトリー作成

sockファイルを展開するディレクトリーを作成します。

# mkdir -p /usr/local/openvswitch/
sockファイル作成

ファイルを作っておきます。作成したファイルはOpen vSwitchが起動するとsockファイルになるようです。

# touch /usr/local/openvswitch/dpdkvhostclient0
# touch /usr/local/openvswitch/dpdkvhostclient1    
(作成するポートの数だけ作成) 
ブリッジ作成

dpdkvhostuserclientポートをぶら下げるためのOVSブリッジポートをnetdevタイプで作成します。

# ovs-vsctl add-br ovsbr1 -- set bridge ovsbr1 datapath_type=netdev
ポート作成

ポート作成方法はvHost User Serverモードとほとんど一緒ですが、type=dpdkvhostuserclientという設定とoptionsとしてvhost-server-pathを指定します。

# ovs-vsctl add-port ovsbr1 dpdkvhostclient0 \
    -- set Interface dpdkvhostclient0 type=dpdkvhostuserclient \
       options:vhost-server-path=/usr/local/openvswitch/dpdkvhostclient0

# ovs-vsctl add-port ovsbr1 dpdkvhostclient1 \
    -- set Interface dpdkvhostclient1 type=dpdkvhostuserclient \
       options:vhost-server-path=/usr/local/openvswitch/dpdkvhostclient1
DPDKポートのマウント

次に、DPDKデバイスポートを追加します。これはvHost User Serverモードと方法は一緒です。

# ovs-vsctl add-port ovsbr1 dpdk0 -- set Interface dpdk0 type=dpdk
vhostuserclient インターフェイスの追加

virsh editコマンドでvHost User Interfaceを設定します。mode='server'と設定するのがvHost User Serverモードで動かした時と異なる点です。この設定にあるmodeはQEMU側の動作モードを指定します。vHost User ClientモードはQEMUをサーバーモードとして動かすのでmode='server'と設定します。

        <interface type='vhostuser'>
                <source type='unix'
                        path='/usr/local/openvswitch/dpdkvhostclient0'
                        mode='server'/>
                <model type='virtio'/>
        </interface>
サービスの再起動

Open vSwitchdサービスを再起動します。

# service openvswitch-switch restart

以上で準備完了です。あとは仮想マシンを再起動して、ゲストOSでIPアドレスを設定することでDPDKポートがアクセス可能になります。通信できない場合、またはエラーが出た場合はovs-vswitchd.logを確認してください。

今回取り上げた手順で、CentOS 7 + OVS/DPDK/KVMの構成で稼働していた環境もvHost User Clientモードに切り替えることができたことを最後に付け加えておきます。

作業後のovs-vsctl showコマンドの実行結果

実行結果から、これまでとは異なるモードである「dpdkvhostuserclient」で動いていることがわかります。

# ovs-vsctl show
51bf3a85-d776-47a7-b9cb-2da68f465b3b
    Bridge "ovsbr1"
        Port "dpdk0"
            Interface "dpdk0"
                type: dpdk
        Port "dpdkvhostclient1"
            Interface "dpdkvhostclient1"
                type: dpdkvhostuserclient
                options: {vhost-server-path="/usr/local/openvswitch/dpdkvhostclient1"}
        Port "dpdkvhostclient0"
            Interface "dpdkvhostclient0"
                type: dpdkvhostuserclient
                options: {vhost-server-path="/usr/local/openvswitch/dpdkvhostclient0"}
        Port "dpdkvhostclient2"
            Interface "dpdkvhostclient2"
                type: dpdkvhostuserclient
                options: {vhost-server-path="/usr/local/openvswitch/dpdkvhostclient2"}
        Port "dpdkvhostclient3"
            Interface "dpdkvhostclient3"
                type: dpdkvhostuserclient
                options: {vhost-server-path="/usr/local/openvswitch/dpdkvhostclient3"}
        Port "ovsbr1"
            Interface "ovsbr1"
                type: internal
    ovs_version: "2.6.1"

Ubuntu Xenial (16.04) でOpen vSwitch+DPDKな環境を作る(QEMUアップデート編)

以前、UbuntuでOpen vSwitch+DPDKを導入してKVMで利用する手順をここで書かせていただきました。

tech.virtualtech.jp

tech.virtualtech.jp

現在Ubuntu 16.04ではOcataリポジトリーを有効にすると、標準パッケージよりも新しいQEMU-KVMパッケージがインストールできるようになります。

~$ apt list -a qemu-kvm
Listing... Done
qemu-kvm/xenial-updates 1:2.8+dfsg-3ubuntu2.3~cloud0 amd64
qemu-kvm/xenial-updates,xenial-security 1:2.5+dfsg-5ubuntu10.14 amd64
qemu-kvm/xenial 1:2.5+dfsg-5ubuntu10 amd64

当然新しいものを選択すると思うのですが、実際に従来のバージョンからアップグレードする場合および新規インストールする際にそれぞれ注意することがあったので、ここにまとめようと思います。

アップグレードする場合

DPDKとOpenvSwitch、KVM環境をNewton版パッケージを使って構築して、Ocata版のパッケージに更新したいと思った場合、通常はこのように実行すると思います。

# add-apt-repository cloud-archive:ocata
# apt update
# apt upgrade && reboot
...
# add-apt-repository -r cloud-archive:newton  #Newtonリポジトリーを無効化

ああ簡単、よかったよかった…などと思っていると、次のようなエラーになりOVS+DPDKがうまく動いていないことがわかります。

~# ovs-vsctl show
2910fa6f-1c8b-4e8d-b321-bf36a65509ba
    Bridge "ovsbr0"
        Port "vhost-user1"
            Interface "vhost-user1"
                type: dpdkvhostuser
                error: "could not open network device vhost-user1 (Address family not supported by protocol)"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "vhost-user2"
            Interface "vhost-user2"
                type: dpdkvhostuser
                error: "could not open network device vhost-user2 (Address family not supported by protocol)"
        Port "dpdk0"
            Interface "dpdk0"
                type: dpdk
                error: "could not open network device dpdk0 (Address family not supported by protocol)"
    ovs_version: "2.6.1"

とりあえずUbuntuでDPDKを使っている環境でアップグレードするときは、apt upgradeした後、update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdkコマンドを実行してDPDK enableモードでOVSを実行する設定を改めて行なったあと、openvswitch-switchサービスを再起動しなさいってことみたいです。

DPDKが正常に動くようになったから早速VMを起動しようとすると、次のようなログが出力されてVMが起動できない問題に出くわします。

仮想マシンの開始中にエラーが発生しました: unsupported configuration: Shared memory mapping is supported only with hugepages
Traceback (most recent call last):
  File "/usr/share/virt-manager/virtManager/asyncjob.py", line 90, in cb_wrapper
    callback(asyncjob, *args, **kwargs)
  File "/usr/share/virt-manager/virtManager/asyncjob.py", line 126, in tmpcb
    callback(*args, **kwargs)
  File "/usr/share/virt-manager/virtManager/libvirtobject.py", line 83, in newfn
    ret = fn(self, *args, **kwargs)
  File "/usr/share/virt-manager/virtManager/domain.py", line 1402, in startup
    self._backend.create()
  File "/usr/lib/python2.7/dist-packages/libvirt.py", line 1035, in create
    if ret == -1: raise libvirtError ('virDomainCreate() failed', dom=self)
libvirtError: unsupported configuration: Shared memory mapping is supported only with hugepages

これはVirt-Managerを使って起動しようとした場合のログですが、virshコマンドでVMを起動してもだいたい同じようなエラーが出て起動しません。hugepagesの書き方がQEMUのバージョンの更新(2.5から2.8)によって変更されたようです。記述の仕方はこちらにまとまっています。

libvirt.org

この「MemoryBacking」というところが今回重要です。HugePagesとして確保したメモリーをどこのノードからVMに割り当てるのか厳密に書く必要があるようです。実際の例で説明すると、従来は次のように記述するだけでした。

<memory unit='KiB'>1048576</memory>
  <currentMemory unit='KiB'>1048576</currentMemory>
  <memoryBacking>
    <hugepages/>
  </memoryBacking>

これで良きに計らってくれていたのですが、QEMU 2.8では次のように記述する必要がありました。

  <memory unit='KiB'>1048576</memory>
  <currentMemory unit='KiB'>1048576</currentMemory>
  <memoryBacking>
    <hugepages>
      <page size='2048' unit='KiB' nodeset='0'/>
    </hugepages>
    <nosharepages/>
  </memoryBacking>

システムで1GのHugePagesを確保している場合は2Mではなく、1Gを割り当てることもできます。以上の設定変更でVMが正常起動し、ネットワークはvhostuserで提供できるようになります。

nodeはNuma Nodeを指定します。numactl -Hコマンドで確認できますので、その出力結果をもとにどのノードからメモリーを確保するか指定します。

Ubuntu XenialでOpen vSwitch+DPDKを新規セットアップする場合

基本的には前編後編の流れでセットアップすれば構いません。新しいQEMUを使いたい場合はOcata以降のリポジトリーを有効にしてDPDK、OVS、KVM環境を構築します。

# add-apt-repository cloud-archive:ocata
# apt update

あとはVMの設定を前で説明したようにHugePagesの設定でpage size、nodeをきちんと指定します。それ以外は前編、後編の流れでOpen vSwitch+DPDK+Linux KVM環境を導入できます。

HPサーバーのGen8以降用ディスクトレイのパチモンをeBayで買う

久しぶりにサーバーネタは、HDDトレイのパチモン(偽造品)を買って試すお話です。はじめに言うとトレイは一応使えましたが、言わずもがな使用は自己責任となります。

背景

長らく弊社の検証サーバー機材として活躍してきたHP ProLiant G6世代のサーバーが、iLO2のJava Appletリモートコンソールが使用不能になるなどしてOSやブラウザの進歩に追いつけなくなり、リプレースの対象になってきました。使う分にはスペック的に悪くないのでやや惜しいですね。現在は、代わりになるサーバーとして同じくHPEサーバーのGen8・Gen9世代や、Dell R620をオークションで調達しています。

Gen8世代以降のサーバーではハードディスクのトレイ形状が変更になったため、サーバーのリプレースに合わせてディスクトレイもそれなりにたくさん必要になります。オークションの中古サーバーは大抵はディスクがついておらず、ディスクトレイのためにまだ使えるディスクごと買い換えるのも惜しいので、eBayからディスクトレイを調達しました。

買い方

eBayで[hp gen8 2.5 caddy]などのように検索するとたくさんアイテムが出てきます。トレイではなくキャディーが正しい?ようです。日本への発送に対応している商品に絞込み、価格+送料が低い順でソートして、適当なものをセレクトします。

パチモンと判別する方法は比較的簡単で、外見的にはトレイのサイドにHPロゴがあるかないかで見分けられました。また、商品によってはGen8以降のトレイの特徴とも言えるLEDが省略された分安いものもあります。潔いですね。今回はLEDつきのトレイを10個ほど調達しました。

比較

左がパチモン、右が正規品です。上から見る分には大きく変わりません。

f:id:virtualtech:20170607211924j:plain:w450

簡単に見分けられるサイド。HPロゴがないことがわかります。

f:id:virtualtech:20170608170614j:plain:w450

真上から。金属加工がいまいちなのか、沿ってしまっていますが誤差ではあります。金属加工は取っ手の付近にあるバネバネしたところもふわふわと浮いていて、折が足りない印象ですね。

f:id:virtualtech:20170608145916j:plain:w450

正面。上がパチモンです。ランプの窓が少し違う気もします。取っ手は金属製でさわり心地もふつうです。

f:id:virtualtech:20170608145504j:plain:w450

LEDの端子。端子のパターンが丸と四角で異なっています。丸くても四角くても利用上わかりませんが。

f:id:virtualtech:20170608145756j:plain:w450

地味につらいのが付属のネジ。HPサーバーでは馴染み深いトルクスネジなのですが、T15でもT10でもなく、何故かT9です。しかもセンターに突起があるのでドライバーを選びそうです。できればネジは別途調達したいですね。

f:id:virtualtech:20170609092753j:plain:w450

動作チェック

さて、これをサーバーに差し込んで起動させてみましょう。Smart Arrayがスキャンした段階で、1709で始まるメッセージが出力されました。調べてをみると、偽造品であることが見事にバレていました。正規品かどうか判別するチップが中に入っているようです。

f:id:virtualtech:20170608170704j:plain:w450

1709-Slot # Drive Array - One or more attached drives could not be authenticated as a genuine HP drive. Smart Array will not control the LEDs to these drives. Please run HP Smart Storage Administrator (HP SSA) or ACU to learn which drives could not be validated as genuine.

( http://h20565.www2.hpe.com/hpsc/doc/public/display?sp4ts.oid=7481826&docId=emr_na-c04597377&docLocale=en_US より)

メッセージ通りなら、LEDが制御されないとのことですが、起動後もアクセスランプがくるくる回るように点灯していました。他のステータス表示に支障があるのかもしれません。透け具合が正規品と違うので、写真写りもイマイチですね。

f:id:virtualtech:20170608170846j:plain:w450

iLOではDegradedという扱いにされてしまっていたため、使用中はサーバーのアラートランプが点滅を続けていました。別の部位がDegradedになったときには不便かもしれません。

f:id:virtualtech:20170608170314j:plain:w450

まとめ

見た目以上に、サーバーお墨付きのパチモンディスクトレイになってしまいましたが、一応使えることが確認できました。エラーを無視して使うことになりそうです。非純正ディスクはセンサーやベンダー独自のステータス取得等ができないなど、ベンダー的には使ってほしくないと言うのはなんとなくわかるのですが、検証が主な用途な弊社的には不自由でやや不便といった感じです。

容量ラベルを貼る部分にはペンギンさんシールを貼り付けて、識別しやすいようにしておきました。次にトレイが不足したらLED省略版を試してみたいです。

おまけ

ちなみに、パチモントレイは今回のものに限らず、旧世代のHPサーバーやDellサーバー向けのトレイもたくさん出回っています。下の写真はDellのトレイの場合ですが、レバーが正規品よりもガバって開いたり、レバーをおこすボタンの色が薄かったりします。

f:id:virtualtech:20170609093800j:plain:w450

Canonical Ubuntu MAAS 2.2.0がリリースされた

2017年5月末にMAAS 2.2がリリースされたので、早速試してみました。

Canonical Ubuntu MAAS 2.2は現在MAAS Stable PPAで公開されており、Ubuntu 16.04.x Serverで利用するには次のようにリポジトリーを有効化する必要があります。

$ sudo add-apt-repository ppa:maas/stable
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install maas  #All-in-Oneインストール

インストール方法についてはドキュメントが公開されています。

MAAS 2.2では様々な機能改修、機能追加が行われていますが、特に便利だったのがPodsと言う新機能でqemu-kvmをサポートしたことが挙げられると思います。

Pod typeとしてvirshを選択、Virsh Address qemu+sshなアドレスを設定して、「Save pod」をクリックで追加されます。このあとデプロイまでに必要な処理は自動的に行われます。すごい。

f:id:virtualtech:20170607102903p:plain

これまでもMAASでKVM仮想マシンを仮想ノードとして管理することは可能でしたが、物理マシンと同列に仮想マシンを管理するだけの機能しか有していませんでした。Podsでqemu-kvmと連携すると、登録した仮想化ホスト上の仮想マシンをMAASに追加するところからデプロイできる状態までの処理を自動で行ってくれるようになります。

f:id:virtualtech:20170607102950p:plain

また、MAAS DashboardやMAAS API経由で関連づけた仮想ホストに仮想マシンを作ってMAASに仮想ホストとして登録することもできるようになったとのことです。

f:id:virtualtech:20170607103016p:plain

標準でデプロイをサポートするOSはUbuntu 12.04LTS,14,04LTS,16.04LTSのほか、16.10,17.04,17.10(devel)のほか、引き続きCentOSの6と7のデプロイをサポートしています。自宅の仮想サーバーの管理とか、検証環境や本番環境のOSのセットアップに活用できそうですね。

なお、Ubuntu 16.04の標準リポジトリーのMAASパッケージも2.1系の最新版である2.1.5に更新されています。こちらはバグ修正が主のようです。

VMware ESXiやWorkstationとFusionに非常に深刻な脆弱性、アップデートパッチが公開される

以下のNEWSGAIA社のニュースサイト「Security NEXT」による報道について、調べてみました。

www.security-next.com

この問題はCVE-2017-4902, CVE-2017-4903, CVE-2017-4904, CVE-2017-4905で報告されている脆弱性で、修正プログラムは2017年03月28日にVMwareより提供されています。

オフィシャルのアドバイザリーはこちらで公開されています。

www.vmware.com

対象の修正プログラムは以下の通りです。

ESXi5.5以前の製品に対するパッチは提供されません。以前のバージョンを利用しているユーザーは直ちにメンテナンスされているバージョンへの更新を検討すべきです。

ESXiのパッチの詳細は次のURLから確認、ダウンロード可能です。

https://my.vmware.com/group/vmware/patch#search

本件や仮想化についてのお問い合わせはこちらまでお願いします。ご要望に合わせて見積もりさせていただきます。

Ubuntu Xenial (16.04) でOpen vSwitch+DPDKな環境を作る(後編)

[2017/7/6 追記] 大幅に内容を書き換えました。

tech.virtualtech.jp

Ubuntu XenialでOpen vSwitch+DPDKな環境を作る(前編) の環境ができたら、次にOpen vSwitch+DPDKをLinux KVM仮想マシンで使ってみます。

Linux KVMのインストール

Linux KVM環境を構築し、仮想マシンを起動して通信できることを確認します。 まずはLinux KVMをインストールします。

kvmhost# apt update
kvmhost# apt install qemu-kvm libvirt-bin

LibvirtでHugePagesを使う設定

こちらの投稿を参考に、/etc/default/qemu-kvmKVM_HUGEPAGESを1に設定変更します。設定変更後はqemu-kvmサービスを再起動します。

仮想マシンを作成

Virt-Managerなどで仮想マシンを作成します。作成した仮想マシンにOSをインストールします。 インストール、アップデートが終わったら、一旦シャットダウンします。

仮想マシンの設定に追記

DPDKに必要な設定を追記します。以下の共通設定は全ての仮想マシンに設定し、vhostuserインターフェイスは別々のポートを各仮想マシンに設定するようにしてください。

共通の設定

  <memory unit='KiB'>1048576</memory>
  <currentMemory unit='KiB'>1048576</currentMemory>
  
<memoryBacking>
    <hugepages/>
  </memoryBacking>
(memoryBackingセクションを追加)

  <cpu mode='host-passthrough'>
    <numa>
      <cell id='0' cpus='0' memory='1048576' unit='KiB' memAccess='shared'/>
    </numa>
 </cpu>
(cpu mode,numaセクションを追加。numaのmemoryサイズはcurrentMemory unitと同じサイズにする)

各VMにDPDKポートの追記

# virsh edit vm1

    <interface type='vhostuser'>
      <source type='unix' path='/var/run/openvswitch/vhost-user1' mode='client'/>
      <model type='virtio'/>
    </interface>

# virsh edit vm2

    <interface type='vhostuser'>
      <source type='unix' path='/var/run/openvswitch/vhost-user2' mode='client'/>
      <model type='virtio'/>
    </interface>

仮想マシンの起動

次のコマンドを実行して仮想マシンの作成、OSイメージの流し込みを行います。仮想マシンの設定には先の手順で作成したファイルを利用します。

kvmhost# virsh start vm1
kvmhost# virsh start vm2

仮想マシンが起動すると、ovs-vswitch.logに次のような出力がされるはずです。

dpdk(vhost_thread1)|INFO|State of queue 0 ( tx_qid 0 ) of vhost device '/var/run/openvswitch/vhost-user1'changed to 'enabled'
dpdk(vhost_thread1)|INFO|vHost Device '/var/run/openvswitch/vhost-user1' has been added on numa node 0
dpdk(vhost_thread1)|INFO|State of queue 0 ( tx_qid 0 ) of vhost device '/var/run/openvswitch/vhost-user2'changed to 'enabled'
dpdk(vhost_thread1)|INFO|vHost Device '/var/run/openvswitch/vhost-user2' has been added on numa node 0

仮想マシンにはsshやvirt-manager,virt-viewerなどでアクセスします。あとは仮想マシンのゲストOSに入って、追加したvhostuserポート側にIPアドレスを割り当てます。

「unable to map backing store for hugepages: Cannot allocate memory」とかエラーが出た場合は、Hugepagesを増やしましょう。

ex.

# sysctl -w vm.nr_hugepages=8192

以上でvhostuserを仮想マシンに割り当てて、仮想マシン間で通信できるようになります。

f:id:virtualtech:20161209141151p:plain:w400

Hello Worldアプリケーションがビルドできない?

5. Hello World Sample Application — Data Plane Development Kit 16.04.0 documentation

に従ってビルドしようとすると、次のようなエラーが出力されます。

# export RTE_SDK=/usr/share/dpdk/
# cd /usr/share/dpdk/examples/helloworld
# make
/usr/share/dpdk//mk/internal/rte.extvars.mk:57: *** Cannot find .config in /usr/share/dpdk//x86_64-native-linuxapp-gcc.  Stop.

それはどうもUbuntuのCloud Airchiveパッケージのバグの可能性があるようです。バグ報告されていない場合はしないといけませんね。どうしても動かしたい場合はDPDKだけビルドした方がいいのかもしれません。

以下の手順で対応可能でした。.configファイルは/usr/share/dpdk/にconfigファイルとして存在していました。また、公式ガイドではexport RTE_TARGET=x86_64-native-linuxapp-gccとなっていますが、Ubuntuパッケージ版はここがx86_64-default-linuxapp-gccになっています。 読み替えて次のように実行します。なお先の手順でDPDKをOpenvSwitchで使っている場合は動作させることができずエラーになりますので、一旦service openvswitch-switch stopが必要です。

# vi /etc/apt/sources.list.d/cloudarchive-newton.list
…
deb-src http://ubuntu-cloud.archive.canonical.com/ubuntu xenial-updates/newton main

# apt install dpdk-doc
# apt update && apt-get build-dep dpdk
# source /usr/share/dpdk/dpdk-sdk-env.sh
# cd ${RTE_SDK}/examples/helloworld
# make
  CC main.o
  LD helloworld
  INSTALL-APP helloworld
  INSTALL-MAP helloworld.map

実行する前にopenvswitch-switchサービスを停止します。

# service openvswitch-switch stop

念のため、こうして置いたほうがいいかもしれません。元に戻すには前編を参考にadd-portしてください。

# ovs-vsctl del-port ovsbr0 dpdk0
# service openvswitch-switch stop

実行してみます。

# ./build/helloworld -c f -n 4
EAL: Detected 16 lcore(s)
EAL: Probing VFIO support...
PMD: bnxt_rte_pmd_init() called for (null)
EAL: PCI device 0000:07:00.0 on NUMA socket -1
EAL:   probe driver: 8086:10d6 rte_igb_pmd
EAL: PCI device 0000:07:00.1 on NUMA socket -1
EAL:   probe driver: 8086:10d6 rte_igb_pmd
EAL: PCI device 0000:08:00.0 on NUMA socket -1
EAL:   probe driver: 8086:10d6 rte_igb_pmd
EAL: PCI device 0000:08:00.1 on NUMA socket -1
EAL:   probe driver: 8086:10d6 rte_igb_pmd
hello from core 1
hello from core 2
hello from core 3
hello from core 0

実行したサンプルプログラムはすぐ終了してしまうので端末を複数開き、一方でtopコマンドを実行し、一方でhelloworldを実行してください。

このエントリーの続編です。

tech.virtualtech.jp

Ubuntu Xenial (16.04) でOpen vSwitch+DPDKな環境を作る(前編)

Open vSwitch+DPDKが今、熱いようです。

早速、Ubuntu XenialでOpen vSwitch+DPDKな環境を作ってみることにしました。次のバージョンのUbuntuを使って動作確認しました。

$ cat /proc/version_signature
Ubuntu 4.4.0-53.74-generic 4.4.30
$ cat /etc/lsb-release |grep DISTRIB_DESCRIPTION
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

[2017/7/6 追記] Ubuntu 4.4.0-83.106-generic 4.4.70、Ubuntu 16.04.2 LTSで前後編を動作確認。

NICの確認

まずは動かそうとしているサーバーに対応するNICが実装されていることを確認します。 なお、NICによってサポートしている機能に差があるため、使おうとしている機能がそのNICで使えることを確認してください。

Numaノードの確認

DPDKポートとして使うNICがどちらのNumaノードに格納されているか確認します。 本例の場合は、Numaノード0側にNICが接続されていることがわかります。

~# hwloc-ls
Machine (63GB total)
  NUMANode L#0 (P#0 31GB)
  ..
..
 HostBridge L#0
      PCIBridge
        PCI 8086:10fb
          Net L#0 "eno1"
        PCI 8086:10fb
          Net L#1 "eno2"
      PCIBridge
        PCI 1000:0073
          Block(Disk) L#2 "sda"
      PCIBridge
        PCI 8086:1521
          Net L#3 "eno3"
        PCI 8086:1521
          Net L#4 "eno4"
..
NUMANode L#1 (P#1 31GB) + Package L#1 + L3 L#1 (20MB)  
...

numactlコマンドを実行して、CPUコアのNumaノードごとの割り振りを確認します。このサーバーには論理32プロセッサーが実装されていることが確認できます。またメモリーは合計64GB、32GB毎割り振られていることがわかります。

~# numactl -H
available: 2 nodes (0-1)
node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
node 0 size: 32128 MB
node 0 free: 31083 MB
node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31
node 1 size: 32251 MB
node 1 free: 31498 MB
node distances:
node   0   1
  0:  10  20
  1:  20  10

PPAの追加

Ubuntu XenialのOVSはバージョン2.5がサポートされます。より新しいバージョンのOVSをUbuntuで使うには、OpenStackのリポジトリー「CloudArchive」にあるパッケージを使うと便利です。次のコマンドを実行します。

Newtonより新しいバージョンのOpenStackが提供された場合はより新しいバージョンを指定してください。

# add-apt-repository cloud-archive:newton
# apt-get update

Ocata以降のリポジトリーパッケージを使う場合は、以下をご覧ください。

tech.virtualtech.jp

インストール

次のようにコマンドを実行してDPDKとDPDK EnableなOVSをインストールします。 パッケージの依存関係で普通のOVSもインストールされるので、二個目のコマンドで切り替えています。

# apt-get install openvswitch-switch-dpdk dpdk
# update-alternatives --set ovs-vswitchd /usr/lib/openvswitch-switch-dpdk/ovs-vswitchd-dpdk

NICのバインド

NIC用のドライバーをバインドするため、modprobeコマンドで読み込みます。

ex.

# modprobe uio_pci_generic 
or
# modprobe vfio-pci 

uio_pci_generic でも良い(パフォーマンスはでない)が、使える環境ならvfio-pciの方が良いようです。

また、e1000のように対応しているNICの場合はuio_pci_genericの代わりに、よりパフォーマンスの良いigb_uioを使うこともできます。Ubuntu Xenialではdpdk-igb-uio-dkmsパッケージの導入により、利用可能になります。

前の手順で読み込んだモジュールを再起動後も読み込むように/etc/modulesに書き込んでください。

# echo "uio_pci_generic" >> /etc/modules

モジュールについてはmodinfoコマンドで概要を確認できます。カーネルを更新すると新しいモジュールが利用できますので最新のものを使うことをおすすめします。Linuxカーネルの更新後は必ずシステムの再起動が必要です。

$ modinfo uio_pci_generic
filename:       /lib/modules/4.4.0-53-generic/kernel/drivers/uio/uio_pci_generic.ko
description:    Generic UIO driver for PCI 2.3 devices
author:         Michael S. Tsirkin <mst@redhat.com>
license:        GPL v2
version:        0.01.0
srcversion:     41BEEDE6B2A7E267E6CCD84
depends:        uio
intree:         Y
vermagic:       4.4.0-53-generic SMP mod_unload modversions

以降の手順は汎用的に利用可能なuio_pci_genericを使う例とします。

ネットワーク設定

管理用NIC以外はコメントアウトします。DPDKがネットワークを管轄するためです。 リモートアクセス用のNICとDPDK用のデバイスは別のものを用意するといいと思います。

# vi /etc/network/interfaces
auto eno1
iface eno1 inet static
address 172.16.214.100
netmask 255.255.0.0
gateway 172.16.0.1
dns-nameservers 8.8.8.8 8.8.4.4

#auto ens1f0
…
#auto ens1f1
…

OVS-DPDK関連の設定変更

まず、次のコマンドを実行してHugePagesを設定します。 ページサイズはのちに動かすアプリケーションに合わせたサイズを指定する必要があります。grep pdpe1gb /proc/cpuinfo |uniq|grep pdpe1gbコマンドを実行してpdpe1gbフラグが出力された場合は1Gの方でページサイズを設定できます。出力されない古いプロセッサーを実装したサーバーでは2Mの方でページサイズを指定してください。1Gで指定した場合、アプリケーションによっては2Mのページも必要な場合があるようです。

# vi /etc/dpdk/dpdk.conf
...
NR_2M_PAGES=8192 (2Mx8192=約16GB分)
...
NR_1G_PAGES=16

# systemctl restart dpdk    #設定を反映
# systemctl enable dpdk    #サービスの永続化

Linuxカーネルパラメーターへの記述

次のようにLinuxカーネルパラメーターでHugePagesを使うための設定を行うこともできます。指定したメモリーサイズは確保されるため、Linux Kernel側から見ると使用中になるので注意してください。改行せずに1行で入力してください。

# vi /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="default_hugepagesz=1G hugepagesz=1G hugepages=16 hugepagesz=2M hugepages=8192"

vfio-pciを使う場合にはVT-dが必要なため、iommu=pt intel_iommu=on の記述が必要です。その場合は次のように実行して、カーネル起動後もIOMMUを有効にするためを入れておきます。 なお、uio_pci_genericを使う場合はこの設定は不要です。

# vi /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="iommu=pt intel_iommu=on"

GRUBの変更を反映させるために次のように実行して、再起動します。

# update-grub && reboot

なお、HPEのサーバーでIOMMUを使うには、次の情報を確認して対応してください。 この対処を施した場合、IOMMUが利用可能になりますが、サーバー前面のステータスランプが警告表示(常時、赤ランプ点滅)になります。ちなみにDellのサーバーでは特に何をする必要もありませんでした。

デバイスの確認とバインド

まず、DPDKのバインド状況を確認します。

# dpdk-devbind --status

初期状態ではコマンドを実行すると次のような出力がされます。「Network devices using DPDK-compatible driver」がnoneと表示されるはずです。この状態ではDPDKがNICに対して有効化されていない状態です。

Network devices using DPDK-compatible driver
============================================
<none>

Network devices using kernel driver
===================================
0000:01:00.0 'NetXtreme II BCM5709 Gigabit Ethernet' if=eno1 drv=bnx2 unused=uio_pci_generic *Active*
0000:01:00.1 'NetXtreme II BCM5709 Gigabit Ethernet' if=eno2 drv=bnx2 unused=uio_pci_generic
0000:02:00.0 'NetXtreme II BCM5709 Gigabit Ethernet' if=eno3 drv=bnx2 unused=uio_pci_generic
0000:02:00.1 'NetXtreme II BCM5709 Gigabit Ethernet' if=eno4 drv=bnx2 unused=uio_pci_generic
0000:07:00.0 '82575GB Gigabit Network Connection' if=enp7s0f0 drv=igb unused=uio_pci_generic
0000:07:00.1 '82575GB Gigabit Network Connection' if=enp7s0f1 drv=igb unused=uio_pci_generic
0000:08:00.0 '82575GB Gigabit Network Connection' if=enp8s0f0 drv=igb unused=uio_pci_generic
0000:08:00.1 '82575GB Gigabit Network Connection' if=enp8s0f1 drv=igb unused=uio_pci_generic

Other network devices
=====================
<none>

Active」とステータスが出ているNICは別の処理で使用中のNICです。NetworkサービスでStaticなIPアドレスを割り当ててUPしているNICであるためです。Linux側で利用しているデバイスはDPDKドライバーを読み込むことはできません。

例えばuio_pci_genericとして、デバイス番号「0000:07:00.0」のNICをバインドするには次のように実行します。アンバインドするには-bオプションを-uに変えて実行してください。

# dpdk-devbind -b uio_pci_generic  0000:07:00.0

もう一度ステータスを確認すると次のように出力されるはずです。これで指定したデバイスでDPDK-compatible driverが読み込まれます。

# dpdk-devbind --status
...
Network devices using DPDK-compatible driver
============================================
0000:07:00.0 '82575GB Gigabit Network Connection' drv=uio_pci_generic unused=igb
...

DPDKバインドしたデバイスをLinux Kernel側に戻すには、同じくdpdk-devbind -bコマンドでドライバーの割り当てを上書きします。例えば先にバインドしたデバイスを元に戻すには現在利用していない(unused)ドライバーを指定すれば良いので、次のように設定することができます。

# dpdk-devbind -b igb 0000:07:00.0

DPDKモジュールの自動読み込みに関する設定

先の手順で手動でバインドしましたが、これは/etc/dpdk/interfacesに記述することで自動的にバインドさせることができます。次のように実行して、指定したデバイス番号のNICでDPDK対応ドライバーを利用するための設定を行っておきます。

# vi /etc/dpdk/interfaces
pci 0000:07:00.0 uio_pci_generic ←追記  

# systemctl restart dpdk    #設定を反映
# systemctl enable dpdk    #サービスの永続化

DPDKとOVSのセットアップ

ここまでできたら、次にOVSの設定を行います。通常のようにOVSを使うのと異なり、いくつかオプションを指定します。以下のページの情報を参考にしましたが、次に実行するコマンドを列挙します。

Documentation/vhost-user-ovs-dpdk - QEMU

# mkdir -p /var/run/openvswitch
# mount -t hugetlbfs -o pagesize=2048k none /dev/hugepages

# modprobe openvswitch

# killall ovsdb-server ovs-vswitchd
# rm -f /var/run/openvswitch/vhost-user*
# rm -f /etc/openvswitch/conf.db

# export DB_SOCK=/var/run/openvswitch/db.sock
# ovsdb-tool create /etc/openvswitch/conf.db /usr/share/openvswitch/vswitch.ovsschema
# ovsdb-server --remote=punix:$DB_SOCK --remote=db:Open_vSwitch,Open_vSwitch,manager_options --pidfile --detach

# ovs-vsctl --no-wait init
# ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0xf
# ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0x2
# ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem=1024,1024
# ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true
# ovs-vswitchd unix:$DB_SOCK --pidfile --detach --log-file=/var/log/openvswitch/ovs-vswitchd.log
# ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-extra="--vhost-owner root:root --vhost-perm 0666"
# service openvswitch-switch restart

# ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
# ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
# ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser
# ovs-vsctl show
cd83e731-6786-4985-9102-25c874b87255
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "vhost-user2"
            Interface "vhost-user2"
                type: dpdkvhostuser
        Port "vhost-user1"
            Interface "vhost-user1"
                type: dpdkvhostuser

OVSにDPDKデバイスをバインドします。次のように実行します。

# ovs-vsctl add-port ovsbr0 dpdk0 -- set Interface dpdk0 type=dpdk
(物理デバイスを指定するのではなく、dpdk番号を指定する)

Interface "dpdk0"が追加されたことを確認します。この段階でtopコマンドを実行すると、ovs-vswitchdプロセスのCPU使用率が上がっているのを確認できます。上がっていない場合は/var/log/openvswitch/ovs-vswitchd.logを確認して原因を探ります。例えば、lcoreやpmdの割り当てが足りないとか、dpdk-socket-memの指定の問題などです。

# ovs-vsctl show
cd83e731-6786-4985-9102-25c874b87255
    Bridge "ovsbr0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "vhost-user2"
            Interface "vhost-user2"
                type: dpdkvhostuser
        Port "vhost-user1"
            Interface "vhost-user1"
                type: dpdkvhostuser
        Port "dpdk0"
            Interface "dpdk0"   ←追加された
                type: dpdk

以上でUbuntu Server XenialにOpen vSwitch+DPDKをインストールできます。

DPDKドライバーの切り替え

-uオプションは稀に失敗するので、unbindせずに新しいドライバーをバインドすると上書きできるようです。

# ovs-vsctl del-port ovsbr0 dpdk0
# dpdk-devbind -b igb_uio 0000:07:00.0
# dpdk-devbind --status
Network devices using DPDK-compatible driver
============================================
0000:07:00.0 '82575GB Gigabit Network Connection' drv=igb_uio unused=igb,uio_pci_generic
...
# service openvswitch-switch restart
# ovs-vsctl add-port ovsbr0 dpdk0 -- set Interface dpdk0 type=dpdk

OVSパラメーターの追加

other_configでパラメータを追加してOVSを再起動すると良いようです。

# ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0x2
# service openvswitch-switch restart

後編に続きます。

tech.virtualtech.jp