Docker容器与容器云读书笔记(二)–CGroup

术语

需要先知道几个术语

  • task 任务:即进程或者线程,tasks里面有许多的进程号码
[root@docker-ns 41986]# ll /sys/fs/cgroup/cpu/tasks
-rw-r--r-- 1 root root 0 Apr  8  2020 /sys/fs/cgroup/cpu/tasks
  • cgroup 控制组:对各个资源进行控制,每个资源下面可以分为多个子系统和task
[root@docker-ns 41986]# ls /sys/fs/cgroup/
blkio  cpu  cpuacct  cpu,cpuacct  cpuset  devices  freezer  hugetlb  memory  net_cls  net_cls,net_prio  net_prio  perf_event  pids  systemd
  • subsystem 子系统:sys/fs/cgroup目录下面的子系统
  • hierarchy 层级:由多个cgroup组成,与子系统绑定,对资源进行控制

原理

Linux当中一切皆文件,进程也是文件,限制也做成了文件;

/sys/fs/cgroup/cpu目录下创建一个目录,看看会发生什么效果?

[root@CloudPower-dev-2-119 cpu]# mkdir /sys/fs/cgroup/cpu/cg1
[root@CloudPower-dev-2-119 cpu]# ll cg1
total 0
-rw-r--r-- 1 root root 0 Nov 26 13:53 cgroup.clone_children
--w--w--w- 1 root root 0 Nov 26 13:53 cgroup.event_control
-rw-r--r-- 1 root root 0 Nov 26 13:53 cgroup.procs
-r--r--r-- 1 root root 0 Nov 26 13:53 cpuacct.stat
-rw-r--r-- 1 root root 0 Nov 26 13:53 cpuacct.usage
-r--r--r-- 1 root root 0 Nov 26 13:53 cpuacct.usage_percpu
-rw-r--r-- 1 root root 0 Nov 26 13:53 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Nov 26 13:53 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Nov 26 13:53 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Nov 26 13:53 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Nov 26 13:53 cpu.shares
-r--r--r-- 1 root root 0 Nov 26 13:53 cpu.stat
-rw-r--r-- 1 root root 0 Nov 26 13:53 notify_on_release
-rw-r--r-- 1 root root 0 Nov 26 13:53 tasks

为什么会多出那么多的文件呢?cg1便是一个cpucgroup,这个乃是系统自动生成,为控制CPU的使用的;可以理解为cgroup是一个对象,这些文件都是它的属性,然后通过外接cpu 子系统的调度算法对cgroup下的cpu进行控制;最重要的两个参数如下:

  • cpu.cfs_quota_us:为-1时表示cpu不受cgroup限制
  • cfs_period_us:设置cpu的带宽,设置某个周期内可以使用cpu,用于提升cpu的吞吐量

通俗理解,一个cpu子系统下面挂载着许多的cpu cgroups,每个cgroup对进程进行限制;

实战

CPU限制

下面这段代码是一个死循环,会把cpu跑满,我们对容器的cpu进行控制

int main(void)
{
    int i = 0;
    for(;;) i++;
    return 0;
}

编译运行

[root@docker-ns cgroup]# gcc -Wall cpu.c -o cpu
[root@docker-ns cgroup]# ./cpu
## TOP里面看到cpu已经到100%了
	PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  7543 root      20   0    4212    352    276 R 100.0  0.0   0:15.79 cpu

其中cpu.cfs_quota_us即为限制cpu的阈值

## 设置阈值
[root@docker-ns cg1]# echo 20000 > /sys/fs/cgroup/cpu/cg1/cpu.cfs_quota_us
## 设置生效的线程
[root@docker-ns cg1]# echo 7543 > /sys/fs/cgroup/cpu/cg1/tasks
## 再运行TOP即可看到cpu控制在20%了
PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  7543 root      20   0    4212    348    276 R  19.9  0.0   0:33.12 cpu

memroy限制

[root@docker-ns ~]# mkdir /sys/fs/cgroup/memory/mem1
[root@docker-ns ~]# cat /sys/fs/cgroup/memory/mem1/memory.limit_in_bytes
9223372036854771712  // 8
[root@docker-ns ~]# echo 64k >  /sys/fs/cgroup/memory/mem1/memory.limit_in_bytes
[root@docker-ns ~]# echo 7543 > /sys/fs/cgroup/memory/mem1/tasks

若进程7543的阈值超过64k会被kill

disk限制

[root@docker-ns ~]# mkdir /sys/fs/cgroup/blkio/disk
[root@docker-ns ~]# cat  /sys/fs/cgroup/blkio/disk/blkio.throttle.read_bps_device
[root@docker-ns ~]# echo '8:0 1048576'  > /sys/fs/cgroup/blkio/io/blkio.throttle.read_bps_device
[root@docker-ns ~]# echo 7543 > /sys/fs/cgroup/blkio/disk/tasks

Dcoker的实现

而现在containerd已经提供了标准的调用方式 cgroups,并且Docker为了生态也实现了,所以咱直接引包,使用即可;创建一个Dcoker容器后,也会在cgroup当中创建对应的目录结构,及对进程的限制信息;

不同的驱动和版本创建的目录不尽相同:https://docs.docker.com/config/containers/runmetrics/#find-the-cgroup-for-a-given-container

# tree /sys/fs/cgroup/cpu/system.slice/docker-30110dfe51d97408e45814afe729cf5aa609a120f300e80795b450830ee81455.scope
/sys/fs/cgroup/cpu/system.slice/docker-30110dfe51d97408e45814afe729cf5aa609a120f300e80795b450830ee81455.scope
├── cgroup.clone_children
├── cgroup.event_control
├── cgroup.procs
├── cpuacct.stat
├── cpuacct.usage
├── cpuacct.usage_percpu
├── cpu.cfs_period_us
├── cpu.cfs_quota_us
├── cpu.rt_period_us
├── cpu.rt_runtime_us
├── cpu.shares
├── cpu.stat
├── notify_on_release
└── tasks

参考