2012-10-31

OpenBlocks AX3でLXCによる仮想化を試してみる

◆はじめに

今回はOSレベルの仮想化環境を実行できるLXC(Linux Containers)を試してみます。
LXCはXenやKVMのような本格的な仮想化環境ではありませんが、導入がそれほど難しくなくオーバーヘッドが少ないという利点があります。
LXCでは複数の仮想化OSを実行することができますが、稼働するLinux Kernelは一つのみとなっています。このLXCをOpenBlocks AX3上で実際に動作させて性能等を確認してみます。

なお今回使用した機材は以下になります。

  • OpenBlocks AX3/4
  • SSD 30GB


◆LXC用にLinux Kernel再構築

LXCはLinux KernelのControl Group機能を使用しています。AX3のデフォルトのconfigだとこれが無効になっているので、Kernelのconfigを変更してbuildしなおします。

(なお、このカーネルコンフィグの変更は、2012/10/29公開の3.0.6-6以降を利用する場合は不要です。)
 $ cd /tmp
 $ wget ftp://ftp.plathome.co.jp/pub/OBSAX3/squeeze/3.0.6-5/source/linux-3.0.6-20120927-1.tar.gz
 $ su
 # cd /usr/src
 # tar zxvf /tmp/linux-3.0.6-20120927-1.tar.gz
 # cd linux-3.0.6
 # cp arch/arm/configs/obsax3_defconfig .config
 # make menuconfig
以下の箇所を変更します。
 --- arch/arm/configs/obsax3_defconfig  2012-09-27 14:07:46.000000000 +0900
 +++ .config                            2012-10-17 16:27:42.000000000 +0900
 @@ -79,18 +79,29 @@
  CONFIG_LOG_BUF_SHIFT=17
  CONFIG_CGROUPS=y
  # CONFIG_CGROUP_DEBUG is not set
 -# CONFIG_CGROUP_FREEZER is not set
 -# CONFIG_CGROUP_DEVICE is not set
 -# CONFIG_CPUSETS is not set
 -# CONFIG_CGROUP_CPUACCT is not set
 -# CONFIG_RESOURCE_COUNTERS is not set
 -# CONFIG_CGROUP_PERF is not set
 +CONFIG_CGROUP_FREEZER=y
 +CONFIG_CGROUP_DEVICE=y
 +CONFIG_CPUSETS=y
 +CONFIG_PROC_PID_CPUSET=y
 +CONFIG_CGROUP_CPUACCT=y
 +CONFIG_RESOURCE_COUNTERS=y
 +CONFIG_CGROUP_MEM_RES_CTLR=y
 +CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
 +CONFIG_CGROUP_MEM_RES_CTLR_SWAP_ENABLED=y
 +CONFIG_CGROUP_PERF=y
  CONFIG_CGROUP_SCHED=y
  CONFIG_FAIR_GROUP_SCHED=y
 -# CONFIG_RT_GROUP_SCHED is not set
 -# CONFIG_BLK_CGROUP is not set
 -# CONFIG_NAMESPACES is not set
 +CONFIG_RT_GROUP_SCHED=y
 +CONFIG_BLK_CGROUP=m
 +# CONFIG_DEBUG_BLK_CGROUP is not set
 +CONFIG_NAMESPACES=y
 +CONFIG_UTS_NS=y
 +CONFIG_IPC_NS=y
 +CONFIG_USER_NS=y
 +CONFIG_PID_NS=y
 +CONFIG_NET_NS=y
  CONFIG_SCHED_AUTOGROUP=y
 +CONFIG_MM_OWNER=y
  # CONFIG_SYSFS_DEPRECATED is not set
  # CONFIG_RELAY is not set
  CONFIG_BLK_DEV_INITRD=y
 @@ -174,11 +185,11 @@
  #
  CONFIG_IOSCHED_NOOP=y
  CONFIG_IOSCHED_DEADLINE=y
 -CONFIG_IOSCHED_CFQ=y
 -# CONFIG_DEFAULT_DEADLINE is not set
 -CONFIG_DEFAULT_CFQ=y
 +CONFIG_IOSCHED_CFQ=m
 +# CONFIG_CFQ_GROUP_IOSCHED is not set
 +CONFIG_DEFAULT_DEADLINE=y
  # CONFIG_DEFAULT_NOOP is not set
 -CONFIG_DEFAULT_IOSCHED="cfq"
 +CONFIG_DEFAULT_IOSCHED="deadline"
  # CONFIG_INLINE_SPIN_TRYLOCK is not set
  # CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
  # CONFIG_INLINE_SPIN_LOCK is not set
 @@ -1063,6 +1074,7 @@
  #
  # Classification
  #
 +CONFIG_NET_CLS=y
  # CONFIG_NET_CLS_BASIC is not set
  # CONFIG_NET_CLS_TCINDEX is not set
  # CONFIG_NET_CLS_ROUTE4 is not set
 @@ -1071,7 +1083,7 @@
  # CONFIG_NET_CLS_RSVP is not set
  # CONFIG_NET_CLS_RSVP6 is not set
  # CONFIG_NET_CLS_FLOW is not set
 -# CONFIG_NET_CLS_CGROUP is not set
 +CONFIG_NET_CLS_CGROUP=y
  # CONFIG_NET_EMATCH is not set
  # CONFIG_NET_CLS_ACT is not set
  CONFIG_NET_SCH_FIFO=y
 @@ -1812,7 +1824,7 @@
  CONFIG_HW_CONSOLE=y
  CONFIG_VT_HW_CONSOLE_BINDING=y
  CONFIG_UNIX98_PTYS=y
 -# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
 +CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
  CONFIG_LEGACY_PTYS=y
  CONFIG_LEGACY_PTY_COUNT=16
  # CONFIG_SERIAL_NONSTANDARD is not set

 # make zImage modules
 # make modules_install
uImageを作成します。
 # gzip -9 < linux-3.0.6/arch/arm/boot/zImage > zImage.gz
 # lzma -3 < ramdisk-squeeze.obsax3.img >ramdisk-squeeze.obsax3.img.lzma
 # mkimage -n "OBSAX3LXC 3.0.6-5" -A arm -O linux -T multi -C gzip -a 0x8000 -e 0x8000 -d zImage.gz:ramdisk-squeeze.obsax3.img.lzma uImage.initrd.obsax3
FlashROMに書き込みます。
 # flashcfg -y -f uImage.initrd.obsax3
Rebootして構築しなおしたLinux Kernelで起動します。
 # reboot


◆LXC導入

AX3のDebian Squeezeではaptでlxcパッケージの導入ができます。ただしパッケージでインストールされるlxcのバージョンは0.7.2となります。
aptでインストールされるものはlxc-startで問題が生じたりするので、今回はソースからビルドすることにします。使うバージョンはリリース版では最新となるlxc 0.7.5です。

まずはlxcのビルドに必要なパッケージをインストールします。
 $ su
 # apt-get install libcap-dev libcap2-bin bridge-utils live-config debootstrap
 --
2013/03/13追記 パッケージ追加における不具合の報告と対処方法について
live-configパッケージの追加により、/etc/rcS.d/S01openblocks-setupが、/etc/rcS.d/S02openblocks-setupにリネームされるのですが、openblocksのディスク共有モードの仕組みにより、本スクリプトが2重起動する不具合を確認しています。
お手数ですが、対策として以下の処置を行ってください。
・/etc/rcS.d/S02openblocks-setupを削除してください。 
・/etc/rcS.d/S01live-configをS02live-configにリネームしてください。

http://lxc.sourceforge.net のDownloadリンクをたどりlxc-0.7.5.tar.gzをダウンロードし展開します。

 $ tar zxvf lxc-0.7.5.tar.gz
 $ cd lxc-0.7.5
 $ ./configure
 $ make
 $ su
 # make install
make install で /usr/local 以下にインストールされます。/usr/local/binにPATHを通しておきます。
 $ PATH=$PATH:/usr/local/bin
lxc-checkconfigコマンドでKernelのconfigがlxcに適したものになっているかを確認します。
 $ lxc-checkconfig
 Kernel config /proc/config.gz not found, looking in other places...
 Found kernel config file /lib/modules/3.0.6/build/.config
 --- Namespaces ---
 Namespaces: enabled
 Utsname namespace: enabled
 Ipc namespace: enabled
 Pid namespace: enabled
 User namespace: enabled
 Network namespace: enabled
 Multiple /dev/pts instances: enabled

 --- Control groups ---
 Cgroup: enabled
 Cgroup namespace: required
 Cgroup device: enabled
 Cgroup sched: enabled
 Cgroup cpu account: enabled
 Cgroup memory controller: enabled
 Cgroup cpuset: enabled

 --- Misc ---
 Veth pair device: enabled
 Macvlan: enabled
 Vlan: enabled
 File capabilities: missing
 enabled

 Note : Before booting a new kernel, you can check its configuration
 usage : CONFIG=/path/to/config /usr/local/bin/lxc-checkconfig
Cgroup namespaceはCONFIG_CGROUP_NSのようですが、Linux Kernel 3.0以降では削除されているようなので無視します。
File capabilitiesもCONFIG_SECURITY_FILE_CAPABILITIESですが、同様に3.0では無視します。

/etc/fstabに以下を追加します。
 cgroup        /cgroup        cgroup        defaults    0    0 
mountでcgroupをマウントします。

 # mkdir -p /cgroup
 # mount -a
ゲストOSのイメージが置かれる場所を作成します。
 # mkdir -p /usr/local/var/lib/lxc
最後にネットワークの設定をします。今回はホストのネットワークインターフェイスeth0とゲストOSのネットワークインターフェイスeth0をブリッジbr0を用いて接続することにします。ちなみに他の設定方法もあります。

/etc/network/interfaces のeth0部分を削除して以下のように設定します。
 auto br0
 iface br0 inet dhcp
        bridge_ports eth0
これでリブートするとbr0にDHCPでIPアドレスが設定されます。
 # ifconfig br0
 br0       Link encap:Ethernet  HWaddr 00:0a:85:00:05:58
           inet addr:192.168.111.217  Bcast:192.168.111.255  Mask:255.255.255.0
           inet6 addr: fe80::20a:85ff:fe00:558/64 Scope:Link
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
           RX packets:638 errors:0 dropped:0 overruns:0 frame:0
           TX packets:140 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:0
           RX bytes:76158 (74.3 KiB)  TX bytes:24563 (23.9 KiB)
ここまでで準備は完了です。


◆LXCでゲストOSを作成

ゲストOSを作成します。ゲストOSの作成はlxc-createコマンドで行います。
今回はDebian Squeezeのイメージを作成します。
ネットワーク設定のためにデフォルトの設定ファイルを作成します。
 # vi lxc.config

 lxc.network.type=veth
 lxc.network.link=br0
 lxc.network.flags=up
デフォルトの設定ファイルを指定してDebianのゲストOSを作成します。-nオプションで識別用のIDを指定します。
 # lxc-create -n deb-1 -f lxc.config -t debian
debootstrapを用いてイメージが/usr/local/var/lib/lxc/deb-1/rootfs以下に生成されます。
初回はパッケージのダウンロードで多少時間を要しますが、生成されたものはキャッシュされるので2度目からは同じdebianの場合には高速に生成可能です。

このままだと起動時にネットワークインターフェイスが正しく認識されずDHCPでIPアドレスが取得できないという問題があります。ゲストの/etc/network/runが/dev/shm/networkのシンボリックリンクとなっていることの起因します。今回はゲストの/etc/network/runを通常のディレクトリとすることで対処します。
 # ls -l /usr/local/var/lib/lxc/deb-1/rootfs/etc/network/run
 lrwxrwxrwx 1 root root 16 Oct 17 19:24 /usr/local/var/lib/lxc/deb-1/rootfs/etc/network/run -> /dev/shm/network
 # rm /usr/local/var/lib/lxc/deb-1/rootfs/etc/network/run
 # mkdir /usr/local/var/lib/lxc/deb-1/rootfs/etc/network/run
lxc-startコマンドでゲストOSの起動ができます。
 # lxc-start -n deb-1
 INIT: version 2.88 booting
 Using makefile-style concurrent boot in runlevel S.
 Cleaning up ifupdown....
 Setting up networking....
 Activating lvm and md swap...done.
 Checking file systems...fsck from util-linux-ng 2.17.2
 done.
 Mounting local filesystems...done.
 Activating swapfile swap...done.
 Cleaning up temporary files....
 Setting kernel variables ...done.
 Configuring network interfaces...Internet Systems Consortium DHCP Client 4.1.1-P1
 Copyright 2004-2010 Internet Systems Consortium.
 All rights reserved.
 For info, please visit https://www.isc.org/software/dhcp/

 Listening on LPF/eth0/6a:0d:f6:ca:50:14
 Sending on   LPF/eth0/6a:0d:f6:ca:50:14
 Sending on   Socket/fallback
 DHCPDISCOVER on eth0 to 255.255.255.255 port 67 interval 4
 DHCPOFFER from 192.168.111.22
 DHCPREQUEST on eth0 to 255.255.255.255 port 67
 DHCPACK from 192.168.111.22
 bound to 192.168.111.230 -- renewal in 122 seconds.
 done.
 Cleaning up temporary files....
 INIT: Entering runlevel: 3
 Using makefile-style concurrent boot in runlevel 3.
 Starting OpenBSD Secure Shell server: sshd.

 Debian GNU/Linux 6.0 deb-1 console

 deb-1 login:
lxc-startを-n以外のオプションなしで起動すると上記のようにloginプロンプトがでてloginできるようになります。rootのパスワードはデフォルトではrootになっています。lxc-startに-dオプションをつけて起動すると、コンソールとは切り離された状態でスタートします。

ゲストのeth0はホストのbr0につながりますがMACアドレスはランダムに決定されるようです。MACアドレスを固定したい場合は、
/usr/local/var/lib/lxc/dev-1/configに
 lxc.network.hwaddr=XX:XX:XX:XX:XX:XX
のように追加します。XX:XX:XX:XX:XX:XXの部分はMACアドレスを指定します。


◆LXCのパフォーマンス測定

ゲストのパフォーマンス測定を行います。測定にはUnixBenchとネットワークの性能測定のためにnuttcpを使います。

まずはホスト上で行います。
 host$ wget http://byte-unixbench.googlecode.com/files/UnixBench5.1.3.tgz
 host$ tar zxvf UnixBench5.1.3.tgz
 host$ cd UnixBench
 host$ make
 host$ ./Run
ホストからゲストのファイルシステムは見えるのでこれをコピーし実行します。
 host$ cp -pr ../UnixBench /usr/local/var/lib/lxc/deb-1/rootfs/tmp

 guest$ cd /tmp/UnixBench
 guest$ ./Run
結果を以下に示します。ゲスト値/ホスト値の比率も示します。
System Benchmarks Index Values          ホスト  ゲスト  比率(%)
Dhrystone 2 using register variables    274.3   274.2    99.9
Double-Precision Whetstone               11.7    11.7   100.0
Execl Throughput                        193.6   196.9   101.7
File Copy 1024 bufsize 2000 maxblocks   236.9   235.3    99.3
File Copy 256 bufsize 500 maxblocks     165.5   161.7    97.7
File Copy 4096 bufsize 8000 maxblocks   411.8   409.4    99.4
Pipe Throughput                         190.0   184.9    97.3
Pipe-based Context Switching            126.1   122.8    97.3
Process Creation                        188.2   183.8    97.6
Shell Scripts (1 concurrent)            480.5   471.2    98.0
Shell Scripts (8 concurrent)            617.4   601.9    97.4
System Call Overhead                    314.5   318.1   101.1
------------------------------------------------------------
System Benchmarks Index Score           200.5   198.4    98.9
1%程度のオーバーヘッドとなりました。

次にnuttcpでのネットワーク性能の測定を行います。
nuttcpはホスト、ゲストともにaptでインストールし、-Sオプションをつけてデーモンで走らせます。
 $ su
 # apt-get install nuttcp
 # exit
 $ nuttcp -S
Linuxを走らせたIntel PCからOpenblocks AX3のゲスト、ホストに向けてそれぞれnuttcpを実行します。
 (for ホスト)
 $ nuttcp -i1 -T10 192.168.111.217
  109.0000 MB /   1.01 sec =  901.4193 Mbps     0 retrans
  112.1875 MB /   1.00 sec =  941.4726 Mbps     0 retrans
  112.3125 MB /   1.00 sec =  941.6154 Mbps     0 retrans
  112.1875 MB /   1.00 sec =  941.5272 Mbps     0 retrans
  112.1875 MB /   1.00 sec =  941.1534 Mbps     0 retrans
  112.2500 MB /   1.00 sec =  941.4358 Mbps     0 retrans
  112.2500 MB /   1.00 sec =  941.6438 Mbps     0 retrans
  112.2500 MB /   1.00 sec =  941.5685 Mbps     0 retrans
  112.2500 MB /   1.00 sec =  941.6052 Mbps     0 retrans

 1118.6250 MB /  10.01 sec =  937.4715 Mbps 8 %TX 100 %RX 0 retrans 0.21 msRTT

 (for ゲスト veth使用)
 $ nuttcp -i1 -T10 192.168.111.230
   81.8750 MB /   1.02 sec =  675.0750 Mbps     0 retrans
   90.1875 MB /   1.00 sec =  756.7284 Mbps     0 retrans
   91.8750 MB /   1.00 sec =  770.9370 Mbps     0 retrans
   94.3125 MB /   1.00 sec =  791.0509 Mbps     0 retrans
   93.3750 MB /   1.00 sec =  783.4030 Mbps     0 retrans
   93.5625 MB /   1.00 sec =  784.8199 Mbps     0 retrans
   92.8125 MB /   1.00 sec =  778.8270 Mbps     0 retrans
   92.9375 MB /   1.00 sec =  778.7542 Mbps     0 retrans
   92.8125 MB /   1.00 sec =  778.9330 Mbps     0 retrans

  915.8125 MB /  10.00 sec =  767.8582 Mbps 5 %TX 98 %RX 0 retrans 0.23 msRTT

767.8582 / 937.4715 = 81.9%
となりゲストの性能はホストに比べ約20%落ちるという結果になりました。

次に仮想ネットワークインターフェイスの設定をvethではなくmacvlanを用いて実験を行いました。
ホストではbr0を使用せずにeth0に直接リンクします。
 lxc.network.type=macvlan
 lxc.network.link=eth0
 lxc.network.flags=up
結果は以下のようになりました。
 (for ゲスト macvlan使用)
 $ nuttcp -i1 -T10 192.168.111.230
   111.5000 MB /   1.01 sec =  923.4068 Mbps     0 retrans
   112.2500 MB /   1.00 sec =  941.4706 Mbps     0 retrans
   112.2500 MB /   1.00 sec =  941.8548 Mbps     0 retrans
   111.6250 MB /   1.00 sec =  936.3596 Mbps     0 retrans
   112.2500 MB /   1.00 sec =  941.5365 Mbps     0 retrans
   112.2500 MB /   1.00 sec =  941.6147 Mbps     0 retrans
   112.2500 MB /   1.00 sec =  941.6599 Mbps     0 retrans
   112.2500 MB /   1.00 sec =  941.5713 Mbps     0 retrans
   112.2500 MB /   1.00 sec =  941.6184 Mbps     0 retrans

  1120.7500 MB /  10.01 sec =  939.2494 Mbps 7 %TX 100 %RX 0 retrans 0.20 msRTT
macvlanを使う方法ではホストとゲストでほぼ同一の値がでていてネットワーク性能の劣化がないという結果になりました。


◆ゲストの台数を増やしてみる実験

ゲストを何台まで起動できるか確認してみます。
lxc-cloneを用いると既存のゲストをコピーできるようですが、lxc-cloneが正しく動作できませんでした。
そこで、lxc-createを用いてゲストを作成してゲストを起動することを繰り返してみます。

 1. lxc-createでゲストを作成
 2. lxc-start -dで起動
 3. sleep 20秒

ということを繰り返して確認しました。
なおディスクアクセスが競合して遅くなってしまうのを防ぐため3でsleepをいれています。

結果は、30台ゲストを作成できました。

SSDの容量の問題(Disk Full)で31台目のゲストが起動できなくなってしまいました。
Disk Full直前でのload average, memory使用量はそれぞれ以下のようになっています。
 load average: 0.00, 0.01, 0.05
 Mem:   1029628k total,   922264k used,   107364k free,   261984k buffers
SSDの容量が許せばまだいけそうな感じです。


◆まとめ

簡単な仮想化環境を構築できるLXCを試してみました。
UNIX Benchではほとんど性能の劣化はありませんでした。ネットワークの性能はmacvlanを使うことで性能の劣化はほぼなくすことができました。

今回作成したバイナリは以下よりダウンロード出来ます。

ftp://ftp.plathome.co.jp/pub/OBSAX3/obdnmag/lxc075/uImage.initrd.obsax3
ftp://ftp.plathome.co.jp/pub/OBSAX3/obdnmag/lxc075/dot.config


◆既知の問題

udev をインストールしようとすると、エラーが発生す正常終了しません。lxc-startの実行前に、次の設定追加が必要です。

# vi /usr/local/var/lib/lxc/deb-1/config

#ppp
lxc.cgroup.devices.allow = c 108:0 rwm
#fuse
lxc.cgroup.devices.allow = c 10:229 rwm
#loop0
lxc.cgroup.devices.allow = b 7:0 rwm
#tun
lxc.cgroup.devices.allow = c 10:200 rwm

ただし、この設定をしてudevのインストールが完了しても、lxc-startの後にコンソールが表示されなくなる現象を確認しています。対策は調査中。sshは可能です。





0 件のコメント:

コメントを投稿