かんたんなcgroups(Control Groups)のはなし
まずは,cgroupsって何か
これはLinuxにおけるプロセスの資源管理用サブシステムです
- CPU使用率
- メモリ使用量
- ディスクI/O
- ネットワークI/O
のこれらの資源を,プロセス(もしくはプロセスグループ)ごとに
かなり詳細にチューニングできます
cgroupsはカーネル2.6.24で初めてマージされてるので
これ以前のカーネル(CentOS 5.6など)の場合は利用できないので注意が必要です
また,搭載されているサブシステムによって
利用できる機能とそうでないものが発生しますので
このあたりにも留意する必要があります
# どのサブシステムが搭載されているかを簡単に判別する方法があります
# これについては後述します
つぎに,実際に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
この場合は,cgroupsのcpuset・cpu・ns・cpuacct・devicesなどの
各サブシステムが利用可能です
各サブシステムの機能について,簡単にまとめておきます
- cpuset
- 使用するCPUコアの指定
- cpu
- CPU時間の優先度の指定(指定した値に比例したCPU時間を割り当て)
- cpuacct
- CPU使用率の情報表示
- memory
- メモリ使用量の上限を指定
- ns
- 名前空間への対応
- devices
- デバイスに対するアクセスコントロールリストの指定
- freezer
- プロセスの一時停止のサポート(対象のプロセスをSIGSTOPするのと同義)
- net_cls
- ネットワークI/Oの優先度の指定
- blkio
- ディスクI/Oの優先度の指定
なお,CPU使用率の設定はniceよりも詳細に指定できます
cpuサブシステムを使う場合について,もう少し詳細に見ておきます
# 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
「-o」オプションで,利用するサブシステムを指定します
複数のサブシステムを利用する場合はコンマで区切ればOKです
利用可能なサブシステムをすべて利用する場合は
「cgroups」を指定するといいようです
# pwd
/dev/cgroup
# mkdir janedoe
# cd janedoe
# ls -1
cgroup.procs
cpu.shares
notify_on_release
tasks
# cat cpu.shares
1024
このように,「janedoe」というプロセスグループに対応する設定を個別に作成できます
このプロセスグループ名は任意に指定でき,またそのグループに属するプロセスも任意に指定できます
あるグループに属するプロセスは,「tasks」というファイルの中身を見ればわかります
このファイルに書き込まれているプロセスIDで判別することができます
cpuサブシステムにおけるCPU使用率の調整は「cpu.shares」というファイルから行います
このファイルに値を書き込むと,その値に応じたCPU使用率が割り振られます
デフォルトはここで示したとおり1,024です
この指定方法ですが,簡単に説明しておきます
たとえば,cpu.sharesが1,024のグループAと,その2倍の2,048のグループBがあるとします
このときは,グループAのプロセスはCPU使用率を33%利用します
いっぽうグループBは67%です
グループBがグループAの2倍のCPU使用率を受け取っていることがわかります
このように,cpu.sharesの値を元にCPU使用率は比例配分されます
実際に,どのようにCPU使用率を調整するかについて
ここから説明していきます
このように,無限ループだけを行うシェルスクリプトを用意し
それぞれ「cpu_jane.sh」と「cpu_john.sh」という名前で保存し,実行します
# cat /root/cpu_jane.sh
#!/bin/sh
while true; do true; done
# cat /root/cpu_john.sh
#!/bin/sh
while true; do true; done
# /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」というプロセスグループを作成します
# 「janedoe」はさっき作りましたね;D
# できていない場合は,「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
つぎに,プロセス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.sharesを2,048にします
# /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を使うと,KVM上で動作する各VMについて
かなり詳細に資源配分を調整できるようになります
すごくフレキシブルな機構なので,いろいろ活用してみるといいと思います
ちなみに,各ディストリビューションには「cgroup-bin」という
この操作を簡単に行ってくれるユーティリティを詰め込んだパッケージが存在します
このあたりを使ってみると,もっとプロセスの資源配分を楽に行えるようになると思います