systemd を使用して AL2023 でのプロセスリソースの使用を制限する - Amazon Linux 2023

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

systemd を使用して AL2023 でのプロセスリソースの使用を制限する

Amazon Linux 2023 (AL2023) では、systemd を使用して、プロセス (またはプロセスのグループ) で使用できるリソースを制御することをお勧めします。systemd の使用は、cgroups の手動操作や、cpulimit (以前にサードパーティの EPEL リポジトリで提供されていた Amazon Linux 専用の機能) などのユーティリティの使用に代わる、強力で使いやすい代替手段となります。

包括的な情報については、アップストリームの「systemd」ドキュメントで「systemd.resource-control」を参照するか、AL2023 インスタンスに関する man ページで「systemd.resource-control」を参照してください。

以下の例では、stress-ng CPU ストレステストを (stress-ng パッケージから) 使用して CPU を大量に使用するアプリケーションをシミュレーションします。また、memcached を使用してメモリを大量に使用するアプリケーションをシミュレートします。

1 回限りのコマンドに CPU 制限を設定する方法と、サービスにメモリ制限を設定する方法を以下の例で示します。systemd が提供するほとんどのリソース制約は、systemd によってプロセスを実行するあらゆる場所で使用でき、複数の制約を同時に使用できます。以下の例では、わかりやすいように 1 つの制約のみを使用しています。

1 回限りのコマンドを実行するための systemd-run によるリソースコントロール

systemd は一般的にシステムサービスに関連付けられていますが、非ルートユーザーによるサービスの実行、タイマーのスケジュール設定、または 1 回限りのプロセスの実行にも使用できます。以下の例では、サンプルアプリケーションとして stress-ng を使用します。最初の例では、ec2-user デフォルトアカウントで systemd-run を使用してアプリケーションを実行し、2 番目の例ではアプリケーションの CPU 使用率を制限します。

例 リソースの使用量を制限せずに、コマンドラインで systemd-run を使用してプロセスを実行する
  1. この例で使用する stress-ng パッケージが、インストール済みであることを確認します。

    [ec2-user ~]$ sudo dnf install -y stress-ng
  2. systemd-run を使用して、10 秒の CPU ストレステストを実行します。使用できる CPU の量は制限しません。

    [ec2-user ~]$ systemd-run --user --tty --wait --property=CPUAccounting=1 stress-ng --cpu 1 --timeout 10 Running as unit: run-u6.service Press ^] three times within 1s to disconnect TTY. stress-ng: info: [339368] setting to a 10 second run per stressor stress-ng: info: [339368] dispatching hogs: 1 cpu stress-ng: info: [339368] successful run completed in 10.00s Finished with result: success Main processes terminated with: code=exited/status=0 Service runtime: 10.068s CPU time consumed: 9.060s

    --user オプションは、ログインしているユーザーとしてコマンドを実行するように systemd-run に指示します。--tty オプションは、TTY がアタッチされていることを意味し、--wait は、サービスが終了するまで待機することを意味します。--property=CPUAccounting=1 オプションは、プロセスの実行に使用された CPU 時間を記録するように systemd-run に指示します。--property コマンドラインオプションを使用して、systemd.unit 設定ファイルで構成できる systemd-run 設定を渡すことができます。

CPU に負荷をかけるように指示すると、stress-ng プログラムは使用可能なすべての CPU 時間を使用して、指示した実行時間が経過するまで、テストを実行します。実際のアプリケーションでは、プロセスの合計実行時間を制限することが望ましい場合があります。次の例では、systemd-run を使用して設定した上限時間よりも長い時間実行するように stress-ng に指示します。

例 コマンドラインで systemd-run を使用してプロセスを実行し、CPU 使用時間を 1 秒に制限する
  1. この例を実行するには、stress-ng がインストール済みであることを確認します。

  2. LimitCPU プロパティは ulimit -t と同等であり、このプロセスで使用できる CPU の最大時間を制限します。この例では、10 秒のストレス実行を要求し、CPU 使用時間を 1 秒に制限しているため、コマンドは SIGXCPU シグナルを受信して失敗します。

    [ec2-user ~]$ systemd-run --user --tty --wait --property=CPUAccounting=1 --property=LimitCPU=1 stress-ng --cpu 1 --timeout 10 Running as unit: run-u12.service Press ^] three times within 1s to disconnect TTY. stress-ng: info: [340349] setting to a 10 second run per stressor stress-ng: info: [340349] dispatching hogs: 1 cpu stress-ng: fail: [340349] cpu instance 0 corrupted bogo-ops counter, 1370 vs 0 stress-ng: fail: [340349] cpu instance 0 hash error in bogo-ops counter and run flag, 3250129726 vs 0 stress-ng: fail: [340349] metrics-check: stressor metrics corrupted, data is compromised stress-ng: info: [340349] unsuccessful run completed in 1.14s Finished with result: exit-code Main processes terminated with: code=exited/status=2 Service runtime: 1.201s CPU time consumed: 1.008s

より一般的には、特定のプロセスで消費できる CPU 時間の割合を制限したい場合があります。次の例では、stress-ng が消費できる CPU 時間の割合を制限します。実際のサービスでは、バックグラウンドプロセスが消費できる CPU 時間の最大割合を制限して、ユーザーリクエストを処理するプロセスのためにリソースを解放することが望ましい場合があります。

systemd-run を使用して 1 つの CPU における CPU 時間の 10% にプロセスを制限する
  1. この例を実行するには、stress-ng がインストール済みであることを確認します。

  2. CPUQuota プロパティを使用して、実行するコマンドの CPU 使用率を制限するように systemd-run に指示します。プロセスの実行時間を制限するのではなく、使用できる CPU の量のみを制限します。

    [ec2-user ~]$ systemd-run --user --tty --wait --property=CPUAccounting=1 --property=CPUQuota=10% stress-ng --cpu 1 --timeout 10 Running as unit: run-u13.service Press ^] three times within 1s to disconnect TTY. stress-ng: info: [340664] setting to a 10 second run per stressor stress-ng: info: [340664] dispatching hogs: 1 cpu stress-ng: info: [340664] successful run completed in 10.08s Finished with result: success Main processes terminated with: code=exited/status=0 Service runtime: 10.140s CPU time consumed: 1.014s

    CPU アカウンティングを参照すると、サービスの実行時間は 10 秒でも、実際の CPU 時間は 1 秒しか消費されなかったことがわかります。

CPU、メモリ、ネットワーク、IO のリソース使用量を制限するように systemd を設定する方法は数多くあります。包括的なドキュメントについては、アップストリームの「systemd」ドキュメントで「systemd.resource-control」を参照するか、AL2023 インスタンスに関する man ページで「systemd.resource-control」を参照してください。

バックグラウンドでは、systemdcgroups などの Linux カーネルの機能を使用して、これらの制限を実装し、手動で設定する必要がないようにしています。cgroup-v2 に関する Linux カーネルのドキュメントには、cgroups 作業に関する多くの詳細が記載されています。

systemd サービスでのリソースコントロール

システムリソースの使用を制御するために、systemd サービスの [Service] セクションに追加できるパラメータがいくつかあります。これらには、ハード制限とソフト制限の両方が含まれます。各オプションの正確な動作については、アップストリームの「systemd」ドキュメントで「systemd.resource-control」を参照するか、AL2023 インスタンスに関する man ページで「systemd.resource-control」を参照してください。

一般的に使用される制限は、メモリ使用量のスロットリング制限を指定する MemoryHigh、ハード上限 (上限に達すると OOM キラーが呼び出されます) を設定する MemoryMax、および CPUQuota (前のセクションの説明を参照) です。また、固定値ではなく、重みと優先順位を設定することもできます。

systemd を使用してサービスにメモリ使用量の制限を設定する

この例では、memcached (単純なキー値キャッシュ) のハードメモリ使用量の制限を設定し、OOM Killer をシステム全体ではなく、該当サービスに対してどのように呼び出すかを示します。

  1. まず、この例に必要なパッケージをインストールする必要があります。

    [ec2-user ~]$ sudo dnf install -y memcached libmemcached-awesome-tools
  2. memcached.service を有効にしてサービスを起動し、memcached が実行されるようにします。

    [ec2-user ~]$ sudo systemctl enable memcached.service Created symlink /etc/systemd/system/multi-user.target.wants/memcached.service → /usr/lib/systemd/system/memcached.service. [ec2-user ~]$ sudo systemctl start memcached.service
  3. memcached.service が実行されていることを確認します。

    [ec2-user ~]$ sudo systemctl status memcached.service ● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Active: active (running) since Fri 2025-01-31 22:36:42 UTC; 1s ago Main PID: 356294 (memcached) Tasks: 10 (limit: 18907) Memory: 1.8M CPU: 20ms CGroup: /system.slice/memcached.service └─356294 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1 Jan 31 22:35:36 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
  4. memcached がインストールして実行したら、ランダムなデータをキャッシュに挿入し、それが機能することを確認できます。

    /etc/sysconfig/memcached で、CACHESIZE 変数はデフォルトで 64 (64 メガバイト) に設定されます。最大キャッシュサイズよりも多くのデータをキャッシュに挿入すると、キャッシュが満杯になり、memcached-tool によって一部の項目が削除されることがわかります。また、memcached.service が約 64 MB のメモリを使用していることもわかります。

    [ec2-user ~]$ for i in $(seq 1 150); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done [ec2-user ~]$ memcached-tool localhost display # Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM 2 120B 0s 1 0 no 0 0 0 39 512.0K 4s 63 126 yes 24 2 0 [ec2-user ~]$ sudo systemctl status memcached.service ● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Active: active (running) since Fri 2025-01-31 22:36:42 UTC; 7min ago Main PID: 356294 (memcached) Tasks: 10 (limit: 18907) Memory: 66.7M CPU: 203ms CGroup: /system.slice/memcached.service └─356294 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1 Jan 31 22:36:42 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
  5. MemoryMax プロパティを使用して memcached.service のハード制限を設定します。上限に達すると、OOM Killer が呼び出されます。サービスに追加のオプションを設定するには、オーバーライドファイルにオプションを追加します。これは、/etc/systemd/system/memcached.service.d/override.conf ファイルを直接編集して行うか、systemctledit コマンドを使用してインタラクティブに行うことができます。

    [ec2-user ~]$ sudo systemctl edit memcached.service

    オーバーライドに以下を追加して、サービスのメモリのハード制限を 32 MB に設定します。

    [Service] MemoryMax=32M
  6. 設定を再ロードするように systemd に指示します。

    [ec2-user ~]$ sudo systemctl daemon-reload
  7. memcached.service が 32 MB のメモリ制限で実行されていることを確認します。

    [ec2-user ~]$ sudo systemctl status memcached.service ● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Drop-In: /etc/systemd/system/memcached.service.d └─override.conf Active: active (running) since Fri 2025-01-31 23:09:13 UTC; 49s ago Main PID: 358423 (memcached) Tasks: 10 (limit: 18907) Memory: 1.8M (max: 32.0M available: 30.1M) CPU: 25ms CGroup: /system.slice/memcached.service └─358423 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1 Jan 31 23:09:13 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
  8. サービスは、32 MB 未満のメモリを使用している間は正常に機能します。これをチェックするには、32 MB 未満のランダムデータをキャッシュにロードし、サービスのステータスを確認します。

    [ec2-user ~]$ for i in $(seq 1 30); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done
    [ec2-user ~]$ sudo systemctl status memcached.service ● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Drop-In: /etc/systemd/system/memcached.service.d └─override.conf Active: active (running) since Fri 2025-01-31 23:14:48 UTC; 3s ago Main PID: 359492 (memcached) Tasks: 10 (limit: 18907) Memory: 18.2M (max: 32.0M available: 13.7M) CPU: 42ms CGroup: /system.slice/memcached.service └─359492 /usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -l 127.0.0.1,::1 Jan 31 23:14:48 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon.
  9. これで 32 MB を超えるメモリを memcached で使用できるようになり、memcached のデフォルト設定である 64 MB のフルキャッシュを試すことができます。

    [ec2-user ~]$ for i in $(seq 1 150); do dd if=/dev/random of=$i bs=512k count=1; memcp -s localhost $i; done

    上記のコマンドの実行中に、memcached サーバーへの接続エラーが発生したことがわかります。これは、OOM Killer で設定した制限により、プロセスが強制終了されたためです。システムの残りの部分は通常どおり機能します。OOM Killer は、制限した memcached.service のみを対象とし、他のプロセスは考慮しません。

    [ec2-user ~]$ sudo systemctl status memcached.service ● memcached.service - memcached daemon Loaded: loaded (/usr/lib/systemd/system/memcached.service; enabled; preset: disabled) Drop-In: /etc/systemd/system/memcached.service.d └─override.conf Active: failed (Result: oom-kill) since Fri 2025-01-31 23:20:28 UTC; 2s ago Duration: 2.901s Process: 360130 ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS (code=killed, signal=KILL) Main PID: 360130 (code=killed, signal=KILL) CPU: 94ms Jan 31 23:20:25 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: Started memcached.service - memcached daemon. Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: A process of this unit has been killed by the OOM killer. Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: Main process exited, code=killed, status=9/KILL Jan 31 23:20:28 ip-1-2-3-4.us-west-2.compute.internal systemd[1]: memcached.service: Failed with result 'oom-kill'.