web-dev-qa-db-ja.com

systemdサービスの複数のインスタンスの合計メモリ使用量を制限する

Ubuntu 16.04(まもなく18.04になる)でsystemdサービスとしていくつかの.NETCoreプロセスを実行しています。次のようなsystemd構成ファイル(/lib/systemd/system/[email protected])があります。

[Unit]
Description=My Service %i

[Service]
Type=simple
User=myservice
EnvironmentFile=/etc/environment
WorkingDirectory=/home/myservice/instances/%i
ExecStart=/opt/dotnet/dotnet My.Service.dll

[Install]
WantedBy=multi-user.target

totalこのサービスのインスタンスが使用できるRAM that allインスタンスの量を制限したい。=を制限したくないRAM個々のインスタンスの場合はそれ未満になるため、MemoryHighMemoryMaxなどの設定は役に立ちません。

Systemdがサービステンプレートのcgroupを作成することを知っているので、そのcgroupのメモリ制限を何らかの方法で変更したいと思います。

Ubuntu 18.04では、/sys/fs/cgroup/memory/system.slice/system-myservice.slice/memory.limit_in_bytesを手動で編集できます。これは基本的に私が望むことを行います(合計メモリ使用量が制限を超えるとプロセスが強制終了されます)が、このアプローチにはいくつかの問題があります。

  • このファイルは、サービスが開始されるまで、起動時に常に存在するとは限りません。
  • Ubuntu 18.04では、systemctl daemon-reloadが呼び出されるたびにこのファイルが上書きされます。
  • ファイルに書き込もうとすると、write error: Device or resource busyが返されることがあります。

(Ubuntu 16.04では、サービスが開始されるたびに制限がリセットされるように見えるため、効果はありません。)

Systemd自体にこの値を設定させる方法があるので、それと戦う必要はありませんか?または、プロセスのグループの合計メモリ使用量を制限する他の方法はありますか?それらはすべて同じユーザーとして実行されるため、たとえば、そのユーザーが使用するRAMを制限しても問題ありません。

手動でcgroup(cgcreate -t myservice:myservice -g memory:mycgroup)を作成してから、サービス構成のExecStart/usr/bin/cgexec -g memory:mycgroup /opt/dotnet/dotnet My.Service.dllに変更してみましたが、これもまた一種の作業ですが、確実ではありません。 memory.limit_in_bytesがどこかでリセットされましたが、いつ、なぜかわかりません.

3
EM0

私はついにこれを機能させました!秘訣は、次のように、独自のスライスを作成してサービスファイルに設定することでした。

[Service]
# Everything else as in the original question
Slice=my_service_limit.slice

そして、次のようなスライスユニットファイル/lib/systemd/system/my_service_limit.sliceを作成します。

[Unit]
Description=Slice that limits memory for all my services

[Slice]
# MemoryHigh works only in "unified" cgroups mode, NOT in "hybrid" mode
MemoryHigh=500M
# MemoryMax works in "hybrid" cgroups mode, too
MemoryMax=600M

注:-は階層区切り文字であるため、スライスの名前には注意してください。 https:/ /systemd.io/CGROUP_DELEGATION -これを構成しようとする人にとって非常に役立つページ。 systemctl status myserviceの出力を見ると、サービスが実際に構成されたスライスを使用しているかどうかを確認できます。

  CGroup: /my_service_limit.slice/[email protected]

MemoryMaxが機能するためにsystemd.unified_cgroup_hierarchy=1松本竜太郎の答えによる)を設定する必要はありませんでしたが、MemoryHighに必要でした-「ハイブリッド」モード(Ubuntu 18.04のデフォルト)でも、暗黙的に無視されます。

また、これらは物理的なRAM使用済み-使用されるスワップスペースを含まない含まない)にのみ適用されることにも注意してください(別のMemorySwapMax設定があります。しかし、MemorySwapHighはないようです。)

2
EM0

nified and Legacy Control Group Hierarchies で説明されているように、「unifiedcgrouphierarchy」を使用する必要があるかもしれません。

この機能を有効にするには、systemd.unified_cgroup_hierarchy = 1をGRUB_CMDLINE_LINUX_DEFAULT/etc/default/grubに追加し、update-grubを実行して、Linuxを再起動します。

systemd.unified_cgroup_hierarchysystemd unified cgroup hierarchy で説明されています。

次に、systemdユニットファイルの[Service]セクションに次の行を追加し、systemctl daemon-reloadを実行します。

Delegate=memory
MemoryHigh=8G (if you choose 8 gigabytes as the limit)

「MemoryHigh」の説明は systemd.resource-control にあります。

1