LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術

第4回 Linuxカーネルのコンテナ機能[3] ─cgroupとは?(その2)

この記事を読むのに必要な時間:およそ 6.5 分

別階層へのプロセスの登録

サブシステムの解説とは少し外れますが,複数のcgroupfsをマウントする例をあげた所で,複数のcgroupfsへのプロセスの登録についても説明しておきましょう。

前回,cgroup間でのプロセスの移動とところで説明したとおり,あるcgroupにプロセスを登録すると,前に登録されていたcgroupからは自動的にプロセスが削除され,同時に2つのcgroupにプロセスが登録されることはありません。

それでは,cgroupfsが複数マウントされている場合はどうなるのでしょうか。先にcpuとmemoryのサブシステムを同時にマウントする例を試していますので,それをアンマウントしたあと,cpuとmemoryを別々にマウントして試してみましょう。

$ sudo mount -n -t cgroup -o cpu cgroup /sys/fs/cgroup/cpu
$ sudo mkdir /sys/fs/cgroup/cpu/test1    (cpu以下にtest1グループを作成)
$ sudo mount -n -t cgroup -o memory cgroup /sys/fs/cgroup/memory
$ sudo mkdir /sys/fs/cgroup/memory/test2 (memory以下にtest2グループを作成)
$ echo $$ | sudo tee -a /sys/fs/cgroup/cpu/test1/tasks (PIDをtest1に登録)
1738
$ cat /sys/fs/cgroup/cpu/test1/tasks     (test1のtasksを確認)
1738
2152
$ echo $$ | sudo tee -a /sys/fs/cgroup/memory/test2/tasks (PIDをtest2に登録)
1738
$ cat /sys/fs/cgroup/memory/test2/tasks  (test2のtasksを確認)
1738
2171
$ cat /sys/fs/cgroup/cpu/test1/tasks     (test1のtasksを確認)
1738
2188

memoryサブシステムに作成したtest2にプロセスを登録した後も,cpuサブシステムに作成したtest1にはPID 1738は登録されたままになっています。つまりcgroupfsの別のマウントであれば,同じプロセスを登録できることがわかります。

実際のシステムでも,サブシステムごとにマウントしたcgroupfsごとにコンテナ用のcgroupを作り,サブシステムごとにPIDを登録してコンテナのリソース制限を行うといったことはよく行われています。


サブシステムの説明と複数のcgroupfsへのプロセスの登録の話が済んだところで,各サブシステムの機能を説明していきましょう。

なお各サブシステムの説明は,それぞれのサブシステムの機能を理解するのに必要な最低限の機能の説明に限りますので,詳しい機能についてはカーネル付属の文書などをご参照ください。

cpuサブシステム

cpuサブシステムでは,以下のような方法でcgroupに対してcpuを割り当てできます。

帯域制限
単位時間内にcgroup内のタスクがCPUを使用できる合計時間を制限
相対配分
cgroup内のタスクが使えるcpu時間の割り当てを相対的に設定

最初に帯域制限を試してみましょう。まずは準備です。test1test2というcgroupを作成します。

sudo mkdir /sys/fs/cgroup/cpu/test1 /sys/fs/cgroup/cpu/test2

test1グループに現在のシェルを登録します。

$ echo $$ | sudo tee -a /sys/fs/cgroup/cpu/test1/tasks 
2278

ここで別のシェルを実行し,同様にtest2グループに登録します。

$ echo $$ | sudo tee -a /sys/fs/cgroup/cpu/test2/tasks
2953

帯域制御を行うにはcpu.cfs_quota_usに実行できる時間をマイクロ秒単位で設定します。これでcpu.cfs_period_usで指定されている単位時間内でどれだけCPUを使用できるかが設定できます。設定方法はtasksファイルへの書き込みと同様にcpu.cfs_quota_usに設定したい値を書き込みます。

ここではtest1グループには5ミリ秒,test2グループには10ミリ秒を設定してみましょう。

$ cat /sys/fs/cgroup/cpu/test1/cpu.cfs_period_us (単位時間は100ミリ秒)
100000
$ cat /sys/fs/cgroup/cpu/test2/cpu.cfs_period_us (単位時間は100ミリ秒)
100000
$ echo 5000 | sudo tee /sys/fs/cgroup/cpu/test1/cpu.cfs_quota_us (5ミリ秒の制限を設定)
5000
$ echo 10000 | sudo tee /sys/fs/cgroup/cpu/test2/cpu.cfs_quota_us (10ミリ秒の制限を設定)
10000
$ cat /sys/fs/cgroup/cpu/test1/cpu.cfs_quota_us (設定の確認)
5000
$ cat /sys/fs/cgroup/cpu/test2/cpu.cfs_quota_us (設定の確認)
10000

さて,ここで2つ起動しているそれぞれのシェルで以下のような処理を実行します。通常であればCPU使用率がほぼ100%になりますね。

$ while :; do true ; done

これをtop -p 2278,2953としてCPU使用率を確認すると,測定タイミングによって値は変化しますが,それぞれのプロセスのCPU使用率はそれぞれおよそ10%と5%になっていることがわかります。

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
 2953 karma     20   0 24768 7224 1632 R 10.0  0.7   0:54.35 bash
 2278 karma     20   0 24860 7364 1680 R  5.0  0.7   0:27.72 bash

相対配分も簡単に説明しておきましょう。相対配分を行う場合は各cgroup以下のcpu.sharesファイルを使います。このファイルに書かれた数値が1024であるtest1グループと,512であるtest2グループがある場合,test1グループにはtest2グループの倍のCPU時間が割り当てられます。

帯域制御についてはカーネル付属文書のsched-bwc.txtに,相対配分についてはsched-design-CFS.txtに少し説明があります。

cpuacctサブシステム

cpuacctはcgroup内のプロセスが使用したCPU時間のレポートが生成されます。このサブシステムには設定するような項目はありません。詳しくはカーネル付属文書のcpuacct.txtをご覧ください。

たとえば以下はcgroup内のプロセスが消費したCPU時間のレポートを表示しています(単位はナノ秒⁠⁠。

$ cat /sys/fs/cgroup/cpuacct/test1/cpuacct.usage
462998808

cpusetサブシステム

cpusetサブシステムは,cgroupにCPUやメモリノードを割り当てます。CPUとメモリノードの設定はそれぞれcgroup内のcpuset.cpuscpuset.memsファイルに設定します。ルート直下のcgroup中のこの2つのファイルはシステム上の全てのCPUとメモリノードが設定されています。

ルート以下に新たにcgroupを作成した場合はこの2つのファイルは空になっており,この2つのファイルに値を設定しなければtasksファイルにプロセスを登録できませんので注意が必要です。ただしcgroupを作成した際,親のcgroupと同じ設定が書き込まれた状態でこの2つのファイルを作成して良いのであれば,cgroup.clone_childrenファイルに1を書き込んでおけば,cgroupを作成した時に親のcgroupの設定がコピーされます。

この2つのファイルには"-"(ハイフン)や","(カンマ)を使って複数の値を設定できます。たとえばCPU 0から1と5を登録する場合,

$ echo "0-1,5" | tee /sys/fs/cgroup/cpuset/test1/cpuset.cpus

といった風に設定できます。

詳しくはカーネル付属文書のcpuset.txtをご覧ください。

著者プロフィール

加藤泰文(かとうやすふみ)

2009年頃にLinuxカーネルのcgroup機能に興味を持って以来,Linuxのコンテナ関連の最新情報を追っかけたり,コンテナの勉強会を開いたりして勉強しています。英語力のない自分用にLXCのmanページを日本語訳していたところ,あっさり本家にマージされてしまい,それ以来日本語訳のパッチを送り続けています。

Plamo Linuxメンテナ

Twitter:@ten_forward
技術系のブログ:http://tenforward.hatenablog.com/