TenForward

技術ブログ。はてなダイアリーから移転しました

Linux 3.16 から試せる cgroup の単一階層構造 (1)

Linux 3.16 からカーネルソースツリーの Documentation/cgroups の下に一つ文書が増えているのに気づいた方もいらっしゃるのではないでしょうか。cgroupの使い方が大幅に変わる変更がマージされています。増えた文書は以下。

今までとの互換性

とは言ってもいきなり 3.16 からドーンと変わっているわけではなく、普通に使うには今までと何も変わりません。このドーンと変わっているのを体験するには cgroupfs を以下のようにマウントする必要があります。

# mount -n -t cgroup -o __DEVEL__sane_behavior cgroup /sys/fs/cgroup/

そう、cgroupをマウントするときのオプションとして '__DEVEL__sane_behavior' というオプションを付ける必要があります (このオプション自体は結構前からあるはず)。

'sane_behavior' !! まともな振る舞い!! 今まではまともじゃなかったのか〜

そうです、まともじゃないから大幅に変えるよなんて話は結構前から出ていて、少しずつ実装されてきていました (おっかけてたわけではないので多分 :p)。

今までの cgroup との互換性を保ちながら新しい機能も使えるようになっています。今、一部のサブシステムだけを使っていてそれ以外は使ってないよ、という方は必要なサブシステムは今まで通りマウントしておいて、その後上記「まともオプション」を使ってマウントすれば、その時点でマウントされていないやつを「まともに」マウントしてくれます。

例えば、memory サブシステムだけ使ってるよ、という場合は memory サブシステムだけマウントします。

# cd /sys/fs/cgroup
# mkdir memory
# mount -n -t cgroup -o memory cgroup /sys/fs/cgroup/memory/
# mkdir unified
# mount -n -t cgroup -o __DEVEL__sane_behavior cgroup /sys/fs/cgroup/unified/

こんな風にやれば、memoryは今まで通りの動きのまま /sys/fs/cgroup/memory 以下で使用でき、それ以外のサブシステムは /sys/fs/cgroup/unified で体験することができます。もちろん __DEVEL__ と付いているように、開発途上の機能であることを理解しているのが前提ですよ。

マウント

今までは /sys/fs/cgroup は tmpfs でマウントするなどして、そこにサブシステム名のディレクトリを作成し、例えば

# mount -t cgroup -o cpu cgroup /sys/fs/cgroup/cpu

という風にサブシステムごとに cgroupfs をマウントしたりしていました。つまり複数の階層構造を持てる、というのが cgroupfs の特徴でした。ところが、'__DEVEL__sane_behavior' オプションでマウントすると単一の階層構造になります

試してみましょう。以下は cgroupfs を全くマウントせずに起動している Plamo Linux 5.2 で試しています。

# uname -r
3.16.1-plamo64-karma
# mount -t cgroup -o __DEVEL__sane_behavior cgroup /sys/fs/cgroup
# ls /sys/fs/cgroup/
blkio.io_merged                   cpuset.mem_hardwall
blkio.io_merged_recursive         cpuset.memory_migrate
blkio.io_queued                   cpuset.memory_pressure
blkio.io_queued_recursive         cpuset.memory_pressure_enabled
blkio.io_service_bytes            cpuset.memory_spread_page
blkio.io_service_bytes_recursive  cpuset.memory_spread_slab
blkio.io_service_time             cpuset.mems
blkio.io_service_time_recursive   cpuset.sched_load_balance
blkio.io_serviced                 cpuset.sched_relax_domain_level
blkio.io_serviced_recursive       devices.allow
blkio.io_wait_time                devices.deny
blkio.io_wait_time_recursive      devices.list
blkio.leaf_weight                 hugetlb.2MB.failcnt
blkio.leaf_weight_device          hugetlb.2MB.limit_in_bytes
blkio.reset_stats                 hugetlb.2MB.max_usage_in_bytes
blkio.sectors                     hugetlb.2MB.usage_in_bytes
blkio.sectors_recursive           memory.failcnt
blkio.throttle.io_service_bytes   memory.force_empty
blkio.throttle.io_serviced        memory.kmem.failcnt
blkio.throttle.read_bps_device    memory.kmem.limit_in_bytes
  : (snip)

使えるサブシステムをコントロールするファイルが大量に生成されました。今までもオプションを指定せずにマウントすると同じディレクトリの下に複数のサブシステム用のファイルができていましたので、ここは特に変化はありません。

子グループの作成と子グループのサブシステムの設定

グループをディレクトリで表現するのは今までの cgroup と変わりません。子グループを作ってみましょう。

# mkdir test
# cd test
# ls
cgroup.controllers  cgroup.populated  cgroup.procs  cgroup.subtree_control

あら、肝心のリソースコントロールを行うファイルがないですね…

これは子グループで使うサブシステムはファイルに指定する必要があるのです。子グループで使用するサブシステムは親グループの "cgroup.subtree_control" ファイルで指定します。

つまり、単一の階層構造になったから、階層の全てで同じサブシステムを使わなければいけないわけではなく、親グループで指定したサブシステムのみが子グループで使用可能になります。

試してみましょう。"cgroup.subtree_control" には "+" もしくは "-" に続けてサブシステム名を指定して書き込みます。"+" は子グループで使用可能なサブシステムを追加する場合、"-" は削除する場合です。コントロール用のファイルに文字列を書き込んで制御を行うのは変わりないですね。

# cd /sys/fs/cgroup
# echo "+memory" > cgroup.subtree_control
# ls /sys/fs/cgroup/test
cgroup.controllers                  memory.kmem.usage_in_bytes
cgroup.event_control                memory.limit_in_bytes
cgroup.populated                    memory.max_usage_in_bytes
cgroup.procs                        memory.memsw.failcnt
cgroup.subtree_control              memory.memsw.limit_in_bytes
memory.failcnt                      memory.memsw.max_usage_in_bytes
memory.force_empty                  memory.memsw.usage_in_bytes
memory.kmem.failcnt                 memory.move_charge_at_immigrate
memory.kmem.limit_in_bytes          memory.numa_stat
memory.kmem.max_usage_in_bytes      memory.oom_control
memory.kmem.slabinfo                memory.pressure_level
memory.kmem.tcp.failcnt             memory.soft_limit_in_bytes
memory.kmem.tcp.limit_in_bytes      memory.stat
memory.kmem.tcp.max_usage_in_bytes  memory.swappiness
memory.kmem.tcp.usage_in_bytes      memory.usage_in_bytes

"+memory" と書き込むと、子グループの "test" に先ほどはなかった memory サブシステム用のファイルができています。

逆に "-memory" を指定してみましょう。

# echo "-memory" > cgroup.subtree_control
# ls /sys/fs/cgroup/test
cgroup.controllers  cgroup.populated  cgroup.procs  cgroup.subtree_control

はい、memory 関係のファイルは削除されてますね。

このように追加、削除が可能です。

まとめ

時間がなくなったので続きは後日 (カーネル付属文書]読めば全部書いてありますが)。

今回のポイントをまとめましょう。

  • 新しいcgroupの機能を試すにはcgroupをマウントするときのオプションとして '__DEVEL__sane_behavior' というオプションを付ける
  • 一部のサブシステムだけを使っていてそれ以外は使ってないよ、という方は必要なサブシステムは今まで通りマウントしておいて、その後 '__DEVEL__sane_behavior' を使ってマウントすれば、その時点でマウントされていないやつを「まともに」マウントしてくれる
  • '__DEVEL__sane_behavior' オプションでマウントすると単一の階層構造になる
  • 子グループで使用するサブシステムは親グループの "cgroup.subtree_control" ファイルで指定する

ではまた〜

Linux 3.16 から試せる cgroup の単一階層構造 (2) - TenForwardの日記へ続く