QEMU
関連記事
QEMU ホームページ より:
- QEMU は汎用なオープンソースのマシンエミュレータ・バーチャライザーです。
マシンエミュレータとして使う場合、QEMU はあるマシン (例: ARM ボード) 用に作られた OS やプログラムを他のマシン (例: x86 PC) で動かすことができます。動的変換を利用することによって、素晴らしいパフォーマンスを実現します。
Xen や KVM など他のハイパーバイザーを使うことで QEMU は仮想化のための CPU 拡張命令を利用することができます。バーチャライザーとして使う場合、ゲストコードをホスト CPU で直接実行することにより QEMU はネイティブに近いパフォーマンスを得ることができます。
目次
QEMU のインストール
QEMU のグラフィカルフロントエンド
VirtualBox や VMware など他の仮想化プログラムと違って、QEMU は仮想マシンを管理するための GUI を提供しません (仮想マシンを動かすときに表示されるウィンドウは別です)。また、保存された設定を使って永続的な仮想マシンを作成する方法も提供していません。仮想マシンを起動するためのカスタムスクリプトを作成しないかぎり、仮想マシンを起動するための全てのパラメータは起動する度にコマンドラインに指定する必要があります。ただし、QEMU の GUI フロントエンドは複数存在します:
- virt-manager (libvirt に含まれています)
- gnome-boxes
- qemu-launcher
- qtemu
AUR より:
新しい仮想化システムの作成
ハードディスクイメージの作成
CD-ROM やネットワークからライブシステムを起動するのでない (そしてオペレーティングシステムをハードディスクイメージにインストールしない) 限り、QEMU を実行するにはハードディスクイメージが必要になります。ハードディスクイメージはエミュレートするハードディスクの内容を保存するファイルです。
ハードディスクイメージを raw にすると、ゲストからは文字通りバイト単位で等しいようになり、ホスト上のゲストハードドライブをフルに使用することになります。この方法は I/O のオーバーヘッドを最小に抑えられますが、ゲストで使用していない領域もホストは使えないため、大量の容量を消費するのが欠点です。
また、ハードディスクイメージを qcow2 などのフォーマットにすることもできます。ゲストオペレーティングシステムが実際に仮想ハードディスク上のセクタに書き込んだ時にイメージファイルに容量を割り当てます。ホストシステムで占める容量はかなり少なくて済み、ゲストオペレーションにはフルサイズのイメージとして見えます。こちらの形式では raw と違ってパフォーマンスに多少影響を与えます。
QEMU にはハードディスクイメージを作成するための qemu-img
コマンドがあります。例えば raw フォーマットで 4GB イメージを作成するには:
$ qemu-img create -f raw image_file 4G
-f qcow2
を使うことで qcow2 ディスクを作成できます。
オーバーレイストレージイメージ
一度ストレージメディアを作成してから ('backing' イメージ)、QEMU にイメージへの変更を overlay イメージとして維持させることができます。これによってストレージメディアを前の状態に戻すことが可能になります。戻りたい時点で、オリジナルの backing イメージを元に新しい overlay イメージを作成することで戻すことができます。
overlay イメージを作成するには、次のようにコマンドを実行してください:
$ qemu-img create -o backing_file=img1.raw,backing_fmt=raw -f qcow2 img1.cow
その後通常通り QEMU VM を起動することができます (仮想化システムを実行するを参照):
$ qemu-system-i386 img1.cow
backing イメージには変更が加えられず、ストレージへの追記は overlay イメージファイルに保存されるようになります。
backing イメージのパスが変更された場合、修正が必要になります。
オリジナルの backing イメージのパスからこのイメージに繋がるようにしてください。必要ならば、オリジナルのパスに新しいパスへのシンボリックリンクを作成します。次のようなコマンドを実行してください:
$ qemu-img rebase -b /new/img1.raw /new/img1.cow
あなたの判断で、backing イメージの古いパスがチェックされない'危険な' rebase を実行することもできます:
$ qemu-img rebase -u -b /new/img1.raw /new/img1.cow
イメージのリサイズ
qemu-img
実行可能ファイルには resize
オプションがあり、ハードドライブイメージの簡単なリサイズができます。このコマンドは raw と qcow2 の両方で使えます。例えば、イメージ容量を 10GB 増やすには、次を実行してください:
$ qemu-img resize disk_image +10G
インストールメディアを準備する
ディスクイメージにオペレーティングシステムをインストールするには、オペレーティングシステムのインストールメディア (例: オプティカルディスク、USB ドライブ、ISO イメージ) が必要です。QEMU はメディアに直接アクセスできないのでインストールメディアをマウントしてはいけません。
オペレーティングシステムのインストール
ここで初めてエミュレータを起動することになります。ディスクイメージにオペレーティングをインストールするには、ディスクイメージとインストールメディアの両方を仮想マシンに結びつけて、インストールメディアから起動するようにする必要があります。
例えば i386 環境で、CD-ROM のブータブル ISO ファイルからインストールするには:
$ qemu-system-i386 -cdrom iso_image -boot order=d qemu_image
フロッピーやディスクイメージ、物理ドライブなどの他のメディアタイプをロードする方法は qemu(1)
を見て下さい。
オペレーティングシステムのインストールが終了したら、直接 QEMU イメージを起動することができます (仮想化システムを実行するを参照)。
仮想化システムを実行する
qemu-system-*
バイナリ (例えば qemu-system-i386
や qemu-system-x86_64
など、エミュレートするアーキテクチャによって異なります) を使って仮想化システムを実行します。使用方法は:
$ qemu-system-i386 options disk_image
全ての qemu-system-*
バイナリでオプションは共通です、全てのオプションのドキュメントは qemu(1)
を見て下さい。
デフォルトで、QEMU は仮想マシンのビデオ出力をウィンドウに表示します。注意: QEMU ウィンドウの中をクリックすると、マウスポインタが取り込まれます。ポインタを戻すには、Ctrl+Alt
を押して下さい。
KVM を有効にする
使用しているプロセッサとカーネルが KVM をサポートしている必要があります。また、必要なカーネルモジュールがロードされてなければなりません。詳しくは KVM を見て下さい。
QEMU を KVM モードで起動するには、起動オプションに -enable-kvm
を追加してください。
ホスト・ゲスト OS 間でデータを移動する
ネットワーク
ファイルを転送できるネットワークプロトコルであれば NFS, SMB, NBD, HTTP, FTP, SSH など何でも使ってホストとゲスト OS 間でデータを共有することができます、ただしネットワークを適切に設定して適切なサービスを有効にする必要があります。
デフォルトのユーザーモードネットワークは IP アドレス 10.0.2.2 でゲストがホスト OS にアクセスするのを許可します。ホスト OS で動作する全てのサーバー、SSH サーバーや SMB サーバーなどは、この IP アドレスでアクセスすることが可能になります。そしてゲストでは、SMB や NFS でホストのディレクトリをマウントしたり、ホストの HTTP サーバーなどにアクセスすることが可能です。 ゲスト OS で動作しているサーバーにホスト OS がアクセスすることはできませんが、他のネットワーク設定を使えば不可能ではありません (#QEMU の Tap ネットワーク を参照)。
QEMU の内蔵 SMB サーバー
QEMU のドキュメントには "内蔵の" SMB サーバーがあると書かれていますが、実際は自動的に生成された設定ファイルで Samba を起動して別の IP アドレス (デフォルトでは 10.0.2.4) でゲストにアクセスできるようにするだけです。この機能はユーザーネットワークでしか動作せず、また、共有を設定していればホストの通常の Samba サービスにゲストがアクセスすることもできるので、必ずしも便利な機能とは言えません。
この機能を有効にするには、次のようなコマンドで QEMU を起動します:
$ qemu-system-i386 disk_image -net nic -net user,smb=shared_dir_path
shared_dir_path
はゲストとホストで共有したいディレクトリに置き換えてください。
これで、ゲストから、ホスト 10.0.2.4 の共有ディレクトリに共有名 "qemu" でアクセスすることができるようになります。例えば、Windows エクスプローラーなら \\10.0.2.4\qemu
を開きます。
raw ディスクイメージの中にパーティションをマウントする
仮想マシンが動作していないときに、raw ディスクイメージファイル内のパーティションをループバックデバイスとして設定することでマウントすることが可能です。これは qcow2 などの特別なフォーマットのディスクイメージでは動作しませんが、qemu-nbd
を使ってマウントすることはできます。
手動でバイトオフセットを指定する
ディスクイメージのパーティションをマウントする一つの方法として、次のようなコマンドを使って特定のオフセットでディスクイメージをマウントする方法があります:
# mount -o loop,offset=32256 disk_image mountpoint
offset=32256
オプションは losetup
プログラムにわたされて、ファイルのバイトオフセット 32256 から最後まで続くループバックデバイスが設定され、それからこのループバックデバイスがマウントされます。sizelimit
オプションを使ってパーティションの実際のサイズを指定することもできますが、これは基本的に必要ありません。
ディスクイメージによって、必要なパーティションがオフセット 32256 から始まってない可能性があります。fdisk -l disk_image
を実行してイメージ内のパーティションを見て下さい。fdisk は512バイトセクタ単位で起点と終点を表示するので、512 を掛けて適当なオフセットを mount
で指定してください。
loop モジュールでパーティションを自動検出する
Linux の loop ドライバーはループバックデバイスのパーティションをサポートしていますが、デフォルトでは無効にされています。有効にするには、以下を行なって下さい:
- 全てのループバックデバイスを取り除いて下さい (マウントされているイメージを全てアンコメントするなど)。
loop
モジュールを一度アンロードしてから、max_part=15
パラメータを設定してロードしてください。
あなたのイメージをループバックデバイスとして設定:
# losetup -f disk_image
これで、デバイスが /dev/loop0
の場合、追加のデバイス /dev/loop0pX
が自動的に作成されます。X はパーティションの番号です。これらのパーティションのループバックデバイスは直接マウントすることができます。例:
# mount /dev/loop0p1 mountpoint
kpartx を使う
AUR の multipath-toolsAUR パッケージに入っている kpartx はデバイスのパーティションテーブルを読み込んでパーティションごとに新しいデバイスを作成することができます。例えば:
# kpartx -a /dev/loop0
qcow2 イメージの中にパーティションをマウントする
qcow2 イメージの中のパーティションは qemu-nbd
を使ってマウントできます。Wikibooks を見て下さい。
実際のパーティションをハードディスクイメージのシングルプライマリパーティションとして使う
場合によって、QEMU の中からシステムパーティションのどれかを使いたくなることもあるでしょう。仮想マシンでの raw パーティションの使用は、読み書きの操作が物理ホストのファイルシステムレイヤーを通過しないため、パフォーマンスが高くなります。そのようなパーティションをホストとゲストでのデータの共有手段として使うこともできます。
Arch Linux では、raw パーティションのデバイスファイルは、デフォルトで、root と disk グループが所有者です。root 以外のユーザーで raw パーティションに読み書きできるようにしたい場合は、パーティションのデバイスファイルの所有者をそのユーザーに変える必要があります。
その後、パーティションを QEMU の仮想マシンに仮想ディスクとしてアタッチできます。
ただし、仮想マシン全体をパーティションに収めたいときは、自体は多少複雑になります。そのような場合、実際に仮想マシンを起動するディスクイメージファイルがないために、MBR でパーティション分けされたデバイスではなくファイルシステムとしてフォーマットされたパーティションにブートローダーをインストールすることができません。このような仮想マシンはカーネルと initrd を手動で指定するか、リニア RAID を使って MBR のディスクをシミュレートすることで起動できます。
カーネルと initrd を手動で指定する
QEMU は GRUB などのブートローダーを迂回して、Linux カーネルと init ramdisk を直接ロードすることをサポートしています。それから root ファイルシステムを含んでいる物理パーティションで、パーティションされていない仮想ディスクとして起動することができます。以下のようなコマンドを実行することで行います:
$ qemu-system-i386 -kernel /boot/vmlinuz-linux -initrd /boot/initramfs-linux.img -append root=/dev/sda /dev/sda3
上の例では、ゲストの root ファイルシステムに使われている物理パーティションはホストの /dev/sda3
で、ゲストでは /dev/sda
として表示されます。
もちろん、Arch Linux で使われているものとは違うカーネルや initrd を自由に指定することができます。
複数のカーネルパラメータを -append
オプションで指定するときは、クォートを使って囲む必要があります。例:
... -append 'root=/dev/sda1 console=ttyS0'
リニア RAID を使って MBR で仮想ディスクをシミュレート
ファイルシステムでフォーマットされたパーティションを維持しながらゲストのパーティションをまるでディスクであるかのようなパーティションにしないで、仮想マシンで物理パーティションを使用するもっと複雑な方法として、MBR をシミュレートして GRUB などのブートローダーを使って起動できるようにする方法があります。
リニアモードのソフトウェア RAID (linear.ko
カーネルドライバーが必要) とループバックデバイスを使えばこれが可能です: 方策としては QEMU の raw ディスクイメーに埋め込みたい物理パーティションに動的にマスターブートレコード (MBR) を先頭に付け加えます。
QEMU ディスクイメージの一部にしたいファイルシステムがあるプレーンな、マウントされていない /dev/hdaN
パーティションがあるとします。まず最初に、MBR を入れるための小さなファイルを作成:
$ dd if=/dev/zero of=/path/to/mbr count=32
これで 16 KB (32 * 512 バイト) のファイルが作成されます。(MBR は512バイトのブロックしか必要としませんが) あまり小さくしすぎないことが重要です。なぜならファイルを小さくすればするほど、ソフトウェア RAID デバイスのチャンクサイズも小さくしなくてはならなくなり、パフォーマンスに影響を与えるからです。次に、MBR ファイルのループバックデバイスを設定します:
# losetup -f /path/to/mbr
Let us assume the resulting device is /dev/loop0
, because we would not already have been using other loopbacks. Next step is to create the "merged" MBR + /dev/hdaN
disk image using software RAID:
# modprobe linear # mdadm --build --verbose /dev/md0 --chunk=16 --level=linear --raid-devices=2 /dev/loop0 /dev/hdaN
The resulting /dev/md0
is what you will use as a QEMU raw disk image (do not forget to set the permissions so that the emulator can access it). The last (and somewhat tricky) step is to set the disk configuration (disk geometry and partitions table) so that the primary partition start point in the MBR matches the one of /dev/hdaN
inside /dev/md0
(an offset of exactly 16 * 512 = 16384 bytes in this example). Do this using fdisk
on the host machine, not in the emulator: the default raw disc detection routine from QEMU often results in non-kilobyte-roundable offsets (such as 31.5 KB, as in the previous section) that cannot be managed by the software RAID code. Hence, from the the host:
# fdisk /dev/md0
Press X
to enter the expert menu. Set number of 's'ectors per track so that the size of one cylinder matches the size of your MBR file. For two heads and a sector size of 512, the number of sectors per track should be 16, so we get cylinders of size 2x16x512=16k.
R
を押してメインメニューに戻って下さい。
P
を押してシリンダーのサイズが 16k になってることを確認します。
Now, create a single primary partition corresponding to /dev/hdaN
. It should start at cylinder 2 and end at the end of the disk (note that the number of cylinders now differs from what it was when you entered fdisk.
Finally, 'w'rite the result to the file: you are done. You now have a partition you can mount directly from your host, as well as part of a QEMU disk image:
$ qemu-system-i386 -hdc /dev/md0 [...]
You can, of course, safely set any bootloader on this disk image using QEMU, provided the original /dev/hdaN
partition contains the necessary tools.
ネットワーク
仮想ネットワークのパフォーマンスはユーザーモードネットワークまたは vde によるよりも tap デバイスやブリッジを用いる方が良いでしょう。tap デバイスやブリッジはカーネル内で実装されているからです。
加えて、デフォルトの e1000 NIC のエミュレーションではなく virtio ネットワークデバイスを仮想マシンに指定することでネットワークのパフォーマンスを向上させることができます。詳しくは #virtio ドライバーのインストール を参照。
Link-level address caveat
By giving the -net nic
argument to QEMU, it will, by default, assign a virtual machine a network interface with the link-level address 52:54:00:12:34:56
. However, when using bridged networking with multiple virtual machines, it is essential that each virtual machine has a unique link-level (MAC) address on the virtual machine side of the tap device. Otherwise, the bridge will not work correctly, because it will receive packets from multiple sources that have the same link-level address. This problem occurs even if the tap devices themselves have unique link-level addresses because the source link-level address is not rewritten as packets pass through the tap device.
Make sure that each virtual machine has a unique link-level address, but it should always start with 52:54:
. Use the following option, replace X with arbitrary hexadecimal digit:
$ qemu-system-i386 -net nic,macaddr=52:54:XX:XX:XX:XX -net vde disk_image
Generating unique link-level addresses can be done in several ways:
1. Manually specify unique link-level address for each NIC. The benefit is that the DHCP server will assign the same IP address each time the virtual machine is run, but it is unusable for large number of virtual machines.
2. Generate random link-level address each time the virtual machine is run. Practically zero probability of collisions, but the downside is that the DHCP server will assign a different IP address each time. You can use the following command in a script to generate random link-level address in a macaddr
variable:
printf -v macaddr "52:54:%02x:%02x:%02x:%02x" $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) qemu-system-i386 -net nic,macaddr="$macaddr" -net vde disk_image
3. Use the following script qemu-mac-hasher.py
to generate the link-level address from the virtual machine name using a hashing function. Given that the names of virtual machines are unique, this method combines the benefits of the aforementioned methods: it generates the same link-level address each time the script is run, yet it preserves the practically zero probability of collisions.
qemu-mac-hasher.py
#!/usr/bin/env python import sys import zlib if len(sys.argv) != 2: print("usage: %s <VM Name>" % sys.argv[0]) sys.exit(1) crc = zlib.crc32(sys.argv[1].encode("utf-8")) & 0xffffffff crc = str(hex(crc))[2:] print("52:54:%s%s:%s%s:%s%s:%s%s" % tuple(crc))
In a script, you can use for example:
vm_name="VM Name" qemu-system-i386 -name "$vm_name" -net nic,macaddr=$(qemu-mac-hasher.py "$vm_name") -net vde disk_image
ユーザーモードネットワーク
デフォルトで、-netdev
引数をつけていないと、QEMU は DHCP サーバーが内蔵されたユーザーモードネットワークを使用します。DHCP クライアントを実行したときに仮想マシンには IP アドレスが与えられ、QEMU による IP マスカレードを通して物理ホストのネットワークにアクセスできるようになります。
ホストがインターネットに接続されていれば、このデフォルトの設定で簡単に仮想マシンをインターネットにアクセスさせることができますが、外部ネットワークからは仮想マシンは直接は見えず、また、複数の仮想マシンを同時に起動していても仮想マシン同士が通信することはできません。
QEMU のユーザーモードネットワークには内蔵の TFTP や SMB サーバー、ゲストを VLAN に追加してゲストの通信を可能にするなどの機能があります。詳しくは -net user
フラグの QEMU ドキュメントを参照してください。
ただし、ユーザーモードネットワークには有用性とパフォーマンスの両方で制約があります。より高度なネットワーク設定をするには tap デバイスや他の方法を使って下さい。
QEMU の Tap ネットワーク
Tap デバイスは Linux カーネルの機能で、本当のネットワークインターフェイスのように見える仮想ネットワークインターフェイスを作成することができます。tap インターフェイスに送られたパケットは、そのインターフェイスに bind された、QEMU などのユーザースペースプログラムに送信されます。
QEMU は仮想マシンで tap ネットワークを利用して、tap インターフェイスに送られたパケットを仮想マシンに送信することで仮想マシンのネットワークインターフェイス (通常は Ethernet インターフェイス) から受け取ったように見せることが可能です。逆に、仮想マシンがネットワークインターフェイスを通して送信したものは全て tap インターフェイスが受け取ります。
Tap デバイスは Linux の bridge ドライバーによってサポートされているため、tap デバイスを互いに、または eth0
といったホストのインターフェイスとブリッジすることができます。これは、仮想マシンを互いに通信できるようにしたい場合や、LAN 上の他のマシンが仮想マシンに通信できるようにしたい場合に価値があります。
ホストオンリーネットワーク
ブリッジに IP アドレスが与えられていてそこへのトラフィックが許可されていながら、本当のインターフェイス (例: eth0
) がブリッジに接続されていない場合、仮想マシンは互いに通信したりホストシステムと通信することができるようになります。しかしながら、物理ホストで IP マスカレードを設定しないかぎり外部ネットワークとは一切通信することができません。この設定は VirtualBox などの他の仮想化ソフトウェアではホストオンリーネットワークと呼ばれています。
内部ネットワーク
ブリッジに IP アドレスを与えずにブリッジへの全てのトラフィックを INPUT チェインで drop する iptables ルールを追加した場合、仮想マシンは互いに通信することはできても、物理ホストや外側のネットワークに接続できなくなります。この設定は VirtualBox などの他の仮想化ソフトウェアでは内部ネットワークと呼ばれています。仮想マシンに固定 IP アドレスを割り当てるかマシンのどれか一つで DHCP サーバーを実行する必要があります。
デフォルトで iptables はブリッジネットワークのパケットを拒否します。ブリッジネットワークのパケットを許可する iptables のツールを使用する必要があります:
# iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT
qemu-bridge-helper を使用するブリッジネットワーク
この方法にはスタートアップスクリプトが必要なく、すぐに複数の tap やブリッジに対応することができます。既存のブリッジに tap デバイスを作成できるようにする、/usr/lib/qemu/qemu-bridge-helper
バイナリを使用します。
まず、/etc/qemu/bridge.conf.sample
を /etc/qemu/bridge.conf
にコピーします。そして /etc/qemu/bridge.conf
を編集して QEMU で使用するブリッジの名前を全て記述します:
/etc/qemu/bridge.conf
allow bridge0 allow bridge1 ...
設定したら VM を起動して下さい。一番基本的な使い方は:
$ qemu-system-i386 -net nic -net bridge,br=bridge0 [...]
tap が複数の場合、追加の NIC 全てに VLAN を指定する必要があります:
$ qemu-system-i386 -net nic -net bridge,br=bridge0 -net nic,vlan=1 -net bridge,vlan=1,br=bridge1 [...]
ブリッジを手動で作成する
The following describes how to bridge a virtual machine to a host interface such as eth0
, which is probably the most common configuration. This configuration makes it appear that the virtual machine is located directly on the external network, on the same Ethernet segment as the physical host machine.
We will replace the normal Ethernet adapter with a bridge adapter and bind the normal Ethernet adapter to it. See http://en.gentoo-wiki.com/wiki/KVM#Networking_2[リンク切れ 2013-07-23].
- ブリッジを制御するための
brctl
が入っている bridge-utils をインストール。
- IPv4 フォワーディングを有効にする:
# sysctl net.ipv4.ip_forward=1
変更を永続的にするために、/etc/sysctl.d/99-sysctl.conf
の net.ipv4.ip_forward = 0
を net.ipv4.ip_forward = 1
に変えます。
tun
モジュールをロードして起動時にロードするように設定してください。詳しくはカーネルモジュールを参照。
- ブリッジを作成します。詳しくは Bridge with netctl を見て下さい。ブリッジの名前を
br0
にするか、下のスクリプトを使用するブリッジの名前に忘れずに変更してください。
- Create the script that QEMU uses to bring up the tap adapter with
root:kvm
750 permissions:
/etc/qemu-ifup
#!/bin/sh echo "Executing /etc/qemu-ifup" echo "Bringing up $1 for bridged mode..." sudo /usr/bin/ip link set $1 up promisc on echo "Adding $1 to br0..." sudo /usr/bin/brctl addif br0 $1 sleep 2
- Create the script that QEMU uses to bring down the tap adapter in
/etc/qemu-ifdown
withroot:kvm
750 permissions:
/etc/qemu-ifdown
#!/bin/sh echo "Executing /etc/qemu-ifdown" sudo /usr/bin/ip link set $1 down sudo /usr/bin/brctl delif br0 $1 sudo /usr/bin/ip link delete dev $1
visudo
を使ってsudoers
ファイルに以下を追加します:
Cmnd_Alias QEMU=/usr/bin/ip,/usr/bin/modprobe,/usr/bin/brctl %kvm ALL=NOPASSWD: QEMU
- 以下の
run-qemu
スクリプトを使って QEMU を起動します:
run-qemu
#!/bin/bash USERID=$(whoami) # Get name of newly created TAP device; see https://bbs.archlinux.org/viewtopic.php?pid=1285079#p1285079 precreationg=$(/usr/bin/ip tuntap list | /usr/bin/cut -d: -f1 | /usr/bin/sort) sudo /usr/bin/ip tuntap add user $USERID mode tap postcreation=$(/usr/bin/ip tuntap list | /usr/bin/cut -d: -f1 | /usr/bin/sort) IFACE=$(comm -13 <(echo "$precreationg") <(echo "$postcreation")) # This line creates a random MAC address. The downside is the DHCP server will assign a different IP address each time printf -v macaddr "52:54:%02x:%02x:%02x:%02x" $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) $(( $RANDOM & 0xff)) $(( $RANDOM & 0xff )) # Instead, uncomment and edit this line to set a static MAC address. The benefit is that the DHCP server will assign the same IP address. # macaddr='52:54:be:36:42:a9' qemu-system-i386 -net nic,macaddr=$macaddr -net tap,ifname="$IFACE" $* sudo ip link set dev $IFACE down &> /dev/null sudo ip tuntap del $IFACE mode tap &> /dev/null
Then to launch a VM, do something like this
$ run-qemu -hda myvm.img -m 512 -vga std
- パフォーマンスとセキュリティ上の理由でブリッジのファイアウォールは無効化するのが推奨されています:
/etc/sysctl.d/10-disable-firewall-on-bridge.conf
net.bridge.bridge-nf-call-ip6tables = 0 net.bridge.bridge-nf-call-iptables = 0 net.bridge.bridge-nf-call-arptables = 0
すぐに変更を適用するには sysctl -p /etc/sysctl.d/10-disable-firewall-on-bridge.conf
を実行してください。
libvirt wiki や Fedora bug 512206 を参照。起動中にファイルが存在しないというエラーが起こるときは、起動時に bridge
モジュールをロードするようにしてください。カーネルモジュール#ロード を参照。
または、次のようにルールを追加することで全てのトラフィックをブリッジで通すように iptables を設定することができます:
-I FORWARD -m physdev --physdev-is-bridged -j ACCEPT
VDE2 によるネットワーク
VDE とは?
VDE は Virtual Distributed Ethernet の略です。uml_switch の拡張として始まりました。仮想ネットワークを管理するためのツールボックスです。
The idea is to create virtual switches, which are basically sockets, and to "plug" both physical and virtual machines in them. The configuration we show here is quite simple; However, VDE is much more powerful than this, it can plug virtual switches together, run them on different hosts and monitor the traffic in the switches. You are invited to read the documentation of the project.
The advantage of this method is you do not have to add sudo privileges to your users. Regular users should not be allowed to run modprobe.
基本
VDE サポートは公式リポジトリの vde2 パッケージでインストールできます。
この設定では、tun/tap を使ってホストに仮想インターフェイスを作成します。tun
モジュールをロード (詳しくはカーネルモジュールを参照):
# modprobe tun
仮想スイッチを作成:
# vde_switch -tap tap0 -daemon -mod 660 -group users
This line creates the switch, creates tap0
, "plugs" it, and allows the users of the group users
to use it.
The interface is plugged in but not configured yet. To configure it, run this command:
# ip addr add 192.168.100.254/24 dev tap0
Now, you just have to run KVM with these -net
options as a normal user:
$ qemu-system-i386 -net nic -net vde -hda [...]
物理ネットワークでやるのと同じようにゲストのネットワークを設定してください。
起動スクリプト
VDE を起動するメインスクリプトの例:
/etc/systemd/scripts/qemu-network-env
#!/bin/sh # QEMU/VDE network environment preparation script # The IP configuration for the tap device that will be used for # the virtual machine network: TAP_DEV=tap0 TAP_IP=192.168.100.254 TAP_MASK=24 TAP_NETWORK=192.168.100.0 # Host interface NIC=eth0 case "$1" in start) echo -n "Starting VDE network for QEMU: " # If you want tun kernel module to be loaded by script uncomment here #modprobe tun 2>/dev/null ## Wait for the module to be loaded #while ! lsmod | grep -q "^tun"; do echo "Waiting for tun device"; sleep 1; done # Start tap switch vde_switch -tap "$TAP_DEV" -daemon -mod 660 -group users # Bring tap interface up ip address add "$TAP_IP"/"$TAP_MASK" dev "$TAP_DEV" ip link set "$TAP_DEV" up # Start IP Forwarding echo "1" > /proc/sys/net/ipv4/ip_forward iptables -t nat -A POSTROUTING -s "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE ;; stop) echo -n "Stopping VDE network for QEMU: " # Delete the NAT rules iptables -t nat -D POSTROUTING "$TAP_NETWORK"/"$TAP_MASK" -o "$NIC" -j MASQUERADE # Bring tap interface down ip link set "$TAP_DEV" down # Kill VDE switch pgrep -f vde_switch | xargs kill -TERM ;; restart|reload) $0 stop sleep 1 $0 start ;; *) echo "Usage: $0 {start|stop|restart|reload}" exit 1 esac exit 0
上のスクリプトを使う systemd サービスの例:
/etc/systemd/system/qemu-network-env.service
[Unit] Description=Manage VDE Switch [Service] Type=oneshot ExecStart=/etc/systemd/scripts/qemu-network-env start ExecStop=/etc/systemd/scripts/qemu-network-env stop RemainAfterExit=yes [Install] WantedBy=multi-user.target
qemu-network-env
が実行できるようにパーミッションを変更:
# chmod u+x /etc/systemd/scripts/qemu-network-env
通常の方法で起動することができます (詳しくは systemd#ユニットを使う を参照):
# systemctl start qemu-network-env
他の方法
上の方法が動作しない場合やカーネル設定, TUN, dnsmasq, iptables を変えたくない場合は以下のコマンドで同じ結果になります。
# vde_switch -daemon -mod 660 -group users # slirpvde --dhcp --daemon
ホストのネットワークの接続を使って VM を起動するには:
$ qemu-system-i386 -net nic,macaddr=52:54:00:00:EE:03 -net vde disk_image
VDE2 Bridge
Based on quickhowto: qemu networking using vde, tun/tap, and bridge graphic. Any virtual machine connected to vde is externally exposed. For example, each virtual machine can receive DHCP configuration directly from your ADSL router.
基本
tun
モジュールと bridge-utils パッケージが必要です。
vde2/tap デバイスを作成:
# vde_switch -tap tap0 -daemon -mod 660 -group users # ip link set tap0 up
ブリッジを作成:
# brctl addbr br0
デバイスを追加:
# brctl addif br0 eth0 # brctl addif br0 tap0
ブリッジインターフェイスを設定:
# dhcpcd br0
起動スクリプト
全てのデバイスを設定する必要があります。ブリッジに必要なのは IP アドレスだけです。ブリッジの物理デバイスは (例: eth0
)、netctl でカスタム Ethernet プロファイルを使います:
/etc/netctl/ethernet-noip
Description='A more versatile static Ethernet connection' Interface=eth0 Connection=ethernet IP=no
以下のカスタム systemd サービスを使うことで users
ユーザーグループで使用する VDE2 tap インターフェイスを作成することができます。
/etc/systemd/system/vde2@.service
[Unit] Description=Network Connectivity for %i Wants=network.target Before=network.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/bin/vde_switch -tap %i -daemon -mod 660 -group users ExecStart=/usr/bin/ip link set dev %i up ExecStop=/usr/bin/ip addr flush dev %i ExecStop=/usr/bin/ip link set dev %i down [Install] WantedBy=multi-user.target
そして最後に、netctl でブリッジネットワークを作成することが可能です。
グラフィック
QEMU は様々なグラフィック出力を使うことができます: std
, cirrus
, vmware
, qxl
, none
。
std
-vga std
では 2560 x 1600 ピクセルまでの解像度を得ることができます。
vmware
多少バグが存在しますが、std や cirrus よりもパフォーマンスが上です。ゲストに、VMware ドライバーをインストールしてください (Arch Linux ゲストなら xf86-video-vmware と xf86-input-vmmouse)。
qxl
QXL は 2D サポートのある準仮想化グラフィックドライバーです。使用するには以下の条件を満たす必要があります:
- ホストシステムで Spice を有効にしなければなりません。
- ゲストにドライバーをインストールします (例: AUR の xf86-video-qxlAUR)。
-vga qxl
スイッチを使って仮想マシンを起動します。
none
これは VGA カードが全くない PC と同じようになります。-vnc
オプションを使ってもアクセスすることはできません。また、QEMU に VGA カードをエミュレートさせ SDL ディスプレイを無効にする -nographic
オプションとは異なります。
vnc
-nographic
オプションを使っている場合、-vnc display
オプションを追加することで QEMU に display
を listen させて VGA ディスプレイを VNC セッションにリダイレクトさせることができます。#ブート時に QEMU 仮想マシンを起動する セクションの設定例にこれのサンプルがあります。
$ qemu-system-i386 -vga std -nographic -vnc :0 $ gvncviewer :0
VNC を使う際、ここで示されているようなキーボードの問題が発生するかもしれません。解決方法は、QEMU で -k
オプションを使わないことと、gtk-vnc の gvncviewer
を使うことです。libvirt のメーリングリストに投稿された この メッセージも参照してください。
virtio ドライバーのインストール
QEMU にで virtio ドライバーを使って準仮想化ブロックとネットワークデバイスをゲストが利用できるようにすることができ、より良いパフォーマンス・少ないオーバーヘッドを実現します。
- virtio ブロックデバイスにはシンプルな
-hd*
の代わりに-drive
オプションとif=virtio
が必要です:
$ qemu-system-i386 -boot order=c -drive file=disk_image,if=virtio
- ネットワークでもほぼ同じです:
$ qemu-system-i386 -net nic,model=virtio
(Arch) Linux ゲストを用意する
Arch Linux ゲストをインストールした後 virtio デバイスを使うには、次のモジュールをゲストでロードする必要があります: virtio
, virtio_pci
, virtio_blk
, virtio_net
, virtio_ring
。32ビットのゲストの場合、特定の "virtio" モジュールは必要ありません。
virtio ディスクから起動したい場合、イニシャル RAM ディスクに必要なモジュールを含ませなければなりません。デフォルトでは、mkinitcpio の autodetect
フックによって管理されています。もしくは /etc/mkinitcpio.conf
の MODULES
行を使って必要なモジュールを含めてイニシャル RAM ディスクをリビルドしてください。
/etc/mkinitcpio.conf
MODULES="virtio virtio_blk virtio_pci virtio_net"
Virtio ディスクは前に v
が付いて認識されます (例: vda
, vdb
など)。なので、virtio ディスクから起動する際は /etc/fstab
や /boot/grub/grub.cfg
などに変更を加える必要があります。
KVM による準仮想化に関する詳細は こちら で読むことができます。
Windows ゲストを用意する
ブロックデバイスドライバー
virtio ディスクから起動するように Windows ゲストを用意するのはやや面倒です。
Fedora のリポジトリ から virtio ディスクドライバーをダウンロードすることができます。
そして Windows がドライバーを検索するように、新しいディスクイメージを作成する必要があります。例:
$ qemu-img create -f qcow2 fake.qcow2 1G
(virtio モードの) フェイクディスクと CD-ROM とドライバーで元の Windows ゲストを起動 (ブートディスクを IDE モードで使う):
$ qemu-system-i386 -m 512 -vga std -drive file=windows_disk_image,if=ide -drive file=fake.qcow2,if=virtio -cdrom virtio-win-0.1-81.iso
Windows はフェイクディスクを検出してそのドライバーを検索します。ドライバーが見つからない場合は、Device Manager を開いて、エクスクラメーションマークのアイコンが付いた SCSI ドライブを探して (開いて下さい)、Update driver をクリックして仮想 CD-ROM を選択してください。ディレクトリを再帰的に検索すると書かれたチェックボックスを選択するのを忘れずに。
インストールが成功したら、仮想マシンを止めて virtio モードのブートディスクで再起動することができます:
$ qemu-system-i386 -m 512 -vga std -drive file=windows_disk_image,if=virtio
ネットワークドライバー
virtio ネットワークドライバーのインストールはもう少し簡単で、上記に -net
引数を追加します:
$ qemu-system-i386 -m 512 -vga std -drive file=windows_disk_image,if=virtio -net nic,model=virtio -cdrom virtio-win-0.1-74.iso
Windows はネットワークアダプタを検出してそのドライバーを検索します。ドライバーが見つからない場合は、Device Manager を開いて、エクスクラメーションマークのアイコンが付いたネットワークアダプタを探して (開いて下さい)、Update driver をクリックして仮想 CD-ROM を選択してください。ディレクトリを再帰的に検索すると書かれたチェックボックスを選択するのを忘れずに。
FreeBSD ゲストを用意する
FreeBSD 8.3 以降を使っている場合は emulators/virtio-kmod
port をインストールしてください、10.0-CURRENT ではカーネルに含まれています。インストール後、/boot/loader.conf
ファイルに以下を追加します:
virtio_loader="YES" virtio_pci_load="YES" virtio_blk_load="YES" if_vtnet_load="YES" virtio_balloon_load="YES"
そして次を実行して /etc/fstab
を修正してください:
sed -i bak "s/ada/vtbd/g" /etc/fstab
それから /etc/fstab
が問題ないか確認してください。何かがおかしい場合、レスキュー CD で起動して /etc/fstab.bak
を /etc/fstab
にコピーします。
Tips and tricks
ブート時に QEMU 仮想マシンを起動する
libvirt を使う
libvirt を使って仮想マシンをセットアップした場合、virt-manager の GUI を通して、仮想マシンの Boot Options から "Start virtual machine on host boot up" を選択することでホストの起動時に仮想マシンを起動するように設定することができます。
カスタムスクリプト
起動時に QEMU VM を実行するように、以下の systemd ユニットと設定を使うことができます。
/etc/systemd/system/qemu@.service
[Unit] Description=QEMU virtual machine [Service] Environment="type=system-x86_64" "haltcmd=kill -INT $MAINPID" EnvironmentFile=/etc/conf.d/qemu.d/%i ExecStart=/usr/bin/env qemu-${type} -name %i -nographic $args ExecStop=/bin/sh -c ${haltcmd} TimeoutStopSec=30 KillMode=none [Install] WantedBy=multi-user.target
VM ごとに、/etc/conf.d/qemu.d/vm_name
という名前の設定ファイルを作成して、以下の変数を設定します:
- type
- 実行する QEMU バイナリ。指定すれば、
/usr/bin/qemu-
が前に付けられて VM を起動するのにそのバイナリが使われます。例えばtype="system-arm"
でqemu-system-arm
イメージが起動できます。 - args
- 起動するときの QEMU コマンドライン。
-name ${vm} -nographic
はいつも前に付けます。 - haltcmd
- VM を安全にシャットダウンするためのコマンド。例えば
-monitor telnet:..
を使ってモニターにsystem_powerdown
を送信して ACPI で VM の電源を切ります。SSH やその他の方法が使えます。
設定例:
/etc/conf.d/qemu.d/one
type="system-x86_64" args="-enable-kvm -m 512 -hda /dev/mapper/vg0-vm1 -net nic,macaddr=DE:AD:BE:EF:E0:00 \ -net tap,ifname=tap0 -serial telnet:localhost:7000,server,nowait,nodelay \ -monitor telnet:localhost:7100,server,nowait,nodelay -vnc :0" haltcmd="echo 'system_powerdown' | nc localhost 7100" # or netcat/ncat # You can use other ways to shut down your VM correctly #haltcmd="ssh powermanager@vm1 sudo poweroff"
/etc/conf.d/qemu.d/two
args="-enable-kvm -m 512 -hda /srv/kvm/vm2.img -net nic,macaddr=DE:AD:BE:EF:E0:01 \ -net tap,ifname=tap1 -serial telnet:localhost:7001,server,nowait,nodelay \ -monitor telnet:localhost:7101,server,nowait,nodelay -vnc :1" haltcmd="echo 'system_powerdown' | nc localhost 7101"
以下のコマンドを使って、ブート時にそれぞれの仮想マシンが起動するように設定します:
# systemctl enable qemu@vm_name # systemctl disable qemu@vm_name
シームレスなマウス
ゲストのオペレーティングシステムのウィンドウをクリックしたときにマウスが取り込まれないようにするには、-usbdevice tablet
オプションを追加します。これによって QEMU はマウスを取り込むことなくマウスの位置を伝えることができるようになります。また、このコマンドは有効化されている場合 PS/2 マウスエミュレーションを上書きします。例:
$ qemu-system-i386 -hda disk_image -m 512 -vga std -usbdevice tablet
上のコマンドで動作しない場合は、#マウスカーソルが敏感すぎたり迷走する を参照してみて下さい。
ホスト USB デバイスのパススルー
VM からホストに接続された物理 USB デバイスにアクセスするために、以下のオプションを使って QEMU を起動することができます:
$ qemu-system-i386 -usbdevice host:vendor_id:product_id disk_image
lsusb
コマンドでデバイスの vendor_id
と product_id
がわかります。
KSM を有効にする
Kernel Samepage Merging (KSM) はアプリケーションがページをマージするように登録した他のプロセスとページをマージするようにカーネルに登録できるようにする Linux カーネルの機能です。この KSM 機構によってゲストの仮想マシンは互いにページを共有することが可能になります。同じようなゲストオペレーティングシステムが多数動作する環境では、メモリの使用量を著しく節約することができます。
KSM を有効にするには、次を実行してください:
# echo 1 > /sys/kernel/mm/ksm/run
systemd の一時ファイルを使って KSM を永続的に有効にできます:
/etc/tmpfiles.d/ksm.conf
w /sys/kernel/mm/ksm/run - - - - 1
KSM が動作しているとき、マージされるページが存在するために (つまり少なくとも2つの同じような VM が動いている)、/sys/kernel/mm/ksm/pages_shared
はゼロになりません。詳しくは https://www.kernel.org/doc/Documentation/vm/ksm.txt を参照。
Spice サポート
Spice プロジェクト は仮想化されたデスクトップデバイスを操作するための完全な、オープンソースのソリューションを提供することを目的としています。主として QEMU 仮想マシンへの高品質なリモートアクセスを提供することに力を注いでいます。
公式の qemu パッケージは Spice サポートを付けてビルドされています。
VM を次のように起動することができます:
$ qemu-system-i386 -vga qxl -spice port=5930,disable-ticketing
それから spice クライアントで接続してください:
$ spicec -h 127.0.0.1 -p 5930
コピーアンドペースト
ホストとゲスト間のコピーアンドペーストを行うには spice エージェント通信チャンネルを有効にする必要があります。それには virtio-serial デバイスをゲストに追加して、spice vdagent のためにポートを開かなければなりません。また、ゲストへの spice vdagent のインストールも必須です (Arch ゲストの場合は spice-vdagentAUR、Windows ゲストの場合は Windows ゲストツール)。エージェントが動いていること (さらに、今後のために、自動で起動すること) を確認してください。
QEMU を次のオプションを使って起動します:
$ qemu-system-i386 -vga qxl -spice port=5930,disable-ticketing -device virtio-serial-pci -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent
-device virtio-serial-pci
オプションが virtio-serial デバイスを追加し、-device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0
がデバイスの spice vdagent のポートを開いて、-chardev spicevmc,id=spicechannel0,name=vdagent
でそのポートに spicevmc chardev を追加します。
chardev
オプションの id=
オプションと、virtserialport
デバイスの chardev=
オプションは一致していなければなりません (この例では spicechannel0
)。ポートの名前が com.redhat.spice.0
であることも重要です、これが vdagent がゲストで探す名前空間だからです。そして、name=vdagent
を指定することで spice がこのチャンネルが何のためなのか知ることができます。
Windows 特有のノート
QEMU は Windows 95 から Windows 8 まで全てのバージョンの Windows を動かすことができます。
QEMU で Windows PE を実行することも可能です。
Remote Desktop Protocol
MS Windows ゲストを使っている場合、RDP を使ってゲスト VM に接続する方法もあります。VLAN を使用してしてゲストが同じネットワークにない場合、次を使って下さい:
$ qemu-system-i386 -nographic -net user,hostfwd=tcp::5555-:3389
そして rdesktop か freerdp を使ってゲストに接続してください。例えば:
$ xfreerdp -g 2048x1152 localhost:5555 -z -x lan
トラブルシューティング
マウスカーソルが敏感すぎたり迷走する
カーソルが画面を飛び回って手に負えない場合、QEMU を起動する前にターミナルに次を入力することで直るかもしれません:
$ export SDL_VIDEO_X11_DGAMOUSE=0
このコマンドで直ったら、~/.bashrc
ファイルにコマンドを追加することができます。
キーボードが壊れているまたは矢印キーが動作しない
キーの一部が動かなかったり間違ったキーが押されてしまう (特に矢印キー) ときは、おそらくキーボードレイアウトをオプションとして指定する必要があります。キーボードレイアウトは /usr/share/qemu/keymaps
で探すことができます。
$ qemu-system-i386 -k keymap disk_image
仮想マシンの動作が遅すぎる
仮想マシンのパフォーマンスを向上させることができる多数のテクニックがあります。例えば:
-cpu host
オプションを使うことで QEMU にホストの CPU を正確にエミュレートさせることができます。このオプションを使わない場合、もっと一般的な CPU がエミュレートされます。- ホストマシンに CPU が複数ある場合は、
-smp
オプションを使ってゲストにもっと多くの CPU を割り当てて下さい。 - 仮想マシンに十分なメモリを割り当てているか確認してください。デフォルトでは、QEMU はそれぞれの仮想マシンに 128 MiB のメモリしか割り当てません。
-m
オプションを使って多めのメモリを割り当てて下さい。例えば、-m 1024
で仮想マシンは 1024 MiB のメモリを使って動作します。 - 可能な限り KVM を使って下さい: QEMU の起動コマンドに
-machine type=pc,accel=kvm
を追加します。 - ゲストのオペレーティングシステムのドライバーによってサポートされているときは、ネットワークやブロックデバイスに virtio を使って下さい。例えば:
$ qemu-system-i386 -net nic,model=virtio -net tap,if=tap0,script=no -drive file=disk_image,media=disk,if=virtio
- ユーザーモードネットワークの代わりに TAP デバイスを使って下さい。#QEMU の Tap ネットワーク を参照。
- ゲスト OS がディスクへの書き込みを頻繁に行う場合、ホストのファイルシステムで特定のマウントオプションを使うと良いかもしれません。例えば、ext4 ファイルシステム を
barrier=0
オプションでマウントすることが考えられます。ファイルシステムのパフォーマンスを向上させるオプションは、場合によってデータの保全性を犠牲にする可能性があるので、変更するオプションのドキュメントを読んでおいたほうが無難です。 - raw ディスクイメージを使っている場合、キャッシュを無効にする:
$ qemu-system-i386 -drive file=disk_image,if=virtio,cache=none
- 複数の仮想マシンを同時に動かしていて、全て同じオペレーティングシステムをインストールしている場合、kernel same-page merging を有効にすることでメモリを節約できます:
# echo 1 > /sys/kernel/mm/ksm/run
- 場合によっては、ゲストのオペレーティングシステムでメモリバルーニングドライバーを実行して QEMU を
-balloon virtio
オプションで起動することで、実行中の仮想マシンからメモリを回収することができます。
詳しくは http://www.linux-kvm.org/page/Tuning_KVM を参照してください。
ウィンドウのリサイズでゲストのディスプレイが引き伸ばされる
デフォルトのウィンドウサイズに戻すには、Ctrl+Alt+u
を押して下さい。
ioctl(KVM_CREATE_VM) failed: 16 Device or resource busy
-enable-kvm
オプションを使って QEMU を起動した時に以下のようなエラーメッセージが表示される場合:
ioctl(KVM_CREATE_VM) failed: 16 Device or resource busy failed to initialize KVM: Device or resource busy
他のハイパーバイザーが動作しています。同時に複数のハイパーバイザーを動かすのは推奨されていません、もしくは不可能です。
参照
- 公式 QEMU ウェブサイト
- 公式 KVM ウェブサイト
- QEMU エミュレーターユーザードキュメント
- QEMU Wikibook
- Hardware virtualization with QEMU by AlienBOB
- Building a Virtual Army by Falconindy
- QEMU, KVM, Xen & libvirt by Robert Warnke and Thomas Ritzau
- Networking QEMU Virtual BSD Systems