概要
カーネルのコントロールグループ (「cgroups」 と略して表記します) は、タスク (プロセス) をまとめたり分割したりすることのできるカーネルの機能で、 子プロセスを階層構造でまとめたグループとして扱うこともできる仕組みです。 これらの階層構造は、利用可能なハードウエアやネットワーク資源を有効に活用する ため、システムチューニングを支援するよう設定することができます。
本章では下記のような用語を使用します:
「cgroup」 はコントロールグループの略称です。
cgroup 内では複数のタスク (プロセス) が関連づけられていて、それらの タスク向けに構成されたパラメータをもとに動作する、各種のサブシステム が存在しています。
サブシステムは cpuset や freezer 、メモリやディスクの I/O などを割り当て たり設定したりするパラメータを提供します。より一般的な書き方をすると、 「資源コントローラ」 と呼びます。
cgroup は木構造で階層管理されています。システム内には複数の木構造を持つ ことができるようになっていて、特定の環境に適応するよう異なる木構造を 利用することもできます。
システム内で動作するすべてのタスクは、必ずいずれかの cgroup の木構造に 属します。
理解を深めるため、下記の資源計画シナリオをお読みください
(ソース:
/usr/src/linux/Documentation/cgroups/cgroups.txt
):
Firefox のような Web ブラウザの場合は Web ネットワーククラスに分類されます し、 (k)nfsd のような NFS デーモンであれば NFS ネットワーククラスに分類 されます。一方、 Firefox は誰がそれを起動したのかに依存して、適切な CPU またはメモリクラスを共有します。
それぞれ下記のようなサブシステムが存在していて、それらは 2 種類に 分類することができます:
cpuset, freezer, devices, checkpoint/restart
cpu (スケジューラ), cpuacct, メモリ, ディスク I/O, ネットワーク
サブシステムのマウントは、下記のようにして別々に行なうこともできます:
mount -t cgroup -o cpu none /cpu mount -t cgroup -o cpuset none /cpuset
一括で行なう場合は下記のようにします。なお、デバイス名に (下記で
none
と設定されている箇所) ついては、任意の名前を
設定することができます。ここで指定した名前は、
/proc/mounts
で表示することができます:
mount -t cgroup none /sys/fs/cgroup
サブシステムに関する追加情報は下記の通りです:
cpuset を使用することで、プロセスをシステム内の CPU のサブセットや メモリ (「メモリノード」) に結びつけることができます。 たとえば 10.4.3項 「例: cpuset」 をお読みください。
freezer サブシステムは、高性能計算機クラスタ (HPC クラスタ) を利用する際に
便利な仕組みで、事前に設定されたチェックポイントに到達した際にグループ内に
あるすべてのタスクをフリーズ (停止) させたりタスク群を停止させたりすることが
できるものです。詳しくは
/usr/src/linux/Documentation/cgroups/freezer-subsystem.txt
をお読みください。
下記に示すのは、 freezer サブシステムの使用方法を説明するための 基本的なコマンド群です:
mount -t cgroup -o freezer freezer /freezer # 子 cgroup を作成: mkdir /freezer/0 # 作成した cgroup にタスクを投入する: echo $task_pid > /freezer/0/tasks # フリーズさせる: echo FROZEN > /freezer/0/freezer.state # フリーズ状態を解除する: echo THAWED > /freezer/0/freezer.state
cgroup に属するすべてのプロセスに対して、それらの状態をダンプファイルに 保存します。これを利用することで、後から実行を再開することができます (もちろん保存後にそのまま実行し続けることもできます) 。
また、 「保存されたコンテナ」 について、物理マシン間を 起動することもできます (仮想マシンで行なうことができるのと同じ機能を 提供します) 。
すべてのプロセスのイメージは、ファイルに出力されます。
システム管理者は、 cgroup 内のプロセスからアクセスできるデバイスに ついて、その一覧を設定することができます。
これにより、そのデバイスに対してのアクセスを指定した cgroup に属する
タスクに対してのみ許可するように制限することができます。詳しくは
/usr/src/linux/Documentation/cgroups/devices.txt
をお読みください。
cpuacct は CPU の使用量を計算するコントローラで、 cgroup を利用すること
でタスクをグループ化し、それらのグループに対する CPU 使用率を計算します。
詳しくは
/usr/src/linux/Documentation/cgroups/cpuacct.txt
をお読みください。
CFS (スケジューラ) のグループスケジュール機能を利用して、グループ間での CPU 帯域の共有を行ないます。かなり複雑な処理を行ないます。
ユーザスペースのプログラムに対して、メモリの使用量を制限します。
カーネルの起動パラメータに対して swapaccount=1
を指定すると、スワップの使用方法を制御することができます。
LRU (Least Recently Used; 使用率の低い) ページを制限します。
匿名ページとファイルキャッシュを対象とします。
カーネルのメモリに対しては制限を行ないません。
必要であれば他のシステムでも利用されます。
詳しくは
/usr/src/linux/Documentation/cgroups/memory.txt
をお読みください。
blkio (ブロック IO) コントローラは、ディスクの I/O コントローラとして 利用できる仕組みです。 blkio コントローラでは、ディスクの使用帯域を 制御するためのポリシーを設定することができます。
blkio.weight
の値で重さ (weight) を設定し、
帯域の重み付けを設定する場合は、基本コマンドで設定することができます:
# /sys/fs/cgroup 内の準備 mkdir /sys/fs/cgroup/blkio mount -t cgroup -o blkio none /sys/fs/cgroup/blkio # 2 つの cgroup の開始 mkdir -p /sys/fs/cgroup/blkio/group1 /sys/fs/cgroup/blkio/group2 # 重み付けの設定 echo 1000 > /sys/fs/cgroup/blkio/group1/blkio.weight echo 500 > /sys/fs/cgroup/blkio/group2/blkio.weight # それぞれのグループに対して、制御下に置くプロセスの # PID を書き込むcommand1
& echo $! > /sys/fs/cgroup/blkio/group1/taskscommand2
& echo $! > /sys/fs/cgroup/blkio/group2/tasks
下記の例は、 blkio.throttle.read_bps_device
で
読み込み量の上限を、 blkio.throttle.write_bps_device
で書き込み量の制限を行なう場合の基本的なコマンド例です:
# /sys/fs/cgroup 内の準備 mkdir /sys/fs/cgroup/blkio mount -t cgroup -o blkio none /sys/fs/cgroup/blkio # ルートグループに対するデバイスの帯域幅の指定; 書式: # <major>:<minor> <byes_per_second> echo "8:16 1048576" > /sys/fs/cgroup/blkio/blkio.throttle.read_bps_device
注意事項やシナリオ、追加のパラメータについて、詳しくは
/usr/src/linux/Documentation/cgroups/blkio-controller.txt
をお読みください。
現在議論中。
cgroup を便利に使用するには、下記の追加パッケージをインストール してください:
libcgroup1
: 資源管理を簡略化するための
基本的なユーザスペースツールが含まれています。
cpuset
: CPU セットを管理するための
cset ツールが含まれています。
libcpuset1
: CPU セットを操作するための
C 言語 API が含まれています。
kernel-source
: ドキュメントを読む場合に
必要なパッケージです。
lxc
: Linux のコンテナ実装です。
openSUSE に同梱されているカーネルであれば、 cgroup に対応しています。 特に追加の修正を適用する必要はありません。 lxc-checkconfig を実行すると、下記のような形式で cgroup の環境を表示することができます:
--- Namespaces --- Namespaces: enabled Utsname namespace: enabled Ipc namespace: enabled Pid namespace: enabled User namespace: enabled Network namespace: enabled Multiple /dev/pts instances: enabled --- Control groups --- Cgroup: enabled Cgroup namespace: enabled Cgroup device: enabled Cgroup sched: enabled Cgroup cpu account: enabled Cgroup memory controller: enabled Cgroup cpuset: enabled --- Misc --- Veth pair device: enabled Macvlan: enabled Vlan: enabled File capabilities: enabled
どのサブシステムが利用可能なのかを知るには、下記を実行します:
mkdir /cgroups mount -t cgroup none /cgroups grep cgroup /proc/mounts
それぞれ下記のサブシステムが利用できます: perf_event, blkio, net_cls, freezer, devices, memory, cpuacct, cpu, cpuset.
コマンドラインを利用する場合は下記のようにします:
CPU 数を判別したり、メモリノードを確認したりするには、
それぞれ /proc/cpuinfo
や
/proc/zoneinfo
ファイルの内容を表示します。
仮想ファイルシステム内に cpuset 用の構造を作成します (情報源: /usr/src/linux/Documentation/cgroups/cpusets.txt):
mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset cd /sys/fs/cgroup/cpuset mkdir Charlie cd Charlie # この cpuset で使用する CPU の一覧を設定します: echo 2-3 > cpuset.cpus # この cpuset で使用するメモリノードを設定します: echo 1 > cpuset.mems echo $$ > tasks # これでサブシェル 'sh' が Charie という名前の cpuset に # 設定されます。下記を実行すると '/Charlie' と表示されるはずです: cat /proc/self/cpuset
cpuset の削除は下記のようなシェルコマンドを実行することで行ないます:
rmdir /sys/fs/cgroup/cpuset/Charlie
上記のコマンドは、 cpuset が使用中の場合には失敗します。削除を行なう 前に、それらに属する内部 cpuset やタスク (プロセス) を取り除いてください。 下記のように実行すると、それらを確認することができます:
cat /sys/fs/cgroup/cpuset/Charlie/tasks
背景となる情報や追加の設定フラグについて、詳しくは
/usr/src/linux/Documentation/cgroups/cpusets.txt
をお読みください。
cset ツールを利用する場合は下記のようにします:
# CPU 数とメモリノードの表示
cset set --list
# cpuset 構造の作成
cset set --cpu=2-3 --mem=1 --set=Charlie
# cpuset 内でプロセスを起動
cset proc --set Charlie --exec -- stress -c 1 &
# 既存のプロセスを cpuset に移動
cset proc --move --pid PID
--toset=Charlie
# cpuset 内のタスク一覧を表示
cset proc --list --set Charlie
# cpuset の削除
cset set --destroy Charlie
コマンドラインを利用する場合は下記のようにします:
cgroup の構造を作成します:
mount -t cgroup cgroup /sys/fs/cgroup cd /sys/fs/cgroup/cpuset/cgroup mkdir priority cd priority cat cpu.shares
cpu.shares の値は下記のような意味があります:
1024 が既定値 (詳しくは
/Documentation/scheduler/sched-design-CFS.txt
を参照) = 50% の使用率
1524 = 60% の使用率
2048 = 67% の使用率
512 = 40% の使用率
cpu.shares を変更します:
echo 1024 > cpu.shares
カーネルのドキュメンテーション: (kernel-source
パッケージ内) /usr/src/linux/Documentation/cgroups
ディレクトリ内:
/usr/src/linux/Documentation/cgroups/blkio-controller.txt
/usr/src/linux/Documentation/cgroups/cgroups.txt
/usr/src/linux/Documentation/cgroups/cpuacct.txt
/usr/src/linux/Documentation/cgroups/cpusets.txt
/usr/src/linux/Documentation/cgroups/devices.txt
/usr/src/linux/Documentation/cgroups/freezer-subsystem.txt
/usr/src/linux/Documentation/cgroups/memcg_test.txt
/usr/src/linux/Documentation/cgroups/memory.txt
/usr/src/linux/Documentation/cgroups/resource_counter.txt
http://lwn.net/Articles/243795/—Corbet, Jonathan: Controlling memory use in containers (2007).
http://lwn.net/Articles/236038/—Corbet, Jonathan: Process containers (2007).