遅くなるウェブサービス、明確なメッセージなしに終了したワーカー、またはスワップするサーバーは、必ずしもマシンのRAMを使い果たしたわけではありません。systemdを使用すると、ユニットに設定された制限が症状を説明するのに十分な場合があります。
cgroupsは、Linuxカーネルがプロセスグループのリソースをカウント、制限、優先することを可能にします。メモリを追加したり、ランダムに再起動したりする前に、systemdが対象のサービスに適用している内容を確認してください。

サービスのcgroupを見る
最近のディストリビューションでは、systemdは各サービスを独自のcgroupに入れます。Nginx、PostgreSQL、またはアプリケーションワーカーのような従来のユニットを診断するために、手動でPIDを移動させる必要はありません。
まず、サービスの状態とリソースに関連するプロパティを確認してください。nginx.serviceを実際のユニット名に置き換えてください。
systemctl status nginx.service --no-pager
systemctl show nginx.service -p ControlGroup -p MainPID -p MemoryCurrent -p MemoryMax -p MemoryHigh -p CPUQuotaPerSecUSec
ControlGroupは、systemdによって管理されているパスを示します。MemoryCurrentは、読み取り時点でのユニットに対して計上されたメモリを表示します。もしMemoryMaxがinfinityの場合、systemdはこのサービスに対してハードメモリ制限を設定していないことを意味します。
PIDから始めて、/procからそのcgroupを再確認します。cgroup v2では、0::/system.slice/nginx.serviceのような行が見えてくることがよくあります。
pid=$(systemctl show nginx.service -p MainPID --value)
cat /proc/$pid/cgroup
もしMainPIDが0なら、そのサービスにはアクティブなメインプロセスがありません。空のPIDから結論を出すのではなく、systemctl statusとjournalctlを再確認してください。
メモリおよびCPUの制限を読む
MemoryMaxはハードリミットです。cgroupがこの上限に達し、カーネルが十分なメモリを回収できない場合、グループ内のプロセスがOOMキラーによって終了される可能性があります。
MemoryHighはより穏やかです。カーネルは割り当てを抑え、この閾値を超えた時にメモリを回収しようとします。サービスが最初のピークでクラッシュしないように抑えるためには、MemoryMaxよりも通常はより良い初期設定です。
CPUQuotaはサービスに対して利用可能なCPU時間を制限します。CPUQuota=25%は論理コアの1/4に相当します。複数のコアがあるマシンでは、CPUQuota=200%が最大で2コアのCPU時間を許可します。
systemctl show nginx.service
-p MemoryCurrent -p MemoryMax -p MemoryHigh
-p CPUUsageNSec -p CPUQuotaPerSecUSec
割り当てと優先度を混同しないでください。割り当てはサービスが超えてはいけないCPU量を制限します。優先度は、niceやCPUWeightを使用して主に複数のタスクが同時にCPUを要求する場合の競争を調停します。
制限の原因を見つける
制限は、パッケージによって提供されたファイル、systemdのドロップイン、またはローカルに作成されたオーバーライドから来る可能性があります。サービスを変更する前に、完全な設定を確認してください。
systemctl cat nginx.service
systemctl show nginx.service -p FragmentPath -p DropInPaths
/etc/systemd/system/nginx.service.d/内のファイルは、通常、パッケージによって提供されたユニットよりも優先されます。/usr/lib/systemd/system/または/lib/systemd/system/内のファイルを直接変更することは避けてください。更新によって上書きされる可能性があります。
次に、症状を確認してください。遅くなるサービスは、遅いSQLクエリ、飽和したディスク、満杯のキュー、またはアプリケーションエラーによっても引き起こされる場合があります。
journalctl -u nginx.service -b --no-pager
journalctl -k -b | grep -Ei 'oom|out of memory|killed process|memory cgroup'
制限がinfinityのままで、カーネルジャーナルにメモリ関連のイベントが表示されない場合、cgroupsに触れる前に他の場所を調査してください:アプリケーションログ、ディスクメトリクス、ネットワーク遅延、またはプロセスの実際の消費量。
サービスに触れずにテストする
構文を検証したり、制限の効果を測定したりするには、systemd-runを使用して一時ユニットを起動します。テストはNginx、PostgreSQL、またはビジネスサービスに変更を加えません。
sudo systemd-run --unit=essai-limite-memoire
--property=MemoryMax=256M
--property=CPUQuota=25%
/usr/bin/bash -c 'sleep 300'
次に、適用されたプロパティを確認してください。CPUQuota=25%のために、systemdは250ms相当の値を表示することがあります。
systemctl show essai-limite-memoire.service
-p MemoryMax -p CPUQuotaPerSecUSec -p ControlGroup -p ActiveState
systemctl cat essai-limite-memoire.service
終了したら、テストユニットを停止してください。sleepの場合、忘れても大きな問題はありませんが、この習慣は実際のコマンドを起動したときに驚きを避ける助けになります。
sudo systemctl stop essai-limite-memoire.service
systemdのオーバーライドを適用する
ログと測定が制限が意味を持つことを確認したら、systemdのオーバーライドを通じて設定してください。以下の例は、800MBのハイサイド、1GBのハードリミット、およびCpuコア1つに相当するサービスを制限します。
sudo systemctl edit mon-service.service
必要なディレクティブのみを追加してください。通常の消費量とピークを観察した後でない限り、これらの値を運用サービスにコピーすることは避けてください。
[Service]
MemoryHigh=800M
MemoryMax=1G
CPUQuota=100%
systemdを再読み込みし、サービスを再起動するのは中断が許される場合にのみ行ってください。重要なコンポーネントに触れるときは、SSHセッションをもう一つ開いておいてください。
sudo systemctl daemon-reload
sudo systemctl restart mon-service.service
systemctl status mon-service.service --no-pager
systemctl show mon-service.service -p MemoryCurrent -p MemoryHigh -p MemoryMax -p CPUQuotaPerSecUSec
もしサービスが起動しなくなったり、遅すぎたりする場合は、注意してオーバーライドを取り消してください。sudo systemctl revert mon-service.serviceはユニットのローカルオーバーライドを削除します。同じディレクトリに他の保持する設定がある場合は使用しないでください。
変更後のチェック
systemctl is-active mon-service.serviceで状態を確認してください。- 再起動後に
MemoryCurrent、MemoryHigh、MemoryMax、およびCPUQuotaPerSecUSecを再確認してください。 - 問題があったピーク負荷中に
journalctl -u mon-service.service -bとカーネルジャーナルを監視してください。 - アプリケーション側の影響を測定してください:応答時間、遅れたジョブ、キュー、ユーザーエラー。
- 設定の理由、日付、保持された値、および修正された症状を運用手順に記録してください。
cgroupsはマシンの残りの部分を保護し、制限を明示化します。メモリリーク、コストの高いクエリ、または不適切にスケールされたワーカーを修正するものではありません。上限に達した場合は、ログ、観察された負荷、および設定値を保持して、制限を調整するかアプリケーションを修正するかを選択してください。
さらに詳しく知りたい場合は、systemd.resource-control(5)が各ディレクティブについて詳しく説明しています。ガイドNice under Linuxは、厳格な上限が合わない場合のCPU優先度を選択する助けになります。