systemd,每个用户的 CPU 和/或内存限制

systemd,每个用户的 CPU 和/或内存限制

还有类似的问题:Cgroups,限制每个用户的内存但该解决方案在“现代”系统中不起作用,因为 cgroups 层次结构由 systemd 管理。

直接的解决方案 — 模板化 user-UID.slice — 不起作用,因为它不受支持,请参阅https://github.com/systemd/systemd/issues/2556

有没有什么方法可以达到预期的效果——根据每个用户管理 CPU 和/或内存资源?

更新型多巴胺:为了历史,我将保留我的解决方案,但systemctl set-property应该在登录时使用来调用,pam_exec请参阅https://github.com/hashbang/shell-etc/pull/183. 在这种方法中,用户登录和设置限制之间没有时间窗口。

我的解决方案org.freedesktop.login1.Manage对象接口/org/freedesktop/login1发出UserNew(u uid, o object_path)信号。我编写了一个简单的守护进程,它监听信号,并且每次发出信号时都会CPUAccounting=true为刚登录的用户的切片设置。

答案1

从 systemd v239 开始,你可以使用插件 https://github.com/systemd/systemd/commit/5396624506e155c4bc10c0ee65b939600860ab67

# mkdir -p /etc/systemd/system/user-.slice.d
# cat > /etc/systemd/system/user-.slice.d/50-memory.conf << EOF
[Slice]
MemoryMax=1G
EOF
# systemctl daemon-reload

答案2

更新型多巴胺:为了历史,我将保留我的解决方案,但systemctl set-property应该在登录时使用来调用,pam_exec请参阅https://github.com/hashbang/shell-etc/pull/183. 在这种方法中,用户登录和设置限制之间没有时间窗口。

旧解决方案

这是一个非常简单的脚本,可以完成这项工作

#!/bin/bash

STATE=1 # 1 -- waiting for signal; 2 -- reading UID

dbus-monitor --system "interface=org.freedesktop.login1.Manager,member=UserNew" |
while read line
do
    case $STATE in
    1) [[ $line =~ member=UserNew ]] && STATE=2 ;;
    2) read dbus_type ID <<< $line
       systemctl set-property user-$ID.slice CPUAccounting=true
       STATE=1
    ;;
    esac
done

它可以轻松扩展以支持每个用户的内存限制。

在具有 2 个 CPU 和 2 个用户的虚拟机上进行了测试。第一个用户运行dd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null命令,第二个用户只运行 的一个实例dd。如果不运行此脚本, 的每个实例dd都会使用大约 70% 的 CPU。

然后我启动了脚本,重新登录用户,并dd再次启动命令。这一次,dd第一个用户的两个进程各自只占用了 50% 的 CPU,而第二个用户的进程占用了 100% 的 CPU。此外,还systemd-cgtop显示,/user.slice/user-UID1.slice/user.slice/user-UID2.slice各自占用了 100% 的 CPU 时间,但第一个切片有 6 个任务,而第二个切片只有 5 个任务。

当我终止dd第二个用户的任务时,第一个用户开始消耗 200% 的 CPU 时间。因此,我们有公平的资源分配,而没有“每个用户只能使用一个核心”这样的人为限制。

答案3

您提到的问题仍然未解决,但这对我来说有用。

sudo systemctl edit --force user-1234.slice

然后输入并保存:

[Slice]
CPUQuota=10%

我不确定它为什么有效。

答案4

在 Ubuntu 上,我需要将TasksMax单个用户(即运行我组所有测试的 CI 服务用户 (UID 2000))的默认限制从 10813 增加到更高的值。我使用 检查了旧限制sudo systemctl status user-2000.slice,然后通过键入并输入以下内容设置了新限制sudo systemctl edit --force user-2000.slice

[Slice]
TasksMax=50000

这将更新限制并创建/etc/systemd/system/user-2000.slice.d/override.conf包含上述设置的文件。我将该文件添加到我的 Ansible playbook 中,现在它已部署到我们所有的机器上,因此即使我们重建服务器,限制仍保持不变。

相关内容