Cgroups (日本語)
cgroups (別名 control groups) は特定のプロセス (プロセスグループ) のリソースの使用量を制限・監視する Linux カーネルの機能です。'nice' コマンドや /etc/security/limits.conf などの他の方法と比べて、cgroups は柔軟性が優れています。
Control groups には使い方が複数存在します:
- cgcreate, cgexec, cgclassify などのツールを使ってオンザフライでグループを作成・管理する
- 特定のユーザーやグループ、コマンドを自動的にグループに移動する"ルールエンジンデーモン" (
/etc/cgrules.confと/usr/lib/systemd/system/cgconfig.service) - Linux Containers (LXC) 仮想化など他のソフトウェアで使う
残念ながら"ハウツー"方式の簡単なドキュメントが存在しないため、この機能はあまり評価を受けていません。この記事ではその穴を埋める説明を行います。
Contents
インストール
まず、cgroups を管理するためのユーティリティをインストールしてください。AUR から libcgroup パッケージをインストールする必要があります。
クライアントスクリプトの cgm を使いたい場合は、cgmanager デーモンを起動する必要があります。
cgmanager デーモンは以下のような systemd ユニットを使うことで起動できます:
/usr/lib/systemd/system/cgmanager.service
[Unit] Description=Control Group manager [Service] Type=simple ExecStart=/usr/bin/cgmanager [Install] WantedBy=sysinit.target
Systemd でリソースグループを管理する
systemd を使って cgconfig サービスを有効にすることができます:
# systemctl enable cgconfig.service
次のコマンドを使えば cgconfig.conf ファイルにエラーがないか簡単に調べることができます:
$ systemctl status cgconfig.service
シンプルな使い方
一時的なグループ
cgroups を使って即座に"一時的な"グループを作成することができます。実際に、通常ユーザーにカスタムグループを作成する権限を与えることも可能です。次のコマンドを root で実行してください ($USER はあなたのユーザー名に、groupname は cgroup に付けたい名前に置き換えてください):
# cgcreate -a $USER -g memory,cpu:groupname
ユーザーによってグループ groupname の全ての設定を書き換えることができます:
$ ls -l /sys/fs/cgroup/memory/groupname total 0 -rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.event_control -rwxrwxr-x 1 user root 0 Sep 25 00:39 cgroup.procs -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_period_us -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.rt_runtime_us -rwxrwxr-x 1 user root 0 Sep 25 00:39 cpu.shares -rwxrwxr-x 1 user root 0 Sep 25 00:39 notify_on_release -rwxrwxr-x 1 user root 0 Sep 25 00:39 tasks
Cgroups は階層式なので、好きなだけサブグループを作成することができます。例えば、通常ユーザーとして、bash シェルを新しいサブグループ 'foo' 下で動作させたい場合:
$ cgcreate -g memory,cpu:groupname/foo $ cgexec -g memory,cpu:groupname/foo bash
さあ、確認してみましょう:
$ cat /proc/self/cgroup 11:memory:/groupname/foo 6:cpu:/groupname/foo
このグループの新しいサブディレクトリが作成されています。このグループ内の全てのプロセスのメモリ使用量を 10 MB に制限するには、次を実行します:
$ echo 10000000 > /sys/fs/cgroup/memory/groupname/foo/memory.limit_in_bytes
メモリ制限は RAM の使用にしか適用されないので注意してください -- タスクが制限に達すると、スワップを始めます。しかしながら他のプロセスのパフォーマンスにはあまり影響を与えません。
同じようにこのグループの CPU 優先度 ("shares") を変更することもできます。デフォルトでは全てのグループは 1024 shares になっています。100 shares のグループは CPU 時間の ~10% だけを使うようになります:
$ echo 100 > /sys/fs/cgroup/cpu/groupname/foo/cpu.shares
cgroup ディレクトリを表示することで他の設定や統計を見ることができます。
また、既に実行中のプロセスの cgroup を変更することも可能です。全ての 'bash' コマンドをこのグループに移動するには:
$ pidof bash 13244 13266 $ cgclassify -g memory,cpu:groupname/foo `pidof bash` $ cat /proc/13244/cgroup 11:memory:/groupname/foo 6:cpu:/groupname/foo
永続的なグループ設定
起動時に cgroup が作成されるようにしたい場合、代わりに /etc/cgconfig.conf でグループを定義することができます。例えば、"groupname" に制限を管理しタスクを追加する $USER のパーミッションとグループ $GROUP の users を定義します。サブグループの "groupname/foo" グループの定義は以下のようになります。
/etc/cgconfig.conf
group groupname {
perm {
# who can manage limits
admin {
uid = $USER;
gid = $GROUP;
}
# who can add tasks to this group
task {
uid = $USER;
gid = $GROUP;
}
}
# create this group in cpu and memory controllers
cpu { }
memory { }
}
group groupname/foo {
cpu {
cpu.shares = 100;
}
memory {
memory.limit_in_bytes = 10000000;
}
}
活用例
Matlab
Matlab にはマシンのメモリや CPU が全て使われるのに対するプロテクトがありません。膨大な計算を始めてしまうとシステムが使えなくなる可能性があります。以下はそれを防止するために /etc/cgconfig.conf に配置するファイルです ($USER はあなたのユーザー名に置き換えてください):
/etc/cgconfig.conf
# Prevent Matlab from taking all memory
group matlab {
perm {
admin {
uid = $USER;
}
task {
uid = $USER;
}
}
cpuset {
cpuset.mems="0";
cpuset.cpus="0-5";
}
memory {
# 5 GiB limit
memory.limit_in_bytes = 5368709120;
}
}
この cgroup は Matlab が使えるコアをコア0から5までに (Matlab には6つのコアだけが認識されます) そしてメモリの使用量を 5 GiB に制限します。"cpu" リソースの強制を使って CPU 使用量の制限も定義することが可能ですが、"cpuset" で十分だと思われます。
matlab を次のようにして起動します:
$ cgexec -g memory,cpuset:matlab /opt/MATLAB/2012b/bin/matlab -desktop
正しい実行可能ファイルのパスを使って下さい。
ドキュメント
- コントローラーや特定のスイッチ・オプションに関する情報はカーネルの Documentation/cgroup を参照してください (または linux-docs をインストールして
/usr/src/linux/Documentation/cgroupを見て下さい)。 - 詳細かつ完全なリソース管理ガイドが fedora プロジェクトのドキュメント にあります。
コマンドや設定ファイルについては、man cgcreate や man cgrules.conf などの該当する man ページを見て下さい。