容器——Cgroup简介

Cgroup简介

  • Cgroup 是 Linux 内核的一个特性,用于对进程组的资源(如 CPU、内存、磁盘 I/O 等)进行限制、监控和管理。

Cgroup核心概念

Cgroup(Control Group)定义

  • 每个 cgroup 是一个进程组,可以包含多个进程,该进程组有很多属性(这些属性需要通过关联子系统的方式附加上去(挂载),挂载完成后就得到了很多cgroup文件),用于限制、监控和管理该进程组的资源。

  • cgroup 是对进程分组管理的一种机制,一个 cgroup 包含一组进程,并可以在这个 cgroup 上增加 Linux subsystem 的各种参数配置,将一组进程和一组 subsystem 的系统参数关联起来。

核心功能

将进程分组,并对这些组的资源使用进行控制。

特点

  • 每个 cgroup 是一个进程组,可以包含多个进程。
  • cgroup 可以嵌套,形成层次结构(树状结构)。
  • 每个 cgroup 可以关联一个或多个子系统(Subsystem),用于管理特定类型的资源。

Cgroup 树(Hierarchy)定义

  • Cgroup 树是 cgroup 的层次结构,由多个 cgroup 节点组成,形成一个树状结构。

特点

  • 每个 cgroup 树是一个独立的层次结构,可以关联一个或多个子系统。
  • 一个系统中可以存在多个 cgroup 树,每个树可以管理不同的资源。
  • 每个进程只能属于一个 cgroup 树中的一个 cgroup 节点,但可以同时属于多个 cgroup 树(每个树关联不同的子系统)。
  • 可以在根 cgroup 下可以设置一些全局的资源限制,而在子 cgroup 中又可以针对特定的进程组设置更具体、更细致的限制。这种层次结构使得系统能够根据不同的需求对进程进行分层管理,实现资源的精细分配。

作用

  • 通过树状结构,实现资源的层次化分配和管理。
  • 父 cgroup 的资源限制会传递给子 cgroup。

Subsystem(子系统)定义

  • 子系统是 cgroup 中负责管理特定类型资源的模块,也称为控制器(Controller)。目前大约有12 - 14个常见的子系统。

常见子系统

  • cpu:控制 CPU 时间分配。
  • memory:控制内存使用。
  • blkio:控制块设备 I/O(如磁盘带宽)。
  • net_cls:控制网络流量分类。
  • freezer:暂停和恢复 cgroup 中的进程。
  • pids:限制 cgroup 中的进程数量。

特点

  • 每个子系统可以绑定到一个 cgroup 树。
  • 一个 cgroup 树可以绑定多个子系统。
  • 子系统的资源控制是独立的,不同子系统可以管理不同的资源。

查看子系统

$ cat /proc/cgroups
#subsys_name    hierarchy       num_cgroups     enabled
cpuset          1               1               1
cpu             2               57              1
cpuacct         3               1               1
blkio           4               36              1
memory          5               98              1
devices         6               50              1
freezer         7               2               1
net_cls         8               1               1
perf_event      9               1               1
net_prio        10              1               1
hugetlb         11              1               1
pids            12              63              1
rdma            13              1               1
misc            14              1               1
  • subsys_name:子系统的名字,比如 cpu 是管理 CPU 资源的,memory 是管理内存资源的。
  • hierarchy:子系统关联的 cgroup 树的 ID。如果为 0,表示没有关联任何树;如果 cpu 和 cpuacct 的 hierarchy 值相同,说明它们绑定到了同一棵树;如果 hierarchy 为 0,说明这个子系统没有绑定到任何树,或者它已经绑定到 cgroup v2 的树。
  • num_cgroups:该子系统关联的 cgroup 树中有多少个进程组(节点)。比如,memory 的 num_cgroups 是 98,表示内存子系统关联的树中有 98 个进程组。
  • enabled:子系统是否开启。1 表示开启,0 表示关闭。

挂载(Mount)定义

  • 挂载是将 cgroup 的功能映射到文件系统的某个目录,从而可以通过文件系统的操作来管理 cgroup。

特点

  • 每个 cgroup 树需要通过挂载到文件系统来使用。
  • 挂载点通常是/sys/fs/cgroup/目录下的子目录。
  • 挂载时可以指定绑定的子系统。

示例

# 挂载一个 cgroup 树,绑定 cpu 和 memory 子系统
mount -t cgroup -o cpu,memory cgroup /sys/fs/cgroup/cpu_memory

作用

  • 通过文件系统的接口(如cgroup.procs、cgroup.controllers等文件)管理 cgroup。
  • 挂载后,可以通过文件操作(如读写文件)来配置资源限制。

Cgroup 文件定义

  • cgroup 通过文件系统暴露接口,每个 cgroup 目录下都有一些核心文件,用于配置和监控资源。

常见文件

  • cgroup.procs:列出属于该 cgroup 的进程 PID。
  • cgroup.controllers:列出该 cgroup 可用的控制器。
  • cgroup.subtree_control:启用或禁用子 cgroup 的控制器。
  • cgroup.events:显示 cgroup 的状态(如是否被冻结)。
  • memory.min和memory.low:设置内存保护。

作用

通过这些文件,用户可以配置资源限制、监控资源使用、迁移进程等。

Cgroup核心交互逻辑

  • 一个 hierarchy 可以理解为一棵 cgroup 树,树的每个节点就是一个进程组,每棵树都会与零到多个 subsystem 关联。

  • 在一颗树里面,会包含 Linux 系统中的所有进程,但每个进程只能属于一个节点(进程组)。

  • 系统中可以有很多颗 cgroup 树,每棵树都和不同的 subsystem 关联。

  • 一个进程可以属于多颗树,即一个进程可以属于多个进程组,只是这些进程组和不同的 subsystem 关联。

  • 目前 Linux 支持 12 - 14 种 subsystem,如果不考虑不与任何 subsystem 关联的情况(systemd 就属于这种情况),Linux 里面最多可以建 12 - 14 颗 cgroup 树,每棵树关联一个 subsystem,当然也可以只建一棵树,然后让这棵树关联所有的 subsystem。

  • 当一颗 cgroup 树不和任何 subsystem 关联的时候,意味着这棵树只是将进程进行分组,至于要在分组的基础上做些什么,将由应用程序自己决定,systemd 就是一个这样的例子。

hierarchy(层级结构)与 subsystem(子系统)的关系

  • 一个 hierarchy 可以附加多个 subsystem。但是一个 subsystem 只能附加到一个 hierarchy 上。
  • Linux 支持 12 - 14 种 subsystem,不考虑特殊情况(如 systemd 这种不与任何 subsystem 关联的情况),Linux 最多可建 12 - 14 颗 cgroup 树,每棵树关联一个 subsystem;也可以只建一棵树并让其关联所有 subsystem。
  • 当一个 hierarchy 不与任何 subsystem 关联时,仅用于进程分组,后续操作由应用程序决定,例如 systemd。

hierarchy 与进程(task)的关系

  • 系统创建新的 hierarchy 后,系统中所有进程都会加入该 hierarchy 的 cgroup 根节点(默认创建)。
  • 对于每个 hierarchy,一个 task 只能存在于其中一个 cgroup 中,即一个 task 不能存在于同一个 hierarchy 的不同 cgroup 中。
  • 一个进程可以作为多个 cgroup 的成员,但这些 cgroup 必须在不同的 hierarchy 中,即一个进程可以属于多颗 cgroup 树(不同 hierarchy),且这些树和不同的 subsystem 关联。

subsystem 与进程(task)的关系

  • 由于 subsystem 附加在 hierarchy 上,进程存在于 hierarchy 的 cgroup 中,所以进程通过所在的 hierarchy 与相应的 subsystem 产生关联。

进程(task)相关操作

  • 一个进程 fork 出子进程时,子进程默认和父进程在同一个 cgroup 中,也可根据需要将其移动到其他 cgroup 中。
  • 进程(task)在 fork 自身时创建的子任务(child task)默认与原 task 在同一个 cgroup 中,同样允许被移动到不同的 cgroup 中。

Cgroup的部分特性

操作的原子性和延迟销毁

  • 原子性:当你在cgroup.subtree_control文件中指定多个控制器时,这些操作要么全部成功,要么全部失败。这意味着,如果你尝试同时启用cpu和memory控制器,但其中一个失败,那么这两个控制器都不会被启用。
  • 延迟销毁:当你销毁一个cgroup的控制器时,这个过程是异步的。这意味着,即使控制器已经被标记为销毁,它可能仍然存在于系统中一段时间,直到所有的引用都被释放。这可能会导致一些延迟引用的问题,即在控制器被销毁后,仍然有进程或代码尝试访问它。

进程和线程的跨cgroup迁移

  • 进程的 cgroup 归属和它与其他进程(比如父进程、子进程)之间的关系是没有必然联系的。例如,父进程在 cgroup A 中,但新创建的子进程可以被放置在 cgroup B、cgroup C 等其他任何 cgroup 中,这为灵活地管理进程资源提供了可能。
### 修改 Docker 使用 Systemd 作为 Cgroup Driver 为了确保 Kubernetes 和 Dockercgroup 驱动程序保持一致,通常建议将 Dockercgroup 驱动设置为 `systemd`。这可以通过编辑 `/etc/docker/daemon.json` 文件来实现。 #### 编辑 Daemon JSON 文件 在文件中加入如下配置: ```json { "exec-opts": ["native.cgroupdriver=systemd"] } ``` 保存并退出编辑器后,重启 Docker 服务以应用更改[^1]。 #### 检查当前的 Cgroup Driver 设置 执行命令查看 Docker 当前使用的 cgroup 驱动是否已更改为 `systemd`: ```bash docker info | grep 'Cgroup' ``` 如果一切正常,则应看到输出显示 `Cgroup Driver: systemd`[^2]。 #### 处理潜在冲突 需要注意的是,在某些情况下可能会遇到由于重复定义而导致的问题——即在同一位置既指定了 `native.cgroupdriver=systemd` 又有其他相同参数的存在。为了避免这种情况发生,请确认 `/lib/systemd/system/docker.service` 或者任何自定义的服务单元文件里没有相同的选项被指定。如果有,请移除这些冗余项后再尝试启动 Docker[^3]。 #### 关于资源约束配置 对于希望进一步控制容器内应用程序行为的需求方来说,还可以利用 Docker 提供的各种资源限制机制来进行精细化管理。例如,通过调整 `--cpus` 参数可限定某个特定容器所能占用的最大 CPU 数量;而当涉及到网络连接时,则可能需要用到像 `iptables` 这样的工具配合操作系统的路由表进行流量导向等高级设定[^4]。 #### 实践案例:压力测试环境搭建 假设现在有一个场景是要模拟高负载情况下的系统表现,那么可以在多个容器内部署同样的工作负载生成器(比如使用 `stress` 工具),并通过宿主机上的相应设置允许它们访问外部互联网从而形成完整的实验闭环。具体做法包括但不限于向系统配置追加必要的 IP 转发指令以及安装所需的软件包等等[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值