在 systemd 下的 Debian 上,默认情况下,libvirt 下的 KVM 虚拟机被分配给“machine.slice”片。
如果我然后为这个切片添加一个 cpusetcset
和一些自定义的 CPU 集,并启动一个 VM,VM 被添加到正确的 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
单元中也没有任何内容。
我怎样才能得到这个新的、自定义的 slice/cgroup 来模拟machine.slice
正在做什么,并将它下面的任何东西强制到这个 cpuset 中?
作为“为什么”/X-to-my-Y 的附录,我尝试ceph-osd
使用命令在 cset 中手动生成进程之类的操作cset proc --exec
,但这不能可靠地工作(有时它完全失败并显示“cannot移动”),即使它确实起作用,即使移动了主进程,它的线程也会最终卡在根 cset 中。因此,似乎我需要一种方法让 systemd 在实际进程开始之前将整个单元视为 cset 的一部分(与cset proc
生成它、分叉它然后更改它的命令不同),这看起来像什么在machine.slice
这里完成。
我最终放弃
cset
了这样做的理想方式。它需要旧的 v1 cgroup 层次结构并且多年来没有显着更新这一事实在其中发挥了重要作用,特别是这个错误导致我更多地研究 systemd 的选项。然后我发现了 systemd 的集成 AllowedCPUs 指令,它似乎也完全符合我的要求,尤其是在切片级别部署时。
/etc/systemd/system
以这种方式,我为我想要隔离的各种子系统中的每一个创建了几个插入式切片单元(system.slice
对于一个 cpuset 的大多数任务,osd.slice
对于我的 OSD 进程,machine.slice
对于 VM),每个都设置一个 AllowedCPUs 与指定限制以及启用 Delegate 以确保。稍后重新启动一次,据我所知,它完全按预期工作。