QEMU/KVMをZVOLで使う その2 QEMU/KVM について
なぜ QEMU/KVM と表現されるか
QEMU/KVMのややこしいところは、本来エミュレーターであるQEMUをハイパーバイザーのフロントエンドとして活用しているところです。
KVM利用時のQEMUはCPUの実行はそのままスルーし、I/Oデバイスのエミュレーションのみを担当します。CPUの直接実行はKVMがハードウェアの仮想化支援機能を通じて行います。
つまり、ハイパーバイザーの中心機能はカーネル・モジュールであるKVMが担当し、入出力などについてはQEMUが担当するという役割分担になっています。
この構成を理解するには、まずエミュレーターとハイパーバイザーという2つの概念を整理しておく必要があります。
用語の解説
emulator(エミュレーター)
ハードウェアをソフトウェアで再現するシステムです。ゲストのCPU命令を解釈・実行することで、ホストとは異なるアーキテクチャのコンピュータを動かすことができます。例えば、x86のLinux上でARMのバイナリを動かすようなことができます。
QEMUは典型的なエミュレーターで、ホスト、ゲストともに多くのアーキテクチャをサポートしています。
hypervisor(ハイパーバイザー)
ゲストのコードをホストのCPU上で直接実行します。コードの変換は行いません。ハードウェアの仮想化支援機能(Intel VT-x、AMD-V)を使い、ゲストとホストが同じアーキテクチャであることが前提です。
ハイパーバイザーは、Type-1とType-2に分類されています。Type-1はベアメタル型と呼ばれ、ハイパーバイザー自体がOSの役割も兼ねてハードウェアを直接管理するものとされています。Type-2は通常のOSの上でアプリケーションとして動作するハイパーバイザーで、ホストOSのカーネルを経由してハードウェアにアクセスするものとされています。
ただ、Type-1/2の区分は、OSの定義の広狭や解釈により曖昧で、厳密な区分は難しいようです。KVMやvmmのように既存のカーネルに統合されたハイパーバイザーは、どちらにも綺麗に収まらない第三の形態とも言えます。
一応の区分では、Xen、Linux KVM、FreeBSD vmm、NetBSD NVMM などがType-1、VirtualBox、VMware WorkstationなどがType-2とされています。
なお、NetBSD NVMM (NetBSD Virtual Machine Monitor) は NetBSD 9.0から導入された仮想化機構で、QEMU/KVM と同様に QEMUと組み合わせて使用されます。
compatibility layer(互換レイヤー)
似たようなものに、互換レイヤーというものがあります。一番有名なのはWine(Wine Is Not an Emulator)でしょう。WindowsのAPIをLinux上で再実装することで、WindowsバイナリをCPUエミュレーションなしに実行します。単にAPIを変換するだけの動作なので、emulator(ハードウェアの再現)とは区別されます。
FreeBSDでは、Linuxバイナリ互換機能(linux.ko)というものがあり、高い評価を得ています。Linuxネイティブで動かすより安定しているなんて言われることもあります。
QEMU/KVM の役割分担
QEMUは、ディスク・ネットワーク・USBなど非常に多彩なI/O機能を持っていて、これを活用することでI/O関連の開発を省略でき、KVMはコアな部分に開発リソースを集中させることができました。合理的な分業と言えます。
これとは対照的に、FreeBSDの場合は、bhyveとvmm.koがそれぞれQEMUとKVMの役割を担っていて、両方FreeBSDプロジェクトで開発しています。これによってFreeBSDらしい統合された機能美とBSDライセンスを実現しています。開発リソースの分散という課題はありますが、独自の道を着実に歩んでいます。
QEMU/KVM を構成するソフトウエア
KVM
KVMはLinuxカーネルに含まれたモジュールです。
$ ls /lib/modules/$(uname -r)/kernel/arch/x86/kvm/
kvm-amd.ko.zst kvm-intel.ko.zst kvm.ko.zst
Intel用、AMD用のモジュールがあります。これはCPU支援機能の実装の違いによるものです。モジュールファイルの拡張子 .zst はZstandard形式の圧縮を示しており、カーネルがロード時に透過的に展開します。
$ lsmod | grep kvm
kvm_amd 241664 0
kvm 1445888 1 kvm_amd
irqbypass 16384 1 kvm
ccp 159744 1 kvm_amd
標準状態でいくつかの関連モジュールが組み込まれています。この例はAMD CPUのもので、Intel CPUの場合はkvm_amdの代わりにkvm_intelが表示されます。
lsmodの表示ではアンダースコア(kvm_amd)ですが、ファイル名はハイフン(kvm-amd.ko.zst)になっています。
QEMU
QEMUにはKVMと連携するためのライブラリが含まれていて、qemuをインストールするだけで使うことができます。-accel kvmというオプションをつけて起動させると、QEMUがKVMの機能を使うようになります。
通常は、KVMと組み合わせて使うことを想定してパッケージングされたqemu-kvmというパッケージをインストールして使います。
その他
libvirt-daemon、libvirt-clientsなど。仮想マシンの管理APIを提供するミドルウェアで、QEMUやKVMを直接操作する代わりに、libvirtを通じて統一的なインターフェースで管理できる層です。virshコマンドやvirt-managerはlibvirtのクライアントにあたります。
virtioは仮想化環境向けに設計された準仮想化(paravirtualization)ドライバ群で、VirtualBoxのGuest Additionsに相当するものです。ゲストOS側にvirtioドライバを入れることで、完全なハードウェアエミュレーションより効率的にI/Oを処理できます。ディスク(virtio-blk)、ネットワーク(virtio-net)などがあります。ホスト側の機能はカーネルに含まれているので設定は必要ありません。
virt-manager / virtinstはlibvirtの管理支援を行うGUIフロントエンドおよびコマンドラインツールです。bridge-utilsはネットワークブリッジの設定ツールで、VMをホストのネットワークに繋ぐために使います。
情報源
KVM公式ドキュメント(Linuxカーネルドキュメント内)
Arch Linuxのドキュメント類は実用的で非常に充実していてオススメです。
Arch Linux QEMUドキュメント
Arch Linux KVMドキュメント
まとめ
今回はqemuの長大なオプションを駆使して使うことで、QEMU/KVM自体の理解を深めることを目的とします。素のコマンドを体験することは、GUIツールを使う上でも大きな助けになります。また、仮想環境と非常に相性の良いZVOLの使い方も併せて紹介します。
次回はいよいよ、QEMU/KVM 実践編です。
