2013/07/21

VirtFS で Qemu ゲストホスト間ファイル共有

はじめに

Qemu/KVM 環境において、ホストゲスト間でのファイル共有ができると、とても便利です。例えば、開発中の Linux Kernel をテストする時には、ホストのコンパイル済み Kernel ソースディレクトリをゲストでマウントし、Kernel のインストールができると捗ります。ファイル共有方法には NFS、CIFS、SSHFS などがありますが、Qemu にはより効率的な "VirtFS" という仕組みがあります。
VirtFS は、ゲストの Linux マシンと virtio-9p デバイスを通じてファイル共有する仕組みです。ゲストホスト間で共有するリングバッファへの読み書きでデータをやり取りするため、他のネットワークファイルシステムなどより効率が良いのです。
今回は virt-manager での VirtFS を使ったファイル共有設定方法についてご紹介します。
Fedora 18で検証しています。(Fedora 15以上であれば Qemu が対応しています。)

virt-manager でのホストゲスト間ファイル共有設定

仮想マシン詳細を開き、「ハードウェアを追加」で 「FileSystem」を選択します。

ファイルシステム・パススルーの各項目を設定していきます。
上記の設定のように設定し、ゲストを起動しましょう。

「ターゲットパス」に指定したワードが、ゲスト上で 9pfs をマウントする際のマウントタグになります。

ゲストでのマウント
マウントタグの確認
# cat /sys/bus/virtio/drivers/9pnet_virtio/virtio<n>/mount_tag
source_tag
マウント
# mkdir source
# mount -t 9p -o trans=virtio source_tag ./source/
これでゲストから /path/to/source_dir がみえるようになりました。

注意

上記の設定では、ゲストからの共有ディレクトリへの書き込みが Permisson Denied になってしまいます。これは、qemu 起動ユーザが共有ファイルへのアクセス権を持っていない時に生じます。書き込みできるようにするためには、qemu を root で起動する必要があります。

qemu を root で起動するための libvirt 設定
/etc/libvirtd/qemu.conf
user = "root"
group = "root"
をコメントアウトし、libvirtd を再起動。

参考文献

Documentation/filesystems/9p.txt
libvirt: Domain XML format
Qemu Wiki : 9psetup
VirtFS LPC 2010
KVM日記 : Rootfs over Virtfsでゲストを起動する

2013/07/18

virsh で 仮想マシンのスナップショットを取る

はじめに

仮想マシン上で頻繁に環境構築・破壊を繰り返す場合、仮想マシンのスナップショットを利用し、素早くディスク状態をもとに戻せると便利です。libvirt, Qemu/KVM は仮想マシンのスナップショット機能を実装しており、とても有用です。今回は virsh コマンドでのスナップショットの扱い方をご紹介します。検証環境は Fedora 18です。

スナップショットの種類

libvirt, Qemu が実装している仮想マシンスナップショットの種類には、以下の2種類がありあます。

- 1. 内部スナップショット
- 2. 外部スナップショット

1. 内部スナップショットは仮想マシンのスナップショットを一つの qcow2 ファイルで管理する方式です。スナップショット取得中は仮想マシンは一時停止状態になります。仮想マシンのディスクのスナップショットのみならず、RAM 状態やデバイス状態などの仮想マシン状態も保存できます。

2. 外部スナップショットは仮想マシンのスナップショットを外部の qcow2 ファイルで管理します。なんと、仮想マシンを停止することなくスナップショットを取得できます。仮想マシンディスク以外の仮想マシン状態を保存することは、今のところできません。また、今のところ、仮想マシン停止中にはスナップショットを取ることができません。
現状動作が安定しておらず、非常に実験的な機能です。

以下、仮想マシンの名前を vm1 として、virsh コマンドの使い方を説明します。

内部スナップショット

内部スナップショットの作成
# virsh snapshot-create-as vm1 snap1 "snap1 description"
ドメインのスナップショット snap1 が作成されました
内部スナップショットは仮想マシン稼働中でもスナップショットを作成できます(ただし、安定していません)。作成している間は、仮想マシンは一時停止状態になります。ストレージ性能や仮想ディスク容量にもよりますが、作成時間は数分かかります。

内部スナップショット確認
# virsh snapshot-list vm1
 名前               作成時間              状態
------------------------------------------------------------
 snap1                2013-07-18 16:43:11 +0900 running

内部スナップショット復元
# virsh snapshot-revert vm1 snap1
スナップショットの復元についても、仮想マシン稼働中に実行可能です。ただし、復元中、仮想マシンは一時停止状態になります。

内部スナップショット情報の取得
指定のスナップショット情報を取得する際のコマンドは以下です。
# virsh snapshot-info vm1 snap1
名前:         snap1
ドメイン:   vm1
カレント:   はい (yes)
状態:         running
親:            -
子:            0
子孫:         0
メタデータ: はい (yes)

スナップショット復元後は下記コマンドで現時点でどのスナップショットを使用しているか確認できます。
# virsh snapshot-info vm1 --current
名前:         snap1
ドメイン:   vm1
カレント:   はい (yes)
状態:         running
親:            -
子:            0
子孫:         0
メタデータ: はい (yes)

スナップショット XML ファイルのダンプ
仮想マシンに関する設定情報(XML ファイル)を含んでいます。下記コマンドで設定情報を出力できます。
# virsh snapshot-dumpxml vm1 snap1

スナップショットの削除
# virsh snapshot-delete vm1 snap1


外部スナップショット

外部スナップショット作成
# virsh snapshot-create-as vm1 disksnap1 "disksnap1 description" --disk-only --atomic
ドメインのスナップショット disksnap1 が作成されました
外部スナップショットは仮想マシン実行中のみ取得可能です。内部スナップショットとは異なり、仮想マシンを停止(一時停止)することなく取得可能(Live Snapshot)です。つまり、仮想マシン無停止での Live Backup が可能です。
外部スナップショット作成後はディスクスナップショットイメージが作成され、current snapshot が作成したスナップショットになります。
# virsh snapshot-info vm1 --current
名前:         disksnap1
ドメイン:   vm1
カレント:   はい (yes)
状態:         disk-snapshot
親:            -
子:            0
子孫:         0
メタデータ: はい (yes)

外部スナップショット確認
# virsh snapshot-list vm1
 名前               作成時間              状態
------------------------------------------------------------
 disksnap1            2013-07-18 17:39:44 +0900 disk-snapshot
 snap1                2013-07-18 16:43:11 +0900 running

外部スナップショットが作成されると、仮想マシンイメージファイルを格納してあるディレクトリ(デフォルトでは /var/lib/libvirt/images)にスナップショットファイル(vm1.disksnap1)が新たに作成されます。
仮想マシンは新たに作成されたスナップショットファイルを使用するようになります。
# virsh domblklist vm1
ターゲット ソース
------------------------------------------------
vda        /home/eiichi/vmimg/vm1.disksnap1
hdc        -

外部スナップショット復元
外部スナップショットの復元は、virsh edit で仮想マシン設定 XML ファイルを開き、disk タグの source タグのfile 属性を復元したいディスクスナップショットに指定します。現状では ディスクスナップショットへの snapshot-revert は対応していないようです。
# virsh snapshot-revert vm1 disksnap2

エラー: サポートされない設定: 外部ディスクスナップショットへの復元はまだサポートされていません

注意
外部スナップショットはまだまだ開発段階の機能です。無停止でスナップショットが取れますが、動作が安定しないのが難点です。また、内部スナップショット機能についても、仮想マシン起動中のスナップショット取得はやはり安定して動作しないことがあります。
安定した動作を希望する場合、一番安全な、"仮想マシン停止時"  の "内部スナップショット" をおすすめします。

参考文献
fedoraproject : Features/Virt Live Snapshots
QEMU wiki : Features/Snapshot
libvirt : Snapshot XML Format
kashyapc fedorapeople : snapshot handout

python-requests の conflict で devstack が失敗する件

昨日(2013/7/17)、devstack による openstack のインストールを試したところ、以下のようなエラーが出て失敗してしましました。

2013-07-17 23:08:34 Processing dependencies for nova==2013.1.3.a39.g378c045
2013-07-17 23:08:34 error: Installed distribution requests 1.2.3 conflicts with requirement requests>=1.1,<1.2.3

python-requests の version conflict のようです。
結論から言うと、python-cinderclient の requirements.txt を下記のように変更することで回避できます。
[eiichi@q01]~/openstack/python-cinderclient% diff -u requirements.txt.org requirements.txt
--- requirements.txt.org2013-07-18 10:40:48.857523886 +0900
+++ requirements.txt2013-07-18 10:16:19.484897288 +0900
@@ -2,6 +2,6 @@
 pbr>=0.5.16,<0.6
 argparse
 prettytable>=0.6,<0.8
-requests>=1.1,<1.2.3
+requests>=1.1,<=1.2.3
 simplejson>=2.0.9
 six

参考情報

調べてみると、install された python-requests のバージョンが、python-cinderclinet の requirement と conflict しているようです。
% cat python-cinderclient/requirements.txt | grep requests
requests>=1.1,<1.2.3
requests のバージョンを cap するようになったのは 7/14 の下記のコミットからです。
Update to latest openstack/requirements

このコミットが入るようになった経緯は下記のバグが原因です。
BUG # 1200214 Relax OpenStack upper capping of client versions

python-requests のバージョンを CAP する理由が特に無いようにみえるため、おそらく上記の回避策で問題無い、と思います。問題があったら、すいません。

追記(2013/8/3)

devstack への下記コミットにより、本問題は修正されました。
Use unique build dir for pip installs

2013/07/16

Linux で VXLAN を使う

はじめに

VXLAN は VMware、Cisco、Redhat などが推進している VLAN に替わるネットワーク論理分割のための規格です。従来、IaaSなどのクラウド環境において、マルチテナントを実現するためには 802.1Q VLAN を用いるのが一般的な解決策でしたが、この VLAN には VLAN ID が 12bit しかないため、最大 4096 セグメントの分離しかできない、という問題があります。
VXLAN はこの問題を解決します。VLAN ID に対応する VNI(VXLAN Network Identifier) に 24bit を設け、 1,677万セグメントの論理分割を実現します。

VXLAN 類似の技術には Microsoft、Intel、Dell などが推進している NVGRE(Network Virtualization using Generic Routing Encapsulation) があります。実装の進み具合で判断すると、やはり VXLAN のほうが勢いがあるため、今後 L2 over L3 を実現するネットワーク論理分割の主流は VXLAN になる、と個人的には思っています。

今回はこの VXLAN の Linux での使い方をご紹介します。

環境

Qemu/KVM を利用した仮想環境で実施しています。
下記のような簡単な環境です。
|VM A(192.168.10.2/24)| --- | vbr | --- |VM B(192.168.10.3/24)|
VM A、VM B の二台が物理マシン上に作った仮想ブリッジに接続されています。
VM A、VM B の間に VXLAN で 仮想ネットワークを構築します。

使い方

VXLAN の実装はユーザ空間版もあるのですが、ここでは Linux Kernel での実装を使います。前準備として、Linux Kernel のバージョンが 3.7 以上である必要があります。
関連コミット:
vxlan: virtual extensible lan

iproute2 コマンドスイートのバージョンが低いと、VXLAN がサポートされていません。その場合は最新版をソースからコンパイルして入れましょう。VM A および VM B で実施します。
# git clone git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git
# cd iproute2
# ./configure
# make
# make install
# ip link help
(snip)
TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | can |
          bridge | ipoib | ip6tnl | ipip | sit | vxlan }
TYPE に vxlan が含まれていれば、OKです。
もし、iproute2 のコンパイル時に "db_185.h がない" というエラーがでた場合は libdb-devel をインストルしましょう。
# yum install libdb-devel

さて、VXLAN を張る作業に入ります。
VM A、 B 上で下記のコマンドを入力します。
# ip link add vxlan0 type vxlan id 42 group 239.1.1.1 dev eth0
VXLAN は多くのトンネリング技術とことなり、1対Nでのトンネリングを行います。そのため、マルチキャストアドレスを指定します。
# ip -d link show vxlan0
4: vxlan0:  mtu 1450 qdisc noop state DOWN mode DEFAULT
    link/ether ba:ea:4d:a8:72:82 brd ff:ff:ff:ff:ff:ff promiscuity 0
    vxlan id 42 group 239.1.1.1 dev eth1 port 32768 61000 ageing 300
# ip link set up vxlan0
# ip maddr
1:  lo
(snip)
2:  eth0
(snip)
    inet  239.1.1.1
3:  vxlan0
(snip)
ip maddr で 239.1.1.1 が表示されていれば、適切にアドレス設定できていると確認できます。

VXLAN デバイスに アドレスを振って、疎通確認をします。
On VM A
ip a add 192.168.42.2/24 dev vxlan0

On VM B
ip a add 192.168.42.3/24 dev vxlan0

疎通確認
On VM A
ping 192.168.42.3
あなたの予想に反せずに pong が返っているでしょうか。pong が返らないようであれば、VM A,B および物理マシンの firewall 設定を確認してみてください。

下記に ping を送った際の wireshark 通信ダンプ結果を載せておきます。

最初に UDP Multicast で 239.1.1.1 に送信され、VM A の VXLAN トンネル終端がMAC アドレス学習後は Unicast で通信していることがわかります。

fdb は下記コマンドで確認できます。
On VM A
# bridge fdb show dev vxlan0
9e:03:cd:ab:b2:91 dst 192.168.10.3 self

参考文献

Documentation/networking/vxlan.txt
VXLAN: A Framework for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks draft-mahalingam-dutt-dcops-vxlan-04
IPA : VXLAN/NVGREによるネットワーク分離

2013/07/15

iproute2 コマンドでルーティングテーブル/アドレス設定の保存/復元

はじめに

iproute2 はLinuxでネットワーク関係の設定を変更するためのコマンドスイートです。もはや非推奨となった ifconfig の代替として利用が推奨されており、ifconfig コマンドではでは行えない設定も可能です。iproute2 コマンドスイートの中には、ルーティングやアドレス設定を行う ip、トラフィック制御を行う tc、ネットワーク統計情報を取得する lnstat, ifstat コマンドなどが含まれます。iproute2 には非常に多くの機能が含まれているのですが、linux-net に併せて開発がとても早く、ドキュメントの整備が追いついていないのが難点です。

今回は ip コマンドを用いてルーティングテーブルおよび、アドレス設定の保存/復元を行う方法についてご紹介します。仮想ネットワークの構築を行うとき等に、ネットワーク設定を素早く手軽に復元できるこれらの機能が有用です。

設定の保存

設定のルーティングテーブル/アドレス設定の保存はそれぞれ ip route/ ip addr コマンドにより行います。
設定はバイナリ形式です。
ルーティングテーブルの保存:
% ip route save > iproute.conf.bin

アドレス設定の保存:
% ip addr save > ipaddr.conf.bin

設定の確認

設定はバイナリ形式なので、人手での確認は showdump オプションを使います。
% ip addr showdump < ipaddr.conf.bin
if1:
    inet 127.0.0.1/8 scope host lo
if2:
    inet 192.168.122.132/24 brd 192.168.122.255 scope global eth0
if2:
    inet 192.168.122.133/24 scope global secondary eth0
if1:
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
if2:
    inet6 fe80::5054:ff:fe30:28ac/64 scope link 
       valid_lft forever preferred_lft forever
% ip route showdump < iproute.conf.bin 
default via 192.168.122.1 dev if2  proto static 
192.168.122.0/24 dev if2  proto kernel  scope link  src 192.168.122.132

設定の復元

restoreコマンドで復元します。
% ip addr restore < ipaddr.conf.bin
% ip route restore < iproute.conf.bin

余談

iproute2 はドキュメント整備が不足していると述べましたが、これはかなりのつらみを感じます。今回もコマンドの使い方を学ぶためにソースコードとコミットログを参照しました。
コミットログによると、今回紹介した ip addr save/restore や ip route save/restore はcheckpoint-restartでも用いられているようです。
Add ip route save/restore
iproute: Add ability to save, restore and show the interfaces' addresses (resend)

参考文献

iproute2 - official
kernel/git/shemminger/iproute2.git
git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git