TenForward

技術ブログ。はてなダイアリーから移転しました

Ubuntu 14.04 LTS での非特権コンテナ

(2014-07-06 追記してます)
(2014-05-11 追記してます)
(2014-04-24 追記してます)

ついにリリースされましたね.Ubuntu の新しい LTS.これを目標に LXC 1.0 の開発は進められてきたわけで,きっと特に苦労する事もなく一般ユーザでのコンテナの作成と実行が出来るのだろうなあと思って試してみました.結論から言うと出来ました.なので特にこのブログエントリを読む事なく作る事が出来るのでお急ぎの方はこの後読まずにさっさとやってしまいましょう :-D

過去,Ubuntu 上で

と 2 度ほどためしていますが,徐々に簡単になって,ついに完成型になりました.

まず Ubuntu 14.04 LTS をインストールしました.amd64 の Server 版です.パッケージは OpenSSH Server だけが有効になるようにシンプルにインストールしました.

インストール

今まで通り apt-get install するだけ.

ubuntu@trusty:~$ sudo apt-get install lxc
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  bridge-utils cgmanager cloud-image-utils debootstrap distro-info
  distro-info-data dnsmasq-base euca2ools genisoimage libaio1
  libboost-system1.54.0 libboost-thread1.54.0 liblxc1 libmnl0
  libnetfilter-conntrack3 libnspr4 libnss3 libnss3-nssdb librados2 librbd1
  libseccomp2 libxslt1.1 lxc-templates python-distro-info python-lxml
  python-requestbuilder python-setuptools python3-lxc qemu-utils sharutils
  uidmap
Suggested packages:
  cgmanager-utils shunit2 wodim cdrkit-doc btrfs-tools lvm2 lxctl
  qemu-user-static python-lxml-dbg bsd-mailx mailx
The following NEW packages will be installed:
  bridge-utils cgmanager cloud-image-utils debootstrap distro-info
  distro-info-data dnsmasq-base euca2ools genisoimage libaio1
  libboost-system1.54.0 libboost-thread1.54.0 liblxc1 libmnl0
  libnetfilter-conntrack3 libnspr4 libnss3 libnss3-nssdb librados2 librbd1
  libseccomp2 libxslt1.1 lxc lxc-templates python-distro-info python-lxml
  python-requestbuilder python-setuptools python3-lxc qemu-utils sharutils
  uidmap
0 upgraded, 32 newly installed, 0 to remove and 0 not upgraded.
Need to get 6,393 kB of archives.
After this operation, 25.3 MB of additional disk space will be used.
Do you want to continue? [Y/n] 

インストール後 lxc 関係のパッケージを確認するとこんな感じに

ubuntu@trusty:~$ dpkg -l | grep lxc
ii  liblxc1                             1.0.3-0ubuntu3                amd64        Linux Containers userspace tools (library)
ii  lxc                                 1.0.3-0ubuntu3                amd64        Linux Containers userspace tools
ii  lxc-templates                       1.0.3-0ubuntu3                amd64        Linux Containers userspace tools (templates)
ii  python3-lxc                         1.0.3-0ubuntu3                amd64        Linux Containers userspace tools (Python 3.x bindings)

Ubuntu 14.04 と LXC 1.0 開発中は systemd が必要だった時期があったり色々ですが,無事 cgmanager を使って cgroup の管理を行うようになりました.13.10 までインストールされていた cgroup-lite パッケージによる起動時の cgroupfs のマウントもなくなり,以下のようにすっきりとした感じに.

ubuntu@trusty:~$ ls -F /sys/fs/cgroup/
cgmanager/  systemd/
ubuntu@trusty:~$ ls -F /sys/fs/cgroup/cgmanager/
sock=

コンテナで使う cgroupfs はいずこへ? ってのはまた 別のブログエントリで.

インストール後,一度システムを再起動しておきましょう.(再起動しないまま色々やってたらコンテナ起動しなかった... 不要かもしれませんが一応)

(2014-07-06 追記)
lxc 1.0.4 で以下 (2014-05-11, 2014-04-24 追記) の修正がマージされています。
(2014-07-06 追記ここまで)

(2014-05-11 追記)
以下の 2014-04-24 の追記ですが、バグということで修正のパッチがマージされています。まだ 1.0 系にはマージされていませんが、そのうちされるような気がします。1.0 系のリリースに入ったらまた追記します。
(2014-05-11 追記ここまで)

(2014-04-24 追記)
systemd-logind がユーザのログインセッションごとに cgroup を使いますので、非特権コンテナ用には cgmanager もそのグループを使います。と言っても /sys/fs/cgroup/systemd 以下を使うわけではなく、/sys/fs/cgroup/systemd に cgroup が出来ると、その構成で cgmanager 側の cgroup にも同じグループが作成されます。なので logind が作成する cgroup がない状態では非特権コンテナは動きません。

さらにコンテナ起動後にログインセッションが変わると、現在のシェルと以前コンテナを起動した時のシェルでは所属する cgroup が異なる事になりますから、権限がなくなり lxc-stop とか lxc-cgroup 等の各種のコンテナ管理コマンドがそのコンテナに対して利かなくなります。
(2014-04-24 追記ここまで)

一般ユーザでコンテナを扱うシステム上の準備

root 権限でシステムに行う設定を行います.

あるユーザにひもづいた uid/gid の範囲の指定を行うため,ユーザに対する subuid, subgid の設定が必要ですが,設定しようと思ったらあらかじめ設定されていました.いつ作られるのかな? 自分で設定する場合は usermod -v/-w を使いましょう.ここでは uid/gid 共に 100000 から 65536 個が "ubuntu" ユーザにひもづく subuid, subgid に設定されています.

ubuntu@trusty:~$ cat /etc/subuid /etc/subgid
ubuntu:100000:65536
ubuntu:100000:65536

あるユーザが使う事の出来るネットワークインターフェースの数を設定するために /etc/lxc/lxc-usernet に設定を行います.ここでは,

  • "ubuntu" ユーザが
  • veth タイプのインターフェースを
  • lxcbr0 にアタッチする形で
  • 10 個利用可能

と設定するために以下のように設定しました.veth はペアで作成しますが,ペアで 1 つに数えます.

ubuntu@trusty:~$ echo "ubuntu veth lxcbr0 10" | sudo tee -a /etc/lxc/lxc-usernet 
ubuntu veth lxcbr0 10

一般ユーザでコンテナを扱うユーザの準備

ユーザ特有の設定を行います.一般ユーザでコンテナを扱う際の設定ファイルは ~/.config/lxc 以下に置かれます.まずは "ubuntu" ユーザでコンテナを扱う時の共通の設定を ~/.config/lxc/default.conf に書きます.これは /etc/lxc/default.conf をコピーしてきて,ユーザのマッピングの設定を追加しただけです.

ubuntu@trusty:~$ mkdir -p .config/lxc
ubuntu@trusty:~$ cp /etc/lxc/default.conf .config/lxc/
ubuntu@trusty:~$ vi .config/lxc/default.conf 
ubuntu@trusty:~$ cat .config/lxc/default.conf 
lxc.network.type = veth
lxc.network.link = lxcbr0
lxc.network.flags = up
lxc.network.hwaddr = 00:16:3e:xx:xx:xx

lxc.id_map = u 0 100000 65536
lxc.id_map = g 0 100000 65536

最後の 2 行を追加しています (/etc/subuid, subgid の設定と合うように).

コンテナの作成

ここまででコンテナを作成する準備は出来ていますので,普通にコンテナの rootfs 以下を作ります.(以下の例は何度か試した後なのでイメージのダウンロードとかしてません)

ubuntu@trusty:~$ lxc-create --name plamo01 --template download -- --dist plamo --release 5.x --arch amd64
Using image from local cache
Unpacking the rootfs

---
You just created a Plamo container (release=5.x, arch=amd64, variant=default)
The default root password is: root

ubuntu@trusty:~$ lxc-ls --fancy
NAME     STATE    IPV4  IPV6  AUTOSTART  
---------------------------------------
plamo01  STOPPED  -     -     NO         

あえて Ubuntu 上に Plamo コンテナを :-)

コンテナ起動

特につまづく所はありません.

ubuntu@trusty:~$ lxc-start -n plamo01 -d
ubuntu@trusty:~$ lxc-ls --fancy
NAME      STATE    IPV4       IPV6  AUTOSTART  
---------------------------------------------
plamo01   RUNNING  10.0.3.72  -     NO         

はい,起動 :-)

参考

(って私はまだ読んでませんがww)