我试图限制特定单元的 IO,但 IOWriteIOPSMax 属性似乎没有影响。
我最初尝试了 IOWeight,但这测试起来更具挑战性,IOPSMax 上的文档表明这是一个纯粹的限制。
pops 操作系统、systemd 249、cgroupv2
默认运行
user@x1:~/tmp$ systemd-run --user --same-dir --pipe --wait \
dd status=progress if=/dev/zero of=loadfile bs=1k count=5000024
Running as unit: run-u233.service
4876370944 bytes (4.9 GB, 4.5 GiB) copied, 32 s, 152 MB/s
5000024+0 records in
5000024+0 records out
5120024576 bytes (5.1 GB, 4.8 GiB) copied, 32.914 s, 156 MB/s
Finished with result: success
Main processes terminated with: code=exited/status=0
Service runtime: 33.592s
CPU time consumed: 16.924s
有限制地运行 - 故意设置得非常低:
user@x1:~/tmp$ systemd-run --user --same-dir --pipe --wait \
-p IOAccounting=yes \
-p IOWriteIOPSMax="/dev/nvme0n1 5" \
-p IOReadIOPSMax="/dev/nvme0n1 5" \
dd status=progress if=/dev/zero of=loadfile bs=1k count=5000024
Running as unit: run-u234.service
5090277376 bytes (5.1 GB, 4.7 GiB) copied, 19 s, 268 MB/s
5000024+0 records in
5000024+0 records out
5120024576 bytes (5.1 GB, 4.8 GiB) copied, 19.2141 s, 266 MB/s
Finished with result: success
Main processes terminated with: code=exited/status=0
Service runtime: 19.899s
CPU time consumed: 16.838s
两次运行似乎花费相同的时间。systemctl show unit | grep IO
确认两个属性均已设置。
在另一个窗口中观看iostat -xd 1/ dev/nvme0n1
显示 300w/s ,我预计应用的属性会将其减少到 < 10,我的方法有什么问题吗?
编辑:添加/proc/self/cgroup
信息:
user@x1:~$ systemd-run --user --same-dir --pipe --wait -p IOAccounting=yes -p IOWriteIOPSMax="/dev/nvme0n1 5" -p IOReadIOPSMax="/dev/nvme0n1 5" cat /proc/self/cgroup
Running as unit: run-u282.service
0::/user.slice/user-1000.slice/[email protected]/app.slice/run-u282.service
编辑:以 root 身份运行
root@x1:~# systemd-run --same-dir --pipe --wait \
-p IOAccounting=yes \
-p IOWriteIOPSMax="/dev/nvme0n1 5" \
-p IOReadIOPSMax="/dev/nvme0n1 5" \
dd status=progress if=/dev/zero of=loadfile bs=1k count=5000024
Running as unit: run-u1099.service
4847981568 bytes (4.8 GB, 4.5 GiB) copied, 17 s, 285 MB/s
5000024+0 records in
5000024+0 records out
5120024576 bytes (5.1 GB, 4.8 GiB) copied, 17.9437 s, 285 MB/s
Finished with result: success
Main processes terminated with: code=exited/status=0
Service runtime: 17.945s
CPU time consumed: 16.748s
IO bytes read: 0B
IO bytes written: 0B
编辑:并作为标准单位。以 root 身份运行
root@x1:/etc/systemd/system# systemctl cat testme.service
# /etc/systemd/system/testme.service
[Service]
IOAccounting=yes
IOReadIOPSMax=/root 10
IOWriteIOPSMax=/root 10
ExecStart=dd status=progress if=/dev/zero of=/root/loadfile bs=1k count=5000024
root@x1:/etc/systemd/system# journalctl -u testme.service -f
Nov 05 14:20:25 x1 systemd[1]: Started testme.service.
Nov 05 14:20:50 x1 dd[56684]: [1.3K blob data]
Nov 05 14:20:50 x1 dd[56684]: 5000024+0 records in
Nov 05 14:20:50 x1 dd[56684]: 5000024+0 records out
Nov 05 14:20:50 x1 dd[56684]: 5120024576 bytes (5.1 GB, 4.8 GiB) copied, 24.6735 s, 208 MB/s
Nov 05 14:20:50 x1 systemd[1]: testme.service: Deactivated successfully.
Nov 05 14:20:50 x1 systemd[1]: testme.service: Consumed 17.352s CPU time.
(相同的结果替换/root
为/dev/nvme..
)
答案1
答案分为两部分:
- 设置时
IOWriteIOPSMax
,限制是通过io.max
cgroups 文件强制执行的。当以模式运行时--user
,您无法更改 cgroup,因此该选项无效。 - 当
dd
按照你的方式运行时,默认是使用异步I/O,这意味着在数据实际写入磁盘之前进程不会阻塞。这就是为什么IOWriteIOPSMax
不会影响运行。为了真正测试它,您需要使用同步 I/O,以便数据实际上写入磁盘。您可以通过将oflag=sync
标志添加到命令中来做到这一点dd
。
测试脚本
为了测试和确认这些条件,我创建了一个执行以下操作的脚本:
- 检查
io.max
cgroup 文件是否存在,以及它是否确实有任何限制。 - 运行两个
dd
命令;第一个具有异步 I/O,第二个具有同步 I/O。
cat systemd_io.sh
#!/bin/bash
CGROUPS="$(</proc/self/cgroup)"
echo "/proc/self/cgroup: '$CGROUPS'"
IO_MAX_FILE="/sys/fs/cgroup/${CGROUPS#0::/}/io.max"
if [ -f "$IO_MAX_FILE" ]
then
IO_MAX="$(<$IO_MAX_FILE)"
if [ -z "$IO_MAX" ]
then echo "$IO_MAX_FILE exists but is empty."
else printf "Content of %s:\n%s\n" "$IO_MAX_FILE" "$IO_MAX"
fi
else
echo $IO_MAX_FILE does not exist.
fi
echo
echo Writing file without sync:
dd if=/dev/zero of=loadfile bs=1k count=10 2>&1 |tail -1
rm -f loadfile
echo
echo Writing file WITH oflag=sync:
dd if=/dev/zero of=loadfile bs=1k count=10 oflag=sync 2>&1 |tail -1
rm -f loadfile
echo
systemd-run
带着--user
旗帜奔跑
- cgroup
io.max
文件甚至没有创建,因此 IO 没有限制。
root:~/tmp$ systemd-run --user --same-dir --pipe --wait -p IOWriteIOPSMax="/dev/vda 5" ./systemd_io.sh 2>/dev/null
/proc/self/cgroup: '0::/user.slice/user-0.slice/[email protected]/app.slice/run-u18.service'
/sys/fs/cgroup/user.slice/user-0.slice/[email protected]/app.slice/run-u18.service/io.max does not exist.
Writing file without sync:
10240 bytes (10 kB, 10 KiB) copied, 0.000142996 s, 71.6 MB/s
Writing file WITH oflag=sync:
10240 bytes (10 kB, 10 KiB) copied, 0.00483422 s, 2.1 MB/s
systemd-run
无--user
旗运行和无旗运行IOWriteIOPSMax
- cgroup文件
io.max
已创建但为空,因此没有任何限制。 - 同步 I/O 的写入比率与用户的写入比率相同。
root:~/tmp$ systemd-run --same-dir --pipe --wait ./systemd_io.sh 2>/dev/null
/proc/self/cgroup: '0::/system.slice/run-u187.service'
/sys/fs/cgroup/system.slice/run-u187.service/io.max exists but is empty.
Writing file without sync:
10240 bytes (10 kB, 10 KiB) copied, 0.000144849 s, 70.7 MB/s
Writing file WITH oflag=sync:
10240 bytes (10 kB, 10 KiB) copied, 0.00446492 s, 2.3 MB/s
systemd-run
不带标志运行--user
且带IOWriteIOPSMax
- cgroup
io.max
文件具有由IOWriteIOPSMax
. - 异步 I/O 不受影响(由于我上面提到的原因),但这次同步 I/O 比以前慢得多(1.8 kB/s,而不是 ~2 MB/s),确认有效
IOWriteIOPSMax
。
root:~/tmp$ systemd-run --same-dir --pipe --wait -p IOWriteIOPSMax="/dev/sda 5" ./systemd_io.sh 2>/dev/null
/proc/self/cgroup: '0::/system.slice/run-u189.service'
Content of /sys/fs/cgroup/system.slice/run-u189.service/io.max:
253:0 rbps=max wbps=max riops=max wiops=5
Writing file without sync:
10240 bytes (10 kB, 10 KiB) copied, 0.000136314 s, 75.1 MB/s
Writing file WITH oflag=sync:
10240 bytes (10 kB, 10 KiB) copied, 5.78732 s, 1.8 kB/s