我有一个服务(HTCondor 批处理系统),它作为 cpu、cpuacct 和内存 cgroup 切片(CentOS 7 @ 3.10.0-*)内的服务单元启动。
该服务启动子进程(~~> 批处理作业),并为其创建子切片,即细分其父资源。无需进一步干预,启动的进程位于子切片中
wc -l /sys/fs/cgroup/cpu,cpuacct/system.slice/condor.service/tasks
19
wc -l /sys/fs/cgroup/cpu,cpuacct/system.slice/condor.service/*/tasks
29 /sys/fs/cgroup/cpu,cpuacct/system.slice/condor.service/[email protected]/tasks
22 /sys/fs/cgroup/cpu,cpuacct/system.slice/condor.service/[email protected]/tasks
22 /sys/fs/cgroup/cpu,cpuacct/system.slice/condor.service/[email protected]/tasks
...
经过交叉检查,这些进程在其进程信息中也有相应的 cgroup,例如,
cat /proc/58683/cgroup
11:perf_event:/
10:memory:/system.slice/condor.service/[email protected]
9:devices:/system.slice
8:blkio:/system.slice/condor.service /[email protected]
7:cpuset:/
6:freezer:/system.slice/condor.service/[email protected]
5:hugetlb:/
4:cpuacct,cpu:/system.slice/condor.service/[email protected]
3:pids:/system.slice/condor.service
2:net_prio,net_cls:/
1:name=systemd:/system.slice/condor.service
据我所知,systemd 似乎不知道子切片,因为 systemd-cgls 显示的进程直接位于父单元的 cgroup 之下
systemd-cgls
...
├─condor.service
│ ├─ 781 /bin/bash ...foo...
│ ├─ 1596 condor_starter -f -a slot1_4 ...baz...
现在,当添加新单元、重新加载 systemd 守护程序并启动新单元时,所有作业子 cgroup 都会消失,并且它们的进程会附加到父 cgroup。
wc -l /sys/fs/cgroup/cpu,cpuacct/system.slice/condor.service/tasks
337 /sys/fs/cgroup/cpu,cpuacct/system.slice/condor.service/tasks
我的假设是,systemd 不知道子切片(从 systemd-cgls 猜测),而从内核的角度来看,这些是正确的 cgroup 切片。启动新单元时,systemd 会注意到与其预期的差异并“清理”。
可以以某种方式避免这种行为吗?
答案1
看起来上游已经通过指定指令修复了这个问题Delegate=
(提交890186d82a– 虽然指定控制器子集比简单地 IMHO 更优雅一些true
)。如果该更新未传播到 CentOS 包,则可以使用以下命令在本地应用它:
systemctl set-property condor.service Delegate=true
答案2
问题是,默认情况下,systemd 假定所有子 cgroup/slices 都由其自身处理,并且任何单元进程都没有自己的控制。
当为某个单元启用委派时,systemd 不会尝试控制该单元的子资源
[Service]
...
Delegate=true
([Slice] 部分也可能是正确的部分,但显然正确的部分取决于版本/内核,所以#YMMV)
请注意,systemd-cgls 和 systemd-cgtop 显示的 cgroups/slices 仍然不同,并且只有 systemd-cgtop 显示 cgroups 的‘正确’内核视图,而 systemd-cgls 即使有委派也不会显示任何切片的子层次结构)