2.3. コントロールグループの変更

systemd によって監視されるそれぞれの永続的なユニットには、/usr/lib/systemd/system/ ディレクトリーにユニット設定ファイルがあります。サービスユニットのパラメーターを変更するには、この設定ファイルを変更します。これは手動で実行することも、systemctl set-property コマンドを使用してコマンドラインインターフェースで実行することもできます。

2.3.1. コマンドラインインターフェースでのパラメーターの設定

systemctl set-property コマンドを実行すると、アプリケーションのランタイム時にリソース制御の設定を永続的に変更することができます。これを実行するには、root として以下の構文を使用します。
systemctl set-property name parameter=value
name を変更する systemd ユニットの名前に、parameter を変更するパラメーターの名前に、value をこのパラメーターに割り当てる新規の値に置き換えます。
すべてのパラメーターをランタイム時に変更できる訳ではありませんが、リソース制御に関連するパラメーターのほとんどは変更することができます。詳細の一覧については、「ユニットファイルの変更」 を参照してください。systemctl set-property を実行すると、複数のプロパティーを一度に変更できることに注意してください。この方法は、プロパティーを個別に設定する方法よりも推奨されます。
変更はユニットファイルに即時に適用され、書き込まれるため、再起動後もそれらの変更は保持されます。設定を一時的な設定にする --runtime オプションを渡すことでこの動作を変更できます。
systemctl set-property --runtime name property=value

例2.2 systemctl set-property の使用

コマンドラインから CPU および httpd.service のメモリー使用を制限するには、以下を入力します。
~]# systemctl set-property httpd.service CPUShares=600 MemoryLimit=500M
この一時的な変更を行うには、--runtime オプションを追加します。
~]# systemctl set-property --runtime httpd.service CPUShares=600 MemoryLimit=500M

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

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

CPU の管理

cpu コントローラーはデフォルトでカーネルで有効にされるため、すべてのシステムサービスはこれに含まれるプロセスの数にかかわらず、同じ量の CPU 時間を受け取ります。このデフォルト動作は、/etc/systemd/system.conf 設定ファイルの DefaultControllers パラメーターで変更することができます。CPU 割り当てを管理するには、ユニット設定ファイルの [Service] セクションで以下の指示文を使用します。
CPUShares=value
value を CPU 共有の数に置き換えます。デフォルト値は 1024 ですが、この数を増やすことにより、さらに多くの CPU 時間をユニットに割り当てることができます。このパラメーターは、ユニットファイルで CPUAccounting がオンにされていることを示します。
CPUShares パラメーターは cpu.shares コントロールグループパラメーターを制御します。他の CPU 関連のコントロールパラメーターを確認するには、コントローラー固有のカーネルのついてのドキュメントcpu コントローラーの説明を参照してください。

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

Apache サービスにデフォルトの 1024 ではなく、1500 の CPU 共有を割り当てるには、/usr/lib/systemd/system/httpd.service ユニットファイルで CPUShares 設定を変更します。
[Service]
CPUShares=1500
変更を適用するには、systemd の設定を再度読み込み、Apache を再起動することで、変更されたサービスファイルが考慮されるようにします。
~]# systemctl daemon-reload
~]# systemctl restart httpd.service

メモリーの管理

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

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

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

ブロック IO の管理

ブロック IO を管理するには、ユニット設定ファイルの [Service] セクションで以下の指示文を使用します。以下に記載されている指示文は BlockIOAccounting パラメーターが有効にされていることを仮定しています。
BlockIOWeight=value
value を、実行されているプロセスの新たなブロック IO 全体の重み (weight) に置き換えます。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 パラメーターを制御します。コントローラー固有のカーネルのついてのドキュメントblkio コントローラーの説明を参照してください。

注記

現在、blkio リソースコントローラーはバッファリングされた書き込み操作をサポートしません。これは主として直接 I/O を対象としているため、バッファリングされた書き込みを使用するサービスは BlockIOWriteBandwidth で設定された制限を無視します。他方、バッファリングされた読み取り操作はサポートされ、BlockIOReadBandwidth 制限は直接およびバッファリングされた読み取りの両方に正しく適用されます。

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

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

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

リソース管理を容易にするためにユニットファイルで使用できる指示文がほかにもいくつかあります。
DeviceAllow=device_name options
このオプションは特定のデバイスノードへのアクセスを制御します。ここで、device_name/proc/devices で指定されるデバイスノードまたはデバイスグループ名を表しています。optionsrw、および 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 機能のサブセットをサポートします。ただし、サービスの swap 使用を防ぐために、ExecStartPost= オプションを、memory.memsw.limit_in_bytes パラメーターの設定と共に使用することもできます。ExecStartPost= の詳細は、systemd.service(5) man ページを参照してください。

例2.6 cgroup オプションの設定

特定の example サービスの swap 使用を避けるために、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