Skip to content

cgroup writeback v1 interface

Caspar Zhang edited this page May 22, 2019 · 5 revisions

1. 开启 cgroup writeback v1 支持

Aliyun Linux Kernel 在 alk-release-12 版本(内核版本 4.19.36-12.al7.x86_64)开始支持 cgroup writeback v1. 即用户在使用 cgroup v1 接口时,也可以对 buffer IO 进行限速。

该功能默认关闭,用户需显式在 grub 里添加 **cgwb_v1 **字段方可开启。

sudo grubby --update-kernel="/boot/vmlinuz-4.19.36-12.al7.x86_64" --args="cgwb_v1"
sudo reboot

系统启动之后,读取 /proc/cmdline , 确保 cmdline 中带有 cgwb_v1:

cat /proc/cmdline | grep cgwb_v1

此时,blkcg 下的 blkio.throttle.write_bps_device 及 blkio.throttle.write_iops_device 就可以用于限制 buffer IO.

2. 限制约束:blkcg 映射必须唯一

cgroup writeback 需要内存子系统和 IO 子系统协作来完成 buffer IO 的限速,但是 cgroup v1 接口各个控制子系统没有默认协同工作,因此需要通过一定的规则把 memory 子系统和 blkio 子系统链接起来,原则就是通过任意一个 memcg 必可找到与之唯一对应的 blkcg. 换言之,假设存在有进程 A 和 B,想要对它们进行 buffer IO 限速,我们需遵循如下限制约束:

  • 如果 A 和 B 分属不同的 memcg, 那么它们可以分别映射到不同的 blkcg,只需各自一一对应。e.g.: A 属于 memcg1, blkcg1; B 属于 memcg2, blkcg0;
  • 如果 A 和 B 分属不同的 memcg, 显而易见它们也可以映射到同一个 blkcg. e.g.: A 属于 memcg1, B 属于 memcg2, 它们都属于 blkcg2;
  • 如果 A 和 B 属于相同的 memcg,那么它们只能映射到同一个 blkcg. e.g.: A & B 均属于 memcg0, 它们同时属于 blkcg3.

显而易见,我们可以将以上约束概括成要点:memcg 与 blkcg 的映射,可以是 1 对 1,可以是 N 对 1,不可以是 1 对 N 或是 M 对 N. 为了避免意外地制造 1 对 N 或者 M 对 N 映射,我们推荐先设置 blkcg 的 cgroup.procs 接口,再设置 memcg 的

在运维上,可能会出现一种会打破 1 对 1 或者 N 对 1 的正确映射的情况,即进程移动到其他 cgroup 的情况。根据映射原则,我们可以知道,如果进程在 memcg 之间移动,是没有问题的;但如果进程在 blkcg 之间移动,就会出现 1 对 N 或者 M 对 N 的情况。举例如下:

进程 A 属于 memcg1, 进程 B 属于 memcg2,原本都映射到 blkcg2 中,后来由于运维操作,将进程 B 从 blkcg2 移动到了 blkcg20 中。由于可能会有未完成的 writeback 存在,因此 blkcg 的移动这个过程,可能会让 memcg2 中未完成的 writeback 不知道该对应查找 blkcg2 还是 blkcg20 的规则,从而造成混乱。

为了避免此种情况,我们在代码中定义了如下逻辑:

一旦工作中的 blkcg 内的进程发生 blkcg 间移动,则将映射关系直接指向 root blkcg。

由此,在上述的例子中,如果进程 B 从 blkcg2 移动到 blkcg20 ,则 memcg2 对应的映射关系直接更改为 root blkcg 。

由于我们一般不在 root blkcg 设置 blkio.throttle 值,所以限速功能此时也一般会失效。因此需要尽量避免将进程在 blkcg 间移动

3. 常用诊断工具

查看 memcg 与 blkio 映射关系

# cat /sys/kernel/debug/bdi/bdi_wb_link
memory     <--->     blkio
test:   35 <---> root:    1
1:173059 <---> 1:  275
2:173443 <---> 1:  275
3:174755 <---> 1:  275

打开 ftrace

echo 1 > /sys/kernel/debug/tracing/events/writeback/insert_memcg_blkcg_link/enable
cat /sys/kernel/debug/tracing/trace_pipe

4. 验证 cgroup writeback 是否生效

我们一般会用不带 oflag=sync 的 dd 命令来产生异步 IO 以检验 cgroup_writeback 功能是否有效,请注意由于 dd 异步 IO 反馈速度较快,正确的方式应该通过 iostat 来查看。
此外,由于 dd 写入为顺序写,由于 ext4 的 bio 初始化是按照 BIO_MAX_PAGES (256 pages) 来的,所以顺序 IO 回刷时,会先攒成1M大小 (4k x 256) 再刷下去。此时如果 blkio.throttle.write_bps_device 设置小于 1M (1048576),会造成一个单独的 IO 都无法完成回刷,从而触发 IO Hang. 正确的做法是,在设置阈值时 write_bps 不要设置为小于 1M.

Clone this wiki locally