Docker进阶与实战
上QQ阅读APP看书,第一时间看更新

2.3.3 Cgroup子系统介绍

对实际资源的分配和管理是由各个Cgroup子系统完成的,下面介绍几个主要的子系统。

1.cpuset子系统

cpuset可以为一组进程分配指定的CPU和内存节点。cpuset一开始是用在高性能计算(HPC)上的,在NUMA架构的服务器上,通过将进程绑定到固定的CPU和内存节点上,来避免进程在运行时因跨节点内存访问而导致的性能下降。当然,现在cpuset也广泛用在了kvm和容器等场景上。

cpuset的主要接口如下。

❏ cpuset.cpus:允许进程使用的CPU列表(例如0~4,9)。

❏ cpuset.mems:允许进程使用的内存节点列表(例如0~1)。

2.cpu子系统

cpu子系统用于限制进程的CPU占用率。实际上它有三个功能,分别通过不同的接口来提供。

❏ CPU比重分配。这个特性使用的接口是cpu.shares。假设在cgroupfs的根目录下创建了两个Cgroup(C1和C2),并且将cpu.shares分别配置为512和1024,那么当C1和C2争用CPU时,C2将会比C1得到多一倍的CPU占用率。要注意的是,只有当它们争用CPU时cpu share才会起作用,如果C2是空闲的,那么C1可以得到全部的CPU资源。

❏ CPU带宽限制。这个特性使用的接口是cpu.cfs_period_us和cpu.cfs_quota_us,这两个接口的单位是微秒。可以将period设置为1秒,将quota设置为0.5秒,那么Cgroup中的进程在1秒内最多只能运行0.5秒,然后就会被强制睡眠,直到进入下一个1秒才能继续运行。

❏ 实时进程的CPU带宽限制。以上两个特性都只能限制普通进程,若要限制实时进程,就要使用cpu.rt_period_us和cpu.rt_runtime_us这两个接口了。使用方法和上面类似。

3.cpuacct子系统

cpuacct子系统用来统计各个Cgroup的CPU使用情况,有如下接口。

❏ cpuacct.stat:报告这个Cgroup分别在用户态和内核态消耗的CPU时间,单位是USER_HZ。USER_HZ在x86上一般是100,即1 USER_HZ等于0.01秒。

❏ cpuacct.usage:报告这个Cgroup消耗的总CPU时间,单位是纳秒。

❏ cpuacct.usage_percpu:报告这个Cgroup在各个CPU上消耗的CPU时间,总和也就是cpuacct.usage的值。

4.memory子系统

memory子系统用来限制Cgroup所能使用的内存上限,有如下接口。

❏ memory.limit_in_bytes:设定内存上限,单位是字节,也可以使用k/K、m/M或者g/G表示要设置数值的单位,例如

# echo 1G > memory.limit_in_bytes

默认情况下,如果Cgroup使用的内存超过上限,Linux内核会尝试回收内存,如果仍然无法将内存使用量控制在上限之内,系统将会触发OOM,选择并“杀死”该Cgroup中的某个进程。

❏ memory.memsw.limit_in_bytes:设定内存加上交换分区的使用总量。通过设置这个值,可以防止进程把交换分区用光。

❏ memory.oom_control:如果设置为0,那么在内存使用量超过上限时,系统不会“杀死”进程,而是阻塞进程直到有内存被释放可供使用时;另一方面,系统会向用户态发送事件通知,用户态的监控程序可以根据该事件来做相应的处理,例如提高内存上限等。

❏ memory.stat:汇报内存使用信息。

5.blkio子系统

blkio子系统用来限制Cgroup的block I/O带宽,有如下接口。

❏ blkio.weight:设置权重值,范围在100到1000之间。这跟cpu.shares类似,是比重分配,而不是绝对带宽的限制,因此只有当不同的Cgroup在争用同一个块设备的带宽时才会起作用。

❏ blkio.weight_device:对具体的设备设置权重值,这个值会覆盖上述的blkio.weight。例如将Cgroup对/dev/sda的权重设为最小值:

# echo 8:0 100 > blkio.weight_device

❏ blkio.throttle.read_bps_device:对具体的设备,设置每秒读磁盘的带宽上限。例如对/dev/sda的读带宽限制在1MB/秒:

# echo "8:0 1048576" > blkio.throttle.read_bps_device

❏ blkio.throttle.write_bps_device:设置每秒写磁盘的带宽上限。同样需要指定设备。

❏ blkio.throttle.read_iops_device:设置每秒读磁盘的IOPS上限。同样需要指定设备。

❏ blkio.throttle.write_iops_device:设置每秒写磁盘的IOPS上限。同样需要指定设备。

注意 blkio子系统有两个重大的缺陷。一是对于比重分配,只支持CFQ调度器。另一个缺陷是,不管是比重分配还是上限限制,都只支持Direct-IO,不支持Buffered-IO,这使得blkio cgroup的使用场景很有限,好消息是Linux内核社区正在解决这个问题。

6.devices子系统

devices子系统用来控制Cgroup的进程对哪些设备有访问权限,有如下接口。

❏ devices.list。只读文件,显示目前允许被访问的设备列表。每个条目都有3个域,分别为:

· 类型:可以是a、c或b,分别表示所有设备、字符设备和块设备。

· 设备号:格式为major:minor的设备号。

· 权限:r、w和m的组合,分别表示可读、可写、可创建设备结点(mknod)。

例如“a*:*rmw”,表示所有设备都可以被访问。而“c 1:3 r”,表示对1:3这个字符设备(即/dev/null)只有读权限。

❏ devices.allow。只写文件,以上面描述的格式写入该文件,就可以允许相应的设备访问权限。

❏ devices.deny。只写文件,以上面描述的格式写入该文件,就可以禁止相应的设备访问权限。