cgroup v2がカーネルに導入された時点では、cgroup v2にはマウントオプションはありませんでした。
しかし、4.13 で nsdelegate
というオプションが導入されました。これは現時点でも cgroup v2 唯一のマウントオプションです。
このオプションは初期の namespace でマウントするときにのみ指定できます。それ以外の namespace では無視されます。
cgroup namespace については、私の連載 の 第34回 で説明しました。ここでは、cgroup namespace で cgroup ツリーを独立させた後でも、cgroup namespace 内の /
(root)を超えてプロセスを移動できました。
これはある意味コンテナ内のプロセスを、別のコンテナに移動させるという意味になります。
普通にコンテナを起動すると、mount namespace を分離させますので、他のコンテナのファイルシステムは見えないはずです。したがってこのようなコンテナをまたいだプロセスの移動はできないはずです。しかし、何らかの理由で別の cgroup 階層が見えるような場合は移動ができることになります。このような操作は通常は行わないケースがほとんどで、禁止したいケースがほとんどであると思います。
nsdelegate を使うとこれを禁止できます。
試してみましょう。以下は Plamo 7.0(4.14.44 kernel)で試しています(sysvinit バンザイ!)。
namespace をまたいだプロセスの移動
nsdelegate がないとき
オプションを指定せずに cgroup v2 をマウントします。これは、私の連載の第34回で説明しています。詳しくはそちらをどうぞ。
# mount -t cgroup2 cgroup2 /sys/fs/cgroup/
test01
と test02
cgroup を作成します。
# mkdir /sys/fs/cgroup/test0{1,2}
現在のシェルの PID を test01
に登録します。
# echo $$ | tee /sys/fs/cgroup/test01/cgroup.procs 4213
unshare で cgroup namespace を作成してシェルを起動します。
# unshare --cgroup -- /bin/bash
起動したシェルは親 cgroup と同じ cgroup に属することになるので、namespace 作成時点で親と自身が cgroup の /
(root)にいることになります。namespace 作成時点にいる cgroup が namespace 内では root となる、これが cgroup namespace でした。
# echo $$ 4284 # cat /proc/4213/cgroup 0::/ # cat /proc/4284/cgroup 0::/
親の namespace から見ると /test01
cgroup にいることになっています。ちゃんと namespace として働いているのがわかりますね。
parent namespace # cat /proc/4213/cgroup 0::/test01 parent namespace # cat /proc/4284/cgroup 0::/test01
ここでおもむろに現在のシェルの PID を test01
と同じレベルの別階層にある test02
に登録します。
# echo $$ > /sys/fs/cgroup/test02/cgroup.procs
すると /
(root)の一つ上の test02
を表す /../test02
という cgroup に属することになっています。/test01
が root になっているので、同じレベルの別階層だとこうなるのはわかりますね。
# cat /proc/$$/cgroup 0::/../test02
nsdelegate があるとき
nsdelegate 機能を使うには cgroup v2 をマウントする際に nsdelegate オプションを指定します。既に cgroup v2 がマウント済みの場合は -o remount,nsdelegate
と指定して再マウントすれば使えるようになります。
# mount -t cgroup2 -o nsdelegate cgroup2 /sys/fs/cgroup/
先ほどと同様に test01
、test02
cgroup を作りましょう。
# mkdir /sys/fs/cgroup/test0{1,2}
そして、test01
にシェルのプロセスを登録し、所属する cgroup を確認します。
# echo $$ > /sys/fs/cgroup/test01/cgroup.procs # unshare --cgroup /bin/bash # cat /proc/$$/cgroup 0::/
test01
が root cgroup になりました。ここまではさきほどと同じですね。
ここで先程と同じようにシェルの PID を test02
に移動させてみましょう。
# echo $$ > /sys/fs/cgroup/test02/cgroup.procs bash: echo: write error: No such file or directory
エラーになりました。nsdelegate
を指定して cgroup v2 をマウントすると、このように namespace の境界(root)をまたいで、別階層の cgroup にプロセスを移動できません(ENOENT
が返ります)。
nsdelegate には他にも重要な機能がありますので、次回にでも。