VPSで遊ぶ -その13 :Ubuntu鯖12.04にLXCをインスコして量産型仮想環境を構築する Part1:初期導入編

皆様こんにちは!
今日はLXC(Linux Containers http://lxc.sourceforge.net/ )(lxc version: 0.7.5)をUbuntu君に仕込んでみる実験を行います。
基本的にはここのヘルプ(https://help.ubuntu.com/12.04/serverguide/lxc.html )が充実してて殆どこれで事足りますが、日本語の情報が少ないので一応私も記録しときます。
(予め Ubuntu Weekly Recipe第226回 LXCで軽量仮想環境の活用 http://gihyo.jp/admin/serial/01/ubuntu-recipe/0226 も読んでおくといいかも)

Part1はインストール→とりあえず立ち上がる所まで。
Part2以降は需要と書く気があれば(LXC内でVPN環境構築・ファイル共有鯖構築等)。


ネットワーク周りをいじるのでイキナリVPSに仕込んでヒャッハーする前にまずは必ずローカルのVirtualBox内のクリーンでぶっ壊していいUbuntu12.04仮想環境等で十分に実験してみましょう。尚設定漏れによってトラブっても私は一切関知いたしません。全て自己責任で。



(2012/08/28追記)

VirtualBoxとLXCを同じ母艦上で同時に動かすと、VirtualBox内のOSを起動するときに母艦丸ごとフリーズするので、どちらか一方だけ動かすべし。(VirtualBox内で動いているUbuntu内に仕込んだLXCの起動は問題無し。母艦上に並列でVirtualBoxとLXCを起動させると再現)

フリーズ再現環境:

  • VirtualBox4.1.16、4.1.20
  • LXC lxc version: 0.7.5
  • 母艦Ubuntu 12.04 64bit (corei3,corei5マシンの実機2台で再現、VT-xをBIOSで有効かつVirtualBoxでも有効(VT無効での再現実験はまだ))

(2012/08/28追記おわり)



(さくらのVPS2G(vps)内LXC環境内Ubuntu(vpsvm0)にxrdpを入れてvpsvm0(のGUI環境)→sshトンネル→vpssshトンネル→Win7マシンのリモートデスクトップGUIをいじってる図)


A:インストール手順

Ubuntu 12.04だと超簡単で拍子抜け

手順1:lxcのインストール

root@xut:~# apt-get install lxc
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
以下の特別パッケージがインストールされます:
  bridge-utils cgroup-lite cloud-utils debootstrap euca2ools libapparmor1 libyaml-0-2 python-boto python-m2crypto python-paramiko python-yaml
提案パッケージ:
  btrfs-tools lvm2 qemu-user-static
以下のパッケージが新たにインストールされます:
  bridge-utils cgroup-lite cloud-utils debootstrap euca2ools libapparmor1 libyaml-0-2 lxc python-boto python-m2crypto python-paramiko python-yaml
アップグレード: 0 個、新規インストール: 12 個、削除: 0 個、保留: 0 個。
2,069 kB のアーカイブを取得する必要があります。
この操作後に追加で 13.6 MB のディスク容量が消費されます。
続行しますか [Y/n]?

(後略)

Y押してズバババっとインスコ完了。



手順2:isc-dhcp-serverのインストール
ぽこぽこ増やす量産型仮想環境を作るためにLXC環境用のdhcpサーバーを立てます。

root@xut:~# apt-get install isc-dhcp-server
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています
状態情報を読み取っています... 完了
提案パッケージ:
  isc-dhcp-server-ldap
以下のパッケージが新たにインストールされます:
  isc-dhcp-server
アップグレード: 0 個、新規インストール: 1 個、削除: 0 個、保留: 0 個。
429 kB のアーカイブを取得する必要があります。
この操作後に追加で 1,005 kB のディスク容量が消費されます。
取得:1 http://ftp.riken.jp/Linux/ubuntu/ precise-updates/main isc-dhcp-server amd64 4.1.ESV-R4-0ubuntu5.2 [429 kB]
429 kB を 0秒 で取得しました (701 kB/s)
パッケージを事前設定しています ...
Selecting previously unselected package isc-dhcp-server.
(データベースを読み込んでいます ... 現在 238643 個のファイルとディレクトリがインストールされています。)
(.../isc-dhcp-server_4.1.ESV-R4-0ubuntu5.2_amd64.deb から) isc-dhcp-server を展開しています...
man-db のトリガを処理しています ...
ureadahead のトリガを処理しています ...
isc-dhcp-server (4.1.ESV-R4-0ubuntu5.2) を設定しています ...
Generating /etc/default/isc-dhcp-server...
isc-dhcp-server start/running, process 13449
isc-dhcp-server6 stop/pre-start, process 13498

インストールは以上!なんて簡単なんでしょう。


B:設定ファイル探訪(全て母艦側)

lxcの設定ファイルはここらへんにあります。
1:/etc/lxc以下 (確認のみ)

root@xut:/# tree -F /etc/lxc
/etc/lxc
├── auto/   (自動起動コンテナ指定用ディレクトリ)
└── lxc.conf (lxc共通設定ファイル)

1 directory, 1 file
root@xut:/# cat /etc/lxc/lxc.conf
lxc.network.type=veth
lxc.network.link=lxcbr0
lxc.network.flags=up
root@xut:/#

特に弄る必要なし。



2:/etc/init/以下(確認のみ)

root@xut:/etc/init# ls|grep lxc
lxc-net.conf (lxc networkの起動スクリプト)
lxc.conf (lxcの起動スクリプト)
root@xut:/etc/init#

lxc-net.conf内では

echo 1 > /proc/sys/net/ipv4/ip_forward

だの

(中略)
# set up the lxc network
echo 1 > /proc/sys/net/ipv4/ip_forward
mkdir -p ${varrun}
brctl addbr ${LXC_BRIDGE}
ifconfig ${LXC_BRIDGE} ${LXC_ADDR} netmask ${LXC_NETMASK} up
iptables -A POSTROUTING -s ${LXC_NETWORK} -t nat -j MASQUERADE
dnsmasq -u lxc-dnsmasq --strict-order --bind-interfaces --pid-file=${varrun}/dnsmasq.pid --conf-file= --listen-address ${LXC_ADDR} --dhcp-range ${LXC_DHCP_RANGE} --dhcp-lease
-max=${LXC_DHCP_MAX} --dhcp-no-override --except-interface=lo --interface=${LXC_BRIDGE} || cleanup
touch ${varrun}/network_up
(後略)

だのiptables周りの設定を全部お任せでやってくれてます。特に弄る必要なし。

もしLXCコンテナ(192.168.40.50 port番号10222)に直接グローバルIPアドレスから接続したい時には

iptables -A PREROUTING -t nat -p tcp --dport 10222 -i eth0 -j DNAT --to 192.168.40.50:10222

等を上記 iptables -A POSTROUTING 行の次あたりにとりあえず追記して(+ ufw allow 10222 を母艦・LXCコンテナ双方で実行)しまえば良いでしょう。(192.168.40.50のLXCコンテナのsshのポートを10222番にしている場合等)



3:/etc/default/lxc (必要に応じて要編集)
LXCのネットワーク(ブリッジ接続)周りの設定ファイルです。

root@xut:/etc/default# cat lxc
# MIRROR to be used by ubuntu template at container creation:
# Leaving it undefined is fine
#MIRROR="http://archive.ubuntu.com/ubuntu"
# or
#MIRROR="http://<host-ip-addr>:3142/archive.ubuntu.com/ubuntu"

# LXC_AUTO - whether or not to start containers symlinked under
# /etc/lxc/auto
LXC_AUTO="true"

# Leave USE_LXC_BRIDGE as "true" if you want to use lxcbr0 for your
# containers.  Set to "false" if you'll use virbr0 or another existing
# bridge, or mavlan to your host's NIC.
USE_LXC_BRIDGE="true"

# If you change the LXC_BRIDGE to something other than lxcbr0, then
# you will also need to update your /etc/lxc/lxc.conf as well as the
# configuration (/var/lib/lxc/<container>/config) for any containers
# already created using the default config to reflect the new bridge
# name.
# If you have the dnsmasq daemon installed, you'll also have to update
# /etc/dnsmasq.d/lxc and restart the system wide dnsmasq daemon.
# LXC_BRIDGE="lxcbr0"
# LXC_ADDR="10.0.3.1"
# LXC_NETMASK="255.255.255.0"
# LXC_NETWORK="10.0.3.0/24"
# LXC_DHCP_RANGE="10.0.3.2,10.0.3.254"
# LXC_DHCP_MAX="253"

# LXC_SHUTDOWN_TIMEOUT=120

LXC_BRIDGE="lxcbr0"
LXC_ADDR="192.168.40.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="192.168.40.0/24"
LXC_DHCP_RANGE="192.168.40.2,192.168.40.254"
LXC_DHCP_MAX="253"

LXC_SHUTDOWN_TIMEOUT=120

root@xut:/etc/default#

特に弄る必要なし。(↑の例ではLXC_ADDR周りを弄ってます。)
(lxcbr0でブリッジ接続させたくない場合とか、LXC_ADDRを変えたい場合に編集)



4:/etc/default/ufw (必要に応じて要編集)
ライトなUbuntu使いなら ufwUbuntuのソフトウェアファイアウォール)を使ってiptalbesの設定をしている筈ですがufwが有効な場合は

DEFAULT_FORWARD_POLICY="ACCEPT"

にする必要があります。(この設定を忘れるとLXC_NETWORKの外に出れない)

# /etc/default/ufw
#
(中略)
# Set the default forward policy to ACCEPT, DROP or REJECT.  Please note that
# if you change this you will most likely want to adjust your rules
#DEFAULT_FORWARD_POLICY="DROP"
DEFAULT_FORWARD_POLICY="ACCEPT"

(後略)

(設定しなおしたら要 service ufw restart)



5:/etc/dhcp/dhcpd.conf(要編集)
LXC_NETWORK用のDHCP鯖の設定はだいたいこんな感じ。(ここでは192.168.40.50〜192.168.40.120 を割り当てている)

ddns-update-style none;
option domain-name "lxc.local";
option domain-name-servers 192.168.40.1;
default-lease-time 600;
max-lease-time 7200;
authoritative;
log-facility local7;
subnet 192.168.40.0 netmask 255.255.255.0 {
 option routers 192.168.40.1;
 option subnet-mask 255.255.255.0;
 option broadcast-address 192.168.40.255;
 option domain-name lxc;
 option domain-name-servers 192.168.40.1;
 range dynamic-bootp 192.168.40.50 192.168.40.120;
 default-lease-time 7200;
 max-lease-time 43200;
}



6: /etc/default/isc-dhcp-server(要編集)

root@xut:~# cat /etc/default/isc-dhcp-server
# Defaults for dhcp initscript
# sourced by /etc/init.d/dhcp
# installed at /etc/default/isc-dhcp-server by the maintainer scripts

#
# This is a POSIX shell fragment
#

# On what interfaces should the DHCP server (dhcpd) serve DHCP requests?
#       Separate multiple interfaces with spaces, e.g. "eth0 eth1".
#INTERFACES=""
INTERFACES="lxcbr0"

INTERFACES="lxcbr0"に限定しておきましょう。
(設定しなおしたら要 service isc-dhcp-server restart)




7: /etc/dnsmasq.d/lxc(確認のみ)

root@xut:~# cat /etc/dnsmasq.d/lxc
bind-interfaces
except-interface=lxcbr0
root@xut:~#

C:LXCコンテナ(仮想環境)作成手順

コマンド一発流してあとは見てるだけ。(初回のみOSに必要なパッケージのダウンロードに十数分程度時間がかかります。2回目以降は爆速。)

(ubuntuの最新版12.04環境を vm0という名前で作成している例)

root@xut:~# lxc-create -t ubuntu -n vm0

No config file specified, using the default config
debootstrap は /usr/sbin/debootstrap です
Checking cache download in /var/cache/lxc/precise/rootfs-amd64 ...
installing packages: vim,ssh
Downloading ubuntu precise minimal ...
I: Retrieving Release
I: Retrieving Release.gpg
I: Checking Release signature
I: Valid Release signature (key id 630239CC130E1A7FD81A27B140976EAF437D05B5)
I: Retrieving Packages
I: Validating Packages
I: Retrieving Packages
I: Validating Packages
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
I: Found additional base dependencies: libbsd0 libedit2 libgpm2 libgssapi-krb5-2 libk5crypto3 libkeyutils1 libkrb5-3 libkrb5support0 libpython2.7 libwrap0 openssh-client openssh-serv
er vim-runtime
I: Checking component main on http://archive.ubuntu.com/ubuntu...
I: Retrieving adduser
I: Validating adduser

(中略)

Processing triggers for resolvconf ...
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_ALL to default locale: No such file or directory
invoke-rc.d: policy-rc.d denied execution of start.
Processing triggers for initramfs-tools ...
Download complete
Copy /var/cache/lxc/precise/rootfs-amd64 to /var/lib/lxc/vm0/rootfs ...
Copying rootfs to /var/lib/lxc/vm0/rootfs ...

##
# The default user is 'ubuntu' with password 'ubuntu'!
# Use the 'sudo' command to run tasks as root in the container.
##

'ubuntu' template installed
'vm0' created
root@xut:~#


インストールが終了すると /var/lib/lxc/vm0(vm0:任意の仮想環境名・コンテナ名) 以下にこんな感じで仮想環境のファイル群が作成されます。

root@xut:/var/lib/lxc/vm0# ll
合計 20
drwxr-xr-x  3 root root 4096  731 22:52 ./
drwxr-xr-x  3 root root 4096  731 22:41 ../
-rw-r--r--  1 root root 1249  731 22:52 config (vm0の設定ファイル)
-rw-r--r--  1 root root  110  731 22:52 fstab
drwxr-xr-x 22 root root 4096  731 22:51 rootfs/ (vm0のルートディレクトリ)

root@xut:/var/lib/lxc/vm0# find ./ -maxdepth 2
./
./fstab
./rootfs
./rootfs/opt
./rootfs/tmp
./rootfs/lib
./rootfs/proc
./rootfs/bin
./rootfs/sys
./rootfs/root
./rootfs/var
./rootfs/srv
./rootfs/home
./rootfs/sbin
./rootfs/lib64
./rootfs/media
./rootfs/selinux
./rootfs/run
./rootfs/dev
./rootfs/boot
./rootfs/mnt
./rootfs/etc
./rootfs/usr
./config
root@xut:/var/lib/lxc/vm0#

/var/lib/lxc/vm0/configでvm0固有の設定を記述します。(通常は特に編集の必要なし)

root@xut:/var/lib/lxc/vm0# cat config
lxc.network.type=veth
lxc.network.link=lxcbr0
lxc.network.flags=up
lxc.network.hwaddr = 00:16:3e:e5:9f:2e
lxc.utsname = vm0

lxc.devttydir = lxc
lxc.tty = 4
lxc.pts = 1024
lxc.rootfs = /var/lib/lxc/vm0/rootfs
lxc.mount  = /var/lib/lxc/vm0/fstab
lxc.arch = amd64
lxc.cap.drop = sys_module mac_admin
lxc.pivotdir = lxc_putold

# uncomment the next line to run the container unconfined:
#lxc.aa_profile = unconfined

lxc.cgroup.devices.deny = a
# Allow any mknod (but not using the node)
lxc.cgroup.devices.allow = c *:* m
lxc.cgroup.devices.allow = b *:* m
# /dev/null and zero
lxc.cgroup.devices.allow = c 1:3 rwm
lxc.cgroup.devices.allow = c 1:5 rwm
# consoles
lxc.cgroup.devices.allow = c 5:1 rwm
lxc.cgroup.devices.allow = c 5:0 rwm
#lxc.cgroup.devices.allow = c 4:0 rwm
#lxc.cgroup.devices.allow = c 4:1 rwm
# /dev/{,u}random
lxc.cgroup.devices.allow = c 1:9 rwm
lxc.cgroup.devices.allow = c 1:8 rwm
lxc.cgroup.devices.allow = c 136:* rwm
lxc.cgroup.devices.allow = c 5:2 rwm
# rtc
lxc.cgroup.devices.allow = c 254:0 rwm
#fuse
lxc.cgroup.devices.allow = c 10:229 rwm
#tun
lxc.cgroup.devices.allow = c 10:200 rwm
#full
lxc.cgroup.devices.allow = c 1:7 rwm
#hpet
lxc.cgroup.devices.allow = c 10:228 rwm
#kvm
lxc.cgroup.devices.allow = c 10:232 rwm
root@xut:/var/lib/lxc/vm0#

D:LXCコンテナ起動確認

ココで一旦母艦(親機)自体をリブートしましょう。
(リブート直後に母艦でifconfig -aしてみた図)

root@xut:~# ifconfig -a
eth0      Link encap:イーサネット  ハードウェアアドレス 08:00:27:fa:a8:39
          inetアドレス:192.168.25.40  ブロードキャスト:192.168.25.255  マスク:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:317 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:422 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:1000
          RXバイト:27923 (27.9 KB)  TXバイト:149231 (149.2 KB)

lo        Link encap:ローカルループバック
          inetアドレス:127.0.0.1  マスク:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  メトリック:1
          RXパケット:2 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:2 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:0
          RXバイト:100 (100.0 B)  TXバイト:100 (100.0 B)

lxcbr0    Link encap:イーサネット  ハードウェアアドレス 7a:33:e0:87:e5:0e
          inetアドレス:192.168.40.1  ブロードキャスト:192.168.40.255  マスク:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:0 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:2 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:0
          RXバイト:0 (0.0 B)  TXバイト:108 (108.0 B)

root@xut:~#

lxcbr0が新たに出来ています。(/etc/default/lxcを編集したので、この例ではinetアドレス:192.168.40.1 になっている。母艦のeth0は192.168.25.40)



インスコしたvm0を起動してみます。

起動は

lxc-start -n vm0

または

lxc-start -n vm0 -d

した後で

lxc-console -n vm0



シャットダウンは

lxc-shutdown -n vm0

強制停止は

lxc-stop -n vm0

です。
(起動した図)

(vm0環境でのifconfig -a)

root@vm0:~# ifconfig -a
eth0      Link encap:Ethernet  HWaddr 00:16:3e:e5:9f:2e
          inet addr:192.168.40.50  Bcast:192.168.40.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1594 (1.5 KB)  TX bytes:1338 (1.3 KB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@vm0:~# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         192.168.40.1    0.0.0.0         UG    100    0        0 eth0
192.168.40.0    *               255.255.255.0   U     0      0        0 eth0
root@vm0:~#

dhcpでちゃんと192.168.40.50が割り当てられたようです。



(vm0を起動した後での母艦側のifconfig -a)

root@xut:/home/xut# ifconfig -a
eth0      Link encap:イーサネット  ハードウェアアドレス 08:00:27:fa:a8:39
          inetアドレス:192.168.25.40  ブロードキャスト:192.168.25.255  マスク:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:14750 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:7298 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:1000
          RXバイト:16875022 (16.8 MB)  TXバイト:2053244 (2.0 MB)

lo        Link encap:ローカルループバック
          inetアドレス:127.0.0.1  マスク:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  メトリック:1
          RXパケット:2 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:2 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:0
          RXバイト:100 (100.0 B)  TXバイト:100 (100.0 B)

lxcbr0    Link encap:イーサネット  ハードウェアアドレス 3a:9f:33:53:15:e1
          inetアドレス:192.168.40.1  ブロードキャスト:192.168.40.255  マスク:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:3144 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:11494 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:0
          RXバイト:160963 (160.9 KB)  TXバイト:16614801 (16.6 MB)

vethR9OLBE Link encap:イーサネット  ハードウェアアドレス 3a:9f:33:53:15:e1
          UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1500  メトリック:1
          RXパケット:3144 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:11501 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:1000
          RXバイト:204979 (204.9 KB)  TXバイト:16615107 (16.6 MB)

root@xut:/home/xut#




(注意点)

初期ユーザー名:ubuntu、パスワードもubuntuなので
即効sudo adduser hogehogekun で別の任意のユーザーhogehogekunを作って
/etc/groupの
sudo:x:27:ubuntu
sudo:x:27:hogehogekunにしつつ
sudo deluser ubuntuしてしまいましょう。
あとはapt-get install ufw;ufw enable した後で好きに弄り回すべし。




lxc-*コマンドの一覧は
https://help.ubuntu.com/12.04/serverguide/lxc.html#lxc-admin あたりに書いてありますので一読してみればヨロシ



今日はここまで。Part2に続くかも。
(その前にバックアップ手順関連エントリーの完結編が先か…)

ではでは!