

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

# systemd を使用して AL2023 でのプロセスリソースの使用を制限する
<a name="resource-limiting-systemd"></a>

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

 包括的な情報については、アップストリームの「`systemd`」ドキュメントで「[systemd.resource-control](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html)」を参照するか、AL2023 インスタンスに関する man ページで「`systemd.resource-control`」を参照してください。

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

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

## 1 回限りのコマンドを実行するための `systemd-run` によるリソースコントロール
<a name="resource-limiting-systemd-interactive"></a>

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

**Example リソースの使用量を制限せずに、コマンドラインで `systemd-run` を使用してプロセスを実行する**  

1.  この例で使用する `stress-ng` パッケージが、インストール済みであることを確認します。

   ```
   [ec2-user ~]$ sudo dnf install -y stress-ng
   ```

1.  `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` に指示します。

**Example コマンドラインで `systemd-run` を使用してプロセスを実行し、CPU 使用時間を 1 秒に制限する**  

1. この例を実行するには、`stress-ng` がインストール済みであることを確認します。

1.  `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 時間の最大割合を制限して、ユーザーリクエストを処理するプロセスのためにリソースを解放することが望ましい場合があります。

**Example `systemd-run` を使用して 1 つの CPU における CPU 時間の 10% にプロセスを制限する**  

1. この例を実行するには、`stress-ng` がインストール済みであることを確認します。

1.  `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](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html)」を参照するか、AL2023 インスタンスに関する man ページで「`systemd.resource-control`」を参照してください。

 バックグラウンドでは、`systemd` は `cgroups` などの Linux カーネルの機能を使用して、これらの制限を実装し、手動で設定する必要がないようにしています。[`cgroup-v2` に関する Linux カーネルのドキュメント](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html)には、`cgroups` 作業に関する多くの詳細が記載されています。

## `systemd` サービスでのリソースコントロール
<a name="resource-limiting-systemd-service"></a>

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

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

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

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

   ```
   [ec2-user ~]$ sudo dnf install -y memcached libmemcached-awesome-tools
   ```

1.  `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
   ```

1.  `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.
   ```

1.  `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.
   ```

1.  `MemoryMax` プロパティを使用して `memcached.service` のハード制限を設定します。上限に達すると、OOM Killer が呼び出されます。サービスに追加のオプションを設定するには、オーバーライドファイルにオプションを追加します。これは、`/etc/systemd/system/memcached.service.d/override.conf` ファイルを直接編集して行うか、`systemctl` の `edit` コマンドを使用してインタラクティブに行うことができます。

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

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

   ```
   [Service]
   MemoryMax=32M
   ```

1. 設定を再ロードするように `systemd` に指示します。

   ```
   [ec2-user ~]$ sudo systemctl daemon-reload
   ```

1. `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.
   ```

1.  サービスは、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.
   ```

1.  これで 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'.
   ```