2011年11月30日水曜日

RHEL6 系で qemu-kvm バイナリを CPU エミュレーション・モードで使う

お疲れ様です、サイオス 那賀です。突然ですが、今どきの仮想マシンにの実現方法としては、おおざっぱに以下の 3 種類があります。

CPU エミュレーション (インタプリタや、全部バイナリ変換 (Binary Translation))
QEMU, Bochs など。超重いが、他 CPU の命令実行もできて柔軟。実装が大変
トラップ実行 (Trap and Execute。TAE とでも?) + 部分バイナリ変換
(Workstation など、昔ながらの) VMware (実は ESXi でもできるんですが), (昔ながらの) VirtualBox, KQEMU (きわめて残念なことに開発終了) など。ハードウェア支援が不要。CPU 命令をネイティブで走らせるので、そこそこ速い。実装が大変
ハードウェア支援仮想化 (Hardware-Assisted Virtualization, HAV)
QEMU virtualizer (QEMU-KVM), Xen-HVM, HAV モードの VMware (ESXi とか), HAV モードの VirtualBox など。intel VT-xAMD-V が必要。速い、と言われている。実装が(比較的に)簡単

# 何かと面倒な準仮想化 (Para-virtualization, PV) や、OS 仮想化のコンテナ方式については脇に置きます

一般に、前者ほど遅くて後者ほど速いです(初期の VT-x は root, non-root 移行のコストが高くて、むしろ TAE の方が速かったりもしたらしいですが)。最近の実用環境では HAV が主流なのですが、HAV 方式の欠点として、VM 環境上では VM が動かせないことがあります。

# AMD-V だと、VM のスタックができるというウワサを聞きましたが、よく知りません →「Running OpenStack under VirtualBox « System Administration and Architecture Blog

何がしたいかと言うと、EucalyptusOpenStack のような IaaS プラットフォームをお手軽にテストしたいのですが、実マシンをそうそうゴロゴロと用意できない時に、VM 上でテストをできるようにしたいのです。しかし、それらのプロットフォームは、最近の流行からして、開発のプライマリに据えているハイパーバイザが KVM なのです。

これらは、実装的には libvirt 配下で VM ハイパーバイザを動かすようになっているので、理屈上は Xen や VirtualBox でも動きそうなものですが、KVM が開発のプライマリなので、何かと動きません。そもそも、RHEL6 だと Xen の Dom0 も動きませんし、RHEL5 だと Python その他が古すぎて IaaS プラットフォームが動かなかったりもします。

そこで、KVM も動作には QEMU-KVM を使っているので、かわりに QEMU を使うと結構動きます。しかし残念なことに、以前はあった KQEMU による TAE 方式は開発が止まってしまったので、泣く泣く QEMU の CPU エミュレーションモードを使います。

RHEL6 に入っている "qemu-kvm" というコマンドは、実態としては "qemu-system-x86_64" であり、ビルド時に名前を変えているだけです。このバイナリは、KVM のオプションをつければ KVM を利用した HAV 方式で動きますが、KVM を切っておけば、CPU エミュレーションでも動きます。KVM virtualizer 推しのために、emulator をわざと使えなくしているようです。

libvirt-0.8.7/src/qemu/qemu_capabilities.c:

static int
qemuCapsInitGuest(virCapsPtr caps,
                  virCapsPtr old_caps,
                  const char *hostmachine,
                  const struct qemu_arch_info *info,
                  int hvm)
{
  ...
  if (STREQ(info->arch, hostmachine) ||
   (STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) {
    if (access("/dev/kvm", F_OK) == 0) {
      ...
      const char *const kvmbins[] =
       { "/usr/libexec/qemu-kvm", /* RHEL */
         "qemu-kvm", /* Fedora */
         "kvm" }; /* Upstream .spec */
      ...
    }
    if (access("/dev/kqemu", F_OK) == 0)
      haskqemu = 1;
  }

上記のように、libvirt は、コマンドのパスとモジュールのロード状況に基づいて、その環境上で利用可能なハイパーバイザーを判断しています。よって、RHEL6 でもリンクを張るだけで、libvirt 経由で QEMU のエミュレーションモードが使えるようになります。

# ln -sf /usr/libexec/qemu-kvm /usr/bin/qemu-system-x86_64

これで、VM 上で QEMU の完全仮想化エミュレーションが動くようになります。Virt-Manager 上での表示としては、以下のようになります。

「Hypervisor」「Architecture」
KVM 有効の virtualizer「KVM」「x86_64」
QEMU emulator「qemu」「x86_64」

以下は、Windows 版の VMware Workstation 上の Scientific Linux 6 (x64) 上の Virt-Manager 上で Scientific Linux (IA32) を動かした例です。

もちろん、とっても遅いです。しかし、動かないよりはマシですので、テスト用に使っています。

では。

0 件のコメント:

コメントを投稿