Linux cgroup 实现 SSH 用户资源与 GPU 访问限制
Linux cgroup 实现 SSH 用户资源与 GPU 访问限制
概述
在多用户共享的 Linux 服务器上,需要解决两个问题:
- 资源限制:防止单个用户过度占用 CPU、内存,影响其他用户
- GPU 隔离:普通用户不能直接访问 GPU,只能通过 Slurm 等调度系统申请使用
通过 systemd 的 slice 机制 + DevicePolicy,可以用极简的配置同时解决这两个问题。
原理
systemd 用户 slice 层级
用户通过 SSH 登录时,systemd 会自动为该用户创建 slice,层级如下:
1 | |
关键机制是 模板继承:user-.slice.d/ 中的配置会自动应用到所有 user-*.slice。而为特定 UID 创建的 user-0.slice.d/ 则可以覆盖模板配置,实现对 root 的豁免。
DevicePolicy 策略
| 策略 | 行为 |
|---|---|
auto |
默认值,不限制设备访问 |
closed |
只允许标准设备(/dev/null、/dev/tty 等),阻止 nvidia 等非标准设备 |
strict |
仅允许 DeviceAllow 中显式列出的设备 |
closed 正好满足需求:普通用户的 SSH 会话看不到 GPU,但正常终端操作不受影响。
Slurm 作业不受影响
Slurm 作业运行在独立的 cgroup 中,由 Slurm 的 task/cgroup 插件管理设备权限。用户通过 srun/sbatch 提交的 GPU 作业不受 DevicePolicy=closed 限制,因为 Slurm 在作业 cgroup 中会放行分配到的 GPU 设备。
完整配置脚本
1 | |
配置详解
1. 清理旧配置
删除所有残留的 slice 配置,确保干净的状态:
1 | |
2. 顶层全局限速 (user.slice.d)
user.slice 是所有用户 slice 的根,它下面的限制对全部用户合计生效:
1 | |
CPUQuota=2400%:所有user-*.slice加起来最多占用 24 核CPUWeight=2400:当整机 CPU 紧张时,user.slice内进程会拿到更高份额(相对system.slice的默认 100)MemoryMax=64G:所有用户合计内存硬限制
不配置这一层的话,单用户限速是有的,但理论上所有用户可以一起把 CPU 跑满。
3. 普通用户模板 (user-.slice.d)
1 | |
CPUWeight=100:默认权重,竞争中处于劣势MemoryMax=8G:内存硬限制,超限触发 OOM KillerDevicePolicy=closed:允许 /dev/null、/dev/tty 等标准设备,阻止 /dev/nvidia* 等 GPU 设备
用
CPUWeight替代CPUQuota的好处:用户需要时可以短时间借用空闲 CPU(抢占空闲核),长时间占用才会被压回 100/2400=4.2% 的份额。这样突发编译等场景不会卡死,但又不会被恶意常驻进程拖垮。
4. root 豁免 (user-0.slice.d)
1 | |
空值表示取消从模板继承的限制。root 用户不受任何约束。
5. 特定用户白名单 (user-<UID>.slice.d)
把可信用户(管理员、研究员)的 UID 单独加 override,让他们与 root 同等待遇:
1 | |
白名单的另一种用法:放开 CPU/内存但仍然禁止 GPU 访问(如服务账号):
1 | |
要新增白名单用户:1
2
3
4
5
6
7
8
9UID=$(id -u <username>)
sudo mkdir -p /etc/systemd/system/user-${UID}.slice.d
sudo tee /etc/systemd/system/user-${UID}.slice.d/override.conf <<'EOF'
[Slice]
CPUWeight=2400
MemoryMax=
DevicePolicy=auto
EOF
sudo systemctl daemon-reload
6. 生效
1 | |
注意:
restart systemd-logind会断开所有 SSH 会话(包括当前的),请在 console 或 IPMI 上操作,或改用sudo reboot重启系统。
验证
检查单个用户的 cgroup 配置
1 | |
批量巡检所有用户 slice(check.sh)
要快速看每个用户当前生效的限制,用以下脚本:
1 | |
输出示例:1
2
3/sys/fs/cgroup/user.slice/user-0.slice: CPU=max 100000, Memory=max
/sys/fs/cgroup/user.slice/user-1003.slice: CPU=max 100000, Memory=max
/sys/fs/cgroup/user.slice/user-1011.slice: CPU=200% 800000, Memory=8G
CPU=max 100000表示不限速(max= 100000 微秒/周期)CPU=200% 800000表示限制为 200%Memory=max表示不限内存Memory=8G表示限制为 8GB
通过对比目录下的限制值与 user-.slice.d/limits.conf 应有值,能立即定位哪个用户的 override 没生效。
验证 GPU 不可见(普通用户)
1 | |
验证 GPU 通过 Slurm 可用
1 | |
查询用户 UID
slice 名称中的数字是 UID,可通过以下命令查询:
1 | |
注意事项
- Slurm 前提:需要 Slurm 配置
ConstrainDevices=yes(在 cgroup.conf 中),否则 Slurm 作业也无法访问 GPU - 已有会话:配置生效后,已登录用户需要重新登录才会应用新限制
- 参数调整:CPUQuota 和 MemoryMax 根据实际硬件资源调整
- 持久化:配置写入 /etc/systemd/system,重启后自动生效
操作前请备份重要数据,建议在测试环境验证后再部署到生产系统。