Previous Post | Top | Next Post |
TOC
特権ユーザーでのシステムとしてのLXC仮想環境はほぼchrootと変わらないので それほど違和感はありませんでした。
この次に非特権ユーザー権限から立ち上げられたLXC仮想環境を実現するための 技術背景を学ぶために、ここはひとまずLXCのコマンドを離れ Linux Namespaces 周辺に着目します。Linux Namespaces は伝統的なUNIXの範疇を越えているので、 Linuxがカーネルレベルでどこがどう拡張されているのかを2021年2月の時点の Debian Bulleseye/testing pre-11 release環境で確認していきます。
Linux Namespaces
どうもLXCも含めた各種コンテナ環境は2002年以降拡充されてきた LinuxのNamespaces というカーネルの機能を使っていることがキーだと分かりました。
とりあえず、以下の関連マンページに目を通しました。
namespaces
(7): LinuxのNamespaces全体の説明cgroup_namespaces
(7): Cgroup root directoryipc_namespaces
(7): System V IPC, POSIX message queuesnetwork_namespaces
(7): Network devices, stacks, ports, etc.mount_namespaces
(7): Mount pointspid_namespaces
(7): Process IDstime_namespaces
(7): Boot and monotonic clocksuser_namespaces
(7): User and group IDsuts_namespaces
(7): Hostname and NIS domain name
Cgroup Namespaces
Linux Namespacesの中でcgroup_namespaces
(7)は、/proc/[pid]/cgroup
と
/proc/[pid]/mountinfo
から見えるプロセスのcgroups (コントロールグループ)
の見え方を仮想化します。各種コンテナ環境を可能にする仮想化技術の中心的な要素
としておもしろそうだったので、自分なりに追加の状況確認をしながらtraceしたの
ですがマンページの通りには行きませんでした。
「Linuxあるある」は、マンページの記載が嘘ではないけど古いスタイルの設定 前提で、現状とずれている可能性を感じました。現在はBulleseyeがtestingにあり、 リリース前です。まず現在のDebianの関連インフラ状況をまとめてみました。
Debian release | Kernel version | util-linux | cgroup hierarchy | Year |
---|---|---|---|---|
Buster 10 | 4.19系 | 2.33系 | hybrid (v1+v2) | 2019 |
Bulleseye 11 | 5.10系 | 2.36系 | unified (v2 only) | 2021 ? |
ここで、2015年に書かれたという、
Control Group v2
によると、hybridヒエラルキーでは“/proc/$PID/cgroup
” 中に複数行でプロセスの
cgroupメンバーシップをリストするのに対して、unifiedヒエラルキーでは
“/proc/$PID/cgroup
” 中の単一行で常に“0::$PATH
”だけで複数行でプロセスの
cgroupメンバーシップをリストしているとのことでした。
こう見ると現行のcgroup_namespaces
(7)の例はhybridヒエラルキー前提なので、
ずれている分かりました。
cgroup v2のunifiedヒエラルキー環境に合わせてでコマンドを調整をしながら
cgroup_namespaces
(7)の例を以下でtraceすることにします。この際に、
各環境で以下の cgck
関数を定義して状況の確認に利用します。
... # declare -f cgck
cgck ()
{
for pid in 1 $(ps --no-headers -o pid);
do
if [ -e "/proc/$pid/cgroup" ]; then
ps --no-headers o pid,cmd --pid "$pid";
cat "/proc/$pid/cgroup";
grep cgroup2 "/proc/$pid/mountinfo";
echo " ---";
fi;
done
}
ここでプロセスを取り巻く状況をモニターしている/proc/$pid/*
ファイルの内容
の意味は、proc
(5)に説明されています。
まずroot権限のBash shellを環境設定抜きで立ち上げ、バックグラウンド プロセスも立ち上げます。
$ PS1='sh1\$ ' sudo bash --norc
sh1# sleep 1000000 &
[1] 397732
この状況を上記のcgck
関数を定義して確認します。
sh1# cgck
1 /sbin/init
0::/init.scope
32 22 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392577 sudo bash --norc
0::/user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-445f3600-af41-459a-9ac3-1e1c5633a188.scope
32 22 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392578 bash --norc
0::/user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-445f3600-af41-459a-9ac3-1e1c5633a188.scope
32 22 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
397732 sleep 1000000
0::/user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-445f3600-af41-459a-9ac3-1e1c5633a188.scope
32 22 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
気になるプロセスのcgroup PATHやcgroupの ファイルシステムのmount point を抜き出して表にします。Systemd+GUI環境のconsoleからなので少々 cgroup PATHが長めです。
command | bash --norc |
sleep 1000000 |
---|---|---|
PID | 392578 |
397732 |
cgroup PATH | /user.slice/...a188.scope |
/user.slice/...a188.scope |
cgroup2-fs mount point | / |
/ |
さてこれらの気になるプロセスのcgroup帰属を変更します。
sh1# echo $$
392578
sh1# mkdir -p /sys/fs/cgroup/freezer/sub
sh1# echo $$ >/sys/fs/cgroup/freezer/sub/cgroup.procs
sh1# echo $!
397732
sh1# mkdir -p /sys/fs/cgroup/freezer/sub2
sh1# echo $! >/sys/fs/cgroup/freezer/sub2/cgroup.procs
sh1# cgck
1 /sbin/init
0::/init.scope
32 22 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392577 sudo bash --norc
0::/user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-445f3600-af41-459a-9ac3-1e1c5633a188.scope
32 22 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392578 bash --norc
0::/freezer/sub
32 22 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
397732 sleep 1000000
0::/freezer/sub2
32 22 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
ここでcgroupのPATHが新規作成した場所に変わっています。
command | bash --norc |
sleep 1000000 |
---|---|---|
PID | 392578 |
397732 |
cgroup PATH | /freezer/sub |
/freezer/sub2 |
cgroup2-fs mount point | / |
/ |
さて、unshare
を用いて新規のcgroupやmountのnamespaces内に新規のshellを
立ち上げましょう。
sh1# PS1='sh2\$ ' unshare --cgroup --mount bash --norc
さてこの状況をcgck
関数を定義してそれを使って確認します。
sh2# cgck
1 /sbin/init
0::/../../init.scope
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392577 sudo bash --norc
0::/../../user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-445f3600-af41-459a-9ac3-1e1c5633a188.scope
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392578 bash --norc
0::/
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
397732 sleep 1000000
0::/../sub2
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
425474 bash --norc
0::/
503 501 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup2 rw
---
sh2# echo $$
425474
unshare
でbash --norc
として立ち上がった新規のshellから見たから見える各プロセスの
cgroupのPATHは、/sys/fs/cgroup/freeze/sub
からの相対になるので変わります。
cgroup2のファイルシステムの mount pointも、/sys/fs/cgroup/freeze/sub
からの
相対になるので変わります。
command | bash --norc |
sleep 1000000 |
bash --norc |
---|---|---|---|
PID | 392578 |
397732 |
425474 |
cgroup PATH | / |
/../sub2 |
/ |
cgroup2-fs mount point | /../.. |
/../.. |
/../.. |
ただこうして作成された新規のshell (PID=425474) のcgroup2-fs mount pointは/
で
あるべきでが、/../..
となっています。これを直します。
sh2# mount --make-rslave /
sh2# cgck
1 /sbin/init
0::/../../init.scope
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392577 sudo bash --norc
0::/../../user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-445f3600-af41-459a-9ac3-1e1c5633a188.scope
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392578 bash --norc
0::/
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
397732 sleep 1000000
0::/../sub2
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
425474 bash --norc
0::/
503 501 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup2 rw
---
sh2# umount /sys/fs/cgroup
sh2# cgck
1 /sbin/init
0::/../../init.scope
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392577 sudo bash --norc
0::/../../user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-445f3600-af41-459a-9ac3-1e1c5633a188.scope
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392578 bash --norc
0::/
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
397732 sleep 1000000
0::/../sub2
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
425474 bash --norc
0::/
---
マウントイベントが他のnamespacesに漏れないようにした上で、一度マウントをはずしました。
command | bash --norc |
sleep 1000000 |
bash --norc |
---|---|---|---|
PID | 392578 |
397732 |
425474 |
cgroup PATH | / |
/../sub2 |
/ |
cgroup2-fs mount point | /../.. |
/../.. |
無し |
sh2# mount -t cgroup2 cgroup2 /sys/fs/cgroup/
sh2# cgck
1 /sbin/init
0::/../../init.scope
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392577 sudo bash --norc
0::/../../user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-445f3600-af41-459a-9ac3-1e1c5633a188.scope
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
392578 bash --norc
0::/
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
397732 sleep 1000000
0::/../sub2
32 22 0:27 /../.. /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:9 - cgroup2 cgroup2 rw
---
425474 bash --norc
0::/
503 501 0:27 / /sys/fs/cgroup rw,relatime - cgroup2 cgroup2 rw
---
cgroup2-fsをマウントしました。
command | bash --norc |
sleep 1000000 |
bash --norc |
---|---|---|---|
PID | 392578 |
397732 |
425474 |
cgroup PATH | / |
/../sub2 |
/ |
cgroup2-fs mount point | /../.. |
/../.. |
/ |
これで新規のshell (PID=425474) のcgroup2-fs mount pointが/
となりました。
もう、このPID=425474のプロセスのシェルから、PID=392578やPID=397732の
プロセスと同じcgroupのnamespacesに属させる操作はできません。なぜなら
/freezer/sub
や /freezer/sub2
が /sys/fs/cgroup
以下に無くなっ
ているからです。
sh2# tree -L 2 /sys/fs/cgroup
/sys/fs/cgroup
├── cgroup.controllers
├── cgroup.events
├── cgroup.freeze
├── cgroup.max.depth
├── cgroup.max.descendants
├── cgroup.procs
├── cgroup.stat
├── cgroup.subtree_control
├── cgroup.threads
├── cgroup.type
├── cpu.pressure
├── cpu.stat
├── io.pressure
└── memory.pressure
0 directories, 14 files
util-linux
Linux Namespaces関連のunshare
(1)やnsenter
(1)等は、
util-linux
が提供するutil-linuxのソース中にあり、
Debianではutil-linux
バイナリーパッケージの中で提供されています。
util-linuxのソースはmount
(8)コマンド等も提供します。
Previous Post | Top | Next Post |