先のエントリーでは、コンテナ内から ext4 ファイルシステムのマウントができたのですが、実は security.syscalls.intercept.mount.shift
という設定が効いていないようで、そこで時間切れでした(どこがうまく行ってないか書いてませんでしたが)。
そこで Ubuntu 20.04 もリリースされたことですし、もう一度試してみましょう。
前回のおさらい
前回と同様に /dev/vdb
というディスクが存在し、パーティションをひとつだけ作成し、ext4
で mkfs
しています。テストのために事前にホスト側でマウントし、testfile
というファイルをひとつだけ作ってあります。
$ ls -l /mnt/ total 16 drwx------ 2 root root 16384 Apr 29 07:38 lost+found -rw-r--r-- 1 root root 0 Apr 29 07:56 testfile karma@focal:~$ sudo umount /mnt
コンテナをひとつ作成して起動します。
$ lxc launch images:alpine/3.11 c1 Creating c1 Starting c1
デバイス(/dev/vdb1
)をコンテナに割り当てます。
$ lxc config device add c1 vdb1 unix-block path=/dev/vdb1
Device vdb1 added to c1
システムコールインターセプションの設定を行います。shiftfs
を有効にして、ext4
をマウントできるように許可します。
$ lxc config set c1 security.syscalls.intercept.mount true $ lxc config set c1 security.syscalls.intercept.mount.shift true $ lxc config set c1 security.syscalls.intercept.mount.allowed ext4 $ lxc restart c1 $ lxc config show c1 architecture: x86_64 config: : (snip) security.syscalls.intercept.mount: "true" security.syscalls.intercept.mount.allowed: ext4 security.syscalls.intercept.mount.shift: "true" : (snip) devices: vdb1: path: /dev/vdb1 type: unix-block : (snip)
設定されているのが確認できましたので、マウントしてみます。
$ lxc exec c1 -- mount /dev/vdb1 /mnt $ lxc exec c1 -- ls -lh /mnt total 16K drwx------ 2 nobody nobody 16.0K Apr 29 07:38 lost+found -rw-r--r-- 1 nobody nobody 0 Apr 29 07:56 testfile
ここまでが前回のおさらいです。
ShiftFS おさらい
マウントはできたのですが、ファイルシステム中のファイルの所有権がホストでは root:root
だったのが、nobody:nobody
となります。
これは User Namespace を使って、ホスト上のユーザーとコンテナ内のユーザーをマッピングしており、マッピングしている範囲外の id はコンテナ内では扱えず、その場合は id が /proc/sys/kernel/overflow{u,g}id
の値になります。つまり nobody:nobody
になるわけです。
$ cat /proc/sys/kernel/overflow{u,g}id 65534 65534
コンテナ内でイメージなどをマウントするには、ホスト上のユーザーが所有する uid/gid はコンテナ内で扱えませんので、このあたりを解決するのに ShiftFS というファイルシステムが開発されており、Ubuntu カーネルにはこの機能のパッチが適用されています。この辺りは
をどうぞ。
LXD で ShiftFS を使えるように設定
ここで、最初のコンテナに対して行った設定をもう一度見てみましょう。うまく働いてないなという security.syscalls.intercept.mount.shift
はマウントの際に ShiftFS を使って uid/gid をコンテナ内の uid/gid に合わせる設定です。
しかし、先の例では nobody:nobody
になってしまっていたので、この ShiftFS が効いていないことがわかります。
lxd の情報を確認してみると、
$ lxc info | grep shiftfs shiftfs: "false"
このように有効になっていないようです。
まずはホスト上で ShiftFS が有効になっているかを確認してみましょう。
$ lsmod | grep shiftfs
$
さすがにデフォルトでは shiftfs のカーネルモジュールはロードされないようです。このモジュールをロードして lxd を再起動してみましょう。lxd は snap パッケージで提供されているので、snap.lxd.daemon
を再起動します。
$ sudo modprobe -v shiftfs insmod /lib/modules/5.4.0-26-generic/kernel/fs/shiftfs.ko $ lsmod | grep shiftfs shiftfs 28672 0 $ sudo systemctl restart snap.lxd.daemon
これでどうでしょう?
$ lxc info | grep shiftfs shiftfs: "false"
おや?ダメですね…
調べてみると、snap の lxd の方に shiftfs が有効であると教えてあげないとダメなようです。
$ sudo snap set lxd shiftfs.enable=true $ sudo systemctl reload snap.lxd.daemon
これでいけるかな?
$ lxc info | grep shiftfs shiftfs: "true"
有効になりました!! コンテナを再度作成してみましょう(再作成しなくてもよさそうな気がしましたが、lxd で ShiftFS が有効になったあとにコンテナを再作成しないとうまくいきませんでした)。
$ lxc launch images:alpine/3.11 c1 Creating c1 Starting c1 $ lxc config device add c1 vdb1 unix-block path=/dev/vdb1 Device vdb1 added to c1 $ lxc config set c1 security.syscalls.intercept.mount true $ lxc config set c1 security.syscalls.intercept.mount.shift true $ lxc config set c1 security.syscalls.intercept.mount.allowed ext4 $ lxc restart c1 $ lxc exec c1 -- mount /dev/vdb1 /mnt $ lxc exec c1 -- ls -l /mnt total 16 drwx------ 2 root root 16384 Apr 29 07:38 lost+found -rw-r--r-- 1 root root 0 Apr 29 07:56 testfile
無事に root:root
の所有になっており、ShiftFS が効いていることがわかります。ちなみにホスト側で見ると
$ ls -l /mnt total 16 drwx------ 2 root root 16384 Apr 29 07:38 lost+found -rw-r--r-- 1 root root 0 Apr 29 07:56 testfile
こちらの id も変わってません。
システムコンテナとして、少しでもVMやベアメタル上でOSを使うのに近づけようとする努力には本当に頭が下がりますね。
(追記)
snap set lxd shiftfs.enable=true
を実行する前に作成したコンテナで ShiftFS を使うには、次のようにすると良いようです(私は未確認)。
$ lxc config set c1 security.privileged true ("c1" のとこはコンテナ名入れてね) $ lxc restart c1 $ lxc config unset c1 security.privileged true $ lxc restart c1