【Docker 内核详解】cgroups 资源限制(二):组织结构与基本规则、子系统简介

本文主要是介绍【Docker 内核详解】cgroups 资源限制(二):组织结构与基本规则、子系统简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

cgroups 资源限制(二):组织结构与基本规则、子系统简介

  • 1.组织结构与基本规则
  • 2.子系统简介

1.组织结构与基本规则

在之前的博客已经介绍过,传统的 Unix 任务管理,实际上是先启动 init 任务作为根节点,再由 init 节点创建子任务作为子节点,而每个子节点又可以创建新的子节点,如此往复,形成一个树状结构。而系统中的多个 cgroup 也构成类似的树状结构,子节点从父节点继承属性。

它们最大的不同在于,系统中的多个 cgroup 构成的层级并非单根结构,可以允许存在多个。如果任务模型是由 init 作为根节点构成的一棵树,那么系统中的多个 cgroup 则是由多个层级构成的森林。这样做的目的很好理解,如果只有一个层级,那么所有的任务都将被迫绑定其上的所有子系统,这会给某些任务造成不必要的限制。在 Docker 中,每个子系统独自构成一个层级,这样做非常易于管理。

了解了 cgroups 的组织结构,再来了解 cgroups、任务、子系统、层级四者间的关系及其基本规则。

规则 1:同一个层级可以附加一个或多个子系统。如下图所示,CPU 和 Memory 的子系统附加到了一个层级。

在这里插入图片描述

规则 2:一个子系统可以附加到多个层级,当且仅当目标层级只有唯一一个子系统时。下图中小圈中的数字表示子系统附加的时间顺序,CPU 子系统附加到层级 A 的同时不能再附加到层级 B,因为层级 B 已经附加了内存子系统。如果层级 B 没有附加过内存子系统,那么 CPU 子系统同时附加到两个层级是允许的。
在这里插入图片描述
规则 3:系统每次新建一个层级时,该系统上的所有任务默认加入这个新建层级的初始化 cgroup,这个 cgroup 也被称为 root cgroup。对于创建的每个层级,任务只能存在于其中一个 cgroup 中,即一个任务不能存在于同一个层级的不同 cgroup 中,但一个任务可以存在于不同层级中的多个 cgroup 中。如果操作时把一个任务添加到同一个层级中的另一个 cgroup 中,则会将它从第一个 cgroup 中移除。在下图中可以看到,httpd 任务已经加入到层级 A 中的 /cg1,而不能加入同一个层级中的 /cg2,但是可以加入层级 B 中的 /cg3

在这里插入图片描述
规则 4:任务在 fork/clone 自身时创建的子任务默认与原任务在同一个 cgroup 中,但是子任务允许被移动到不同的 cgroup 中。即 fork/clone 完成后,父子任务间在 cgroup 方面是互不影响的。下图中小圈中的数字表示任务出现的时间顺序,当 httpdfork 出另一个 httpd 时,两者在同一个层级中的同一个 cgroup 中。但是随后如果 ID 为 4840httpd 需要移动到其他 cgroup 也是可以的,因为父子任务间已经独立。总结起来就是:初始化时子任务与父任务在同一个 cgroup,但是这种关系随后可以改变。

在这里插入图片描述

2.子系统简介

子系统实际上就是 cgroups 的资源控制系统,每种子系统独立地控制一种资源,目前 Docker 使用如下 9 种子系统,其中,net_cls 子系统在内核中已经广泛实现,但是 Docker 尚未采用,Docker 在网络方面的控制方式将在后续详细介绍,以下是它们的用途。

  • blkio:可以为块设备设定输入 / 输出限制,比如物理驱动设备(包括磁盘、固态硬盘、USB 等)。
  • cpu:使用调度程序控制任务对 CPU 的使用。
  • cpuacct:自动生成 cgroup 中任务对 CPU 资源使用情况的报告。
  • cpuset:可以为 cgroup 中的任务分配独立的 CPU(此处针对多处理器系统)和内存。
  • devices:可以开启或关闭 cgroup 中任务对设备的访问。
  • freezer:可以挂起或恢复 cgroup 中的任务。
  • memory:可以设定 cgroup 中任务对内存使用量的限定,并且自动生成这些任务对内存资源使用情况的报告。
  • perf _event:使用后使 cgroup 中的任务可以进行统一的性能测试。
  • net_cls:Docker 没有直接使用它,它通过使用等级识别符(classid)标记网络数据包,从而允许 Linux 流量控制程序(Traffic ControllerTC)识别从具体 cgroup 中生成的数据包。

上述子系统如何使用虽然很重要,但是 Docker 并没有对 cgroup 本身做增强,容器用户一般也不需要直接操作 cgroup,所以这里我们只大致说明一下操作流程,让大家有一个感性的认识。

Linux 中 cgroup 的实现形式表现为一个文件系统,因此需要 mount 这个文件系统才能够使用(也有可能已经 mount 好了),挂载成功后,就能看到各类子系统。

在这里插入图片描述

cpu 子系统为例,先看一下挂载了这个子系统的控制组下的文件。

在这里插入图片描述

/sys/fs/cgroupcpu 子目录下创建控制组,控制组目录创建成后,它下面就会有很多类似的文件了。

在这里插入图片描述

下面的例子展示了如何限制 PID 为 18828 的进程的 cpu 使用配额:

在这里插入图片描述

>>> 其实都属于输出重定向,都可以输出内容到指定文件。

  • > 会覆盖目标的原有内容,当文件存在时,会先删除原文件,再重新创建文件,然后把内容写入该文件(即清空了原文件),否则直接创建文件。
  • >> 会在目标原有内容后追加内容,当文件存在时直接在文件末尾进行内容追加,不会删除原文件,否则直接创建文件。

在 Docker 的实现中,Docker daemon 会在单独挂载了每一个子系统的控制组目录(比如 /sys/fs/cgroup/cpu)下创建一个名为 docker 的控制组,然后在 docker 控制组里面,再为每个容器创建一个以容器 ID 为名称的容器控制组,这个容器里的所有进程的进程号都会写到该控制组 tasks 中,并且在控制文件(比如 cpu.cfs_quota_us)中写入预设的限制参数值。综上,docker 组的层级结构如下。

在这里插入图片描述
在这里插入图片描述
关于 Docker 如何实现 cgroup 的配置的问题,将会在后续有关 libcontainer 的博客里解释。

这篇关于【Docker 内核详解】cgroups 资源限制(二):组织结构与基本规则、子系统简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/303341

相关文章

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

MySQL数据库中ENUM的用法是什么详解

《MySQL数据库中ENUM的用法是什么详解》ENUM是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用,下面:本文主要介绍MySQL数据库中ENUM的用法是什么的相关资料,文中通过代码... 目录mysql 中 ENUM 的用法一、ENUM 的定义与语法二、ENUM 的特点三、ENUM 的用法1

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

java实现docker镜像上传到harbor仓库的方式

《java实现docker镜像上传到harbor仓库的方式》:本文主要介绍java实现docker镜像上传到harbor仓库的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 前 言2. 编写工具类2.1 引入依赖包2.2 使用当前服务器的docker环境推送镜像2.2

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

mysql中的服务器架构详解

《mysql中的服务器架构详解》:本文主要介绍mysql中的服务器架构,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、mysql服务器架构解释3、总结1、背景简单理解一下mysqphpl的服务器架构。2、mysjsql服务器架构解释mysql的架