EM0*_*EM0 6 linux ubuntu memory systemd cgroups
我在 Ubuntu 16.04(即将推出 18.04)下运行一些 .NET Core 进程作为 systemd 服务。我有一个 systemd 配置文件 ( /lib/systemd/system/myservice@.service
),如下所示:
[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
Run Code Online (Sandbox Code Playgroud)
我想限制此服务的所有实例可以使用的 RAM总量。我不想将任何单个实例的 RAM 限制为小于该值,因此类似的设置并没有帮助。MemoryHigh
MemoryMax
我知道 systemd 为服务模板创建了一个 cgroup,所以我想以某种方式更改该 cgroup 的内存限制。
在 Ubuntu 18.04 上,我可以手动编辑/sys/fs/cgroup/memory/system.slice/system-myservice.slice/memory.limit_in_bytes
,这基本上可以满足我的要求(当总内存使用量超过限制时,进程会被终止),但是这种方法存在一些问题:
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
在某个时候被重置,我不知道何时或为什么。
我终于成功了!诀窍是创建我自己的切片并将其设置在服务文件中,如下所示:
[Service]
# Everything else as in the original question
Slice=my_service_limit.slice
Run Code Online (Sandbox Code Playgroud)
并创建一个切片单元文件/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
Run Code Online (Sandbox Code Playgroud)
注意:请小心切片的命名,就像-
层次结构分隔符一样,如https://systemd.io/CGROUP_DELEGATION中所述- 对于任何尝试配置此功能的人来说,这是一个非常有用的页面。您可以通过查看输出来检查服务是否真正使用配置的切片systemctl status myservice
- 它应该显示:
CGroup: /my_service_limit.slice/myservice@myinstance.service
Run Code Online (Sandbox Code Playgroud)
没有必要设置systemd.unified_cgroup_hierarchy=1
(根据Ryutaroh Matsumoto的回答)MemoryMax 才能工作,但MemoryHigh是必要的 - 即使在“混合”模式(Ubuntu 18.04 中的默认模式)下,它也会被默默地忽略。
另外值得注意的是,这些仅适用于使用的物理 RAM - 它们不包括使用的交换空间。(似乎有一个单独的 MemorySwapMax 设置,但没有 MemorySwapHigh。)
我们可能需要使用“统一的 cgroup 层次结构”,如 Unified and Legacy Control Group Hierarchies 中所述。
要启用此功能,请将 systemd.unified_cgroup_hierarchy=1 添加到GRUB_CMDLINE_LINUX_DEFAULT
in 中/etc/default/grub
,运行update-grub
,然后重新启动 Linux。
systemd.unified_cgroup_hierarchy
中解释systemd unified cgroup hierarchy
。
[Service]
然后在systemd 单元文件的部分添加以下行,然后运行systemctl daemon-reload
:
Delegate=memory
MemoryHigh=8G (if you choose 8 gigabytes as the limit)
Run Code Online (Sandbox Code Playgroud)
“MemoryHigh”的解释在 中给出
systemd.resource-control
。