LXC (Linux Containers)

最近、LinuxLXCで遊んでいる。Linux上にはVServerOpenVZというコンテナ技術がすでに存在するのに、なぜLXCなのか。カーネル2.6.29でメインラインへのマージが完了しているので(残っているホットな話題の一つはチェックポイント・リスタートか)、カーネルパッチが不要になのと同時に、将来性がありそうだから。現時点で実戦投入するには、機能的に物足りないし、安定性も未知数だけど、時間誰かが解決してくれそうな気がする。と思っている割にはドキュメントが少ないのは、なぜだろう?

コンテナ技術の肝は、コンテナ間の隔離、資源管理をどう実現するかにあるが、この点は名前空間の導入と、cgroup(control group)の利用で実現している。LXCの実装の経緯はよく知らないが(フランスのIBMの人たちが開発していたMetaClusterプロジェクトが基になったらしい)、名前空間の実装にはOpenVZの開発者なども関係してそうだ。

名前空間に関してはcloneシステムコールの拡張になるので、Plan9のrforkに近い。これまでもアドレス空間やオープンファイルFDを共有するかどうかを指定できたが(アドレス空間を共有すればスレッドで、非共有ならプロセスなど)、これが拡張されたと思えばよい。Plan9の場合、すべての資源がファイル空間にマッピングされているので、rfork時に親プロセスの名前空間を継承する場合はREFNAMEG、新規に生成する場合はREFNAMEGをフラグに指定する具合でシンプルだ。しかし、Linuxの場合、すべての資源に統一的なインタフェースがあるわけじゃないので、UTS、IPC、ユーザ、PID、ネットワークごとにフラグがある。たとえば、CLONE_NEWNETをフラグをセットすると、子プロセスからはローカルネットワークインタフェース(lo)以外は見えなくなる。LXCはnetlinkインタフェースを使って、子プロセス(コンテナ)に対して、仮想ネットワークインタフェースを追加し、アドレスなどをセットアップする。

一方、cgroupはプロセスのグループに対して資源割当を制御する仕組みで、LXCではコンテナ毎にcgroupを割り当てている。

ファイルシステムchroot jail。


では、実際に動かしてみよう。環境はUbuntu 8.10で、カーネルは2.6.29。CONFIG_XXX_NSのたぐいはすべて有効にする。ptsデバイス名前空間もコンテナごとにわけるために、CONFIG_DEVPTS_MULTIPLE_INSTANCESも有効にしておく。ユーザランドツールは(まだパッケージ化されていないようなので)LXCのページからダウンロードし、コンパイルする。現時点では0.6.1が最新。

ここではネットワークはvethデバイスを使い、ブリッジで外界につなげることにする。物理デバイスeth0のIPアドレスは192.168.0.1と仮定する。

$ sudo ifconfig eth0 down
$ sudo brctl addbr br0
$ sudo brctl addif br0 eth0
$ sudo ifconfig eth0 0.0.0.0 up
$ sudo ifconfig br0 inet 192.168.0.1 netmask 255.255.255.0 up

では、コンテナ環境を作ってみる。一番簡単なのは、lxc-debianスクリプトを使うこと。コンテナ名はtestにしている。

$ sudo lxc-debian create
What is the name for the container ? [debian] test
What hostname do you wish for this container ? [test]
What IP address do you wish for this container ? [172.20.0.21] 192.168.0.101
What is the gateway IP address ? [172.20.0.1] 192.168.0.1
What is the MTU size ? [1500]
Specify the location of the rootfs [./rootfs.test]

debootstrapが動いて、ルートファイルシステムがセットアップされる。

そしてlxc-start -n testでコンテナが起動する。

sudo lxc-start -n test
INIT: version 2.86 booting
Activating swap...done.
Cleaning up ifupdown....
Checking file systems...fsck 1.41.3 (12-Oct-2008)
done.
Setting kernel variables (/etc/sysctl.conf)...done.
Mounting local filesystems...done.
Activating swapfile swap...done.
Setting up networking....
Configuring network interfaces...if-up.d/mountnfs[eth0]: waiting for interface lo before doing NFS mounts (warning).
done.
INIT: Entering runlevel: 3
Starting OpenBSD Secure Shell server: sshd.
Starting network benchmark server.

Debian GNU/Linux 5.0 test console

test login: