自动将 systemd 切片分配给特定的 cset

自动将 systemd 切片分配给特定的 cset

在 systemd 下的 Debian 上,默认情况下,libvirt 下的 KVM 虚拟机被分配到“machine.slice”切片。

如果我随后为该切片添加一个 cpusetcset和一些自定义的 CPU 集,并启动虚拟机,则虚拟机将添加到正确的 cpuset,即

user@host ~ $ sudo cset set --list --recurse
cset: 
         Name       CPUs-X    MEMs-X Tasks Subs Path
 ------------ ---------- - ------- - ----- ---- ----------
         root       0-31 y       0 y   610    1 /
 machine.slice 2-15,18-31 n       0 n     0    1 /machine.slice
 machine-qemu\x2d1\x2dweb1.scope 2-15,18-31 n       0 n     0    5 /ma....scope
        vcpu1 2-15,18-31 n       0 n     1    0 /machine.sli...web1.scope/vcpu1
        vcpu2 2-15,18-31 n       0 n     1    0 /machine.sli...web1.scope/vcpu2
        vcpu0 2-15,18-31 n       0 n     1    0 /machine.sli...web1.scope/vcpu0
     emulator 2-15,18-31 n       0 n    82    0 /machine.sli...1.scope/emulator
        vcpu3 2-15,18-31 n       0 n     1    0 /machine.sli...web1.scope/vcpu3

我尝试使用单独的切片和 cpuset 来复制此行为。但是,这似乎不起作用。

首先我创建 cset:

user@host ~ $ sudo cset set -c 0-1,16-17 osd.slice
cset: --> created cpuset "osd.slice"

然后我设置我想要使用切片的服务:

user@host ~ $ diff -u /lib/systemd/system/[email protected] /etc/systemd/system/[email protected]
--- /lib/systemd/system/[email protected]       2021-05-27 06:04:21.000000000 -0400
+++ /etc/systemd/system/[email protected]       2022-11-08 17:20:32.515087642 -0500
@@ -6,6 +6,7 @@
 Wants=network-online.target local-fs.target time-sync.target remote-fs-pre.target ceph-osd.target
 
 [Service]
+Slice=osd.slice
 LimitNOFILE=1048576
 LimitNPROC=1048576
 EnvironmentFile=-/etc/default/ceph

然后我启动其中一项服务。如果我检查服务状态,我确实看到它在正确的切片/cgroup 中:

user@host ~ $ systemctl status [email protected][email protected] - Ceph object storage daemon osd.0
     Loaded: loaded (/etc/systemd/system/[email protected]; disabled; vendor preset: enabled)
     Active: active (running) since Tue 2022-11-08 17:22:32 EST; 1s ago
    Process: 251238 ExecStartPre=/usr/lib/ceph/ceph-osd-prestart.sh --cluster ${CLUSTER} --id 0 (code=exited, status=0/SUCCESS)
   Main PID: 251245 (ceph-osd)
      Tasks: 25
     Memory: 29.5M
        CPU: 611ms
     CGroup: /osd.slice/[email protected]
             └─251245 /usr/bin/ceph-osd -f --cluster ceph --id 0 --setuser ceph --setgroup ceph

出于理智考虑,如果我检查 VM 瞬态服务,它看起来基本相同:

$ systemctl status machine-qemu\\x2d1\\x2dweb1.scope 
● machine-qemu\x2d1\x2dweb1.scope - Virtual Machine qemu-1-web1
     Loaded: loaded (/run/systemd/transient/machine-qemu\x2d1\x2dweb1.scope; transient)
  Transient: yes
     Active: active (running) since Tue 2022-11-08 17:03:57 EST; 22min ago
      Tasks: 87 (limit: 16384)
     Memory: 1.7G
        CPU: 4min 33.514s
     CGroup: /machine.slice/machine-qemu\x2d1\x2dweb1.scope
             └─234638 /usr/bin/kvm -name guest=web1,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-1-web1/master-key.aes -machine pc-i440fx-2.7,accel=kvm,usb=off,dump-guest-core=off,memory-ba>

然而这就是我被困住的地方:如果我再检查cset一下,“任务”是不是正如我所料,它们被分配给了切片 cset;root相反,它们是 cset 的一部分,并且切片 cset 有 0 个任务和 0 个子任务:

user@host ~ $ sudo cset set --list --recurse
cset: 
         Name       CPUs-X    MEMs-X Tasks Subs Path
 ------------ ---------- - ------- - ----- ---- ----------
         root       0-31 y       0 y   622    2 /
    osd.slice  0-1,16-17 n       0 n     0    0 /osd.slice

我看不出machine.slice这是如何实现的,在实际的单元文件中没有对它的引用machine.slice,在瞬态scope单元中也没有任何内容。

我如何才能让这个新的自定义切片/cgroup 模拟machine.slice正在做的事情,并将其下的任何东西强制放入这个cpuset 中?

作为“为什么”/X-to-my-Y 的补充,我尝试ceph-osd使用命令手动在 cset 中生成进程cset proc --exec,但这并不可靠(有时它会完全失败并显示“无法移动”),即使它确实有效,即使主进程被移动,它的线程最终也会卡在根 cset 中。因此,似乎我需要一种方法来让 systemd 在实际进程启动之前将整个单元视为 cset 的一部分(与生成cset proc它、分叉它然后更改它的命令不同),这看起来就像这里所做的一样machine.slice

答案1

我最终放弃了cset这个理想的方法。它需要旧的 v1 cgroup 层次结构,并且多年来没有进行重大更新,这是造成这种情况的主要原因,特别是这个错误促使我更多地研究 systemd 的选项。

然后我发现了 systemd 集成的 AllowedCPUs 指令,它似乎也完全按照我的要求执行,尤其是在切片级别部署时。

/etc/systemd/system按照这种方式,我为想要隔离的各个子系统创建了多个嵌入式切片单元(system.slice对于大多数任务,一个 cpuset,osd.slice对于我的 OSD 进程,machine.slice对于虚拟机),每个单元都设置了具有指定限制的 AllowedCPUs,并启用了 Delegate 以确保万无一失。一次重启后,据我所知,它完全按预期运行。

相关内容