启用cgroup writeback功能

在Alibaba Cloud Linux 2(内核版本4.19.36-12.al7开始)和Alibaba Cloud Linux 3中,对内核接口cgroup v1新增了控制群组回写(cgroup writeback)功能。该功能使您在使用内核接口cgroup v1时,可以对缓存异步I/O (Buffered I/O) 进行限速。

背景信息

控制群组(control group)简称为cgroup,分为v1和v2两个版本。更多信息,请参见什么是控制群组。本文介绍如何启用cgroup v1的cgroup writeback功能,并对进程进行Buffered I/O限速。

使用限制

在启用cgroup writeback功能之后,您可以先确认内存子系统(memcg)和IO子系统(blkcg)的映射关系是否符合下文所述的规则,再对进程进行Buffered I/O限速。

cgroup writeback功能需要memcg和blkcg协同工作,完成Buffered I/O的限速,但是内核接口cgroup v1的各个控制子系统间默认不协同工作。因此需要通过一定的规则把memcg和blkcg连接起来,规则为:通过任意一个memcg必须可以找到与之唯一对应的blkcg。即memcg和blkcg的映射关系可以是一对一或多对一,不可以是一对多或多对多。

例如,存在进程A和B,对它们进行Buffered I/O限速,需要遵循以下约束。

  • 如果A和B分属不同的memcg,它们可以映射到不同的blkcg,只需各自一一对应。例如:A属于memcg1blkcg1;B属于memcg2blkcg0

  • 如果A和B分属不同的memcg,它们也可以映射到同一个blkcg。例如:A属于memcg1,B属于memcg2,A和B都属于blkcg2

  • 如果A和B属于相同的memcg,那么它们只能映射到同一个blkcg。例如:A和B均属于memcg0,它们同时属于blkcg3

为了避免出现意外情况,建议您在启用cgroup writeback功能后,对进程进行Buffered I/O限速前,优先设置blkcg的cgroup.procs接口,向该接口写入一个进程ID来保证blkcg映射的唯一性。同时您也可以通过工具查看memcg和blkcg的映射关系,更多信息,请参见确认memcg和blkcg的映射关系

在实际运维中,可能出现进程移动到其它cgroup的情况。根据上述规则,如果进程在memcg之间移动,不会出现问题,但如果进程在blkcg之间移动,将会出现异常情况。为了避免产生异常,该功能的代码中定义了规则:一旦工作中的blkcg内的进程发生blkcg间的移动,则将映射关系直接指向root blkcg。由于一般情况是不在root blkcg设置限流阈值,所以当映射关系直接指向root blkcg时,限速功能会失效。

重要

内核代码虽定义了规则避免出现意外,但您需要在实际操作中尽量避免将进程在blkcg间移动。

开启cgroup writeback功能

cgroup v1接口中的cgroup writeback功能默认是关闭的,按照以下步骤开启该功能。

  1. 通过命令grubby内添加cgwb_v1字段开启该功能。

    本示例中内核版本为4.19.36-12.al7.x86_64,您在操作中需要更换为实际的内核版本,内核版本的查看命令为uname -r

    sudo grubby --update-kernel="/boot/vmlinuz-4.19.36-12.al7.x86_64" --args="cgwb_v1"
  2. 重启系统使功能生效。

    sudo reboot
  3. 使用以下命令读取内核文件/proc/cmdline,确认内核命令行参数中带有cgwb_v1字段。此时,blkcg下的blkio.throttle.write_bps_deviceblkio.throttle.write_iops_device接口能够对Buffered I/O进行限速。

    cat /proc/cmdline | grep cgwb_v1
说明

在k8s环境下,开启cgroup writeback功能后,您需要额外绑定memory和blkio cgroup子系统,以避免因为进程移动导致限速功能失效。

  1. 合并memory和blkio cgroup子系统。

    1. 编辑system.conf文件。

      sudo vim /etc/systemd/system.conf
    2. 修改JoinControllers配置,例如:

      JoinControllers=cpu,cpuacct net_cls,net_prio memory,blkio
    3. Ecs 键退出编辑模式,输入 :wq保存并退出。

  2. 运行以下命令,重做内核镜像,确保systemd的配置修改生效。

    sudo dracut /boot/initramfs-4.19.36-12.al7.x86_64.img 4.19.36-12.al7.x86_64 --force
  3. 运行以下命令,重启系统。

    sudo reboot
  4. 运行以下命令,验证memory、blkio子系统是否合并。

    ls /sys/fs/cgroup

验证cgroup writeback是否生效

本示例将模拟出两个产生I/O的进程,用于验证cgroup writeback功能是否有效。

说明
  • 由于dd命令的反馈速度较快,结果使用iostat命令查看。

  • 由于dd命令为顺序写入,顺序IO回刷时,会生成1 MB数据再回刷,因此设置阈值时,blkio.throttle.write_bps_device不得小于1 MB(1048576)。如果设置值小于1 MB,可能会引发IO hang。

  1. 模拟出两个产生I/O的进程,并按照限制条件优先设置blkcg的cgroup.procs接口。

    sudo mkdir /sys/fs/cgroup/blkio/blkcg1
    sudo mkdir /sys/fs/cgroup/memory/memcg1
    sudo bash -c "echo $$ > /sys/fs/cgroup/blkio/blkcg1/cgroup.procs"    # $$为您的进程ID
    sudo bash -c "echo $$ > /sys/fs/cgroup/memory/memcg1/cgroup.procs"    # $$为您的进程ID
  2. 使用blkcg下的blkio.throttle.write_bps_device接口对Buffered I/O进行限速。

    sudo bash -c "echo 254:48 10485760 > /sys/fs/cgroup/blkio/blkcg1/blkio.throttle.write_bps_device"    # 通过设备号配置磁盘的回写限流bps为10 M
  3. 使用不带参数oflag=syncdd命令产生缓存异步I/O。

    sudo dd if=/dev/zero of=/mnt/vdd/testfile bs=4k count=10000
  4. 使用iostat工具查询结果。查看输出列wMB/s,如果被限制到10 MB/s,则表示cgroup writeback功能已生效。

    iostat -xdm 1 vdd

确认memcg和blkcg的映射关系

您可以使用以下任意一种方式诊断memcg和blkcg的映射关系是否为一对一或多对一。

  • 查看memcg与blkcg映射关系。

    sudo cat /sys/kernel/debug/bdi/bdi_wb_link

    返回结果示例如下,该示例表示memcg和blkcg符合一对一的映射规则。

    memory     <--->     blkio
    memcg1:   35 <---> blkcg1:   48
  • 使用ftrace内核监测工具。

    1. 开启ftrace工具。

      sudo bash -c "echo 1 > /sys/kernel/debug/tracing/events/writeback/insert_memcg_blkcg_link/enable"
    2. 查看信息输出接口。

      sudo cat /sys/kernel/debug/tracing/trace_pipe

      输出内容示例如下,其中memcg_ino=35 blkcg_ino=48表示memcg和blkcg符合一对一的映射规则。

      <...>-1537  [006] ....    99.511327: insert_memcg_blkcg_link: memcg_ino=35 blkcg_ino=48 old_blkcg_ino=0