cgroup v1

cpu

cpu的限制可以采用两种模式:

这里主要讨论CFS。它有两套参数:

  1. cfs_quota_us, cfs_period_us

用于限制某个cgroup的最大CPU使用量(具体的计算方式参考这里)。如果当前cgroup(A)有子cgroup(B,C),并且有以下配置:

    A
    |
    +- cpu.cfs_quota_us: -1
    +- cpu.cfs_period_us: 10^5
    +- tasks: 1, 2
    +-B
    | |
    | +- cpu.cfs_quota_us: 10^5
    | +- cpu.cfs_period_us: 10^5
    | +- tasks: 3, 4
    +-C
      |
      +- cpu.cfs_quota_us: 10^5
      +- cpu.cfs_period_us: 10^5
      +- tasks: 5, 6

其中的tasks都是单核的spin程序(e.g. stress).

写一段简单的脚本来模拟这个hierarchy:

  #!/bin/bash
  
  #########################################################################
  # Author: Zhaoting Weng
  # Created Time: Mon 18 Feb 2019 05:55:46 PM CST
  # Description:
  #########################################################################
  
  cgroup_root="/sys/fs/cgroup/cpu/magodo"
  cgroup_foo="$cgroup_root/foo"
  cgroup_bar="$cgroup_root/bar"
  
  # setup cgroup hierarchy
  mkdir -p $cgroup_foo
  mkdir -p $cgroup_bar
  
  echo -1 > $cgroup_root/cpu.cfs_quota_us
  echo 100000 > $cgroup_foo/cpu.cfs_quota_us
  echo 100000 > $cgroup_bar/cpu.cfs_quota_us
  
  stress --cpu 2 &
  for pid in $(pgrep -P $!); do
      echo "$pid" > "$cgroup_root"/tasks
  done
  
  stress --cpu 2 &
  for pid in $(pgrep -P $!); do
      echo "$pid" > "$cgroup_foo"/tasks
  done
  
  stress --cpu 2 &
  for pid in $(pgrep -P $!); do
      echo "$pid" > "$cgroup_bar"/tasks
  done
  
  read -n 1 -r -s -p 'Enter any key to continue...'
  
  # clean up
  kill $(pidof stress)
  rmdir $cgroup_foo
  rmdir $cgroup_bar
  rmdir $cgroup_root
  

执行结果如下图:

cpu1

即:

task cpu(%)
1 100
2 100
3 50
4 50
5 50
6 50

1和2为100的原因是A没有做CPU限制,所以每个进程跑满一个核;而其他4个因为限制了B,C各总共只能用1核,所以,其中的进程各跑满半个核。

这里的A的意义除了可以限制自己group内的进程,还可以限制它的子group(B,C)。

所以,如果我们手动把Acpu.cfs_quota_us也改成10^5之后,它意味着: A以及A的子group中的所有进程最多在一个周期内使用10^5(us)的CPU时间。因此,结果是1-6的进程的均占用1/6核:

cpu2

  1. shares

所有cgroup中的进程之间的相对cpu占有量。关于它和cfs_quota_us的关系,参考我的这个回答

blkio

blkio.throttle.write_bps_device

REHL7的官方文档中对于io写有这样一段描述:

Currently, the blkio resource controller does not support buffered write operations. It is primarily targeted at direct I/O, so the services that use buffered write will ignore the limits set with BlockIOWriteBandwidth. On the other hand, buffered read operations are supported, and BlockIOReadBandwidth limits will be applied correctly both on direct and buffered read.

这段话的解释在这篇博客中得到了很好的解释。大致意思是,由于cgroup-v1中的memoryblkiosubsystem是没有关联性的。而buffered write 先将数据写入kernel buffer中,当后续系统进行fsync/fdatasync的时候,memory ctonrller是无法判断buffer中的page数据来源于哪个blkio的cgroup,因此也就无法使用blkio cgroup 中的设置来限制写的io。

引用