Red Hat Training

A Red Hat training course is available for Red Hat Enterprise Linux

2.3.2. ユニットファイルの変更

Systemd サービスユニットファイルは、リソース管理に役立つ高レベルの設定パラメーターを多数提供します。これらのパラメーターは、カーネルで有効にする必要がある Linux cgroup コントローラーと通信します。これらのパラメーターを使用すると、CPU、メモリー消費、ブロック IO、さらに細かいユニットプロパティーを管理できます。

CPU の管理

CPU コントローラーはカーネルでデフォルトで有効になっているため、含まれるプロセスの数に関係なく、すべてのシステムサービスは同じ量の CPU 時間を受け取ります。このデフォルトの動作は、/etc/systemd/system.conf 設定ファイルの DefaultControllers パラメーターで変更できます。CPU 割り当てを管理するには、ユニット設定ファイルの Service セクションで次のディレクティブを使用します。
CPUShare = value
value は、CPU シェアの数に置き換えます。デフォルト値は 1024 です。数値を増やすと、より多くの CPU 時間がユニットに割り当てられます。CPUShares パラメーターの値を設定すると、ユニットファイルで CPUAccounting が自動的にオンになります。したがって、ユーザーは systemd-cgtop コマンドを使用してプロセッサーの使用状況を監視できます。
CPUShares パラメーターは、cpu.shares コントロールグループパラメーターを制御します。他の CPU 関連の制御パラメーターを確認するには、コントローラー固有のカーネルドキュメントcpu コントローラーの説明を参照してください。

例2.3 ユニットの CPU 消費の制限

デフォルトの 1024 ではなく 1500 の CPU シェアを Apache サービスに割り当てるには、次の内容で新しい /etc/systemd/system/httpd.service.d/cpu.conf 設定ファイルを作成します。
[Service]
CPUShares=1500
変更を適用するには、変更されたサービスファイルが考慮されるように、systemd の設定をリロードして Apache を再起動します。
~]# systemctl daemon-reload
~]# systemctl restart httpd.service
CPUQuota = value
value は、 CPU 時間クォータの値に置き換えて、指定された CPU 時間クォータを実行されるプロセスに割り当てます。パーセンテージで表される CPUQuota パラメーターの値は、1 つの CPU で使用可能な合計 CPU 時間に対して、ユニットが最大で取得する CPU 時間を指定します。
100% を超える値は、複数の CPU が使用されていることを示します。CPUQuota は、統合されたコントロールグループ階層の cpu.max 属性と、従来の cpu.cfs_quota_us 属性を制御します。CPUQuota パラメーターの値を設定すると、ユニットファイルで CPUAccounting が自動的にオンになります。したがって、ユーザーは systemd-cgtop コマンドを使用してプロセッサーの使用状況を監視できます。

例2.4 CPUQuota の使用

CPUQuota を 20% に設定すると、実行プロセスに対して、単一の CPU で 20% 以上の CPU 時間が渡されないようにします。
20% の Apache サービス CPU クォータを割り当てるには、次の内容を /etc/systemd/system/httpd.service.d/cpu.conf 設定ファイルに追加します。
[Service]
CPUQuota=20%
変更を適用するには、変更されたサービスファイルが考慮されるように、systemd の設定をリロードして Apache を再起動します。
~]# systemctl daemon-reload
~]# systemctl restart httpd.service

メモリーの管理

ユニットのメモリー消費量を制限するには、ユニット設定ファイルの Service セクションで次のディレクティブを使用します。
MemoryLimit=value
value は、cgroup で実行されるプロセスの最大メモリー使用量の制限に置き換えます。測定単位のキロバイト、メガバイト、ギガバイト、またはテラバイトを指定するには、接尾辞 KMGまたは T を使用します。また、ユニットに対して MemoryAccounting パラメーターを有効にする必要があります。
MemoryLimit パラメーターは、memory.limit_in_bytes コントロールグループパラメーターを制御します。詳細は、コントローラー固有のカーネルドキュメントメモリー コントローラーの説明を参照してください。

例2.5 ユニットのメモリー消費の制限

Apache サービスに 1GB のメモリー制限を割り当てるには、 /etc/systemd/system/httpd.service.d/cpu.conf ユニットファイルの MemoryLimit 設定を変更します。
[Service]
MemoryLimit=1G
変更を適用するには、変更されたサービスファイルが考慮されるように、systemd の設定をリロードして Apache を再起動します。
~]# systemctl daemon-reload
~]# systemctl restart httpd.service

ブロック IO の管理

ブロック IO を管理するには、ユニット設定ファイルの Service セクションで次のディレクティブを使用します。以下にリストされているディレクティブは、BlockIOAccounting パラメーターが有効になっていることを前提としています。
BlockIOWeight = value
value は、実行されたプロセスの新しい全体的なブロック IO の重みに置き換えます。10 から 1000 の間の単一の値を選択します。デフォルト設定は 1000 です。
BlockIODeviceWeight=device_name value
value は、device_name で指定されたデバイスのブロック IO の重みに置き換えます。device_name は、名前またはデバイスへのパスに置き換えます。BlockIOWeight と同様に、10 から 1000 までの単一の重み値を設定できます。
BlockIOReadBandwidth=device_name value
このディレクティブを使用すると、ユニットの特定の帯域幅を制限できます。device_name は、デバイスの名前またはブロックデバイスノードへのパスに置き換え、value は帯域幅レートを表します。接尾辞 KMG、または T を使用して、測定単位を指定します。接尾辞のない値は、1 秒あたりのバイト数として解釈されます。
BlockIOWriteBandwidth=device_name value
指定されたデバイスの書き込み帯域幅を制限します。BlockIOReadBandwidth と同じ引数を受け入れます。
前述の各ディレクティブは、対応する cgroup パラメーターを制御します。その他の CPU 関連の制御パラメーターについては、コントローラー固有のカーネルドキュメントblkio コントローラーの説明を参照してください。
注記
現在、blkio リソースコントローラーは、バッファーリングされた書き込み操作をサポートしていません。これは主にダイレクト I/O を対象としているため、バッファーリングされた書き込みを使用するサービスは BlockIOWriteBandwidth で設定された制限を無視します。一方、バッファリングされた読み取り操作はサポートされており、BlockIOReadBandwidth の制限は、直接読み取りとバッファリングされた読み取りの両方に正しく適用されます。

例2.6 ユニットのブロック IO の制限

/home/jdoe/ ディレクトリーにアクセスする Apache サービスのブロック IO の重みを下げるには、次のテキストを /etc/systemd/system/httpd.service.d/cpu.conf ユニットファイルに追加します。
[Service]
BlockIODeviceWeight=/home/jdoe 750
/var/log/ ディレクトリーからの Apache 読み取りの最大帯域幅を 1 秒あたり 5MB に設定するには、次の構文を使用します。
[Service]
BlockIOReadBandwidth=/var/log 5M
変更を適用するには、変更されたサービスファイルが考慮されるように、systemd の設定をリロードして Apache を再起動します。
~]# systemctl daemon-reload
~]# systemctl restart httpd.service

その他のシステムリソースの管理

リソース管理を容易にするために、ユニットファイルで使用できるその他のディレクティブがいくつかあります。
DeviceAllow=device_name options
このオプションは、特定のデバイスノードへのアクセスを制御します。ここで、device_name/proc/devices で指定されているデバイスノードまたはデバイスグループ名へのパスを表します。オプションrw、および m の組み合わせに置き換えて、ユニットがデバイスノードを読み取り、書き込み、または作成できるようにします。
DevicePolicy=value
ここで、value は、strict (DeviceAllow で明示的に指定されたタイプのアクセスのみを許可する)、closed (/dev/null、/dev/zero、/dev/full、/dev/random などの標準の疑似デバイスへのアクセスを許可する) および/dev/urandom) または auto (デフォルトの動作である明示的な DeviceAllow が存在しない場合、すべてのデバイスへのアクセスを許可します) のいずれかです。
Slice=slice_name
slice_name は、ユニットを配置するスライスの名前に置き換えます。デフォルトは system.slice です。スコープユニットは、親スライスに関連付けられているため、この方法で配置することはできません。
ExecStartPost=command
現在、systemd は cgroup 機能のサブセットのみをサポートしています。ただし、回避策として、ExecStartPost= オプションを memory.memsw.limit_in_bytes パラメーターの設定と共に使用して、サービスのスワップの使用を防ぐことができます。ExecStartPost= の詳細は、systemd.service (5) の man ページを参照してください。

例2.7 Cgroup オプションの設定

特定の example サービスのスワップの使用を防ぐために、memory.memsw.limit_in_bytes 設定をユニットの MemoryLimit = と同じ値に変更すると想定します。
ExecStartPost=/bin/bash -c "echo 1G > /sys/fs/cgroup/memory/system.slice/example.service/memory.memsw.limit_in_bytes"
変更を適用するには、変更された設定が考慮されるように、systemd 設定をリロードしてサービスを再起動します。
~]# systemctl daemon-reload
~]# systemctl restart example.service