maidsphere

A quantization noise whispers through the net.

かんたんなコントロールグループ(cgroups)のはなし

May 16, 2015 13:08:19 JST

コントロールグループ(cgroups)とは,Linuxにおけるプロセスの資源管理用サブシステムです.

などの資源を,プロセス(もしくはプロセスのまとまり)ごとにかなり詳細にチューニングできます.

cgroupsはカーネル2.6.24で初めてマージされています. そのため,これ以前のカーネル(CentOS 5.xなど)の場合は利用できないので注意が必要です.

また,搭載されているサブシステムによって利用できる機能とそうでないものが発生します. カーネルのバージョンによって,どのサブシステムが利用できるかに差があります. どのサブシステムが搭載されているかを簡単に判別する方法は後述します.

実際にcgroupsを使う

cgroupsが使えるか確認する

最初に,使っているカーネルがそもそもcgroupsに対応しているか,またどのサブシステムが使えるかを確認します.

% dmesg | grep cgroup
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.015177] Initializing cgroup subsys ns
[    0.015273] Initializing cgroup subsys cpuacct
[    0.015335] Initializing cgroup subsys devices
[    0.015387] Initializing cgroup subsys freezer
[    0.015415] Initializing cgroup subsys net_cls

この場合は,cpusetcpunscpuacctdevicesfreezernet_clsの各サブシステムが利用可能です. ここで何も出てこなかった場合はあきらめてください.

各サブシステムの機能について,簡単にまとめておきます

CPU使用率の設定はniceよりも詳細に指定できます.

cpuサブシステムを使う

cpuサブシステムの使いかたを,もう少し詳細に見ておきます. まず,cgroupを使うために仮想ファイルシステムをマウントします.

# mkdir /dev/cgroup
# mount -t cgroup -o cpu cgroup /dev/cgroup
# ls -1 /dev/cgroup
cgroup.procs
cpu.shares
notify_on_release
release_agent
sysdefault
tasks

mount-oオプションで,利用するサブシステムを指定します. 複数のサブシステムを利用する場合はコンマで区切ればOKです. 利用可能なサブシステムをすべて利用する場合は,単にcgroupsを指定します.

プロセスグループを作成する

プロセスのまとまりであるプロセスグループを作ることができます. プロセスグループは設定変更の単位です. 複数の異なる設定を異なるプロセスに対して行う場合は必ず作成しなければいけません.

たとえば,janedoeというプロセスグループを作成するには,以下のようにします.

# pwd
/dev/cgroup
# mkdir janedoe
# cd janedoe
# ls -1
cgroup.procs
cpu.shares
notify_on_release
tasks
# cat cpu.shares
1024

このプロセスグループ名は任意に指定でき,またそのグループに属するプロセスも1プロセスから任意に指定できます. あるグループに属するプロセスは,tasksというファイルにプロセスIDが列挙されているので確認できます.

CPU使用率を調節する

cpuサブシステムにおけるCPU使用率の調整はcpu.sharesというファイルでおこないます. このファイルに値を書き込むと,その値に応じたCPU使用率が割り振られます. デフォルトは上で示したとおり1024です.

CPU使用率の指定方法について,簡単に説明しておきます. たとえば,cpu.shares1024のグループAと,その2倍の2048のグループBがあるとします. このときは,グループAのプロセスはCPU使用率を33%利用します. いっぽうグループBは67%になり,グループBがグループAの2倍のCPU使用率を受け取ります. このように,cpu.sharesの値を元にCPU使用率は比例配分されます.

実際に,どのようにCPU使用率を調整するかについてここから説明していきます.

下記のような,無限ループだけを行うシェルスクリプトを用意します.

#!/bin/sh
while true; do true; done

それぞれcpu_jane.shcpu_john.shという名前で保存し,実行します.

# /root/cpu_jane.sh &
# /root/cpu_john.sh &

このときのtopの結果はこのようになります.

top - 13:32:43 up 36 min,  4 users,  load average: 1.35, 0.40, 0.14
Tasks: 102 total,   4 running,  98 sleeping,   0 stopped,   0 zombie
Cpu(s):100.0%us,  0.0%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
2185 root      20   0  3952  556  464 R 49.8  0.1   0:38.33 cpu_jane.sh
2186 root      20   0  3952  556  464 R 49.8  0.1   0:33.63 cpu_john.sh

双方のプロセスともに,50%ずつCPU使用率を受け取っていることがわかります.

この状態で,johndoeというプロセスグループを作成します.

# pwd
/dev/cgroup
# mkdir johndoe
# ls janedoe johndoe
janedoe:
cgroup.procs  cpu.shares  notify_on_release  tasks

johndoe:
cgroup.procs  cpu.shares  notify_on_release  tasks

janedoeは先ほど作りました ;D

つぎに,プロセスID 2185(cpu_jane.sh)をjanedoeグループに,プロセスID 2186(cpu_john.sh)をjohndoeグループに属させます.

# /bin/echo 2185 > /dev/cgroup/janedoe/tasks
# /bin/echo 2186 > /dev/cgroup/johndoe/tasks

さいごに,janedoeグループのcpu.shares2048にします.

# /bin/echo 2048 > /dev/cgroup/janedoe/cpu.shares
# cat /dev/cgroup/janedoe/cpu.shares
2048
# cat /dev/cgroup/johndoe/cpu.shares
1024

このときに,topを見てみると以下のようになります.

top - 13:36:31 up 40 min,  4 users,  load average: 2.07, 1.28, 0.55
Tasks: 103 total,   3 running, 100 sleeping,   0 stopped,   0 zombie
Cpu(s): 99.0%us,  1.0%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
2185 root      20   0  3952  556  464 R 67.2  0.1   2:35.74 cpu_jane.sh
2186 root      20   0  3952  556  464 R 32.6  0.1   2:22.37 cpu_john.sh

janedoeグループのcpu_jane.shが67%のCPU使用率をもらっていることがわかります. いっぽうで,johndoeグループのcpu_john.shは33%しか使えていません.

このように,cgroupsを使うと簡単にプロセスの資源配分を調節することができます. すごくフレキシブルな機構なので,いろいろ活用してみるといいと思います.

ちなみに,ディストリビューションによってはcgroup-binという,こうした操作を簡単に行ってくれるユーティリティを詰め込んだパッケージが存在します. このあたりを使ってみると,もっとプロセスの資源配分を楽に行えるようになると思います.