さて,
そのエントリしたカレンダーのひとつがLinux Advent Calendar 2016です。一昨年から,
今年も同様に,
昨年のエントリ
今回の実行例はUbuntu 16.
前回は,
Ubuntu 14.
cgmanagerから置き換わったLXCFSがUbuntu 15./proc
以下をコンテナ向けに仮想化する機能がありますのでなくなるわけではありませんが,
LXCFSのcgroup関連機能が不要になった理由は,
/proc/[PID]/nsディレクトリ
cgroup名前空間を紹介する前に,/proc/[PID]/ns
ディレクトリについて紹介しておきましょう
各プロセスに関連する情報を格納したファイルが存在する/proc/[PID]
ディレクトリ以下にはns
というディレクトリが存在します。
このディレクトリには,
ls -l
を実行すると,
$ ls -l /proc/self/ns total 0 lrwxrwxrwx 1 ubuntu ubuntu 0 Dec 6 19:41 cgroup -> cgroup:[4026531835] lrwxrwxrwx 1 ubuntu ubuntu 0 Dec 6 19:41 ipc -> ipc:[4026531839] lrwxrwxrwx 1 ubuntu ubuntu 0 Dec 6 19:41 mnt -> mnt:[4026531840] lrwxrwxrwx 1 ubuntu ubuntu 0 Dec 6 19:41 net -> net:[4026531957] lrwxrwxrwx 1 ubuntu ubuntu 0 Dec 6 19:41 pid -> pid:[4026531836] lrwxrwxrwx 1 ubuntu ubuntu 0 Dec 6 19:41 user -> user:[4026531837] lrwxrwxrwx 1 ubuntu ubuntu 0 Dec 6 19:41 uts -> uts:[4026531838]
リンク先に数字が表示されていますが,
この/proc/[PID]/ns
以下のファイルには,
あるプロセスが所属する名前空間に移動するためのシステムコールとしてsetns(2)というシステムコールがあります。このsetns(2)
はファイルディスクリプタと名前空間の種類を引数に取ります。ここで与えるファイルディスクリプタが,/proc/[PID]/ns
ディレクトリ以下に存在するファイルのファイルディスクリプタです。
LXCでsetns(2)
を使うコマンドは,lxc-attach
です。この/proc/[PID]/ns
以下の実装が完成したのは3.setns(2)
がすべての名前空間に対してきちんと動作し,lxc-attach
コマンドが動作するようになったのがこの時でした。
cgroup名前空間
それではいよいよcgroup名前空間について見ていきましょう。
cgroup名前空間は4.
cgroup名前空間は名前空間ごとにcgroupを仮想化します。具体的には,
cgroup名前空間が使えるかどうかは,/proc/[PID]/ns
以下にcgroup
というファイルが存在するかを見ればわかります。先の実行例で示したように,ns
ディレクトリ以下を見ると,
$ ls /proc/self/ns cgroup ipc mnt net pid user uts
以上のようにcgroup
というファイルが存在しており,/proc/[PID]/ns
を見ても,cgroup
というファイルは存在しません。
cgroup名前空間が提供する機能
LXCFSが提供するコンテナ内のcgroupfs
まずは比較のために前回紹介したLXCFSを使うとコンテナ内でcgroupfsがどのように見えたかをおさらいしておきましょう。
$ lxc-start -n xenial01
以上のように起動した非特権コンテナ"xenial01"用のcgroupは,
- 親環境上で見た場合
/sys/
に存在fs/ cgroup/ cpu/ user/ 1000. user/ 1. session/ lxc/ xenial01/ - コンテナ内で見た場合
/sys/
に存在fs/ cgroup/ cpu/ user/ 1000. user/ 1. session/ lxc/ xenial01/
以上のように親であるホスト上の環境でもコンテナ内でも同じパスに存在しました
ただし,
つまりLXCFSは,
cgroup名前空間が提供するコンテナ内のcgroupfs
それではUbuntu 16.
$ lxc-start -n xenial01 $ lxc-attach -n xenial01 -- ls -F /sys/fs/cgroup/cpu,cpuacct/ cgroup.clone_children cpuacct.usage_percpu cpu.stat cgroup.procs cpu.cfs_period_us notify_on_release cpuacct.stat cpu.cfs_quota_us tasks cpuacct.usage cpu.shares
cpuサブシステムがマウントされた直下のルートグループを見ると,
そして,
つまり非特権コンテナ"xenial01"用のcgroupは,
- 親環境上で見た場合
/sys/
に存在fs/ cgroup/ cpu,cpuacct/ user/ ubuntu/ 1/lxc/ xenial01 (ログインユーザの環境により異なります) - コンテナ内で見た場合
/
(ルート) に存在
実際にはコンテナ用のcgroupがコンテナ内でのルートになるのは,
cgroupに属するPIDが書かれたtasks
ファイルcgroup.
ファイル)
$ head -n1 /sys/fs/cgroup/cpu,cpuacct/user/ubuntu/1/lxc/xenial01/tasks 1374 (コンテナ内systemdの親の名前空間でのPID) $ lxc-attach -n xenial01 -- sudo head -n1 /sys/fs/cgroup/cpu,cpuacct/tasks 1 (コンテナ内systemdのコンテナ内でのPID)
このように,
cgroup名前空間の機能を簡単に紹介したところで,
/proc/[PID]/cgroupファイル
プロセスがどのcgroupに属しているかは,/proc/[PID]/cgroup
というファイルを見ればわかります。
まずはテスト用にcgroupを作成します。
# mkdir /sys/fs/cgroup/memory/test01 (test01グループを作成) # echo $$ 1220 # echo 1220 > /sys/fs/cgroup/memory/test01/tasks (プロセスをtest01に登録)
以上のようにmemoryサブシステムのルート直下に"test01"グループを作成し,
# cat /proc/1220/cgroup | grep memory
4:memory:/test01 (所属するcgroupは"/test01")
cgroupファイルのmemory
行を見ると,/test01
と書かれています。つまり/test01
グループに属しているということですね。