linux的cgroups详解

时间:2023-03-01 13:17:20


引子

最近在研究k8s,学习到容器的一些知识。了解到docker的核心原理:

  • 利用linux namespace 隔离资源;
  • 利用cgroups 限制资源的使用;
  • 利用chroot 改变进程的根目录到指定的目录;

我来详细的了解下cgroups。

物理机是4C8G 首先看下操作的系统版本

[root@dev215 ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)

基本概念

Cgroups全称为:linux Control Group,crgroups为每种可以控制的资源定义了一个子系统。这么说有点抽象,直白点它的主要作用就是限制一个进程组能够使用cpu、内存、磁盘、带宽等资源的上限。提供以下功能:

  • 限制资源使用,各种子系统的资源限制;
  • 优先级控制,cpu使用、内存、磁盘io吞吐等;
  • 资源使用报告,可以用来计费;
  • 控制,挂起、恢复进程;

子系统

我们看下都有哪些子系统。

[root@dev215 ~]# mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,net_prio,net_cls)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,pids)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuset)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,memory)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,hugetlb)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,perf_event)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,blkio)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,devices)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,cpuacct,cpu)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,freezer)
  • systemd 是维护的自己使用子系统;
  • net_cls,net_prio :可以标记 cgroups 中进程的网络数据包,然后可以使用 tc 模块(traffic control)对数据包进行控制;
  • pids:可以限制cgroup的进程数,里面有各种策略;
  • cpuset:如果为多核cpu,可以为cgroups中的任务分配单独的cpu和内存;
  • memory :设置每个cgroup的内存限制以及产生内存资源报告
  • hugetlb:这个子系统主要针对于HugeTLB系统进行限制,这是一个大页文件系统;
  • perf_event:增加了对每group的监测跟踪的能力,即可以监测属于某个特定的group的所有线程以及运行在特定CPU上的线程,此功能对于监测整个group非常有用
  • blkio:可以限制进程的块设备(磁盘、usb)的输入/输出存取限制;
  • devices:可以控制进程能够访问某些设备
  • cpu:主要限制进程的cpu使用率
  • cpuacct:可以统计cgroups中的进程使用cpu的资源报告
  • freezer:可以挂起或者恢复cgroups中的进程

cgroup形态

linux的cgroups详解

  • hierarchy: cgroups从用户态看,提供了一种组cgroup类型的文件系统(Filesystem),这是一组虚拟的文件系统,通过对这个文件系统的配置,告诉内核,如何希望对哪些进程使用多少资源。文件系统本身是层级的,所以构成了hierarchy。
  • task:进程在cgroups中称为task,taskid就是pid;
  • subsystem:cgroup支持的所有可配置的资源称为子系统,如:cpu、内存、网络等都是子系统;
  • libcgroup: 一个开源的软件,提供一组cgroups的应用程序和库;

cgroups 层级结构(Hierarchy)

内核使用 cgroup 结构体来表示一个 control group 对某一个或者某几个 cgroups 子系统的资源限制。cgroup 结构体可以组织成一颗树的形式,每一棵cgroup 结构体组成的树称之为一个 cgroups 层级结构。

cgroups层级结构可以 attach 一个或者几个 cgroups 子系统,当前层级结构可以对其 attach 的 cgroups 子系统进行资源的限制。每一个 cgroups 子系统只能被 attach 到一个 cpu 层级结构中。

好好理解下这个图即可:

linux的cgroups详解

创建了 cgroups 层级结构中的节点(cgroup 结构体)之后,可以把进程加入到某一个节点的控制任务列表中,一个节点的控制列表中的所有进程都会受到当前节点的资源限制。同时某一个进程也可以被加入到不同的 cgroups 层级结构的节点中,因为不同的 cgroups 层级结构可以负责不同的系统资源。所以说进程和 cgroup 结构体是一个多对多的关系。

linux的cgroups详解

上面这个图从整体结构上描述了进程与 cgroups 之间的关系。最下面的P代表一个进程。每一个进程的描述符中有一个指针指向了一个辅助数据结构css_set(cgroups subsystem set)。指向某一个css_set的进程会被加入到当前css_set的进程链表中。一个进程只能隶属于一个css_set,一个css_set可以包含多个进程,隶属于同一css_set的进程受到同一个css_set所关联的资源限制。

上图中的”M×N Linkage”说明的是css_set通过辅助数据结构可以与 cgroups 节点进行多对多的关联。但是 cgroups 的实现不允许css_set同时关联同一个cgroups层级结构下多个节点。这是因为 cgroups 对同一种资源不允许有多个限制配置。

一个css_set关联多个 cgroups 层级结构的节点时,表明需要对当前css_set下的进程进行多种资源的控制。而一个 cgroups 节点关联多个css_set时,表明多个css_set下的进程列表受到同一份资源的相同限制。

我们来实际操作下:

# 进入cpu的文件系统
[root@dev215 ]# cd /sys/fs/cgroup/cpu
#挂载cpu子系统test
[root@dev215 cpu]# mkdir test
# 操作系统自动生成了对应子系统对应的资源限制文件
[root@dev215 test]# ls
cgroup.clone_children cgroup.procs cpuacct.usage cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
cgroup.event_control cpuacct.stat cpuacct.usage_percpu cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks
#我们写一个死循环来测试下
[root@dev215 cpu]# while : ; do : ; done &
[1] 21699 #死循环的进程号

linux的cgroups详解

我们可以看到21699把进程打满了

之前我们创建的cpu子系统,没有说明对哪些资源做怎么样的限制,我们操作下

# 配置test对子进程21699起作用
[root@dev215 cpu]# echo 21699 > test/tasks
# cpu.cfs_quota_us 默认是-1 表示不限制,最大值100000,写50000表示50%
[root@dev215 cpu]# echo 50000 > test/cpu.cfs_quota_us

我们再top看下

linux的cgroups详解

cpu已经限制在了50%了。

此处有两个参数:

  • cpu.cfs_quota_us 默认值-1,此值越高cpu使用率越高
  • cpu.cfs_period_us 默认值100000,表示cpu的时间片分为100000份,此值越低cpu使用越高

容器技术就是通过这一系列的子系统来限制资源的使用。


如果觉得对你有帮助,请关注公众号:5ycode,后续会不断更新哦

linux的cgroups详解