cgroup V1和V2的原理和区别

简介: cgroup V1和V2的原理和区别

(备注: 不显示声明就是基于V1版本来讲解的)


  • 1 什么是 cgroups
  • 2 为什么我们需要 cgroups
  • 3 crgoups 是如何实现的
  • 4 如何使用 cgroups
  • 5 `cgroup V2`版本有什么不一样
  • 6 总结


1 什么是 cgroups


1.1 基本概念


cgroups机制是用来限制一个进程或者多个进程的资源。

概念:

  1. Subsystem(子系统): 每种可以控制的资源都被定义成一个子系统,比如CPU子系统Memory子系统
  2. Control Group(控制组): cgroup是用来对一个subsystem(子系统)或者多个子系统的资源进行控制。
  3. Hierarchy(层级): Control group使用层次结构 (Tree) 对资源做划分。参考下图:


640.png

每个层级都会有一个根节点, 子节点是根节点的比重划分。

关系:

  1. 一个子系统最多附加到一个层级(Hierarchy)上。
  2. 一个层级(Hierarchy)可以附加多个子系统。


1.2 进程和cgroup的关系


一个进程限制内存和CPU资源,就会绑定到CPU cgroupMemory cgroup的节点上,CPU cgroup 节点和Memory cgroup节点属于两个不同的层级(Hierarchy)。进程和cgroup 节点是多对多的关系,因为一个进程涉及多个子系统,每个子系统可能属于不同的层次结构(Hierarchy)。

如图:

640.png


上图P代表进程,因为多个进程可能共享相同的资源,所以会抽象出一个CSS_SET,每个进程会属于一个CSS_SET 链表中,同一个CSS_SET下的进程都被其管理。一个CSS_SET关联多个cgroup节点,也就是关联多个子系统的资源控制,那么CSS_SETcgroup节点就是多对多的关系。

参考下 CSS_SET 结构定义:

#ifdef CONFIG_CGROUPS
    /* Control Group info protected by css_set_lock */
    struct css_set __rcu *cgroups; 关联的cgroup 节点
    /* cg_list protected by css_set_lXock and tsk->alloc_lock */
    struct list_head cg_list; // 关联所有的进程
#endif


2 为什么我们需要 cgroups


我们希望能够细粒度的控制资源,我们可以为一个系统的不同用户提供不同的资源使用量,比如一个学校的校园服务器,老师用户可以使用15%的资源,学生用户可以使用5%的资源。我们可以用 cgroups 机制做到。


3 crgoups 是如何实现的


3.1 cgroups 数据结构

  • 每个进程都会指向一个 CSS_SET 数据结构。(上文进程和cgroups关系已经提供过)
    参考源码:
struct task_struct { //进程的数据结构
...
#ifdef CONFIG_CGROUPS
    /* Control Group info protected by css_set_lock */
    struct css_set __rcu *cgroups; 关联的cgroup 节点
    /* cg_list protected by css_set_lXock and tsk->alloc_lock */
    struct list_head cg_list; // 关联所有的进程
#endif
...
}
  • 一个 CSS_SET关联多个cgroup_subsys_state对象,cgroup_subsys_state指向一个cgroup子系统。所以进程和cgroup是不直接关联的,需要通过cgroup_subsys_state对象确定属于哪个层级,属于哪个cgroup节点。
    参考下CSS_SET源码:
  • 640.png
  • 一个 cgroup hierarchy(层次)其实是一个文件系统, 可以挂载在用户空间查看和操作。
  • 我们可以查看、绑定任何一个cgroup节点下的所有进程Id(PID)
  • 实现原理: 通过进程的fork和退出,从 CSS_SET attach 或者 detach 进程


3.2 cgroups文件系统


上面我们了解到进程和cgroup的关系,那么在用户空间内的进程是如何使用cgroup功能的呢?

cgroup通过VFS文件系统将功能暴露给用户,用户创建一些文件,写入一些参数即可使用,那么用户使用crgoup功能会创建哪些文件?

文件如下:

  1. tasks文件: 列举绑定到某个cgroup的所有进程ID(PID).
  2. cgroup.procs文件: 列举一个cgroup节点下的所有线程组ID.
  3. notify_on_releaseflag文件:填 01,表示是否在cgroup中最后一个task退出时通知运行release agent,默认情况下是 0,表示不运行。
  4. release_agent文件: 指定 release agent执行脚本的文件路径(该文件在最顶层cgroup目录中存在),在这个脚本通常用于自动化umount无用的cgroup
  5. 每个子系统也会创建一些特有的文件。


3.3 什么是 VFS 文件系统


VFS是一个内核抽象层,能够隐藏具体文件系统的实现细节,从而给用户态进程提供一套统一的 API 接口。VFS 使用了一种通用文件系统的设计,具体的文件系统只要实现了 VFS 的设计接口,就能够注册到 VFS 中,从而使内核可以读写这种文件系统。 这很像面向对象设计中的抽象类与子类之间的关系,抽象类负责对外接口的设计,子类负责具体的实现。其实,VFS本身就是用c语言实现的一套面向对象的接口。


3.4 clone_children标志是干什么的


这个标志只会影响 cpuset子系统,如果这个标志在 cgroup 中开启,一个新的cpuset子系统cgroup节点 的配置会继承它的父级cgroup节点配置。


4 如何使用 cgroups


我们创建一个cgroup,使用到cpuset这个cgroup子系统,可以按照下面的步骤:

  1. mount -t tmpfs cgroup_root /sys/fs/cgroup
  2. mkdir /sys/fs/cgroup/cpuset
  3. mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
  4. 通过创建和写入新的配置到/sys/fs/cgroup/cpuset虚拟文件系统,创建新的cgroup
  5. 启动一个父进程任务
  6. 得到进程PID,写入到 /sys/fs/cgroup/cpusettasks文件中
  7. forkexec或者clone父进程任务。

举个例子,我们可以创建一个cgroup,命名为Charlie,包含CPU资源23核,memory节点为1,操作如下:

mount -t tmpfs cgroup_root /sys/fs/cgroup
mkdir /sys/fs/cgroup/cpuset
mount -t cgroup cpuset -ocpuset /sys/fs/cgroup/cpuset
cd /sys/fs/cgroup/cpuset
mkdir Charlie
cd Charlie
echo 2-3 > cpuset.cpus
echo 1 > cpuset.mems
echo $$ > tasks
## 查看cgroup信息
sh
# sh是进入当前cgroup
cat /proc/self/cgroup

默认只有root具有cgroup的操作权限。


5 cgroup V2版本有什么不一样


不同于v1版本,cgroup v2版本只有一个层级 Hierarchy(层级)。

cgroup v2的层级可以通过下面的命令进行挂载:

# mount -t cgroup2 none $MOUNT_POINT

cgroupv2文件系统有一个根cgroup,以0x63677270数字来标识,所有支持v2版本的子系统控制器会自动绑定到 v2的唯一层级上并绑定到根cgroup。没有使用cgroup v2版本的进程,也可以绑定到v1版本的层级上,保证了前后版本的兼容性。

v2版本中,因为只有一个层级,所有进程只绑定到cgroup的叶子节点。

如图:


640.png

节点说明:

  1. 父节点开启的子系统控制器控制到儿子节点,比如A节点开启了memory controller,那么C节点``cgroup就可以控制进程的memory
  2. 叶子节点不能控制开启哪些子系统的controller,因为叶子节点关联进程Id。所以非叶子节点不能控制进程的使用资源。

cgroup v2cgroup目录下文件说明:

  • cgroup.procs文件,用来关联 进程Id。这个文件在V1版本使用列举线程组Id的。
  • cgroup.controllers文件(只读)和cgroup.subtree_control文件是用来控制 子cgroup节点可以使用的 子系统控制器。
  • tasks文件用来关联进程信息,只有叶子节点有此文件。

5.1 为什么这么改造?

v1版本为了灵活一个进程可能绑定多个层级(Hierarchy),但是通常是每个层级对应一个子系统,多层级就显得没有必要。所以一个层级包含所有的子系统就比较简单容易管理。

5.2 线程模式

cgroup v2版本支持线程模式,将 threaded 写入到cgroup.type就会开启Thread模式。当开始线程模式后,一个进程的所有线程属于同一个cgroup,会采用Tree结构进行管理。

6 总结

通过对 cgroup的学习,大致了解Linux crgoup的数据结构,v2版本层级结构的优化和支持线程模式的功能。

相关文章
|
监控 Docker 容器
Docker 启动命令里 --cgroupns host 是什么作用?
【8月更文挑战第19天】Docker 启动命令里 --cgroupns host 是什么作用?
565 1
|
存储 Dragonfly 缓存
Nydus:开源的下一代容器镜像加速服务
让更多的容器用户能够体验到容器快速启动和安全加载方面的能力。
7763 0
Nydus:开源的下一代容器镜像加速服务
|
监控 调度 开发工具
IO神器blktrace使用介绍
## 前言 1. blktrace的作者正是block io的maintainer,开发此工具,可以更好的追踪IO的过程。 2. blktrace 结合btt可以统计一个IO是在调度队列停留的时间长,还是在硬件上消耗的时间长,利用这个工具可以协助分析和优化问题。 ## blktrace的原理 一个I/O请求的处理过程,可以梳理为这样一张简单的图: ![](http://image
19666 0
|
Linux 调度 Docker
Linux中的cgroup技术
【8月更文挑战第2天】cgroup (control group) 是 Linux 内核提供的资源管理机制,用于控制进程资源使用。它包含多个子系统,如 CPU、cpuacct、cpuset、memory、blkio、devices、net_cls 和 freezer,分别用于限制 CPU 使用率、统计 CPU 使用、分配 CPU 或内存节点、限制内存使用、限制块设备 I/O、控制设备访问、标记网络数据包和挂起或恢复进程。
|
Ubuntu
systemd挂载cgroup文件系统流程简要分析
systemd挂载cgroup文件系统流程简要分析
|
Kubernetes 异构计算 容器
Kubelet之Topology Manager分析
Topology Manager是kubelet的一个组件,在kubernetes 1.16加入,而kubernetes 1.18中该feature变为beta版。本篇文档将分析Topology Manager的具体工作原理。1.为什么需要Topology Manager现代计算机的CPU架构多采用NUMA(Non-Uniform Memory Access,非统一内存)架构。NUMA就是将cpu
4584 0
|
Ubuntu 网络协议 测试技术
|
Kubernetes 监控 Linux
K8s 如何启用 cgroup2 支持?
K8s 如何启用 cgroup2 支持?
|
存储 弹性计算 资源调度
K8S下一代设备管理机制:DRA
背景Kubernetes从1.8开始引入了Device Plugin机制,用于第三方设备厂商以插件化的方式将设备资源(GPU、RDMA、FPGA、InfiniBand等)接入Kubernetes集群中。用户无需修改Kubernetes代码,只需在集群中以DaemonSet方式部署设备厂商提供的插件,然后在Pod中申明使用该资源的使用量,容器在启动成功后,便可在容器中发现该设备。然而,随着Kuber
3718 2
K8S下一代设备管理机制:DRA