リソース管理ガイド
Red Hat Enterprise Linux 6 のシステムリソース管理
エディッション 4
概要
第1章 コントロールグループについて (cgroup)
cgconfig (control group config) サービスがブート時に起動し、事前に定義された cgroup を再構築するように設定して、再起動後も永続されるようにすることが可能です。
1.1. コントロールグループの構成
Linux プロセスモデル
init プロセスという、共通の親プロセスの子プロセスです。init プロセスは、ブート時にカーネルによって実行され、その他のプロセスを開始します (その結果、その他のプロセスがそれら独自の子プロセスを開始する場合もあります)。プロセスはすべて、単一の親プロセスの下位プロセスであるため、Linux プロセスモデルは、単一の階層またはツリーとなっています。
init を除いた Linux プロセスはすべて、環境 (例: PATH 変数)[1] および親プロセスのその他特定の属性 (例: オープンファイル記述子) を継承します。
cgroup モデル
- 階層型である
- 子 cgroup は、親 cgroup から特定の属性を継承する
Red Hat Enterprise Linux で利用可能なサブシステム
blkio— このサブシステムは、物理ドライブ (例: ディスク、ソリッドステート、USB) などのブロックデバイスの入出力アクセスの制限を設定します。cpu— このサブシステムは、スケジューラーを使用して cgroup タスクに CPU へのアクセスを提供します。cpuacct— このサブシステムは、cgroup 内のタスクで使用される CPU リソースについての自動レポートを生成します。cpuset— このサブシステムは、個別の CPU (マルチコアシステム上) およびメモリーノードを cgroup 内のタスクに割り当てます。devices— このサブシステムは、cgroup 内のタスクによるデバイスへのアクセスを許可または拒否します。freezer— このサブシステムは、cgroup 内のタスクを一時停止または再開します。memory— このサブシステムは、cgroup 内のタスクによって使用されるメモリーに対する制限を設定し、それらのタスクによって使用されるメモリーリソースについての自動レポートを生成します。net_cls— このサブシステムは、Linux トラフィックコントローラー (tc) が特定の cgroup から発信されるパケットを識別できるようにするクラス識別子 (classid) を使用して、ネットワークパケットにタグを付けます。net_prio— このサブシステムは、ネットワークインターフェース別にネットワークトラフィックの優先度を動的に設定する方法を提供します。ns— namespace サブシステム。
注記
1.2. サブシステム、階層、コントロールグループ、タスクの関係
ルール 1
cpu および memory のサブシステム (もしくは任意数のサブシステム) を単一階層に接続できます。ただし、各サブシステムは、別のサブシステムがすでに接続された別の階層に接続されていないことが条件となります (ルール 2 を参照)。

図1.1 ルール 1
ルール 2
cpu) を複数の階層に接続することはできません。
memory サブシステムが接続された階層がある場合には、cpu サブシステムは 2 つの異なる階層には決して接続できませんが、両方の階層に接続されているのがそのサブシステムのみの場合には、単一のサブシステムを 2 つの階層に接続することが可能です。

図1.2 ルール 2 (丸数字は、サブシステムが接続される時間的順序)
ルール 3
cpu と memory サブシステムが cpu_mem_cg という名前の階層に接続されて、net_cls サブシステムが net という名前の階層に接続された場合、稼働中の httpd プロセスは、cpu_mem_cg 内の任意の単一 cgroup および net 内の任意の単一 cgroup のメンバーとすることができます。
httpd プロセスがメンバーとなっている cpu_mem_cg 内の cgroup によって、CPU 時間が、他のプロセスに割り当てられた時間の半分に制限され、メモリー使用量が最大で 1024 MB に限定される可能性があります。また、メンバーとなっている net 内の cgroup によって、転送速度が 30 メガバイト毎秒に制限される場合があります。

図1.3 ルール 3
ルール 4
cpu_and_mem 階層内の half_cpu_1gb_max という名前の cgroup と、net 階層内の trans_rate_30 という cgroup のメンバーである httpd タスクについて検討してください。 この httpd プロセスが自分自身をフォークすると、その子プロセスは自動的に half_cpu_1gb_max cgroup と trans_rate_30 cgroup のメンバーとなり、親タスクが属するのとまったく同じ cgroup を継承します。

図1.4 ルール 4 (丸数字は、タスクがフォークする時間的順序)
1.3. リソース管理に対する影響
- タスクは、単一の階層内では一つの cgroup のみにしか属すことができないため、単一サブシステムによってタスクが制限されたり、影響を受ける状況は一つのみということになります。これは、制限ではなく特長であり、論理にかなっています。
- 単一階層内の全タスクに影響を及ぼすように、複数のサブシステムをまとめてグループ化することができます。その階層内の cgroup には異なるパラメーターが設定されているため、これらのタスクが受ける影響が異なってきます。
- 場合によっては、階層の リファクタリング が必要となることがあります。たとえば、複数のサブシステムが接続された階層からサブシステムを削除したり、新たな別の階層に接続する場合などです。
- 逆に言えば、別個の階層間でサブシステムを分割する必要性が低減した場合には、階層を削除して、そのサブシステムを既存の階層に接続することができるということになります。
- この設計により、
cpuとmemoryのサブシステムのみが接続されているような単一階層内の特定のタスクに対して、いくつかのパラメーターを設定するなど、cgroup の簡易な使用方法が可能となります。 - また、この設計により、高度に特化した構成も可能となり、システム上の各タスク (プロセス) は、単一のサブシステムが接続された各階層のメンバーとすることができます。このような構成では、システム管理者があらゆるタスクの全パラメーターを全面的に管理することができます。
第2章 コントロールグループの使用法
注記
~]# yum install libcgroup2.1. cgconfig サービス
cgconfig サービスは、階層を作成して、サブシステムを階層に接続し、それらの階層内の cgroup を管理するのに便利な方法を提供します。システム上の階層と cgroup の管理には、cgconfig を使用することを推奨します。
cgconfig サービスはデフォルトで起動しません。chkconfig を使用してサービスを起動すると、システムは cgroup の設定ファイル /etc/cgconfig.conf を読み取ります。そのため、cgroup はセッションからセッションへと再作成されて永続化します。cgconfig は、設定ファイルの内容に応じて、階層の作成、必要なファイルシステムのマウント、cgroup の作成、各グループ用のサブシステムパラメーターの設定を行います。
/etc/cgconfig.conf ファイルは、各サブシステム用の個別の階層を作成およびマウントし、それらの階層にサブシステムを接続します。
cgconfig サービスを停止 (service cgconfig stop コマンドを使用) すると、マウントされていたすべての階層がアンマウントされます。
2.1.1. /etc/cgconfig.conf ファイル
/etc/cgconfig.conf ファイルに含まれるエントリには、mount と group の 2 つの主要なタイプがあります。mount エントリは、仮想ファイルシステムとして階層を作成してマウントし、サブシステムをそれらの階層に接続します。mount エントリは、以下のような構文を用いて定義します。
mount {
<controller> = <path>;
…
}
例2.1 mount エントリの作成
cpuset サブシステム用の階層を作成します。
mount {
cpuset = /cgroup/red;
}
~]#mkdir /cgroup/red~]#mount -t cgroup -o cpuset red /cgroup/red
group <name> {
[<permissions>]
<controller> {
<param name> = <param value>;
…
}
…
}
permissions セクションはオプションである点に注意してください。グループエントリのパーミッションを定義するには、以下のような構文を使用します。
perm {
task {
uid = <task user>;
gid = <task group>;
}
admin {
uid = <admin name>;
gid = <admin group>;
}
}
例2.2 group エントリの作成
sqladmin グループ内のユーザーのパーミッションで SQL デーモン用の cgroup を作成し、タスクを cgroup と root ユーザーに追加してサブシステムのパラメーターを変更します。
group daemons/sql {
perm {
task {
uid = root;
gid = sqladmin;
} admin {
uid = root;
gid = root;
}
} cpu {
cpuset.mems = 0;
cpuset.cpus = 0;
}
}
~]#mkdir -p /cgroup/red/daemons/sql~]#chown root:root /cgroup/red/daemons/sql/*~]#chown root:sqladmin /cgroup/red/daemons/sql/tasks~]#echo 0 > /cgroup/red/daemons/sql/cpuset.mems~]#echo 0 > /cgroup/red/daemons/sql/cpuset.cpus
注記
/etc/cgconfig.conf への変更内容を有効にするには、cgconfig を再起動する必要があります。ただし、このサービスを再起動すると、全 cgroup 階層が再構築され、以前に存在していた cgroup (例: libvirtd によって使用される既存の cgroup) はいずれも削除される点に注意してください。cgconfig サービスを再起動するには、以下のコマンドを実行します。
~]# service cgconfig restart/etc/cgconfig.conf に書き込まれます。行頭にハッシュ記号 ('#') が付いている場合、その行はコメントアウトされ、cgconfig サービスには不可視となります。
2.2. 階層の作成とサブシステムの接続
警告
cgconfig サービスを使用して) のシステム上では、最初に既存の階層をアンマウントしておかないと、これらのコマンドは失敗し、システムの操作に影響を及ぼします。実稼働システム上ではこれらの手順を試さないようにしてください。
/etc/cgconfig.conf ファイルの mount セクションを編集します。mount セクションのエントリは、以下のような形式になります。
subsystem = /cgroup/hierarchy;
cgconfig は次回の起動時に、階層を作成し、サブシステムを接続します。
cpu_and_mem という名前の階層を作成し、cpu、cpuset、cpuacct、および memory のサブシステムを接続します。
mount {
cpuset = /cgroup/cpu_and_mem;
cpu = /cgroup/cpu_and_mem;
cpuacct = /cgroup/cpu_and_mem;
memory = /cgroup/cpu_and_mem;
}その他の方法
~]# mkdir /cgroup/name~]# mkdir /cgroup/cpu_and_memmount コマンドを使用して、階層をマウントし、同時に一つまたは複数のサブシステムを接続します。以下はその例です。
~]# mount -t cgroup -o subsystems name /cgroup/name例2.3 mount コマンドを使用したサブシステムの接続
/cgroup/cpu_and_mem という名前のディレクトリがすでに存在しており、作成する階層のマウントポイントとして機能します。cpu、cpuset、および memory のサブシステムを cpu_and_mem という名前の階層に接続し、/cgroup/cpu_and_mem 上の cpu_and_mem 階層に mount します。
~]# mount -t cgroup -o cpu,cpuset,memory cpu_and_mem /cgroup/cpu_and_memlssubsys [3] コマンドを使用します。
~]# lssubsys -am
cpu,cpuset,memory /cgroup/cpu_and_mem
net_cls
ns
cpuacct
devices
freezer
blkiocpu、cpuset、およびmemoryのサブシステムは、/cgroup/cpu_and_memにマウントされた階層に接続されています。net_cls、ns、cpuacct、devices、freezer、およびblkioのサブシステムは、対応するマウントポイントがないことから、まだ、どの階層にも接続されていないことを示しています。
2.3. 既存の階層へのサブシステムの接続と接続解除
/etc/cgconfig.conf ファイルの mount セクションを 「階層の作成とサブシステムの接続」 に記載されているのと同じ構文を用いて編集します。cgconfig は、次回の起動時に、指定した階層にしたがってサブシステムを再編成します。
その他の方法
mount コマンドで、追加するサブシステムと remount オプションを指定します。
例2.4 階層の再マウントとサブシステムの追加
lssubsys コマンドは、cpu_and_mem 階層に接続されている cpu、cpuset、および memory のサブシステムを表示します。
~]# lssubsys -am
cpu,cpuset,memory /cgroup/cpu_and_mem
net_cls
ns
cpuacct
devices
freezer
blkioremount オプションを使用して cpu_and_mem 階層を再マウントし、サブシステムの一覧に cpuacct を追加します。
~]# mount -t cgroup -o remount,cpu,cpuset,cpuacct,memory cpu_and_mem /cgroup/cpu_and_memlssubsys コマンドを実行すると、cpuacct が cpu_and_mem 階層に接続されていると表示されるようになりました。
~]# lssubsys -am
cpu,cpuacct,cpuset,memory /cgroup/cpu_and_mem
net_cls
ns
devices
freezer
blkiocpuacct サブシステムの接続を解除するには、単に再マウントして名前を削除します。
~]# mount -t cgroup -o remount,cpu,cpuset,memory cpu_and_mem /cgroup/cpu_and_mem2.4. 階層の接続解除
umount コマンドを使用します。
~]# umount /cgroup/name~]# umount /cgroup/cpu_and_memcgclear コマンドを使用すると、空でない階層も非アクティブ化することができます — 「コントロールグループのアンロード」 を参照してください。
2.5. コントロールグループの作成
cgcreate コマンドを使用して cgroups を作成します。cgcreate の構文は以下のとおりです。
cgcreate-tuid:gid-auid:gid -g subsystems:path
-t(オプション) は、ユーザー (ユーザー ID、uid) とグループ (グループ ID、gid) を指定して、この cgroup のtasks疑似ファイルを所有するためのオプションです。このユーザーは cgroup にタスクを追加することができます。注記
cgroup からタスクを削除するには、異なる cgroup に移動するのが唯一の手段である点に注意してください。タスクを移動するには、ユーザーは 移動先の cgroup への書き込みアクセスが必要となります。元の cgroup への書き込みアクセスは重要ではありません。-a(オプション) — ユーザー (ユーザー ID、uid) とグループ (グループ ID、gid) を指定して、このcgroup のtasks以外の全疑似ファイルを所有するようにします。このユーザーは cgroup 内のタスクが持つシステムリソースへのアクセスを変更できます。-g— cgroup が作成されるべき階層を、それらの階層に関連付けられる、コンマ区切りの subsystems 一覧として指定します。この一覧内のサブシステムが異なる階層にある場合には、それらの各階層内でグループが作成されます。階層の一覧の後には、コロンならびに階層に対して相対的な子グループへの path が続きます。このパスには、階層のマウントポイントを入れないでください。たとえば、/cgroup/cpu_and_mem/lab1/ディレクトリ内に配置されている cgroup が単にlab1という名前である場合でも、1 つのサブシステムに対して階層は 1 つしかないため、そのパスは既に一意に特定されていることになります。また、グループは、cgroup が作成された階層内に存在する全サブシステムによって制御される点にも注意してください。cgcreateコマンドでこれらのサブシステムが指定されていない場合でも変わりません。例2.5「cgcreate の使用方法」 を参照してください。
例2.5 cgcreate の使用方法
cpu および memory サブシステムが cpu_and_mem 階層に一緒にマウントされており、かつ net_cls コントローラーが net という名前の別の階層にマウントされているシステムを想定して、以下のコマンドを実行します。
~]# cgcreate -g cpu,net_cls:/test-subgroupcgcreate コマンドにより、test-subgroup という名前の 2 つのグループを作成します。一方は、cpu_and_mem 階層に、もう一方は net 階層に入ります。 cgcreate コマンドで指定してなくても、cpu_and_mem 階層内の test-subgroup グループは、 memory サブシステムによって制御されます。
その他の方法
mkdir コマンドを使用します:
~]# mkdir /cgroup/hierarchy/name/child_name~]# mkdir /cgroup/cpuset/lab1/group12.6. コントロールグループの削除
cgdelete で cgroup を削除します。構文は cgcreate と同様です。以下のコマンドを実行してください。
cgdelete subsystems:path
- subsystems は、コンマ区切りのサブシステム一覧です。
- path は、階層の root に対して相対的な cgroup へのパスです。
~]# cgdelete cpu,net_cls:/test-subgroupcgdelete で -r のオプションを使用すると、すべてのサブグループを再帰的に削除することもできます。
2.7. パラメーターのセッティング
cgset コマンドで、サブシステムのパラメーターを設定します。たとえば、/cgroup/cpuset/group1 が存在する場合には、以下のようなコマンドで、このグループがアクセスできる CPU を指定します。
cpuset]# cgset -r cpuset.cpus=0-1 group1cgset の構文は以下のとおりです。
cgset -r parameter=value path_to_cgroup- parameter は設定するパラメーターで、特定の cgroup のディレクトリ内のファイルに対応しています。
- value はパラメーター用の値です
- path_to_cgroup は 階層の root に相対的な cgroup へのパスです。たとえば、root グループのパラメーターを設定するには、(
/cgroup/cpuacct/が存在する場合)、以下のコマンドを実行します。cpuacct]#
cgset -r cpuacct.usage=0 /また、.は root グループ (つまり、root グループ自体) に対して相対的であるため、以下のコマンドを実行することもできます。cpuacct]#
cgset -r cpuacct.usage=0 .ただし、/が推奨の構文である点に注意してください。注記
root グループに設定できるパラメーターはごくわずかです (例: 上記の例に示した、cpuacct.usageパラメーター)。これは、root グループが既存のリソースをすべて所有しており、特定のパラメーター (例:cpuset.cpuパラメーター) を定義することによって既存のプロセスを制限することは意味がないためです。root グループのサブグループであるgroup1のパラメーターを設定するには、以下のコマンドを実行します。cpuacct]#
cgset -r cpuacct.usage=0 group1グループ名の末尾のスラッシュ (例:cpuacct.usage=0 group1/) はオプションです。
cgset で設定できる値は、特定の階層のよりも高いレベルで設定されている値によって左右される可能性があります。たとえば、group1 がシステム上の CPU 0 のみを使用するように制限されている場合、group1/subgroup1 が CPU 0 および 1 を使用するように、もしくは CPU 1 のみを使用するようには設定できません。
cgset を使用して、異なる cgroup からパラメーターをコピーすることもできます。以下はその例です。
~]# cgset --copy-from group1/ group2/cgset を使用してパラメーターをコピーする構文は以下のとおりです。
cgset --copy-from path_to_source_cgroup path_to_target_cgroup- path_to_source_cgroup は、コピーするパラメーターを持つ、その階層の root グループに対して相対的な cgroup へのパスです。
- path_to_target_cgroup は、その階層の root グループに対して相対的な、コピー先 cgroup へのパスです。
その他の方法
echo コマンドを使用して その値を該当するサブシステムの疑似ファイルに書き込みます。たとえば、以下のコマンドは、値 0-1 を cgroup group1 の cpuset.cpus 疑似ファイルに書き込みます。
~]# echo 0-1 > /cgroup/cpuset/group1/cpuset.cpus2.8. コントロールグループへのプロセス移動
cgclassify コマンドを実行して、プロセスを cgroup に移動します。
~]# cgclassify -g cpu,memory:group1 1701cgclassify の構文は以下のとおりです。
cgclassify -g subsystems:path_to_cgroup pidlist- subsystems は、コンマ区切りのサブシステム一覧、または、利用可能なすべてのサブシステムに関連付けられた階層内のプロセスを起動するための
*とします。同じ名前の cgroup が複数の階層に存在する場合には、-gオプションを指定すると、それらの各グループ内にプロセスが移動される点に注意してください。ここで指定するサブシステムの各階層内に cgroup が存在していることを確認してください。 - path_to_cgroup は、その階層内の cgroup へのパスです
- pidlist は、プロセス識別子 (PID) のスペースで区切られた一覧です。
--sticky オプションを追加すると、同じ cgroup 内の任意の子プロセスを維持することもできます。このオプションを設定せず、かつ cgred サービスが稼働中の場合、子プロセスは /etc/cgrules.conf の設定に基づいて cgroup に割り当てられます。そのプロセス自体は、それを起動した cgroup に残ります。
cgclassify を使用すると、いくつかのプロセスを同時に移動することができます。たとえば、以下のコマンドは 1701 と 1138 の PID を持つプロセスを cgroup group1/ に移動します:
~]# cgclassify -g cpu,memory:group1 1701 1138その他の方法
tasks ファイルに 書き込みます。たとえば、PID 1701 の付いたプロセスを /cgroup/lab1/group1/ にある cgroup に 移動する場合は、以下のコマンドを実行します。
~]# echo 1701 > /cgroup/lab1/group1/tasks2.8.1. cgred サービス
/etc/cgrules.conf ファイルに設定されているパラメータセットにしたがってタスクを cgroup に移動するサービスです (このサービスが cgrulesengd デーモンを起動します)。/etc/cgrules.conf ファイル内のエントリは、次の 2 つの形式のいずれかとなります。
- user subsystems control_group
- user:command subsystems control_group
maria devices /usergroup/staff
maria というユーザーに属するプロセスはいずれも /usergroup/staff cgroup 内に指定されたパラメーターにしたがって devices サブシステムにアクセスすることを指定します。特定のコマンドを特定の cgroup に関連付けるには、以下のようにして command パラメーターを追加します。
maria:ftp devices /usergroup/staff/ftp
maria という名前のユーザーが ftp コマンドを使用する時には、devices サブシステムが入っている階層の /usergroup/staff/ftp cgroup へプロセスが自動的に移動するように指定されるようになります。 ただし、このデーモンは、該当する条件が満たされている場合にのみ、プロセスを cgroup に移動する点に注意してください。このため、ftp プロセスが、誤ったグループで短時間実行される可能性があります。また、そのプロセスが誤ったグループ内にある間に子プロセスが急速に発生した場合には、それらは移動されない可能性があります。
/etc/cgrules.conf ファイル内のエントリには、以下のような注記を追加することが可能です。
@— user にプレフィックスを付けた場合には、個別のユーザーではなくグループを示します。 たとえば、@adminsはadminsグループ内のすべてのユーザーです。*— 「すべて」を示します。たとえば、subsystemフィールド内の*は全サブシステムを示します。%— その上の行の項目と同じ項目を示します。以下はその例です。@adminstaff devices /admingroup @labstaff % %
2.9. コントロールグループ内のプロセスの開始
重要
cpuset サブシステムを使用する cgroup にタスクを移動する前には、その cgroup に対して、cpuset.cpus と cpuset.mems のパラメーターを定義する必要があります。
cgexec コマンドを実行して、cgroup 内のプロセスを開始することもできます。たとえば、 以下のコマンドは、そのグループに課せられた制限にしたがって、group1 cgroup 内で lynx Web ブラウザーを起動します。
~]# cgexec -g cpu:group1 lynx http://www.redhat.comcgexec の構文は以下のとおりです。
cgexec -g subsystems:path_to_cgroup command arguments- subsystems は、コンマ区切りのサブシステム一覧、または、利用可能なすべてのサブシステムに関連付けられた階層内のプロセスを起動するための
*とします。「パラメーターのセッティング」 でも説明しているように、同じ名前の cgroup が複数の階層に存在する場合には、-gオプションを指定すると、それらの各グループ内にプロセスが作成される点に注意してください。ここで指定するサブシステムの各階層内に cgroup が存在していることを確認してください。 - path_to_cgroup は、階層に対して相対的な cgroup へのパスです。
- command は実行するコマンドです。
- arguments はそのコマンドの引数です。
-- sticky オプションを追加すると、同じ cgroup の子プロセスを維持することもできます。このオプションを設定しないで cgred が稼働すると、子プロセスは /etc/cgrules.conf にあるセッティングに基づいて cgroup に割り当てられます。しかし、プロセス自体はそれを開始した cgroup 内に残ります。
その他の方法
~]#echo $$ > /cgroup/lab1/group1/tasks~]#lynx
group1 cgroup にあることに注意してください。したがって、より適切な方法は以下のようになります。
~]# sh -c "echo \$$ > /cgroup/lab1/group1/tasks && lynx"2.9.1. コントロールグループ内のサービスの開始
/etc/sysconfig/servicenameファイルを使用する- サービスを起動するのに
/etc/init.d/functionsのdaemon()関数を使用する
/etc/sysconfig 内でそのサービスのファイルを編集して、 CGROUP_DAEMON="subsystem:control_group" の 形式でエントリを追加します。ここで、subsystem は特定の階層に関連付けられたサブシステムであり、 control_group はその階層内の cgroup です。以下はその例です。
CGROUP_DAEMON="cpuset:daemons/sql"
2.9.2. root コントロールグループ内のプロセスの振る舞い
blkio および cpu の特定の設定オプションは、root cgroup 内で実行中のプロセス (タスク) に影響を及ぼします。これは、サブグループ内で実行中のプロセスの場合とは方法が異なります。以下の例を検討してください。
- root グループ下に 2 つのサブグループを作成します:
/rootgroup/red/および/rootgroup/blue/ - 各サブグループおよび root グループで
cpu.shares設定オプションを定義し、1に指定します。
/rootgroup/tasks、/rootgroup/red/tasks、および /rootgroup/blue/tasks に 1 タスク)、CPU を 33.33% 消費します。
/rootgroup/process: 33.33%/rootgroup/blue/process: 33.33%/rootgroup/red/process: 33.33%
blue および red にその他のプロセスを配置すると、その特定のサブグループに割り当てられている 33.33% の CPU は、そのサブグループ内の複数のプロセス間で分割されます。
/rootgroup/ に 3 つのプロセス、/rootgroup/red/ に 1 つのプロセス、/rootgroup/blue/ に 1 つのプロセスがあり、全グループで cpu.shares オプションが 1 に設定されている場合、CPU リソースは以下のように分配されます。
/rootgroup/processes: 20% + 20% + 20%/rootgroup/blue/process: 20%/rootgroup/red/process: 20%
blkio および cpu 設定オプション (例: cpu.shares、blkio.weight など) を使用する場合には、全プロセスを root グループから特定のサブグループに移動することを推奨します。root グループから特定のサブグループに全タスクを移動するには、以下のコマンドを使用することができます。
rootgroup]#cat tasks >> red/tasksrootgroup]#echo > tasks
2.10. /etc/cgconfig.conf ファイルの生成
/etc/cgconfig.conf ファイルの設定は、cgsnapshot ユーティリティを使用して現在の cgroup 設定から生成することができます。このユーティリティは全サブシステムおよびその cgroup の現在の状態のスナップショットを作成し、その設定を /etc/cgconfig.conf ファイルで表示されるのと同じように返します。例2.6「cgsnapshot ユーティリティの使用法」 には、cgsnapshot ユーティリティの使用例を示しています。
例2.6 cgsnapshot ユーティリティの使用法
~]#mkdir /cgroup/cpu~]#mount -t cgroup -o cpu cpu /cgroup/cpu~]#mkdir /cgroup/cpu/lab1~]#mkdir /cgroup/cpu/lab2~]#echo 2 > /cgroup/cpu/lab1/cpu.shares~]#echo 3 > /cgroup/cpu/lab2/cpu.shares~]#echo 5000000 > /cgroup/cpu/lab1/cpu.rt_period_us~]#echo 4000000 > /cgroup/cpu/lab1/cpu.rt_runtime_us~]#mkdir /cgroup/cpuacct~]#mount -t cgroup -o cpuacct cpuacct /cgroup/cpuacct
cpu サブシステムに、一部のパラメーターには特定の値を指定して、2 つのサブシステムがマウントされ、2 つの cgroup が作成されました。cgsnapshot コマンドを (-s オプションおよび空の /etc/cgsnapshot_blacklist.conf ファイル[4] を使用して) 実行すると、以下のような出力が生成されます。
~]$ cgsnapshot -s
# Configuration file generated by cgsnapshot
mount {
cpu = /cgroup/cpu;
cpuacct = /cgroup/cpuacct;
}
group lab2 {
cpu {
cpu.rt_period_us="1000000";
cpu.rt_runtime_us="0";
cpu.shares="3";
}
}
group lab1 {
cpu {
cpu.rt_period_us="5000000";
cpu.rt_runtime_us="4000000";
cpu.shares="2";
}
}
-s オプションは、cgsnapshot に対して、cgsnapshot ユーティリティのブラックリストまたはホワイトリストで定義されていないパラメーターによって生じるすべての警告を無視するように指示します。パラメーターのブラックリスト化についての詳しい情報は 「パラメーターのブラックリスト化」 を参照してください。パラメーターのホワイトリスト化についての詳しい情報は 「パラメーターのホワイトリスト化」 を参照してください。
-f オプションを使用します。以下はその例です。
~]$ cgsnapshot -f ~/test/cgconfig_test.conf警告
-f オプションを使用する際には、指定したファイルの内容がすべて上書きされる点に注意してください。このため、直接 /etc/cgconfig.conf ファイルには出力指定しないことを推奨します。
~]$ cgsnapshot cpuacct
# Configuration file generated by cgsnapshot
mount {
cpuacct = /cgroup/cpuacct;
}
2.10.1. パラメーターのブラックリスト化
/etc/cgsnapshot_blacklist.conf ファイルでブラックリストパラメーターをチェックします。パラメーターがブラックリストに入っていない場合には、ホワイトリストをチェックします。別のブラックリストを指定するには、-b オプションを使用します。以下はその例です。
~]$ cgsnapshot -b ~/test/my_blacklist.conf2.10.2. パラメーターのホワイトリスト化
~]$ cgsnapshot -f ~/test/cgconfig_test.conf
WARNING: variable cpu.rt_period_us is neither blacklisted nor whitelisted
WARNING: variable cpu.rt_runtime_us is neither blacklisted nor whitelisted
-w オプションを使用します。以下はその例です。
~]$ cgsnapshot -w ~/test/my_whitelist.conf-t オプションを指定することにより、cgsnapshot に対してホワイトリストのみからのパラメーターを使用して設定を生成するように指示します。
2.11. コントロールグループに関する情報の取得
2.11.1. プロセスの確認
~]$ ps -O cgroup~]$ cat /proc/PID/cgroup2.11.2. サブシステムの確認
~]$ cat /proc/cgroups~]$ lssubsys -m subsystemslssubsys -m コマンドでは、各階層ごとの最上位のマウントポイントのみが返される点に注意してください。
2.11.3. 階層の確認
/cgroup 下にマウントすることを推奨します。ご使用のシステムがそのようになっていることを前提として、そのディレクトリの内容を一覧表示または閲覧し、階層の一覧を取得します。tree がインストールされている場合には実行して、全階層およびその中の cgroup の概観を確認します。
~]$ tree /cgroup2.11.4. コントロールグループの確認
~]$ lscgroupcontroller:path の形式でコントローラーとパスを指定すると、特定の階層への出力を限定することができます。以下はその例です。
~]$ lscgroup cpuset:adminuserscpuset サブシステムが接続されている階層内の adminusers cgroup のサブグループのみを一覧表示します。
2.11.5. コントロールグループのパラメーターの表示
~]$ cgget -r parameter list_of_cgroups~]$ cgget -r cpuset.cpus -r memory.limit_in_bytes lab1 lab2lab1 および lab2 の cpuset.cpus 値と memory.limit_in_bytes 値を表示します。
~]$ cgget -g cpuset /2.12. コントロールグループのアンロード
警告
cgclear コマンドにより、全階層内のすべての cgroup が破棄されます。これらの階層が設定ファイル内に記載されていない場合は、簡単には再構築できません。
cgclear コマンドを使用します。
注記
mount コマンドを使用して cgroup を作成すると (cgconfig サービスを使用して作成するのではなく) 、/etc/mtab ファイル (マウント済みファイルシステムテーブル) にエントリが作成されます。この変更は、/proc/mounts ファイルにも反映されます。しかし、cgclear コマンドを使用した cgroup のアンロードには、他の cgconfig コマンドと同様に直接のカーネルインターフェースが使用され、その変更は /etc/mtab ファイルに反映されず、新規情報のみが /proc/mounts ファイルに書き込まれます。このため、cgclear コマンドを使用して cgroup をアンロードした後に、マウント解除された cgroup が /etc/mtab で可視状態のままとなって、 mount コマンドを実行すると表示されてしまう場合があります。マウントされている cgroup の正確な一覧は /proc/mounts ファイルを参照してください
2.13. 通知 API の使用
memory.oom_control。通知ハンドラーを作成するには、以下の手順にしたがって、C プログラムを作成します。
eventfd()関数を使用して、イベント通知のファイル記述子を作成します。詳しくは、eventfd(2)の man ページを参照してください。memory.oom_controlファイルをモニタリングするには、open()関数を使用して開きます。詳しくはopen(2)の man ページを参照してください。- モニタリングする
memory.oom_controlファイルの cgroup のcgroup.event_controlファイルに以下の引数を書き込むには、write()関数を使用します。<event_file_descriptor> <OOM_control_file_descriptor>
ここで、cgroup.event_controlファイルを開くには、event_file_descriptor を使用します。- 適切な
memory.oom_controlファイルを開くには、OOM_control_file_descriptor を使用します。
ファイルへの書き込みについての詳しい情報は、write(1)の man ページを参照してください。
memory.oom_control の調節可能なパラメーターについての詳しい情報は、「memory」 を参照してください。OOM 制御の通知設定についての詳しい情報は、例3.3「OOM の制御と通知」 を参照してください。
2.14. その他のリソース
libcgroup の man ページ
man 1 cgclassify—cgclassifyコマンドは、実行中のタスクを単一もしくは複数の cgroup に移動するのに使用します。man 1 cgclear—cgclearコマンドは、一つの階層内のすべての cgroup を削除するのに使用します。man 5 cgconfig.conf— cgroup はcgconfig.confファイル内で定義されます。man 8 cgconfigparser—cgconfigparserコマンドは、cgconfig.confファイルを解析して、階層をマウントします。man 1 cgcreate—cgcreateコマンドは、階層内に新たな cgroup を作成します。man 1 cgdelete—cgdeleteコマンドは、特定の cgroup を削除します。man 1 cgexec—cgexecコマンドは、特定の cgroup 内のタスクを実行します。man 1 cgget—cggetコマンドは、cgroup のパラメーターを表示します。man 1 cgsnapshot— tcgsnapshotコマンドは、既存のサブシステムから設定ファイルを生成します。man 5 cgred.conf—cgred.confは、cgredサービスの設定ファイルです。man 5 cgrules.conf—cgrules.confには、特定の cgroup にタスクが属する場合に判断するためのルールが含まれます。man 8 cgrulesengd—cgrulesengdサービスは、タスクを cgroup に配分します。man 1 cgset—cgsetコマンドは、cgroup のパラメーターを設定します。man 1 lscgroup—lscgroupコマンドは、階層内の cgroup を一覧表示します。man 1 lssubsys—lssubsysコマンドは、特定のサブシステムを含む階層を一覧表示します。
lssubsys コマンドは、libcgroup パッケージによって提供されるユーティリティの一つです。これを使用するには、libcgroup をインストールする必要があります。lssubsys を実行できない場合には、2章コントロールグループの使用法 を参照してください。
第3章 サブシステムと調整可能なパラメーター
/usr/share/doc/kernel-doc-kernel-version/Documentation/cgroups/ にインストールされているカーネルのドキュメント cgroups.txt (kernel-doc パッケージにより提供) に記載されています。cgroup に関するドキュメントの最新バージョンは、オンラインでもご覧いただけます: http://www.kernel.org/doc/Documentation/cgroups/cgroups.txt。ただし、最新版のドキュメントに記載されている機能は、ご使用のシステムにインストールされているカーネルで利用可能な機能と一致しない場合がある点に注意してください。
cpuset.cpus は、cgroup によるアクセスが許可されている CPU を指定する疑似ファイルです。システム上で稼働する Web サーバー用の cgroup が /dev/cgroup/webserver/ である場合には、以下のコマンドを実行してください。
~]# echo 0,2 > /cgroup/cpuset/webserver/cpuset.cpus0,2 の値を cpuset.cpus 疑似ファイルに書き込むことにより、/cgroup/cpuset/webserver/tasks に記載されている PID のタスクがシステム上の CPU 0 と CPU 2 のみを使用するように限定します。
3.1. blkio
blkio) サブシステムは、cgroup 内のタスクによる、ブロックデバイス上の I/O へのアクセスを制御・監視します。これらの疑似ファイルに値を書き込むと、アクセスまたは帯域幅が限定され、またこれらの疑似ファイルから値を読み取ると、I/O 操作についての情報が提供されます。
blkio サブシステムは I/O へのアクセスを制御する 2 つのポリシーを提供します。
- 重み付け比例配分 — Completely Fair Queuing I/O スケジューラーに実装されているこのポリシーにより、特定の cgroup にウェイトを設定することができます。これは、各 cgroup に、全予約済み I/O 操作に対する一定の割合が (その cgroup のウェイト応じて) 設定されることを意味します。詳しい情報は 「重み付け比例配分の調整可能なパラメーター」 を参照してください。
- I/O スロットリング (上限) — このポリシーは、特定のデバイスが実行する I/O 操作数の上限を設定するのに使用します。これは、デバイスの 読み取り または 書き込み 操作の速度を制限できることを意味します。詳しくは 「I/O スロットリングの調整可能なパラメーター」 を参照してください。
重要
3.1.1. 重み付け比例配分の調整可能なパラメーター
- blkio.weight
- デフォルトで cgroup に提供される ブロック I/O アクセスの相対的比率 (ウェイト) を
100から1000の範囲内で指定します。この値は、blkio.weight_deviceパラメーターを使用すると、特定のデバイスでオーバーライドされます。たとえば、ブロックデバイスにアクセスするためのデフォルトのウェイト500を cgroup に割り当てるには、以下のコマンドを実行します。echo 500 > blkio.weight - blkio.weight_device
- cgroup に提供される特定のデバイス上の I/O アクセスの相対的比率 (ウェイト) を
100から1000の範囲内で指定します。このパラメーターの値は、指定したデバイスのblkio.weightパラメーターの値を上書きします。これらの値は、major:minor weight の形式を取り、major と minor は、http://www.kernel.org/doc/Documentation/devices.txt から入手可能な 『Linux Allocated Devices』 (別名 『Linux Devices List』) で指定されているデバイスタイプとノード番号となります。たとえば、cgroup による/dev/sdaへのアクセスに500のウェイトを割り当てるには、以下のコマンドを実行します。echo 8:0 500 > blkio.weight_device『Linux Allocated Devices』 の表記では、8:0は/dev/sdaを示します。
3.1.2. I/O スロットリングの調整可能なパラメーター
- blkio.throttle.read_bps_device
- デバイスが実行できる 読み取り 操作数の上限を指定します。読み取り 操作の速度はバイト毎秒単位で指定します。エントリは major、minor、および bytes_per_second の 3 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。また bytes_per_second は、読み込み 操作を実行できる速度の上限です。たとえば、
/dev/sdaデバイスが最大 10 MBps で 読み取り 操作を実行できるようにするには、以下のコマンドを実行します。~]#
echo "8:0 10485760" > /cgroup/blkio/test/blkio.throttle.read_bps_device - blkio.throttle.read_iops_device
- デバイスが実行できる 読み取り 操作数の上限を指定します。読み取り 操作は毎秒の操作数で指定します。エントリは、major、minor、および operations_per_second の 3 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。また operations_per_second は 読み取り 操作を実行できる速度の上限です。たとえば、
/dev/sdaデバイスが最大 10 回の 読み取り 操作を実行できるようにするには、以下のコマンドを実行します。~]#
echo "8:0 10" > /cgroup/blkio/test/blkio.throttle.read_iops_device - blkio.throttle.write_bps_device
- デバイスが実行できる 書き込み 操作数の上限を指定します。書き込み 操作の速度はバイト毎秒単位で指定します。エントリは major、minor、および bytes_per_second の 3 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。また bytes_per_second は、書き込み 操作を実行できる速度の上限です。たとえば、
/dev/sdaデバイスが最大 10 MBps で 書き込み 操作を実行できるようにするには、以下のコマンドを実行します。~]#
echo "8:0 10485760" > /cgroup/blkio/test/blkio.throttle.write_bps_device - blkio.throttle.write_iops_device
- デバイスが実行できる 書き込み 操作数の上限を指定します。書き込み 操作の速度は、毎秒の操作数で指定します。エントリは、major、minor、および operations_per_second の 3 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。また operations_per_second は、書き込み 操作を実行できる速度の上限です。たとえば、
/dev/sdaデバイスが 書き込み 操作を最大で毎秒 10 回実行できるようにするには、以下のコマンドを実行します。~]#
echo "8:0 10" > /cgroup/blkio/test/blkio.throttle.write_iops_device - blkio.throttle.io_serviced
- スロットリングのポリシーに認識されるように、特定のデバイス上で cgroup により実行された I/O 操作の回数をレポートします。エントリは major、minor、operation、および number の 4 つのフィールドで構成されます。major と minor は 『Linux Allocated Devices』 で指定されているデバイスタイプとノード数で、operation は操作のタイプ (
read、write、sync、またはasync)、number は操作回数を示します。 - blkio.throttle.io_service_bytes
- cgroup により、特定のデバイスとの間で転送されたバイト数をレポートします。
blkio.io_service_bytesとblkio.throttle.io_service_bytesの唯一の相違点は、前者の場合 CFQ スケジューラーが要求キューで稼働している時には更新されない点です。エントリは major、minor、operation、および bytes の 4 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。また operation は操作のタイプ (read、write、sync、またはasync)、bytes は転送されるバイト数を示します。
3.1.3. blkio 共通の調整可能なパラメーター
- blkio.reset_stats
- その他の疑似ファイルに記録されている統計をリセットします。この cgroup の統計をリセットするには、このファイルに整数を書き込みます。
- blkio.time
- cgroup が特定のデバイスに I/O アクセスを行った時間をレポートします。エントリは、major、minor、および time の 3 つのフィールドで構成されます。major と minor は 『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号、また time はミリ秒 (ms) 単位の時間です。
- blkio.sectors
- cgroup により、特定のデバイスとの間で転送されたセクターの数をレポートします。エントリは、major、minor、および sectors の 3 つのフィールドで構成されます。major と minor は 『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号、また sectors はセクター数です。
- blkio.avg_queue_size
- グループ存在の全時間にわたる、cgroup による I/O 操作の平均キューサイズをレポートします。キューサイズは、この cgroup がタイムスライスを取得する度にサンプリングされます。このレポートは、システム上で
CONFIG_DEBUG_BLK_CGROUP=yが設定されている場合のみ利用可能である点に注意してください。 - blkio.group_wait_time
- cgroup が一つのキューで費した待ち時間の合計を (ナノ秒単位 — ns で) レポートします。レポートは、この cgroup がタイムスライスを取得する度に更新されるので、cgroup がタイムスライスを待っている間にこの疑似ファイルを読んだ場合には、現在キューに入っている操作を待つのに費した時間は含まれません。このレポートは、システム上で
CONFIG_DEBUG_BLK_CGROUP=yが設定されている場合のみ利用可能である点に注意してください。 - blkio.empty_time
- cgroup が保留中の要求なしに費した時間の合計を (ナノ秒単位 — ns で) レポートします。レポートは、保留中の要求がこの cgroup のキューに入る度に更新されるので、cgroup に保留中の要求がない時に疑似ファイルを読んだ場合には、現在の空の状態で費した時間はレポートには含まれません。このレポートは、システム上で
CONFIG_DEBUG_BLK_CGROUP=yが設定されている場合のみ利用可能である点に注意してください。 - blkio.idle_time
- すでにキューに入っている別の要求や別のグループからの要求よりも高い要求に備えて、cgroup に対してスケジューラーがアイドリング状態で費した時間の合計を (ナノ秒単位 — ns で) レポートします。レポートは、グループがアイドリング状態でなくなった時点で毎回更新されるため、cgroup がアイドリング状態の間にこの疑似ファイルを読み込んだ場合には、最新のアイドリング状態で費した時間はレポートには含まれません。このレポートは、システム上で
CONFIG_DEBUG_BLK_CGROUP=yが設定されている場合のみ利用可能である点に注意してください。 - blkio.dequeue
- cgroup による I/O 操作の要求がキューから削除された回数をデバイス別にレポートします。エントリは、major、minor、および number の 3 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。number は、グループがキューから削除された要求の回数です。このレポートは、システム上で
CONFIG_DEBUG_BLK_CGROUP=yが設定されている場合のみ利用可能である点に注意してください。 - blkio.io_serviced
- CFS スケジューラーに認識されるように、cgroup により特定のデバイス上で実行された I/O 操作の回数をレポートします。エントリは major、minor、operation、および number の 4 つのフィールドで構成されます。major と minor は 『Linux Allocated Devices』 で指定されているデバイスタイプとノード数で、operation は操作のタイプ (
read、write、sync、またはasync)、number は操作回数を示します。 - blkio.io_service_bytes
- CFQ スケジューラーに認識されるように、cgroup により特定のデバイスとの間で転送されたバイト数をレポートします。エントリは、major、minor、operation、および bytes の 4 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。operation は操作のタイプ (
read、write、sync、またはasync)、bytes は転送されたバイト数を示します。 - blkio.io_service_time
- CFQ スケジューラーに認識されるように、cgroup により特定のデバイス上で行われる I/O 操作の要求がディスパッチされてから完了するまでの合計時間をレポートします。エントリは、major、minor、operation、および time の 4 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。operation は操作のタイプ (
read、write、sync、またはasync)、time は時間をナノ秒 (ns) 単位で示します。時間は、大きな単位ではなく、ナノ秒単位でレポートされるため、ソリッドステートのデバイスでもレポートが有意となります。 - blkio.io_wait_time
- スケジューラーキュー内のサービスを待つのに費した、cgroup による 特定のデバイス上の I/O 操作の合計時間をレポートします。このレポートを解析する際には、以下の点に注意してください。
- レポートされる時間は、cgroup 自体が I/O 操作を待つのに費した時間ではなく、cgroup の全 I/O 操作の累計であるため、経過時間の合計よりも長い場合があります。グループ全体として費した待ち時間を確認するには、
blkio.group_wait_timeパラメーターを使用します。 - デバイスに
queue_depth> 1 がある場合は、レポートされる時間には、デバイスが要求を並べ替える間に費した待ち時間ではなく、要求がデバイスにディスパッチされるまでの時間のみが含まれます。
エントリは、major、minor、operation、および time の 4 つのフィールドで構成されます。major と minor は、『Linux Allocated Devices』 で指定されているデバイスタイプとノード番号です。operation は操作のタイプ (read、write、sync、またはasync)、time はナノ秒 (ns) 単位の時間を示します。時間は、大きな単位ではなく、ナノ秒単位でレポートされるため、ソリッドステートのデバイスでもレポートが有意となります。 - blkio.io_merged
- cgroup により、I/O 操作要求にマージされた、BIOS 要求数をレポートします。エントリは number と operation の 2 つのフィールドで構成されます。number は、要求数、operation は操作のタイプ (
read、write、sync、またはasync) を示します。 - blkio.io_queued
- cgroupt により、I/O 操作のキューに入れられた要求の数をレポートします。エントリは、number と operation の 2 つのフィールドで構成されます。number は、要求数、operation は操作のタイプ (
read、write、sync、またはasync) を示します。
3.1.4. 使用例
blkio.weight 値を使用して 2 つの異なる cgroup で 2 つの dd スレッドを実行する簡易テストについては、例3.1「blkio の重み付け比例配分」 を参照してください。
例3.1 blkio の重み付け比例配分
blkioサブシステムをマウントします。~]#
mount -t cgroup -o blkio blkio /cgroup/blkio/blkioサブシステム用に 2 つの cgroup を作成します。~]#
mkdir /cgroup/blkio/test1/~]#mkdir /cgroup/blkio/test2/- あらかじめ作成した cgroup に別々の
blkioウェイトを設定します。~]#
echo 1000 > /cgroup/blkio/test1/blkio.weight~]#echo 500 > /cgroup/blkio/test2/blkio.weight - 大容量ファイルを 2 つ作成します。
~]#
dd if=/dev/zero of=file_1 bs=1M count=4000~]#dd if=/dev/zero of=file_2 bs=1M count=4000上記のコマンドにより、サイズが 4 GB のファイルが 2 つ (file_1およびfile_2) 作成されます。 - 各テスト cgroup で、1 つの大容量ファイルに対して
ddコマンド (ファイルの内容を読み取り、null デバイスに出力するコマンド) を実行します。~]#
cgexec -g blkio:test1 time dd if=file_1 of=/dev/null~]#cgexec -g blkio:test2 time dd if=file_2 of=/dev/nullこれらのコマンドはいずれも、完了すると完了時間を出力します。 - iotop ユーティリティを使用すると、実行中の 2 つの
ddスレッドと同時に、リアルタイムでパフォーマンスを管理することができます。iotop ユーティリティをインストールするには、root としてyum install iotopのコマンドを実行します。 以下は、前に起動したddスレッドの実行中に iotop ユーティリティで表示される出力の例です。Total DISK READ: 83.16 M/s | Total DISK WRITE: 0.00 B/s TIME TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND 15:18:04 15071 be/4 root 27.64 M/s 0.00 B/s 0.00 % 92.30 % dd if=file_2 of=/dev/null 15:18:04 15069 be/4 root 55.52 M/s 0.00 B/s 0.00 % 88.48 % dd if=file_1 of=/dev/null
dd コマンドを実行する前に以下のコマンドを実行して、すべてのファイルシステムのバッファーをフラッシュし、ページキャッシュ、デントリ、inode を解放しておきます。
~]#sync~]#echo 3 > /proc/sys/vm/drop_caches
~]# echo 1 > /sys/block/<disk_device>/queue/iosched/group_isolationsda)。
3.2. cpu
cpu サブシステムは cgroup への CPU アクセスをスケジュールします。CPU リソースへのアクセスは、次の 2 つのスケジューラーを使用してスケジュールすることができます。
- Completely Fair Scheduler (CFS) — タスクの優先度/ウェイトや cgroup に割り当てられている割合に応じて、タスクグループ (cgroup) 間で CPU 時間 (CPU 帯域幅) を比例配分するプロポーショナルシェアスケジューラー。CFS を使用したリソース制限についての詳しい情報は 「CFS の調整可能なパラメーター」 を参照してください。
- リアルタイムスケジューラー (RT) — リアルタイムのタスクが使用できる CPU 時間を指定する方法を提供するタスクスケジューラー。リアルタイムのタスクのリソース制限についての詳しい情報は、「RT の調整可能なパラメーター」 を参照してください。
3.2.1. CFS の調整可能なパラメーター
上限の適用の調整可能なパラメーター
- cpu.cfs_period_us
- cgroup による CPU リソースへのアクセスを再割り当てする一定間隔をマイクロ秒単位 (µs、ただしここでは "
us" と表示) で指定します。cgroup 内のタスクが 1 秒あたり 0.2 秒間、単一の CPU にアクセスできる必要がある場合には、cpu.cfs_quota_usを200000に、cpu.cfs_period_usを1000000に設定してください。cpu.cfs_quota_usパラメーターの上限は 1 秒、下限は 1000 マイクロ秒です。 - cpu.cfs_quota_us
- cgroup 内の全タスクが (
cpu.cfs_period_usで定義された) 一定の期間に実行される合計時間をマイクロ秒単位 (µs、ただしここでは "us" と表示) で指定します。クォータによって指定された時間を cgroup 内のタスクがすべて使い切ってしまうと、その期間により指定されている残りの時間はタスクがスロットリングされ、次の期間まで実行を許可されなくなります。cgroup 内のタスクが 1 秒あたり 0.2 秒間、単一の CPU にアクセスできる必要がある場合にはcpu.cfs_quota_usを200000に、cpu.cfs_period_usを1000000に設定します。クォータおよび期間のパラメーターは CPU ベースで動作する点に注意してください。プロセスが 2 つの CPU を完全に使用できるようにするには、たとえば、cpu.cfs_quota_usを200000に、cpu.cfs_period_usを100000に設定します。cpu.cfs_quota_usの値を-1に設定すると、cgroup が CPU 時間制限を順守しないことを示します。これは、全 cgroup のデフォルト値でもあります (root cgroup は除く)。 - cpu.stat
- 以下の値を使用して、CPU 時間の統計をレポートします。
nr_periods— 経過済みの期間間隔の数 (cpu.cfs_period_usで指定されている)nr_throttled— cgroup 内のタスクがスロットリングされた回数 (クォータによって指定された利用可能な時間をすべて使い果たしたため、実行することができない)throttled_time— cgroup 内のタスクがスロットリングされた合計時間 (ナノ秒単位)
相対的配分の調整可能なパラメーター
- cpu.shares
- cgroup 内のタスクで使用できる CPU 時間の相対的配分を指定する整数値を含みます。たとえば、
cpu.sharesが100に設定された 2 つの cgroup のタスクには同等の CPU 時間が提供されますが、cpu.sharesが200に設定された cgroup のタスクには、cpu.sharesが100に設定された cgroup のタスクの 2 倍の CPU 時間が提供されます。cpu.sharesファイルで指定する値は、2以上とする必要があります。CPU 時間の配分は、マルチコアシステム上の全 CPU コアを対象に分配されることに注意してください。マルチコアシステムで cgroup の上限が CPU の 100% に設定されている場合、各 CPU コアの 100% を使用できるということになります。次の例を検討してください: cgroupAが CPU の 25%、cgroupBが CPU の 75% を使用するように設定されている場合、4 コアのシステムで CPU を集中的に使用するプロセスを起動すると (Aで 1 プロセス、Bで 3 プロセス)、CPU 配分は以下のように分配されます。表3.1 CPU 配分の分配
PID cgroup CPU CPU 配分 100 A 0 CPU0 の 100% 101 B 1 CPU1 の 100% 102 B 2 CPU2 の 100% 103 B 3 CPU3 の 100% 相対的配分を使用して CPU アクセスを指定する場合に考慮する必要のあるリソース管理への影響は以下の 2 点です。- CFS は同等の CPU 使用率を要求しないので、cgroup が消費できる CPU 時間を予測するのは困難です。1 つの cgroup 内のタスクがアイドル状態で CPU 時間を全く消費していない場合、その残り時間は未使用 CPU サイクルのグローバルプールに収集されます。他の cgroup は、このプールから CPU サイクルを借りることができます。
- cgroup が使用できる実際の CPU 時間は、システムに存在する cgroup の数によって異なります。cgroup の相対的配分が
1000に設定され、かつ他の 2 つの cgroup の相対的配分が500に設定されている場合、全 cgroup 内のプロセスが CPU の 100% の使用を試みると、最初の cgroup に全 CPU 時間の 50% が割り当てられます。しかし、1000の相対的配分が設定された別のグループが追加されると、 最初の cgroup は CPU の 33% しか使用できなくなります (残りの cgroup は、CPU の 16.5%、16.5%、33% となります)。
3.2.2. RT の調整可能なパラメーター
- cpu.rt_period_us
- リアルタイムスケジューリングのタスクにのみで使用できます。このパラメーターは、cgroup による CPU リソースへのアクセスを再割り当てする一定間隔をマイクロ秒単位 (µs、ただしここでは "
us" と表示) で指定します。cgroup 内のタスクが 1 秒あたり 0.2 秒間、単一の CPU にアクセスできる必要がある場合には、cpu.rt_runtime_usを200000に、cpu.rt_period_usを1000000に設定してください。 - cpu.rt_runtime_us
- リアルタイムスケジューリングのタスクのみに適用されます。cgroup 内のタスクによる CPU リソースへのアクセスの最長連続時間をマイクロ秒(µs、ただしここでは "
us" と表示)で指定します。この上限を設定することにより、cgroup 内のタスクが CPU 時間を独占できないようにします。cgroup 内のタスクが 1 秒あたり 0.2 秒間、単一の CPU にアクセスできるようにする必要がある場合は、cpu.rt_runtime_usを200000、cpu.rt_period_usを1000000に設定します。ランタイムおよび時間のパラメーターは CPU ベースで動作する点に注意してください。リアルタイムのタスクが 2 つの CPU を完全に使用できるようにするには、たとえばcpu.cfs_quota_usを200000に、cpu.cfs_period_usを100000に設定します。
3.2.3. 使用例
例3.2 CPU アクセスの制限
cpu サブシステムがシステム上にマウントされていることを前提としています。
- 1 つの cgroup が単一の CPU の 25% を使用し、別の cgroup が 同じ CPU の 75% を使用できるようにするには、以下のコマンドを実行します。
~]#
echo 250 > /cgroup/cpu/blue/cpu.shares~]#echo 750 > /cgroup/cpu/red/cpu.shares - cgroup が単一の CPU を完全に使用するように制限するには、以下のコマンドを実行します。
~]#
echo 10000 > /cgroup/cpu/red/cpu.cfs_quota_us~]#echo 10000 > /cgroup/cpu/red/cpu.cfs_period_us - cgroup が単一の CPU の 10 % を使用するように制限するには、以下のコマンドを実行します。
~]#
echo 10000 > /cgroup/cpu/red/cpu.cfs_quota_us~]#echo 100000 > /cgroup/cpu/red/cpu.cfs_period_us - マルチコアシステムで cgroup が 2 つの CPU コアを完全に使用できるようにするには、以下のコマンドを実行します。
~]#
echo 200000 > /cgroup/cpu/red/cpu.cfs_quota_us~]#echo 100000 > /cgroup/cpu/red/cpu.cfs_period_us
3.3. cpuacct
cpuacct) サブシステムは、cgroup 内のタスクで使用される CPU リソースに関する自動レポートを生成します。3 つのレポートが利用できます:
- cpuacct.usage
- この cgroup 内の全タスク (下位階層のタスクを含む) により消費される総 CPU 時間 (ナノ秒単位) をレポートします。
注記
cpuacct.usageの値をリセットするには、以下のコマンドを実行します。~]#
echo 0 > /cgroup/cpuacct/cpuacct.usage上記のコマンドは、cpuacct.usage_percpuの値もリセットします。 - cpuacct.stat
- この cgroup 内の全タスク (下位階層のタスクを含む) により消費されている CPU 時間を、以下のような形でユーザーとシステムにレポートします。
user— ユーザーモード内のタスクによって消費されている CPU 時間system— システム (カーネル) モードのタスクによって消費されている CPU 時間
CPU 時間は、USER_HZ変数によって定義されている単位でレポートされます。 - cpuacct.usage_percpu
- この cgroup 内の全タスク (下位階層のタスクを含む) により、各 CPU 上で消費される CPU 時間 (ナノ秒単位) をレポートします
3.4. cpuset
cpuset サブシステムは、個別の CPU とメモリーノードを cgroup に割り当てます。各 cpuset は、以下のパラメーターにしたがって、それぞれを cgroup 仮想ファイルシステム内の別々の 疑似ファイル 内で指定することができます。
重要
cpuset を使用する cgroup にタスクを cgroup に移動する前に、その cgroup に対して cpuset.cpus と cpuset.mems のパラメーターを定義しておく必要があります。
- cpuset.cpus (必須)
- cgroup 内のタスクがアクセスを許可される CPU を指定します。これは ASCII 形式のコンマ区切りの一覧で、ダッシュ ("
-") はその範囲を示します。以下はその例です。0-2,16
これは、CPU 0、1、2、および 16 を示します。 - cpuset.mems (必須)
- この cgroup 内のタスクがアクセスを許可されるメモリーを指定します。これは ASCII 形式のコンマ区切りの一覧で、ダッシュ ("
-") は範囲を示します。以下はその例です。0-2,16
これは、メモリーノード 0、1、2、および 16 を示します。 - cpuset.memory_migrate
cpuset.mems内の値が変更された場合に、メモリー内のページが新規ノードに移行すべきかどうかを指定するフラグ (0または1) が含まれます。デフォルトでは、メモリー移行は無効 (0) になっており、元のノードがcpuset.memsに指定されているノードの1つでなくなっても、ページは最初に割り当てられたノードに残ります。有効 (1) にすると場合、システムはcpuset.memsにより指定された新規のパラメーター内のメモリーノードにページを移行します。また、可能な場合には、それらの相対的配置を維持します。たとえば、最初にcpuset.memsで指定されていた一覧の第 2 のノードにあるページは、この場所が使用可能な場合には、cpuset.memsで今回指定された一覧の第 2 のノードに割り当てられます。- cpuset.cpu_exclusive
- 他の cpuset がこの cpuset 用に指定された CPU を共有できるかどうかを指定するフラグ (
0または1) が含まれます。デフォルト (0) では、CPU は 1つの cpuset 専用には割り当てられません。 - cpuset.mem_exclusive
- この cpuset 用に指定されたメモリーノードを他の cpuset が共有できるかどうかを指定するフラグ (
0または1) が含まれます。デフォルト (0) では、メモリーノードは1つの cpuset 専用には割り当てられません。cpuset 専用にメモリーノードを確保 (1) することは、cpuset.mem_hardwallパラメーターを使用してメモリーのハードウォールを有効にすることと機能的に同じです。 - cpuset.mem_hardwall
- メモリーページとバッファーデータのカーネル割り当てが、この cpuset 用に指定されたメモリーノードに制限されるべきかどうかを指定するフラグ (
0または1) が含まれます。デフォルト (0) では、ページと バッファーデータは複数ユーザーに属するプロセス全体にわたって共有されます。ハードウォールが有効 (1) になっていると 各タスクのユーザー割り当ては別々に維持できます。 - cpuset.memory_pressure
- この cpuset 内のプロセスによって発生した メモリー負荷 の累積平均を含む読み取り専用のファイルです。
cpuset.memory_pressure_enabledが有効化されている場合、この疑似ファイル内の値は自動的に更新されます。そうでない場合、疑似ファイルには、値0が含まれます。 - cpuset.memory_pressure_enabled
- この cgroup 内のプロセスによって発生した メモリー負荷 をシステムが計算すべきかどうかを指定するフラグ (
0または1) が含まれます。計算された値はcpuset.memory_pressureに出力されて、プロセスが使用中のメモリーの解放を試みるレートを示します。これは、1 秒あたりのメモリー再生試行回数に 1000 を乗じた整数値としてレポートされます。 - cpuset.memory_spread_page
- この cpuset に割り当てられたメモリーノード全体にわたってファイルシステムバッファーを均等に分散すべきかどうかを指定するフラグ (
0または1) が含まれます。デフォルト (0) では、これらの バッファー用にメモリーページを均等に分散しようとする試みはなく、バッファーはそれを作成したプロセスを実行しているのと同じノードに配置されます。 - cpuset.memory_spread_slab
- ファイルの入力/出力演算用のカーネルスラブキャッシュが cpuset 全体に均等に分散されるべきかどうかを指定するフラグ (
0または1) が含まれます。デフォルト (0) では、カーネルスラブキャッシュを均等に分散しようとする試みはなく、スラブキャッシュはそれを作成したプロセスを実行しているのと同じノード上に配置されます。 - cpuset.sched_load_balance
- カーネルがこの cpuset 内の CPU 全体にわたって負荷を分散するかどうかを指定するフラグ (
0または1) が含まれます。デフォルト (1) では、カーネルは過負荷状態の CPU から、使用頻度のより低い CPU へ プロセスを移動して負荷を分散します。ただし、いずれかの親 cgroup でロードバランシングが有効化されている場合には、ロードバランシングがより高いレベルで既に実行されていることになるため、cgroup 内におけるこのフラグの設定は、無効となる点に注意してください。したがって、cgroup 内でロードバランシングを無効にするには、その階層内の各親 cgroup でもロードバランシングを無効にしてください。この場合には、対象となる cgroup の兄弟のロードバランシングも無効にすべきかどうかも検討すべきです。 - cpuset.sched_relax_domain_level
-1から小さい正の値までの間の整数が含まれます。これはカーネルが負荷を分散するために試行すべき CPU の範囲の幅を示します。cpuset.sched_load_balanceが無効になっている場合には、この値は意味がありません。この値の正確な効果はシステムアーキテクチャーに応じて変化しますが、以下の値が標準的です:cpuset.sched_relax_domain_level の値値 効果 -1ロードバランシングにシステムデフォルト値を使用 0ロードバランシングを即実行せず、定期的に負荷を分散 1同じコア上のスレッド全体にわたって、ロードバランシングを即実行 2同じパッケージ内のコア全体にわたって、ロードバランシングを即実行 3同じノードまたはブレード上の CPU 全体にわたって、ロードバランシングを即実行 4NUMA (非均等メモリーアクセス) を使用するアーキテクチャー上のいくつかの CPU にわたって、ロードバランシングを即実行 5NUMA を使用するアーキテクチャー上の全 CPU にわたって、ロードバランシングを即実行
3.5. devices
devices サブシステムは、cgroup 内のタスクによるデバイスへのアクセスを許可または拒否します。
重要
devices) サブシステムはテクノロジープレビュー扱いとなります。
- devices.allow
- cgroup 内のタスクがアクセスをするデバイスを指定します。エントリは type、major、minor、および access の 4 つのフィールドで構成されます。type、major、および minor のフィールドに使用される値は、http://www.kernel.org/doc/Documentation/devices.txt に掲載の 『Linux Allocated Devices』 (別名 『Linux Devices List』) で指定されているデバイスタイプ、ノード番号に対応します。
- type
- type は以下の 3 つの値のいずれか 1 つを取ります。
a— 文字デバイス と ブロックデバイス の両方を併せた全デバイスに適用しますb— ブロックデバイスを指定しますc— 文字デバイスを指定します
- major, minor
- major と minor は、『Linux Allocated Devices』 で指定されているデバイスノード番号です。メジャー(major) とマイナー(minor)番号はコロンで区切られます。たとえば、
8は、SCSI ディスクドライブを指定するメジャー番号であり、マイナー番号1は第 1 の SCSI ディスクドライブ上の第 1 のパーティションを指定します。したがって、8:1は、このパーティションを完全に指定し、/dev/sda1の ファイルシステムの場所に相当します。*は、すべてのメジャーまたはマイナーデバイスノードを表します。たとえば、9:*(全 RAID デバイス) または*:*(全デバイス) というように表示します。 - access
- access は、以下の文字 (単一または複数) からなるシーケンスです。
r— タスクによる指定デバイスの読み取りを許可しますw— タスクによる指定デバイスへの書き込みを許可しますm— タスクによる、まだ存在していないデバイスファイルの作成を許可します
たとえば、access がrと指定されている時は、タスクは指定デバイスから読み取るだけですが、 access がrwと指定されていると、タスクはデバイスからの読み取りとデバイスへの書き込みができます。
- devices.deny
- cgroup 内のタスクがアクセスできないデバイスを指定します。エントリの構文は
devices.allowと全く同じです。 - devices.list
- この cgroup 内のタスクによるアクセス制御が設定されている対象デバイスをレポートします。
3.6. freezer
freezer サブシステムは cgroup 内のタスクを一時停止あるいは再開します。
- freezer.state
freezer.stateは root 以外の cgroup でのみ使用することができます。設定可能な値は以下の 3 つです。FROZEN— cgroup 内のタスクは一時停止しています。FREEZING— システムが cgroup 内のタスクを一時停止している最中です。THAWED— cgroup 内のタスクが再開しています。
freezerサブシステムが接続された階層内の cgroup にそのプロセスを移動します。- 特定の cgroup をフリーズさせて、その中に含まれるプロセスを一時停止します。
FROZEN と THAWED の値は freezer.state に書き込むことができますが、FREEZING の書き込みは出来ず、読み取りのみが可能である点に注意してください。
3.7. memory
memory サブシステムは、cgroup 内のタスクによって使用されるメモリーリソースの自動レポートを生成し、他のタスクによるメモリー使用の上限を設定します。
- memory.stat
- 以下の表に記載した、広範囲なメモリーの統計をレポートします。
表3.2 memory.stat によりレポートされる値
統計 説明 cachetmpfs(shmem) を含むページキャッシュ (バイト単位)rsstmpfs(shmem) を含まない匿名のスワップキャッシュ (バイト単位)mapped_filetmpfs(shmem) を含むメモリーマップドファイルのサイズ (バイト単位)pgpginメモリー内へページされたページ数 pgpgoutメモリーからページアウトされたページ数 swapスワップの使用量 (バイト単位) active_anontmpfs(shmem) を含む、アクティブな最長時間未使用 (LRU) 一覧上の匿名のスワップキャッシュ (バイト単位)inactive_anontmpfs(shmem) を含む、非アクティブ LRU 一覧上の匿名のスワップキャッシュ (バイト単位)active_fileアクティブ LRU 一覧にある、ファイルと関連づけされたメモリー (バイト単位) inactive_file非アクティブ LRU 一覧にある、ファイルに関連付けされたメモリー (バイト) unevictable再生不可のメモリー (バイト単位) hierarchical_memory_limitmemorycgroup が含まれる階層のメモリー制限 (バイト単位)hierarchical_memsw_limitmemorycgroup が含まれる階層のメモリーとスワップの制限 (バイト単位)また、これらのファイルの中で、hierarchical_memory_limitおよびhierarchical_memsw_limit以外のファイルには、それぞれ、total_というプレフィックスの付いた対応ファイルがあり、cgroup についてだけでなく、その子グループについてもレポートします。たとえば、swapは cgroup によるスワップの使用量をレポートし、total_swapは cgroup とその子グループによるスワップの使用量をレポートします。memory.statによってレポートされた値を解析する際には、さまざま統計が相互に関連している点に注意してください。active_anon+inactive_anon= 匿名メモリー +tmpfsのファイルキャッシュ + スワップキャッシュしたがって、active_anon+inactive_anon≠rssとなります。これは、rssにtmpfsが含まれないのが理由です。active_file+inactive_file= cache - size oftmpfs
- memory.usage_in_bytes
- cgroup 内のプロセスによる現在のメモリー総使用量をレポートします (バイト単位)。
- memory.memsw.usage_in_bytes
- cgroup 内のプロセスによる現在のメモリー使用量と使用済みスワップ領域の和をレポートします (バイト単位)。
- memory.max_usage_in_bytes
- cgroup 内のプロセスによるメモリー最大使用量をレポートします (バイト単位)。
- memory.memsw.max_usage_in_bytes
- cgroup 内のプロセスによるスワップメモリー最大使用量と使用済みスワップ領域をレポートします (バイト単位)。
- memory.limit_in_bytes
- ユーザーメモリーの最大値 (ファイルキャッシュを含む) を設定します。単位が指定されていない場合、その値はバイト単位と解釈されますが、より大きな単位を示すサフィックスを使用することが可能です (キロバイトには
kまたはK、メガバイトにはmまたはM、ギガバイトにはgまたはG)。root cgroup を制限するのには、memory.limit_in_bytesは使用できません。値を適用できるのは、下位階層のグループに対してのみです。memory.limit_in_bytesに-1と書き込み、現行の制限値を削除します。 - memory.memsw.limit_in_bytes
- メモリーとスワップ使用量の合計の最大値を設定します。単位が指定されていない場合、その値はバイト単位と解釈されますが、より大きな単位を示すサフィックスを使用することが可能です (キロバイトには
kまたはK、メガバイトにはmまたはM、ギガバイトにはgまたはG)。root cgroup を制限するのに、memory.memsw.limit_in_bytesは使用できません。値を適用できるのは、下位階層のグループに対してのみです。memory.memsw.limit_in_bytesに-1と書き込み、現行の制限値を削除します。重要
memory.limit_in_bytesパラメーターは、memory.memsw.limit_in_bytesを設定する前に 設定しておくことが重要となります。逆の順序で設定を試みると、エラーが発生します。これは、memory.memsw.limit_in_bytesを使用できるようになるのが、(memory.limit_in_bytesで事前に設定されている) メモリー制限をすべて使い切った後のみであるためです。次の例を検討してください: 特定の cgroup に対してmemory.limit_in_bytes = 2Gとmemory.memsw.limit_in_bytes = 4Gと設定すると、cgroup 内のプロセスが 2 GB のメモリーを割り当てることが可能となり、それを使い果たすと、さらに 2 GB のスワップのみを割り当てます。memory.memsw.limit_in_bytesパラメーターはメモリーとスワップの合計を示しています。memory.memsw.limit_in_bytesパラメーターが設定されていない cgroup 内のプロセスは、(設定されているメモリーの上限を消費した後に) 使用可能なスワップをすべて使い果たしてしまい、空きスワップがなくなるために Out Of Memory (OOM) の状態を引き起こす可能性があります。また、/etc/cgconfig.confファイルでmemory.limit_in_bytesとmemory.memsw.limit_in_bytesのパラメーターを設定する順序も重要です。この設定の正しい例は以下のとおりです。memory { memory.limit_in_bytes = 1G; memory.memsw.limit_in_bytes = 1G; } - memory.failcnt
memory.limit_in_bytesに設定されているメモリーの上限値に達した回数をレポートします。- memory.memsw.failcnt
memory.memsw.limit_in_bytesに設定されているメモリーとスワップ領域の合計が上限に達した回数をレポートします。- memory.force_empty
0に設定されている場合には、cgroup 内のタスクによって使用される全ページのメモリーを空にします。このインターフェイスは、cgroup がタスクを持たない時にのみ使用できます。メモリーを解放できない場合は、可能ならば 親 cgroup に移動されます。cgroup を削除する前には、memory.force_emptyを使用して、未使用のページキャッシュが親 cgroup に移動されないようにしてください。- memory.swappiness
- ページキャッシュからページを再生する代わりに、カーネルがこの cgroup 内のタスクで使用されるプロセスメモリーをスワップアウトする傾向を設定します。これはシステム全体用に
/proc/sys/vm/swappiness内に設定されているのと同じ傾向で、同じ方法で算出されます。デフォルト値は60です。これより低い値を設定すると、カーネルがプロセスメモリーをスワップアウトする傾向が低減します。また100以上に設定すると、カーネルはこの cgroup 内のプロセスのアドレス領域となる部分のページをスワップアウトできるようになります。0の値に設定しても、プロセスメモリーがスワップアウトされるのを防ぐことはできない点に注意してください。グローバル仮想メモリー管理ロジックは、cgroup の値を読み取らないため、システムメモリーが不足した場合に、依然としてスワップアウトが発生する可能性があります。ページを完全にロックするには、cgroup の代わりにmlock()を使用してください。以下にあげるグループの swappiness は変更できません。/proc/sys/vm/swappinessに設定された swappiness を使用している root cgroup- 配下に子グループがある cgroup
- memory.use_hierarchy
- cgroup の階層全体にわたって、メモリー使用量を算出すべきかどうかを指定するフラグ (
0または1) が含まれます。有効 (1) となっている場合、メモリーサブシステムはメモリーの上限を超過しているプロセスとその子プロセスからメモリーを再生します。デフォルト (0) では、サブシステムはタスクの子からメモリーを再生しません。 - memory.oom_control
- cgroup に対して Out of Memory Killer を有効化/無効化するフラグ (
0または1) が含まれています。これを有効にすると (0)、許容量を超えるメモリーを使用しようとするタスクは OOM Killer によって即時に強制終了されます。OOM Killer は、memoryサブシステムを使用するすべての cgroup でデフォルトで有効になっています。これを無効にするには、memory.oom_controlファイルに1と記載します。~]#
echo 1 > /cgroup/memory/lab1/memory.oom_controlOOM Killer が無効になると、許容量を超えるメモリーを使用しようとするタスクは、追加のメモリーが解放されるまで一時停止されます。memory.oom_controlファイルは、現在の cgroup の OOM ステータスもunder_oomエントリにレポートします。cgroup がメモリー不足の状態で、その cgroup 内のタスクが一時停止されている場合には、under_oomエントリで値が1とレポートされます。memory.oom_controlファイルは、通知 API を使用して OOM 状態の発生をレポートすることができます。詳しくは、「通知 API の使用」 および 例3.3「OOM の制御と通知」 を参照してください。
3.7.1. 使用例
例3.3 OOM の制御と通知
memoryサブシステムを階層に接続し、cgroup を作成します。~]#
mount -t memory -o memory memory /cgroup/memory~]#mkdir /cgroup/memory/bluebluecgroup 内のタスクが使用できるメモリーを 100 MB に設定します。~]#
echo 104857600 > memory.limit_in_bytesblueディレクトリに移動して、OOM Killer が有効になっていることを確認します。~]#
cd /cgroup/memory/blueblue]#cat memory.oom_controloom_kill_disable 0 under_oom 0- 現在のシェルプロセスを
bluecgroup のtasksファイルに移動し、このシェルで起動したその他すべてのプロセスが自動的にbluecgroup に移動するようにします。blue]#
echo $$ > tasks - ステップ 2 で設定した上限を超える大容量のメモリーを割り当てようとするテストプログラムを起動します。
bluecgroup の空きメモリーがなくなるとすぐに OOM Killer がテストプログラムを強制終了し、標準出力にKilledをレポートします。blue]#
~/mem-hogKilled以下は、このようなテストプログラムの一例です。[5]#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define KB (1024) #define MB (1024 * KB) #define GB (1024 * MB) int main(int argc, char *argv[]) { char *p; again: while ((p = (char *)malloc(GB))) memset(p, 0, GB); while ((p = (char *)malloc(MB))) memset(p, 0, MB); while ((p = (char *)malloc(KB))) memset(p, 0, KB); sleep(1); goto again; return 0; } - OOM Killer を無効にし、テストプログラムを再度実行します。今回は、テストプログラムが一時停止の状態のままとなり、追加のメモリーが解放されるのを待機します。
blue]#
echo 1 > memory.oom_controlblue]#~/mem-hog - テストプログラムが一時停止されている間は、cgroup の
under_oom状態が変わり、空きメモリーが不足していることを示している点に注意してください。~]#
cat /cgroup/memory/blue/memory.oom_controloom_kill_disable 1 under_oom 1OOM Killer を再度有効にすると、テストプログラムは即時に強制終了されます。 - すべての OOM 状態についての通知を受信するためには、「通知 API の使用」 に記載したようにプログラムを作成してください。以下はその一例です[6]。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/eventfd.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <stdlib.h> static inline void die(const char *msg) { fprintf(stderr, "error: %s: %s(%d)\n", msg, strerror(errno), errno); exit(EXIT_FAILURE); } static inline void usage(void) { fprintf(stderr, "usage: oom_eventfd_test <cgroup.event_control> <memory.oom_control>\n"); exit(EXIT_FAILURE); } #define BUFSIZE 256 int main(int argc, char *argv[]) { char buf[BUFSIZE]; int efd, cfd, ofd, rb, wb; uint64_t u; if (argc != 3) usage(); if ((efd = eventfd(0, 0)) == -1) die("eventfd"); if ((cfd = open(argv[1], O_WRONLY)) == -1) die("cgroup.event_control"); if ((ofd = open(argv[2], O_RDONLY)) == -1) die("memory.oom_control"); if ((wb = snprintf(buf, BUFSIZE, "%d %d", efd, ofd)) >= BUFSIZE) die("buffer too small"); if (write(cfd, buf, wb) == -1) die("write cgroup.event_control"); if (close(cfd) == -1) die("close cgroup.event_control"); for (;;) { if (read(efd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) die("read eventfd"); printf("mem_cgroup oom event received\n"); } return 0; }上記のプログラムはコマンドラインの引数として指定された cgroup 内の OOM 状態を検出し、mem_cgroup oom event receivedの文字列を使用して標準出力にレポートします。 bluecgroup の制御ファイルを引数として指定して、上記の通知ハンドラープログラムを別のコンソールで実行します。~]$
./oom_notification /cgroup/memory/blue/cgroup.event_control /cgroup/memory/blue/memory.oom_control- 別のコンソールで
mem_hogテストプログラムを実行し、OOM 状態を発生させてoom_notificationプログラムがそれを標準出力にレポートするのを確認します。blue]#
~/mem-hog
3.8. net_cls
net_cls サブシステムは、Linux トラフィックコントローラー (tc) が特定の cgroup から発信されるパケットを識別できるようにするクラス識別子 (classid) を使用して、ネットワークパケットをタグ付けします。トラフィックコントローラーは、異なる cgroup からのパケットに異なる優先順位を割り当てるように設定できます。
- net_cls.classid
net_cls.classidには、トラフィック制御ハンドルを示す単一値が含まれます。net_cls.classidファイルから読み取られるclassidの値は、10 進数形式で表示されますが、ファイルに書き込まれる値は 16 進数形式となります。たとえば、0x100001は、iproute2 で使用されている形式では従来10:1として記述されていたハンドルを示します。net_cls.classidファイルでは、1048577の数字で示されます。これらのハンドルの形式は:0xAAAABBBBです。ここで AAAA は 16 進法のメジャー番号、BBBB は 16 進法のマイナー番号です。また、先頭のゼロを省略することができ、0x10001は0x00010001と同じで、1:1を示します。以下は、net_cls.classidファイルでの10:1ハンドルの設定例です。~]#
echo 0x100001 > /cgroup/net_cls/red/net_cls.classid~]#cat /cgroup/net_cls/red/net_cls.classid1048577
net_cls がネットワークパケットに追加するハンドルを使用するためのトラフィックコントローラーの設定法を確認するには tc の man ページを参照してください。
3.9. net_prio
net_prio) サブシステムは、さまざまな cgroup 内でアプリケーション用の各ネットワークインターフェイス毎にネットワークトラフィックの優先度を動的に設定する方法を提供します。ネットワーク優先度はネットワークトラフィックに割り当てられる番号で、システムおよびネットワークデバイスにより内部で使用されます。ネットワーク優先度は、送信、キューに配置、またはドロップされるパケットを区別するために使用されます。tc コマンドは、ネットワーク優先度の設定に使用することができます (tc コマンドを使用したネットワーク優先度の設定は本ガイドのスコープ外です。詳しくは tc man ページを参照してください)。
SO_PRIORITY ソケットオプションによりトラフィックの優先度を設定しますが、アプリケーションが優先度の値を設定するようにコードが書かれていなかったり、アプリケーションのトラフィックがサイト固有で定義された優先度を提供しない場合が多くあります。
net_prio サブシステムを使用すると、管理者はプロセスを特定の cgroup に割り当てて、任意のネットワーク上の送信トラフィックの優先度を定義することができます。
- net_prio.prioidx
- この cgroup の内部表現としてカーネルが使用する、一意の整数値を含む読み取り専用ファイル。
- net_prio.ifpriomap
- このグループ内のプロセスが送信元となっているトラフィック、およびさまざまなインターフェースでシステムから外に送信されるトラフィックに割り当てられた優先度のマップを含みます。このマップは、
<network_interface> <priority>の形式でペアで示されます~]#
cat /cgroup/net_prio/iscsi/net_prio.ifpriomapeth0 5 eth1 4 eth2 6net_prio.ifpriomapファイルの内容は、上記の形式を使用して、文字列を echo コマンドでファイルに書き込むことによって変更することができます。以下はその例です。~]#
echo "eth0 5" > /cgroup/net_prio/iscsi/net_prio.ifpriomap上記のコマンドは、iscsinet_priocgroup に属するプロセスから送信されるトラフィック、およびeth0ネットワークインターフェース上で送信されるトラフィックで優先度の値が5に設定されるよう強制します。親 cgroup には、システムのデフォルト優先度を設定するのに使用できる書き込み可能なnet_prio.ifpriomapファイルもあります。
3.10. ns
ns サブシステムは、プロセスを異なる 名前空間 にグループ化する手段を提供します。特定の名前空間内では、プロセス間における相互の対話が可能ですが、他の名前空間で実行されているプロセスからは分離しています。このように分離した名前空間は、オペレーティングシステムレベルの仮想化に使用される場合には、コンテナー とも呼ばれています。
3.11. perf_event
perf_event サブシステムが階層に接続されると、その階層内の全 cgroups は、グループプロセスおよびスレッドに使用できることが可能となり、プロセス/スレッド別または CPU 単位ではなく、perf ツールでモニタリングできるようになります。perf_event サブシステムを使用する cgroup には、「共通の調整可能なパラメーター」 に記載されている共通のパラメーター以外の特殊な調整可能パラメーターは含まれません。
3.12. 共通の調整可能なパラメーター
- tasks
- cgroup で実行中のプロセスの一覧が含まれ、PID で表示されます。PID の一覧が順位付けされていることや、一意であることは保証されません (つまり、重複したエントリが含まれている可能性があります)。PID を cgroup の
tasksファイルに書き込むと、そのプロセスは cgroup に移動します。 - cgroup.procs
- cgroup で実行中のスレッドグループの一覧が含まれ、TGID で表示されます。TGID の一覧が順位付けされていることや、一意であることは保証されません (つまり、重複したエントリが含まれている可能性があります)。TGID を cgroup の
tasksファイルに書き込むと、そのスレッドグループは cgroup に移動します。 - cgroup.event_control
- cgroup 通知 API とともに、cgroup のステータス変更についての通知を送付できるようにします。
- notify_on_release
- ブール値が含まれ、
1または0でリリースエージェントの実行を有効化または無効化します。notify_on_releaseが有効化されると、cgroup にタスクがなくなった時にカーネルがrelease_agentファイルの内容を実行します (つまり、cgroup のtasksファイルにいくつかの PID が含まれ、それらの PID が削除されてファイルが空の状態となっています)。空の cgroup へのパスは、空の cgroup へのパスは、引数としてリリースエージェントに提供されます。root cgroup 内のnotify_on_releaseパラメーターのデフォルト値は0です。root 以外の cgroups はすべて、親 cgroup からnotify_on_release内の値を継承します。 - release_agent (root cgroup のみに存在)
- 「notify on release」 がトリガーされた時に実行されるコマンドが含まれます。cgroup の全プロセスが空となると、
notify_on_releaseフラグが有効化され、カーネルがrelease_agentファイル内のコマンドを実行して、相対パス(root cgroup に相対) で空の cgroup に引数として提供します。リリースエージェントは、たとえば、空の cgroup を自動的に削除するのに使用することができます。詳しくは、例3.4「空の cgroup の自動削除」 を参照してください。例3.4 空の cgroup の自動削除
以下の手順にしたがって、空になった cgroup を自動的にcpucgroup から削除するように設定します。- 空の
cpucgroups を削除するシェルスクリプトを作成して/usr/local/binなどに配置し、実行できるようにします。~]#
cat /usr/local/bin/remove-empty-cpu-cgroup.sh#!/bin/sh rmdir /cgroup/cpu/$1 ~]#chmod +x /usr/local/bin/remove-empty-cpu-cgroup.sh$1の変数には空になった cgroup への相対パスを記載します。 cpucgroup でnotify_on_releaseフラグを有効にします。~]#
echo 1 > /cgroup/cpu/notify_on_releasecpucgroup には、使用するリリースエージェントを指定します。~]#
echo "/usr/local/bin/remove-empty-cpu-cgroup.sh" > /cgroup/cpu/release_agent- 設定をテストして、空になった cgroup が適切に削除されることを確認します。
cpu]#
pwd; ls/cgroup/cpu cgroup.event_control cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.rt_period_us cpu.rt_runtime_us cpu.shares cpu.stat libvirt notify_on_release release_agent tasks cpu]#cat notify_on_release1 cpu]#cat release_agent/usr/local/bin/remove-empty-cpu-cgroup.sh cpu]#mkdir blue; lsblue cgroup.event_control cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.rt_period_us cpu.rt_runtime_us cpu.shares cpu.stat libvirt notify_on_release release_agent tasks cpu]#cat blue/notify_on_release1 cpu]#cgexec -g cpu:blue dd if=/dev/zero of=/dev/null bs=1024k &[1] 8623 cpu]#cat blue/tasks8623 cpu]#kill -9 8623cpu]#lscgroup.event_control cgroup.procs cpu.cfs_period_us cpu.cfs_quota_us cpu.rt_period_us cpu.rt_runtime_us cpu.shares cpu.stat libvirt notify_on_release release_agent tasks
3.13. その他のリソース
サブシステム固有のカーネルのドキュメント
/usr/share/doc/kernel-doc-<kernel_version>/Documentation/cgroups/ ディレクトリ下に配置されています (kernel-doc パッケージにより提供)。
blkioサブシステム —blkio-controller.txtcpuacctサブシステム —cpuacct.txtcpusetサブシステム —cpusets.txtdevicesサブシステム —devices.txtfreezerサブシステム —freezer-subsystem.txtmemoryサブシステム —memory.txtnet_prioサブシステム —net_prio.txt
cpu サブシステムについての詳しい情報は、以下のファイルを参照してください。
- リアルタイムスケジューリング —
/usr/share/doc/kernel-doc-<kernel_version>/Documentation/scheduler/sched-rt-group.txt - CFS スケジューリング —
/usr/share/doc/kernel-doc-<kernel_version>/Documentation/scheduler/sched-bwc.txt
第4章 ユースケースシナリオ
4.1. データベース I/O の優先

図4.1 リソース割り当てを使用しない I/O スループット
手順4.1 I/O スループットの優先度設定
blkioサブシステムを/cgroup/blkiocgroup に接続します。~]#
mkdir /cgroup/blkio~]#mount -t cgroup -o blkio blkio /cgroup/blkio- 優先度の高い cgroup と低い cgroup を作成します。
~]#
mkdir /cgroup/blkio/high_prio~]#mkdir /cgroup/blkio/low_prio - 両仮想ゲスト (データベースサーバーを実行している) を示す PID を取得し、それら固有の cgroup に移動します。この例では、
VM_highは優先度の高いデータベースサーバーを実行している仮想ゲストを示し、VM_lowは優先度の低いデータベースサーバーを実行している仮想ゲストを示しています。以下はその例です。~]#
ps -eLf | grep qemu | grep VM_high | awk '{print $4}' | while read pid; do echo $pid >> /cgroup/blkio/high_prio/tasks; done~]#ps -eLf | grep qemu | grep VM_low | awk '{print $4}' | while read pid; do echo $pid >> /cgroup/blkio/low_prio/tasks; done high_priocgroup とlow_priocgroup の比を 10:1 に設定します。それらの cgroup 内のプロセス (前のステップでそれらの cgroup に追加した仮想ゲストを実行しているプロセス) は、それらのプロセスが利用可能なリソースのみを即時に使用します。~]#
echo 1000 > /cgroup/blkio/high_prio/blkio.weight~]#echo 100 > /cgroup/blkio/low_prio/blkio.weightこの例で、優先度の低い cgroup は、優先度の低いデータベースサーバーが約 10 % の I/O 操作を使用するのを許可する一方、優先度の高い cgroup は、優先度の高いデータベースサーバーが約 90 % の I/O 操作を使用するのを許可します。

図4.2 I/O スループットとリソース割り当て
blkio サブシステムに関するさらに詳しい情報は、「blkio」 を参照してください。
4.2. ネットワークトラフィックの優先度設定
net_prio サブシステムを使用して、cgroup 内のプロセスの優先順位を設定することができます。次に、これらの優先度が Type Of Service (TOS) ビットに変換され、各パケットに埋め込まれます。二つのファイル共有サービス (NFS と Samba) の優先度を設定するには、手順4.2「ファイル共有サービスのネットワーク優先度の設定」 の手順にしたがってください。
手順4.2 ファイル共有サービスのネットワーク優先度の設定
net_prioサブシステムを/cgroup/net_priocgroup に接続します。~]#
mkdir /cgroup/net_prio~]#mount -t cgroup -o net_prio net_prio /cgroup/net_prio- サービスごとに 2 つの cgroup を作成します。
~]#
mkdir /cgroup/net_prio/nfs_high~]#mkdir /cgroup/net_prio/samba_low nfs_highcgroup にnfsを自動的に移動するには、/etc/sysconfig/nfsファイルに以下の行を追加します。CGROUP_DAEMON="net_prio:nfs_high"
この設定は、nfsサービスが起動または再起動された時に、nfsサービスプロセスがnfs_highcgroup に移動するようにします。cgroup への サービスプロセス移動についての詳細は、「コントロールグループ内のサービスの開始」 を参照してください。smbdデーモンの設定ファイルは/etc/sysconfigディレクトリにはありません。smbdデーモンをsamba_lowcgroup に自動的に移動するには、/etc/cgrules.confファイルに以下の行を追記してください。*:smbd net_prio samba_low
このルールにより、/usr/sbin/smbdのみではなく、すべてのsmbdデーモンがsamba_lowcgroup に移動する点に注意してください。同様に、nmbdおよびwinbinddデーモンをsamba_lowcgroup に移動させるルールを定義することができます。cgredサービスを起動して、前の手順からの設定を読み込みます。~]#
service cgred startStarting CGroup Rules Engine Daemon: [ OK ]- この例では、両サービスが
eth1ネットワークインターフェースを使用していることを前提とします。各 cgroup にネットワークの優先度を定義します。ここで1優先度低く、10は優先度が高い数値を示します。~]#
echo "eth1 1" > /cgroup/net_prio/samba_low~]#echo "eth1 10" > /cgroup/net_prio/nfs_high nfsおよびsmbのサービスを起動し、それらのプロセスが正しい cgroup に移動したことを確認します。~]#
service smb startStarting SMB services: [ OK ] ~]#cat /cgroup/net_prio/samba_low16122 16124 ~]#service nfs startStarting NFS services: [ OK ] Starting NFS quotas: [ OK ] Starting NFS mountd: [ OK ] Stopping RPC idmapd: [ OK ] Starting RPC idmapd: [ OK ] Starting NFS daemon: [ OK ] ~]#cat /cgroup/net_prio/nfs_high16321 16325 16376NFS から発信されるネットワークトラフィックの優先度が、Samba から発信されるトラフィックよりも高くなりました。
net_prio サブシステムはクライアントアプリケーション (例: Firefox) のネットワーク優先度設定に使用することができます。
4.3. CPU およびメモリーリソースのグループ別配分
~]$ grep home /etc/passwd
martin:x:500:500::/home/martin:/bin/bash
john:x:501:501::/home/john:/bin/bash
mark:x:502:502::/home/mark:/bin/bash
peter:x:503:503::/home/peter:/bin/bash
jenn:x:504:504::/home/jenn:/bin/bash
mike:x:505:505::/home/mike:/bin/bash
~]$ grep -e "50[678]" /etc/group
finance:x:506:jenn,john
sales:x:507:mark,martin
engineering:x:508:peter,mike
/etc/cgconfig.conf および /etc/cgrules.conf のファイルを使用して階層を作成し、各ユーザー用のリソースの量を決定するルールを設定することができます。この設定は、手順4.3「グループ別の CPU およびメモリーリソースの管理」 に記載した手順にしたがって行ってください。
手順4.3 グループ別の CPU およびメモリーリソースの管理
/etc/cgconfig.confファイルで、以下のようなサブシステムをマウントして、cgroup を作成するように設定します。mount { cpu = /cgroup/cpu_and_mem; cpuacct = /cgroup/cpu_and_mem; memory = /cgroup/cpu_and_mem; } group finance { cpu { cpu.shares="250"; } cpuacct { cpuacct.usage="0"; } memory { memory.limit_in_bytes="2G"; memory.memsw.limit_in_bytes="3G"; } } group sales { cpu { cpu.shares="250"; } cpuacct { cpuacct.usage="0"; } memory { memory.limit_in_bytes="4G"; memory.memsw.limit_in_bytes="6G"; } } group engineering { cpu { cpu.shares="500"; } cpuacct { cpuacct.usage="0"; } memory { memory.limit_in_bytes="8G"; memory.memsw.limit_in_bytes="16G"; } }上記の設定ファイルが読み込まれると、cpu、cpuacct、およびmemoryのサブシステムが単一のcpu_and_memcgroup にマウントされます。これらのサブシステムについての詳しい情報は、3章サブシステムと調整可能なパラメーター を参照してください。次にcpu_and_memに階層が作成されます。これには、sales、finance、engineering の 3 つの cgroup が含まれます。これらの cgroup にはそれぞれ、各サブシステムに対するカスタムパラメーターが設定されます。cpu—cpu.sharesパラメーターは、全 cgroup 内の各プロセスに提供する CPU リソースの配分を決定します。このパラメーターを finance cgroup に250、sales cgroup に250、engineering cgroup に500と設定すると、これらのグループで起動されたプロセスはリソースを 1:1:2 の割合で分割することになります。実行されているプロセスが 1 つの場合、そのプロセスはどの cgroup に配置されているかに関わらず、 必要なだけ CPU を消費する点に注意してください。CPU の制限は、複数のプロセスが CPU リソースを競い合う場合のみに有効となります。cpuacct—cpuacct.usage="0"パラメーターは、cpuacct.usageおよびcpuacct.usage_percpuのファイルに保存されている値をリセットするのに使用します。これらのファイルは、1 つの cgroup 内の全プロセスが消費する CPU 時間の合計 (ナノ秒単位) をレポートします。memory—memory.limit_in_bytesパラメーターは、特定の cgroup 内の全プロセスに提供されるメモリーの容量を示します。以下の例は、finance cgroup で起動したプロセスに 2 GB のメモリー、sales cgroup には 4 GB のメモリー、engineering cgroup には 8 GB のメモリーが割り当てられます。memory.memsw.limit_in_bytesパラメーターは、スワップ領域のプロセスが使用できるメモリー容量の合計を指定します。finance cgroup 内のプロセスが 2 GB のメモリー上限に達すると、追加で 1 GB のスワップ領域を使用することができるので、合計で 3GB が設定されることになります。
- 特定の cgroup にプロセスを移動するために
cgrulesengdデーモンが使用するルールを定義するには、/etc/cgrules.confを以下のように設定します。#<user/group> <controller(s)> <cgroup> @finance cpu,cpuacct,memory finance @sales cpu,cpuacct,memory sales @engineering cpu,cpuacct,memory engineering
上記の設定により、特定のシステムグループ (例:@finance) に使用可能なリソースコントローラー (例:cpu、cpuacct、memory) とそのシステムグループから起動される全プロセスを格納する cgroup (例:finance) を割り当てるルールを作成します。この例では、service cgred startコマンドによって起動されたcgrulesengdデーモンが、finance システムグループに属するユーザー (例:jenn) によって起動されたプロセスを検出すると、そのプロセスは自動的に/cgroup/cpu_and_mem/finance/tasksファイルに移動し、finance cgroup で設定されているリソース制限の対象となります。 cgconfigサービスを起動し、cgroup の階層を作成して、作成した全 cgroup 内で必要なパラメーターを設定します。~]#
service cgconfig startStarting cgconfig service: [ OK ]cgredサービスを起動して、/etc/cgrules.confファイルで設定されたシステムグループ内で起動されたプロセスをcgrulesengdデーモンに検出させます。~]#
service cgred startStarting CGroup Rules Engine Daemon: [ OK ]cgredとは、cgrulesengdデーモンを起動するサービスの名前である点に注意してください。- リブート後にも変更をすべて保持するには、
cgconfigおよびcgredのサービスがデフォルトで起動するように設定します。~]#
chkconfig cgconfig on~]#chkconfig cgred on
dd コマンドを実行します。
~]$ dd if=/dev/zero of=/dev/null bs=1024k/dev/zero を読み取り、その内容を 1024 KB 単位で /dev/null に出力します。top ユーティリティが起動すると、以下のような結果を確認することができます。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8201 peter 20 0 103m 1676 556 R 24.9 0.2 0:04.18 dd 8202 mike 20 0 103m 1672 556 R 24.9 0.2 0:03.47 dd 8199 jenn 20 0 103m 1676 556 R 12.6 0.2 0:02.87 dd 8200 john 20 0 103m 1676 556 R 12.6 0.2 0:02.20 dd 8197 martin 20 0 103m 1672 556 R 12.6 0.2 0:05.56 dd 8198 mark 20 0 103m 1672 556 R 12.3 0.2 0:04.28 dd ⋮
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8202 mike 20 0 103m 1676 556 R 66.4 0.2 0:06.35 dd 8200 john 20 0 103m 1672 556 R 33.2 0.2 0:05.08 dd ⋮
その他の方法
cgrulesengd デーモンは、 /etc/cgrules.conf に設定された該当する条件が満たされた後でしかプロセスを cgroup に移動しないので、そのプロセスが誤った cgroup で数ミリ秒間実行される場合があります。指定の cgroup にプロセスを移動する別の方法として、pam_cgroup.so PAM モジュールを使用する方法があります。このモジュールは、/etc/cgrules.conf ファイルで定義されているルールにしたがって使用可能な cgroup にプロセスを移動します。手順4.4「PAM モジュールを使用した、cgroup へのプロセス移行」 に記載した手順にしたがって pam_cgroup.so PAM モジュールを設定してください。
手順4.4 PAM モジュールを使用した、cgroup へのプロセス移行
- オプションの Red Hat Enterprise Linux Yum リポジトリから libcgroup-pam パッケージをインストールします。
~]#
yum install libcgroup-pam --enablerepo=rhel-6-server-optional-rpms - PAM モジュールがインストール済みで、存在していることを確認します。
~]#
ls /lib64/security/pam_cgroup.so/lib64/security/pam_cgroup.so32 ビットのシステムでは、モジュールは/lib/securityディレクトリに配置される点に注意してください。 /etc/pam.d/suファイルに以下の行を追記して、suコマンドが事項されるたびにpam_cgroup.soモジュールを使用するようにします。session optional pam_cgroup.so
/etc/cgrules.confファイルの cgroup 設定の影響を受けるユーザーをすべてログアウトし、上記の設定を適用します。
pam_cgroup.so PAM モジュールを使用する際には、cgred サービスを無効にすることができます。
付録A 改訂履歴
| 改訂履歴 | ||||||||
|---|---|---|---|---|---|---|---|---|
| 改訂 1.0-18.5.400 | 2013-10-31 | |||||||
| ||||||||
| 改訂 1.0-18.5 | Fri Mar 29 2013 | |||||||
| ||||||||
| 改訂 1.0-18.4 | Tue Mar 19 2013 | |||||||
| ||||||||
| 改訂 1.0-18.3 | Mon Mar 11 2013 | |||||||
| ||||||||
| 改訂 1.0-18.2 | Mon Mar 4 2013 | |||||||
| ||||||||
| 改訂 1.0-18.1 | Mon Mar 4 2013 | |||||||
| ||||||||
| 改訂 1.0-18 | Thu Feb 21 2013 | |||||||
| ||||||||
| 改訂 1.0-7 | Wed Jun 20 2012 | |||||||
| ||||||||
| 改訂 1.0-6 | Tue Dec 6 2011 | |||||||
| ||||||||
| 改訂 1.0-5 | Thu May 19 2011 | |||||||
| ||||||||
| 改訂 1.0-4 | Tue Mar 1 2011 | |||||||
| ||||||||
| 改訂 1.0-3 | Wed Nov 17 2010 | |||||||
| ||||||||
| 改訂 1.0-2 | Thu Nov 11 2010 | |||||||
| ||||||||
| 改訂 1.0-1 | Wed Nov 10 2010 | |||||||
| ||||||||
| 改訂 1.0-0 | Tue Nov 9 2010 | |||||||
| ||||||||
