tkokamoの日記

HPCの研究開発なのでそんなことをかきたい

Xen on KVM (1)

KVMの上でXen(HVM)を動かそうとした時になかなか、解決方法がわからなかったので記録しておく。

とは言っても、まだXenの上でDom Uは動かして無いんですが、、、。

Dom 0が動くまでの道のりは以下の通り

動作環境はホストがUbuntu 14.04、ゲストがUbuntu 12.04

  1. Linuxの/etc/modprobe.d/qemu-system-x86.confを編集し、ネステッドEPTを行う設定にする
  2. virt-managerから(あるいはVMxmlをいじる)、仮想CPUの設定をホストと一緒にする
  3. VMを作り、その上でXenのビルド、インストールを行う。
  4. Xen がエラーを起こして起動しないので、仮想CPUの設定変更
  5. Xenは動いたがDom0のロード中にloop modules loadedでとまるので、virtioを用いないようにするに変更する

これでDom0の起動までは行えた。大変だったのは4, 5に気付くまで、、、。

1. /etc/modprobe.d/qemu-system-x86.confの編集

ハイパーバイザの上までは、通常ハードウェアによる仮想化支援が届かない。これを有効にするために以下のように編集する。

#echo 'options kvm_intel nested=1' > /etc/modprobe.d/qemu-system-x86.conf

qemu-system-x86.confはUbuntuでのファイルでcentOSなどはkvm.confを編集。

2. VMのCPUの設定をホストと一緒にする。

virt-managerを起動し 起動するVMを開き、メニューから[view]>[Details]を選び、ProcessorのConfiguration項目のModelを自分の物理マシンのCPUにし、Copy host CPU configutationをクリックすることで、VMのCPUの設定をホストと同じにできる。

3. Xenのビルドとか

aptで入れても、コンパイルしていれてもおk

4. VMのCPU設定でx2apicをdisableにする

さぁ、起動とおもって動かしたら起動しない。。。色々調べたら、2.でも触れたConfigurationのでx2apicが有効になっていることが問題らしい。x2apicをdisableにすることで解決。
x2apicはNehalemから採用された割り込みコントローラらしい。有効だとなぜ動かなくなるのか謎、、、だがとりあえず解決したので気にしない。

ここまでは調べて出てきた。

5. Dom0のロード中にloop modules loadedでとまる

いつもののりでvirtio、virtio、、、と無意識に設定してたのが落とし穴だった。良く考えたらxenに準仮想化のフロントエンドドライバなんてないの当たり前。ということで、すべてvirtioを用いない設定にすることで解決。
めでたしめでたし



とりあえず、まだ起動してログインができただけの段階なので色々頑張っていきたい。

virtio(vhost)の概要

48-146407
kvmなどの仮想化環境において、ゲストOSのネットワークやディスクI/Oを早くするために、virtioと呼ばれる準仮想化ドライバドライバを用いることがある。
今回は、あまり技術的に細かい部分には突っ込まず、なぜゲストOSのI/Oが遅いのか、なぜvirtioを用いると速くなるのか簡単に整理してみた。

virtio(vhost)の反映の仕方(virt-manager)

virtio-net(vhost-net)の場合

virt-managerを開いてvirtioを反映させたいVMをを開く。VMのコンソールのメニューで[表示]→[詳細]を選択し、NICのデバイスモデルをvirtioにし、適用を押せばよい。この時、すでにVMが起動している場合、一度シャットダウンしてからでないと反映されない。

f:id:tkokamo:20140818193231p:plain

システムのバージョンに依存すると思われるが、virtioを適用していても実際にはvhost-netを用いている可能性がある。これらの違いについては後述するが、確認をしたい場合には、ターミナルから以下のコマンドを実行して

$ ps ax | grep vhost
 4964 ?        Sl     0:04 qemu-system-x86_64 -enable-kvm /*途中省略*/ vhost=on,vhostfd=25 /*省略*/

vhost=onとなっていればvhost-netを使っていることになる。

通常のOSとゲストOSのI/Oの違い

通常のOSにおけるI/OとゲストOSにおけるI/Oの違いを最初に考えてみる。

f:id:tkokamo:20140819010811p:plain

 上の図で、通常のOSでは、アプリケーションがシステムコールを行なうと(①)、カーネルに制御が移る。そして、カーネルが処理を行なった後(③)で、アプリケーションに戻ってくる(④)。
 これと同じ処理を仮想化環境(kvmの場合を考える)で行なおうとすると非常に大変になってくる(上手の右)。まず通常のOSと同様にゲストOS上のアプリケーションが(ゲストOSの)システムコールを行なうと(①)、ゲストカーネルに制御が移る。この時、ネットワークのI/Oの場合であれば、ゲストカーネルがネットワークコントローラのレジスタを書き換えようとする(②)。しかし、ゲストOSが勝手にハードウェアをいじることができてしまうと、勝手にホストのシステムの状態を変えることができてしまうので、危険である。そのため、CPUが例外を発生させ、KVMに制御を移す(③)。KVMでは、ゲストOSのI/Oを処理する時のデバイスのエミュレーションは、qemuによって行なうので、KVMからqemuに対して制御が移る(④)。qemuは、例外の発生の原因に応じてデバイスのエミュレーションを行なうが、このときの⑤~⑧の処理の流れは、通常のOSの場合の処理と概ね同じである。qemuは、デバイスのエミュレーションを行なった後にkvmに制御を戻し(⑨)、kvmはゲストカーネルに処理を戻す(⑩)。最後に、ゲストOSのアプリケーションに戻ってくることで処理が完了する(⑪)。
 kvmでは、仮想化環境を構築するために、CPUによる仮想化支援機構を用いている。ここでは細かく言及しないが、この仮想化支援機構によって、ゲストOSのモード(VMX non root mode)とVMMのモード(VMX root mode)に切り替えながら処理を行なうことで、従来の仮想化支援を用いない場合に比べて、比較的容易に仮想化環境を構築することができる。上図では、ゲストOSとホスト間を行き来している数だけ状態の切り替えが生じている。この状態の切り替えには1000サイクル程度かかる(ハイパーバイザの作り方~ちゃんと理解する仮想化技術~ 第11回 virtioによる準仮想化デバイス その1「virtioの概要とVirtio PCI」)。実際のネットワークなどのI/Oでは、複数回デバイスのレジスタに書き込みを行なう必要があり、この度に①~⑪までの処理を行なう必要があるので、オーバーヘッドが非常に多い。

virtioとvhost

このオーバーヘッドを削減するために、virtio、そしてvhostという方法が考えられている。
 virtioでは、qemuとゲストOS間で共有メモリを用意し、一定のデータを溜める。そして、実際に処理を行なう時に、VMMに制御を移し処理を行なうことで、VMX non root modeとVMX root modeのモードの遷移数を減らし、オーバーヘッドの削減を実現している。その一方で、virtioでは、デバイスのエミュレーションにqemuを用いている。そのため、実際にデータの処理を行なう場合に、userlandとkernellandで状態の遷移が起きる(上の図では④~⑨)ため、性能の低下を招く懸念がある。
 これに対し、vhostではゲストOSとホストのカーネル間で共有メモリを用いることで、qemuを介さず処理を行なうことで、virtioに比べ更なる実行速度の改善を図っている。

性能比

 実際にどの程度性能が上がるかが
https://www.nic.ad.jp/ja/materials/iw/2012/proceedings/d1/d1-Asama.pdf
に示されている。
 準仮想化ドライバを用いない場合とvirtio-netを用いた場合ではTCPの送信で17~20倍、UDPの送信で9~12倍という高い速度改善が見られる(受信についても、十分に速度が改善している)。
 一方、virtio-netとvhost-netでは概ねvhost-netの方が高いスループットを示しているが、そうでもないものもある。

今後、細かい部分に触れることができればいいなぁ