第3章 サブシステムと調整可能なパラメーター
サブシステム とは、cgroup を認識するカーネルモジュールで、通常は、異なるレベルのシステムリソースを異なる cgroup に割り当てるリソースコントローラーです。ただし、サブシステムは、プロセスグループによって異なった扱いをする必要がある場合に、カーネルとのその他の対話用にプログラムすることも可能です。新規サブシステムを開発するための アプリケーションプログラミングインターフェース (API) については、ご使用のシステムの
/usr/share/doc/kernel-doc-kernel-version/Documentation/cgroups/
にインストールされているカーネルのドキュメント cgroups.txt
(kernel-doc パッケージにより提供) に記載されています。cgroup に関するドキュメントの最新バージョンは、オンラインでもご覧いただけます: http://www.kernel.org/doc/Documentation/cgroups/cgroups.txt。ただし、最新版のドキュメントに記載されている機能は、ご使用のシステムにインストールされているカーネルで利用可能な機能と一致しない場合がある点に注意してください。
cgroup 用のサブシステムパラメーターを含んでいる 状態オブジェクト (State object) は cgroup の仮想ファイルシステム内で 疑似ファイル (pseudofiles) として表示されます。これらの疑似ファイルは、シェルコマンドまたはそれに相当するシステムコールで操作することができます。たとえば、
cpuset.cpus
は、cgroup によるアクセスが許可されている CPU を指定する疑似ファイルです。システム上で稼働する Web サーバー用の cgroup が /dev/cgroup/webserver/
である場合には、以下のコマンドを実行してください。
~]# echo 0,2 > /cgroup/cpuset/webserver/cpuset.cpus
上記のコマンドは、
0,2
の値を cpuset.cpus
疑似ファイルに書き込むことにより、/cgroup/cpuset/webserver/tasks
に記載されている PID のタスクがシステム上の CPU 0 と CPU 2 のみを使用するように限定します。
3.1. blkio
ブロック I/O (
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 スロットリングの調整可能なパラメーター」 を参照してください。
重要
現在、block 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」 に記載のいずれのポリシーにも使用することができます。
- 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
例3.1「blkio の重み付け比例配分」 で最も正確な結果を得るには、
dd
コマンドを実行する前に以下のコマンドを実行して、すべてのファイルシステムのバッファーをフラッシュし、ページキャッシュ、デントリ、inode を解放しておきます。
~]#sync
~]#echo 3 > /proc/sys/vm/drop_caches
また、スループットを代償にして、グループ間の分離を強化する group isolation を有効化することができます。グループ分離が無効になっている場合、公平性が期待できるのは順次ワークロードに対してのみです。デフォルトでは、グループ分離は有効化されており、ランダム I/O ワークロードでも公平性が期待できます。グループ分離を有効化するには、以下のコマンドを実行します。
~]# echo 1 > /sys/block/<disk_device>/queue/iosched/group_isolation
ここで <disk_device> は対象のデバイス名を表しています (例:
sda
)。