SLESに導入したKVM上でWindowsを動かす
現在、kvmはkernelに取り込まれたため、RedHatはもとより、SuSEでもパッケージを用いて簡単にインストールできる。
正直、VM面倒くさそうだし、少なくなったとは言えオーバーヘッドも発生するので、あまりメリットを感じていない。
周りには仕事でやっている人も要るのだが、手間がかかる割りに儲けの少なそうな作業だなぁ。と思って遠くから見守っておりました。
この度、結構速いサーバー機を入手したので、家の時代遅れのWindowsマシンを集約して有効活用したいと思い、勉強がてら導入することにしました。
# zypper se kvm
Loading repository data...
Reading installed packages...
S | Name | Summary | Type
--+-----------------+----------------------------------------+-----------
i | Dom0_KVM | KVM Virtualization Host (non-embedded) | pattern
| ikvm | A JVM Based on the Mono Runtime | package
| ikvm | A JVM Based on the Mono Runtime | srcpackage
| kvm | Kernel-based Virtual Machine | srcpackage
i | kvm | Kernel-based Virtual Machine | package
i | kvm_server | KVM Virtual Machine Host Server | pattern
i | sles-kvm_en-pdf | SLES KVM Guide (English, PDF) | package
i | slessp3-kvm | Recommended update for kvm | patch
あとは、libvirtdを動作させるだけでホストOSの準備は完了。
ゲストOSの準備
次にGuest OSの準備であるが、OSのiso imageからインストールする場合はvirt-managerの指示に従えば難しくないと思う。
私はP2Vから始めたが、イメージが正しく作成されておらず嵌った。raw(ddで取り出すのと一緒)に加え、XenやVMWareなど幾つかのOSイメージの形式をサポートしているようだが、これがミスマッチだとOSが全く起動しない。
最初、XenやVMWareのイメージが使えるなら、CitrixやVMWareが無償配布しているP2Vソフトを使えば良いだろうと思ったのだが、どうやら新しすぎてKVM側が対応していないのか、全く起動できなかった。
ここで嵌ってしまうと、適当なエラーも出ず、BIOSの画面も出ないので、特に初心者は頑張らずに無難な方法でやり直すことをオススメする。
試行錯誤の末、結局virt-p2vのCD-ROMから起動してrawフォーマットのイメージを保存することで解決しまた。Windowsはddコマンドがないから不便ですね。
整合性のチェック、スナップショットや暗号化のサポートなどの必要性から幾つかのタイプが存在しているようです。
詳細はman qemu-img(1)に書いてあります。うまくいかない場合は、まずrawで動くようにしてから、タイプを変換する方法がオススメです。
rawの場合は直接マウントしてfsckしたり、OSの中身を見れたりする点で便利ですし、トラブルシュートもしやすいです。
起動ディスクのタイプはIDEを選んでおくのが定石となっているようです。
ネットワーク設定
KVMはGuest OSが直接外部のネットワークと通信することを許していないので、これを行いたい場合はbridge I/Fをつくり、そこに仮想のNICが接続されているかのように扱う必要がある。これはKVM使う場合は嵌りポイントらしいです。
ホストOSもこのbridgeを経由する様な設定になるため、いささか異和感があるのですが、気にしない事します。
設定例。うちでは、eth0,eth1をbondingをしているため、bond0をbridgeに接続しています。
# cat /etc/sysconfig/network/ifcfg-bond0
BONDING_MASTER='yes'
BONDING_SLAVE0='eth0'
BONDING_SLAVE1='eth1'
BONDING_MODULE_OPTS='mode=802.3ad miimon=100'
BOOTPROTO='none'
STARTMODE='auto'
USERCONTROL='no'
NM_CONTROLLED=no
# cat /etc/sysconfig/network/ifcfg-br0
DEVICE=br0
TYPE=Bridge
BRIDGE=yes
BRIDGE_PORTS=bond0
STARTMODE=auto
BOOTPROTO=static
NM_CONTROLLED=no
IPADDR=192.168.0.2/24
VMが起動すると、bridgeにvnet*というI/Fが追加されます。
# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.0025900941e4 no bond0
virtio
完全仮想化が動作するようになったら、パフォーマンスを出したい部分は順仮想化に置き換えます。
順仮想化のサポートにはホストOS側のkernelサポートと、Guest OSへのvirtioドライバの導入が必要ですが、KVMはすでにkernelに取り込まれているので、今や専用のkernelは不要となっています。virtioドライバについては、Linuxでは標準で付属していますが、Windows7はRedHat配布のドライバを入れる必要がありました。
因みに、うちの環境ではシーケンシャルI/Oに関しては、滅茶苦茶速くなるということは無かったです。
PCIパススルー
PCIデバイスをホストOSから切り離し、あたかもGuest OSに接続されているかのように見せる機能です。
外付けUSB HDDを動的に接続したり外したりするため、Guest OSにパススルーで見せたいと思います。
まず、BIOS上で、Intel Vt-dを有効にします。多分最近のマシンならデフォルトで有効になっていると思います。
次にkernel optionでIOMMUを有効に設定します。こちらも特に必要ありませんでした。
virsh nodedev-list --treeコマンドを使って、全デバイスをリストし、該当のデバイスを探します。
同じデバイスが複数つながっていたりすると、探すのは少々困難かもしれません。HDDについてはlsscsiで表示されるデバイスIDと同様のデバイス名がつけられているようです。
# lsscsi | grep sdh
[8:0:0:0] disk USB 3.0 MassStorage 0100 /dev/sdh
saka@oxygen3:~> virsh nodedev-list --tree
:
+- pci_0000_00_1d_7
| |
| +- usb_usb2
| |
| +- usb_2_0_1_0
| +- usb_2_2
| | |
| | +- usb_2_2_1_0
| | |
| | +- scsi_host8
| | |
| | +- scsi_target8_0_0
| | |
| | +- scsi_8_0_0_0
| | |
| | +- block_sdh_USB_3_0_MassStorage_WD_WMC1F0485482_0_0 <----
このケースではPCIデバイスはpci_0000_00_1d_7になります。
このデバイス名を用いて、デバイスの詳細情報を得ます。bus0-slot29-function7に接続されていることがわかります。
saka@oxygen3:~> virsh nodedev-dumpxml pci_0000_00_1d_7
pci_0000_00_1d_7
computer
ehci_hcd
0
0
29
7
82801JI (ICH10 Family) USB2 EHCI Controller #1
Intel Corporation
デバイスをホストOSから切り離します。
oxygen3:/home/saka # virsh nodedev-dettach pci_0000_00_1d_7
Device pci_0000_00_1d_7 detached
virsh editを用いて(xmlを直接変更しても構わないと思いますが)デバイスをGuest OSに追加します。
セクションに次の記述を追加します。bus, slot, functionの値は16進数で記入します。
oxygen3:/home/saka # virsh edit Win7
error: internal error unknown hostdev mode 'sybsystem'
Failed. Try again? [y,n,f,?]:
NG。virt-managerからUSBデバイスの追加を単純に行ってみたがpanicした。
さてどうしたものか
この後、パススルーは必要なくなってしまったため、続きはまたの機会にしたいと思う。