TenForward

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

aufs を使った一般ユーザ権限で起動するコンテナ

LXC ではコンテナのクローンを行う際に色々なストレージバックエンドの特徴を生かしたスナップショットクローンを行えます。この辺りは 連載の第 19 回〜 22 回 辺りで詳しく解説しています。

今まで、非特権LXCコンテナでストレージバックエンドの特徴を生かしたスナップショットクローンは、btrfs か overlayfs でしか行えませんでした。

先日、私の送ったパッチで aufs を使ったスナップショットクローンが一般ユーザ権限でもできるようになりました。

前者は liblxc 側の変更で lxc-clone や lxc-start 側で関係するパッチ、後者は lxc-start-ephemeral コマンドに関係するパッチです。

これで一般ユーザでも aufs を使った非特権クローンとコンテナが起動できるようなりました。簡単に紹介しておきます。

Plamo 5.3.1 に aufs パッチを当てた 4.1.1 カーネルを使っています。

$ lsb_release -d
Description:	Plamo Linux release 5.3.1
$ uname -r
4.1.1-plamo64-aufs

最近の aufs では allow_userns というモジュールオプションを Y にすると User Namespace 内の特権ユーザが aufs をマウントできるようになります。マニュアルにも記載があります。

私も手元では以下のように設定しています。

$ cat /etc/modprobe.d/aufs.conf 
options aufs allow_userns=1

こんな一般ユーザで操作しています。

$ id
uid=1000(karma) gid=100(users) groups=100(users),26(audio),28(dialout),29(video),32(cdrom),36(kvm),38(pulse),39(pulse-access),44(mlocate),47(libvirt),60(docker),1000(sudo)

まず、普通に dir バックエンドを使ったコンテナを作成します。以下がその config の rootfs の設定。

$ grep lxc.rootfs ~/.local/share/lxc/ct01/config 
lxc.rootfs = /home/karma/.local/share/lxc/ct01/rootfs

このコンテナのクローンを作成します。

$ lxc-clone -o ct01 -n aufs01 -s -B aufs
Created container aufs01 as snapshot of ct01
$ lxc-ls -f
NAME    STATE    IPV4  IPV6  GROUPS  AUTOSTART  
----------------------------------------------
aufs01  STOPPED  -     -     -       NO         
ct01    STOPPED  -     -     -       NO         

クローンは成功しています。

$ grep lxc.rootfs ~/.local/share/lxc/aufs01/config
lxc.rootfs = aufs:/home/karma/.local/share/lxc/ct01/rootfs:/home/karma/.local/share/lxc/aufs01/delta0

こんな感じに aufs を使うコンテナのルートファイルシステムの定義がされています。

起動してみます。Plamo では cgmanager とか systemd-logind とかないので、起動前には自分で一般ユーザ権限の cgroup を作成して、現在のシェルの PID を登録してから起動しています。

$ lxc-start -n aufs01 -d
$ lxc-ls -f
NAME    STATE    IPV4          IPV6  GROUPS  AUTOSTART  
------------------------------------------------------
aufs01  RUNNING  10.0.100.179  -     -       NO         
ct01    STOPPED  -             -     -       NO         

無事起動しましたね。

なぜ今 aufs ?

以上が動きと機能の紹介でした。でも、overlayfs がカーネルにマージされた今、なぜ aufs なのか? ってところですが...

色々なファイルシステムを扱う場合は特権が必要となります。例え User Namespace を使った Namespace 内の特権であっても、ファイルシステムをマウントできなかったりします。

User Namespace 内の特権ユーザがファイルシステムをマウントするには、カーネル内でファイルシステムのフラグに "FS_USERNS_MOUNT" というフラグが指定されている必要があります。(参考: overlayfs と LXC 非特権コンテナの snapshot によるクローン - TenForwardの日記)

このフラグ、4.1.1 カーネルで指定されているファイルシステムを調べてみると

$ find fs/ -type f | xargs grep FS_USERNS_MOUNT
fs/devpts/inode.c:	.fs_flags	= FS_USERNS_MOUNT | FS_USERNS_DEV_MOUNT,
fs/proc/root.c:	.fs_flags	= FS_USERNS_MOUNT,
fs/ramfs/inode.c:	.fs_flags	= FS_USERNS_MOUNT,
fs/sysfs/mount.c:	.fs_flags	= FS_USERNS_MOUNT,
fs/namespace.c:		if (!(type->fs_flags & FS_USERNS_MOUNT)) {

最後の (fs/namespace.c) は関係ないので devpts, proc, ramfs, sysfs だけです。この辺りはマウントできないとそもそも非特権のシステムコンテナが起動できなかったりするので指定されていて当然という気がしますね。つまり普通のファイルシステムはこれがそもそも指定されていないわけです。

overlayfs もこのフラグは指定されていません。なのに LXC で非特権 overlayfs がサポートされているのはなぜか? という話ですが、これは Ubuntuカーネルにパッチが当たっているからです。パッチがあたっていないバニラカーネルだと当然これは失敗します。

$ lxc-clone -o ct01 -n overlay01 -s -B overlayfs
clone failed

私の使っている 4.1.1 の overlayfs には特に何の変更も加えていないので、このように失敗します。

一方、aufs はカーネルにはマージされていないものの、最新の aufs が使える環境では素の aufs で User Namespace 内の特権ユーザが aufs をマウントできるわけです。この辺りからでしょうか。

まあ、パッチの量の大小の差はあるにせよ、overlayfs も aufs もバニラカーネルにパッチを当てないと非特権コンテナでは使えないわけで、なら aufs の非特権コンテナサポートを追加することで少しでも非特権コンテナのサポートする範囲が広がれば良いかなと思ってパッチを作りました。

あ、ちなみに Ubuntuカーネルに当たっている aufs は古いバージョンなので、allow_userns は使えない模様です。Ubuntu は aufs 止めちゃうみたいですものね。

ま、LXC の overlayfs 周りとかは以前もパッチ送ったことがあってコードをよく知ってたので、非特権 aufs 対応はさほど難しくないって分かってたから作ったんですけどね。(^_^;)