ラベル LXC の投稿を表示しています。 すべての投稿を表示
ラベル LXC の投稿を表示しています。 すべての投稿を表示

2013年3月21日木曜日

OpenBlocks AX3上のLXC用の最小構成Arch Linux rootfsを作る

前回構築したOpenBlocks用Arch Linuxコンテナには 不要なパッケージも多く含まれている。そこで、作成したコンテナを利用し最小構成 (systemdとsshdが上がりログインができる状態)のrootfs tarballを作成する。

基本的な構築方法は x86_64環境のArch LinuxでLXCコンテナ用rootfsを作成した時と同じであるが、 今回はpacstrap時にbaseを丸ごと入れるのではなく、systemdとopensshのみ導入する。

miku@arch% su
root@arch# pacman -S arch-install-scripts
root@arch# mkdir rootfs
root@arch# pacstrap -d rootfs pacman systemd openssh bash
root@arch# chroot rootfs /bin/bash
root@arch(chroot)# ln -s /usr/lib/systemd/system/sshd.service \
> /etc/systemd/system/multi-user.target.wants/sshd.service
root@arch(chroot)# ln -s /usr/lib/systemd/system/sshdgenkeys.service \
> /etc/systemd/system/multi-user.target.wants/sshdgenkeys.service
root@arch(chroot)# pacman -Sc
root@arch(chroot)# rm /var/cache/pacman/pkg/*
root@arch(chroot)# mkdir /dev/pts
root@arch(chroot)# passwd
root@arch(chroot)# groupadd -g 3939 miku
root@arch(chroot)# useradd -g miku -u 3939 -s /bin/bash -m miku
root@arch(chroot)# passwd miku
root@arch(chroot)# exit
root@arch# rm rootfs/root/.bash_history
root@arch# tar cJpf rootfs.tar.gz rootfs

今回作成した最小構成環境が正しく動作するか試したところ、/dev/consoleが 存在しないとのエラーが発生する。

miku@obs$ sudo /usr/miku/bin/lxc-start -n test -- /usr/lib/systemd/systemd
lxc-start: No such file or directory - stat(/proc/26644/root/dev//console)

これも/dev/ptsが存在しない問題と似た問題のようなので、/dev/consoleを作 成しておく。

root@arch(chroot)# mknod -m 600 mini/rootfs/dev/console c 5 1

LXC側で必要としている/dev/tty{1..4}等はLXC側で自動作成しているようなの で、LXC側で必要であるのに/dev/consoleを自動作成できていないのが原因だ と考えられる。

/dev/console作成後は想定通り動作するようになった。

miku@obs% sudo /usr/miku/bin/lxc-start -n test -- /usr/lib/systemd/systemd
<30>systemd[1]: Smack is not enabled in the kernel, not loading access rules.

今回作成したOpenBlocks用の最小構成のrootfs tarballは、以下からダウンロードできるよ うにしておいたので、試してみたい方はどうぞ。
http://repo.hachune.net/Linux/ArchLinux/rootfs/armv7h/2013.03.21/obs_rootfs.tar.xz

OpenBlocks AX3上のLXC内のArch Linuxにmikutter環境を構築

前回作成したOpenBlocks AX3上のLXC内のArch Linux環境にmikutterをインストールし動かしてみる。

Arch Linuxでのmikutterは、Arch User Repository(AUR)にPKGBUILDが存在するため、 環境構築が他ディストリに比べ容易である。 AURのPKGBUILDを利用する場合は、pacmanのフロントエンドyaourtが便利であ るので、それをインストールする。また、一般ユーザでPKGBUILDを元にパッケー ジを作成する場合は、fakerootコマンドが必要であるので、それも合わせてイ ンストールする。
miku@arch% sudo pacman -S yaourt fakeroot
mikutterはアーキテクチャ非依存であるハズなので、サポートアーキテクチャに i686とx86_64と指定されている部分をanyに変更する。
miku@arch% yaourt -S mikutter
PKGBUILDの
arch=('i686' 'x86_64')
を
arch=('any')
に修正しビルド、インストールする。
OpenBlocksには直接ディスプレイを接続することができないため、SSHのX forwarding経由にてmikutterを実行する。 /etc/ssh/sshd_configのX11Forwardingの項を有効にする。
X11Forwarding yes
設定を反映させるため、sshdを再起動する。
miku@arch% sudo systemctl restart sshd.service
また、LXCはIP Masqueradeの内側となるため、SSH Proxyを利用する。 OpenBlocksのIPアドレスは10.39.39.39/24、その中のコンテナのIPアドレスは 10.3.93.11/24であるので、手元の環境の~/.ssh/configに以下のように追記し ておく。
Host obs
HostName 10.39.39.39

Host obs.arch
HostName 10.3.93.11
ProxyCommand ssh -W %h:%p obs
これにより、"ssh obs.arch"だけでobsのsshdを経由しobs.archに接続可能に なる。
miku@hachune% ssh -X obs.arch
X11 forwarding request failed on channel 0
Last login: Wed Mar 20 16:41:43 2013 from 10.3.93.1
どうやら、X11 forwardingに失敗しているようだ。xauthが存在していないの が原因のようなので、xorg-xauthパッケージをインストールする。
miku@arch% yaourt -S xorg-xauth
miku@arch% sudo systemctl restart sshd.service
ようやくX forwardingができたものの、フォントがないため非常に残念なこと になる。
miku@hachune% ssh -X obs.arch
Last login: Wed Mar 20 17:06:50 2013 from 10.3.93.1
miku@arch% mikutter

VL Gothicフォントを入れてやり直し。
miku@arch% yaourt -S ttf-vlgothic
今度は無事mikutterが起動し利用できる状態になった。RUBY_PLATFORMがarmv7l-linux-eabiとなっていることが確認できる。

SSH Proxy経由のX forwardingであるため、かなり残念な表示速度と操作性と なってしまっている。ただ、CPU負荷は500アカウント程度フォローしているホー ムタイムラインのUserStream有効の状態で5%〜30%程度に落ち着いているため、 CPUの性能不足という事は無いようだ。また、Disk I/Oも余裕があるように見 受けられる。
やはりOpenBlocks上でmikutterを利用する場合は、mikutterのデーモンモード を利用するのが無難かと思う。

OpenBlocks AX3上のLXCにArch Linuxを導入

LXCはi386/amd64環境以外でも利用できる。ここでは、ARMv7なマイクロサーバ OpenBlocks AX3にインストールされているDebianにLXCを導入し、その中にArch Linuxをインストールする。ホストとコンテナの論理的な構成(ネットワーク等)は 前回の構成と同じになるよう構築する。 前回とはディストリビューションは異なるものの、設定ファイルの扱い等が少々異なる以外基本はほぼ同じであ る。

ネットワーク設定

ホスト側ブリッジインターフェースとIP Masqueradeは、先に設定したものと 全く同じになるよう設定を行う。当然ながらこの設定は再起動等で消えてしま うため、恒久化する必要があるのであれば/etc/network/interfaces等に記述 しておく。

miku@obs% sudo ip link add br0 type bridge
miku@obs% sudo ip link set br0 up
miku@obs% sudo ip address add 10.3.93.1/24 dev br0
miku@obs% sudo sysctl net.ipv4.ip_forward=1
miku@obs% sudo iptables -t nat -A POSTROUTING \
> -s 10.3.93.0/24 -o eth0 -j MASQUERADE

bootstrap

Arch Linuxのarm版は各armアーキテクチャ毎にrootfsのtarballが用意されて いるが、残念ながらOpenBlocks AX6用のものは用意されていない。そこで、最 も近いと思われるものを http://archlinuxarm.org/platforms/armv7 から選 び試す。ここでは、 http://archlinuxarm.org/os/ArchLinuxARM-cubox-latest.tar.gz を利用する。

まずはlxcパッケージを導入しcgroupをmountする。また、入手したtarballを 展開し、その中にchrootして作業できるようsysfsやproc等をmountする。

miku@obs% sudo aptitude install lxc
miku@obs% sudo mount -t cgroup cgroup /cgroup
miku@obs% sudo mkdir -p /var/lib/lxc/arch/rootfs
miku@obs% sudo tar xpf ArchLinuxARM-cubox-latest.tar.gz \
> -C /var/lib/lxc/arch/rootfs/
miku@obs% sudo mount -t proc proc /var/lib/lxc/arch/rootfs/proc
miku@obs% sudo mount -t sysfs sysfs /var/lib/lxc/arch/rootfs/sys
miku@obs% sudo mount -t devtmpfs devtmpfs /var/lib/lxc/arch/rootfs/dev
miku@obs% sudo mkdir /dev/pts
miku@obs% sudo mount -t devpts devpts /var/lib/lxc/arch/rootfs/dev/pts

コンテナ内の設定

展開したシステムディレクトリにchrootし環境設定を行う。 ここでは、パッケージの更新とssh鍵の作成、LXC環境に必要ないデーモンの無 効化を行なう。

miku@obs% sudo chroot /var/lib/lxc/arch/rootfs /bin/bash
root@obs(chroot)# echo nameserver 10.39.39.1 > /etc/resolv.conf
root@obs(chroot)# pacman -Syu
root@obs(chroot)# find /etc -name "*.pacnew" -exec sh \
> -c 'mv "{}" "`basename {} .pacnew`"' \;
root@obs(chroot)# rm /etc/ssh/ssh_host_*
root@obs(chroot)# ssh-keygen -A
root@obs(chroot)# cd /etc/systemd/system/multi-user.target.wants
root@obs(chroot)# rm {openntpd,netcfg\@ethernet-eth0}.service
root@obs(chroot)# mkdir /dev/pts

最後にユーザアカウントを設定しておく。

root@obs(chroot)# passwd
root@obs(chroot)# groupadd -g 3939 miku
root@obs(chroot)# useradd -g miku -u 3939 -s /bin/bash -m miku
root@obs(chroot)# passwd miku
root@obs(chroot)# exit

コンテナ設定ファイルの作成

今回利用するコンテナ設定ファイルは、 前回Arch Linux上のLXCコンテナ内にArch Linux環境を構築した際に作成したもの と全く同じものを利用する。

コンテナの起動

早速起動してみたところ、カーネルバージョンが3.0.6、lxc-0.7.2-1のホスト 環境ではcgroupディレクトリのrenameに失敗し、コンテナが起動できない問題 が発生した。

miku@obs% uname -a
Linux obsax3 3.0.6 #1 SMP Thu Mar 7 19:14:19 JST 2013 armv7l GNU/Linux
miku@obs% sudo lxc-start -n arch -- /usr/lib/systemd/systemd
lxc-start: No such file or directory - failed to rename cgroup
/cgroup/7787->/cgroup/arch
lxc-start: failed to spawn 'arch'
lxc-start: No such file or directory - failed to remove cgroup '/cgroup/arch'

LXCは既に新しいバージョンが出ているため、最新版を野良ビルドし試す。 今回は、 LXC-0.9.0-RC1(http://lxc.sourceforge.net/download/lxc/lxc-0.9.0.rc1.tar.gz) で試した。このソースのビルドには、gccとmake等の他、libcap-devが必要な ようだ。 設定ファイルが置かれるディレクトリは、システムにインストールされている lxcパッケージと同じところを参照するよう、–with-config-pathオプション を設定しておく。

miku@obs% wget http://lxc.sourceforge.net/download/lxc/lxc-0.9.0.rc1.tar.gz
miku@obs% tar xf lxc-0.9.0.rc1.tar.gz -C /home/miku/src
miku@obs% cd /home/miku/src/lxc-0.9.0.rc1
miku@obs% ./configure --prefix=/usr/miku --with-config-path=/var/lib/lxc
miku@obs% make && sudo make install

今回ビルドしたlxcコマンド群を利用し再度コンテナを起動。

miku@obs% sudo /usr/miku/bin/lxc-start -n arch -- /usr/lib/systemd/systemd
<30>systemd[1]: Smack is not enabled in the kernel, not loading access rules.

カーネルオプションの不足による警告メッセージが現れているが、とりあえず ssh経由でコンテナ内にアクセスすることができた。

miku@obs$ ssh 10.3.93.11                                                                            
miku@10.3.93.11's password: 
Last login: Tue Mar 19 15:41:07 2013 from 10.3.93.1
[miku@alarmcubox ~]$ telnet mikutter.hachune.net 80
Trying 115.177.182.220...
Connected to mikutter.hachune.net.
Escape character is '^]'.

次回は、この環境にてmikutterを動かしてみようと思う。

LXCにArchLinuxを入れる

Arch Linux上のLXCにArch Linuxを入れ、systemdとsshが正しく動作するか試し てみる。 大まかな流れは、
  1. ネットワーク設定
    • ブリッジインターフェースの作成
    • IP Masqueradeの設定
  2. コンテナの作成
    • コンテナ内システムのbootstrap
    • コンテナ内の設定
    • コンテナ設定ファイルの作成
  3. コンテナの起動と終了
となる。
完成時のネットワーク構成は、以下の図のようになる。

ホスト側ブリッジインターフェースの設定

LXCのvethネットワークを束ねるブリッジインターフェース(br0)を作成する。 ブリッジインターフェースの作成とアドレスの割当にはipコマンドを用いる。
miku@host% sudo ip link add br0 type bridge
miku@host% sudo ip link set br0 up
miku@host% sudo ip address add 10.3.93.1/24 dev br0
毎度手動でインターフェース設定を行うのは面倒なので、netcfgの設定を行っ ておく。まずは、/etc/network.d/examples/bridgeを参考に /etc/network.d/bridge0を記述する。
INTERFACE="br0"
CONNECTION="bridge"
DESCRIPTION="Hatsune Bridge connection"
BRIDGE_INTERFACES=""
IP="static"
ADDR="10.3.93.1"
NETMASK="24"
最後に、systemctlでnetcfg@bridge0がシステム起動時に実行されるよう設定 する。
miku@host% sudo systemctl enable netcfg@bridge0.service
一時的に手動でnetcfgを起動することもできる。
miku@host% sudo systemctl start netcfg@bridge0.service

IP Masqueradeの設定

LXCコンテナ側から外部ネットワークにアクセスできるよう、IP Masqueradeを 設定する。まず、IP Forwardingを有効である必要があるため、 /etc/sysctl.confのnet.ipv4.ip_forwardを1に設定する。
net.ipv4.ip_forward = 1
手動で一時的に有効にするには、"sudo sysctl net.ipv4.ip_forward=1"でよ い。
次に、iptablesにて10.3.93.0/24から外部ネットワークに接続されたネットワー クインターフェース(enp2s0)へのIP Masqueradeを設定する。
miku@host% sudo iptables -t nat -A POSTROUTING \
> -s 10.3.93.0/24 -o enp2s0 -j MASQUERADE
この時点のiptablesの状態をiptables-saveコマンドでdumpし、それをそのま まiptablesの恒久的なルールとして利用する。 このルールファイルを置くべきパスは、/etc/conf.d/iptablesに "IPTABLES_CONF=/etc/iptables/iptables.rules"として定義されている。
miku@host% sudo sh -c 'iptables-save > /etc/iptables/iptables.rules'
最後に、システム起動時にこのルールが適用されるようにsystemdを設定する。
miku@host% sudo systemctl enable iptables.service

bootstrap

Arch Linuxのrootfsの構築は、Arch LinuxのLiveCDからインストールする際と 同様にarch-install-scriptsのpacstrapコマンドを用いる。合わせて、lxcパッ ケージとiproute2パッケージを導入しておく。
miku@host% sudo pacman -S lxc arch-install-scripts iproute2
/lxc/arch/rootfs以下に環境を作成する場合の操作は以下のようになる。 Arch LinuxのLXCテンプレートも存在するのだが、Arch Linux側の仕様がよく 変わり使い物にならない(すぐ使い物にならなくなる)ため、pacstrapを直接利 用する。
miku@host% sudo mkdir -m 0755 /var/lib/lxc/arch/rootfs
miku@host% sudo pacstrap -i -d /var/lib/lxc/arch/rootfs base openssh
baseパッケージグループを導入する際には、カーネルパッケージ等LXCコンテ ナ内に必要ないパッケージも多数含まれるので、必要に応じて除外する。
:: There are 52 members in group base:
:: Repository core
   1) bash  2) bzip2  3) coreutils  4) cronie  5) cryptsetup  6) device-mapper  7) dhcpcd  8) diffutils
   9) e2fsprogs  10) file  11) filesystem  12) findutils  13) gawk  14) gcc-libs  15) gettext  16) glibc
   17) grep  18) gzip  19) heirloom-mailx  20) inetutils  21) iproute2  22) iputils  23) jfsutils  24) less
   25) licenses  26) linux  27) logrotate  28) lvm2  29) man-db  30) man-pages  31) mdadm  32) nano  33) netcfg
   34) pacman  35) pciutils  36) pcmciautils  37) perl  38) ppp  39) procps-ng  40) psmisc  41) reiserfsprogs
   42) sed  43) shadow  44) sysfsutils  45) systemd-sysvcompat  46) tar  47) texinfo  48) usbutils
   49) util-linux  50) vi  51) which  52) xfsprogs
LXCパッケージのデフォルトでは各コンテナは/var/lib/lxc以下に置かれるの だが、パスが長くて面倒だという場合は以下のようにシンボリックリンクを張っ ておく。(LXC側で設定を変更することもできるが、lxcパッケージ側で /var/lib/lxcにハードコートされているものが存在するようでエラーとなるた め)
miku@host% sudo ln -s /var/lib/lxc /lxc

コンテナ内の設定

コンテナを起動しssh経由にてログインする際に必要な設定を行う。 sshdの有効化とユーザアカウントの設定が必須で、必要に応じてロケール等の 設定を行う。
miku@host% sudo chroot /var/lib/lxc/arch/rootfs /bin/bash
root@host(chroot)# ln -s /usr/lib/systemd/system/sshd.service \
> /etc/systemd/system/multi-user.target.wants/sshd.service 
root@host(chroot)# passwd
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
root@host(chroot)# groupadd -g 3939 miku
root@host(chroot)# useradd -g miku -u 3939 -s /bin/bash -m miku
root@host(chroot)# passwd miku
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
root@host(chroot)# exit
デバイスノードの管理はsystemd-udevdが行うため、後述するLXCのconfigでの 許可ルール設定のみ注意すればよい。また、/tmpのtmpfsや/devのdevtmpfs、 /sysのsysfs、/procのprocfs等もsystemdが自動でマウントを行うため、LXCの configやfstabへの記述は特に必要ない。

コンテナ設定ファイルの作成

今回設定するコンテナの設定ファイルは、"/var/lib/lxc/arch/config"である。 ここでは、コンテナに割り当てられるネットワークとファイルシステム、デバ イスのルールについて定義を行う。 設定ファイルの詳細については、lxc.conf(5)や/usr/share/doc/lxc/examples 以下のファイル、デバイス番号の一覧は以下のドキュメントを参照。 http://www.kernel.org/pub/linux/docs/device-list/devices.txt
# ホスト名とネットワークの設定
lxc.utsname                     = arch
lxc.network.type                = veth
lxc.network.name                = eth0
lxc.network.flags               = up
lxc.network.link                = br0
lxc.network.ipv4                = 10.3.93.11/24
lxc.network.ipv4.gateway        = 10.3.93.1


# ファイルシステムの設定
lxc.rootfs      = /var/lib/lxc/arch/rootfs


# デバイスの設定
lxc.pts                         = 1024
lxc.tty                         = 4

# deny all devices
lxc.cgroup.devices.deny         = a

# /dev/tty0..3
lxc.cgroup.devices.allow        = c 4:0 rwm
lxc.cgroup.devices.allow        = c 4:1 rwm
lxc.cgroup.devices.allow        = c 4:2 rwm
lxc.cgroup.devices.allow        = c 4:3 rwm

# /dev/tty
lxc.cgroup.devices.allow        = c 5:0 rwm
# /dev/console
lxc.cgroup.devices.allow        = c 5:1 rwm
# /dev/ptmx
lxc.cgroup.devices.allow        = c 5:2 rwm

# /dev/null
lxc.cgroup.devices.allow        = c 1:3 rwm
# /dev/zero
lxc.cgroup.devices.allow        = c 1:5 rwm
# /dev/random
lxc.cgroup.devices.allow        = c 1:8 rwm
# /dev/urandom
lxc.cgroup.devices.allow        = c 1:9 rwm

# /dev/pts/*
lxc.cgroup.devices.allow        = c 136:* rwm
# /dev/rtc
lxc.cgroup.devices.allow        = c 254:0 rwm
最終的に許可されたデバイスの一覧は "/sys/fs/cgroup/devices/lxc/コンテナ名/devices.list" から参照できる。

コンテナ内のArch Linuxの起動と終了

コンテナ内のinitの起動にはlxc-startを用いる。このシステムの場合はコン テナ名がarch、コマンドは/usr/lib/systemd/systemdとなる。
早速起動した所、pivot_root(2)が失敗する問題に遭遇した。
miku@host% sudo lxc-start -n arch -- /usr/lib/systemd/systemd
lxc-start: Invalid argument - pivot_root syscall failed
lxc-start: failed to setup pivot root
lxc-start: failed to set rootfs for 'arch'
lxc-start: failed to setup the container
lxc-start: invalid sequence number 1. expected 2
lxc-start: failed to spawn 'arch'
これはsystemdとLXCの組み合わせで発生する問題で、/以下をprivate mountす ることで解決できるようだ。
miku@host% sudo mount --make-rprivate /
このprivate mountの詳細については、以下のページが詳しい。
再度起動した所、今度は/dev/ptsが存在しないとのエラーが発生。どうや らLXC側で/dev/ptsにdevptsをマウントしようとして失敗しているようなので、 /lxc/arch/dev/ptsを作成しておく。
miku@host% sudo lxc-start -n arch -- /usr/lib/systemd/systemd
lxc-start: No such file or directory - failed to mount a new instance of '/dev/pts'
lxc-start: failed to setup the new pts instance
lxc-start: failed to setup the container
lxc-start: invalid sequence number 1. expected 2
lxc-start: failed to spawn 'arch'
miku@host% sudo mkdir -m 755 /var/lib/lxc/arch/dev/pts
以上2つの問題を解決し、ようやくsystemdとsshdが起動した。
miku@host% sudo lxc-start -n arch -- /usr/lib/systemd/systemd
miku@host% lxc-ps -n arch
CONTAINER   PID TTY          TIME CMD
arch       1113 ?        00:00:00 systemd
arch       1124 ?        00:00:00 systemd-udevd
arch       1132 ?        00:00:00 systemd-journal
arch       1243 ?        00:00:00 sshd
arch       1245 ?        00:00:00 dbus-daemon
arch       1246 ?        00:00:00 systemd-logind
arch       1253 ?        00:00:00 agetty
arch       1254 tty1     00:00:00 agetty
デーモンとして動作させる場合は、以下のように-dオプションとログ出力オプ ションを設定し起動する。
miku@host% sudo lxc-start -n arch  -d \
> --logfile=/var/lib/lxc/arch/lxc.log \
> --console=/var/lib/lxc/arch/console.log  -- /usr/lib/systemd/systemd
LXCコンテナを終了する場合は、lxc-stopコマンドを利用する。
miku@host% sudo lxc-stop -n arch
Arch Linux上のLXCコンテナ内でArch Linuxを動かし、基本的な操作(起動と終了)が 行えることが確認できた。

その他の問題

今回作成した環境には、lxc-consoleにてコンソールにアクセスできない問題 がある。LXCが想定する/dev以下の扱いとsystemd-udevdの挙動の問題なように 見受けられるので、そのあたりを探っておこうと思う。 (LXC側で掴んだデバイスノードと別に/devにmountされたdevtmpfs上のデバイ スノードをsystemd側でgettyしているのが原因?)