什么是Cgroup @

根据维基百科的介绍

cgroups (abbreviated from control groups) is a Linux kernel feature that limits, accounts for, and isolates the resource usage of a collection of processes.

cgroups是linux内核提供的一项能力,用来控制某一个进程组的资源(IO、内存、CPU等)使用能力,这项功能的好处就是便于用户自己针对某个进程组分配资源。

cgroups也是docker的核心能力之一,目前cgroup主要分为两个版本,V1和V2,目前最新的内核都已经采用V2版本。V1由于规划较乱,实现版本较早,不易维护等问题会渐渐被V2版本完全取代。

cgruops可以理解为将进程组织为一棵棵树,每棵树用来限制一组资源,而树的节点就是一组进程,例如下图所示:

image

​Subsystem: 可以理解为资源控制的模块,当它被一颗cgroup树关联后,就可以控制该树所有进程的资源,目前为止Linux 支持 12 种 subsystem。

​hierarchy​: 可以理解为一棵 cgroup 树,树的每个节点就是一组进程,其可以被多个Subsystem关联,用来控制多种资源。

在cgroupV2版本,所有 Subsystem 使用统一的单层次树形结构,并且每个进程只能属于一个 cgroup,与V1版本对比的优点是更简洁、更一致、更容易管理。

cGroups文件系统 @

Cgroup通过VFS 文件系统将功能暴露给用户, 只需要通过写文件即可进行cgruop配置

VFS 是一个内核抽象层,能够隐藏具体文件系统的实现细节,从而给用户态进程提供一套统一的 API 接口。VFS 使用了一种通用文件系统的设计,具体的文件系统只要实现了 VFS 的设计接口,就能够注册到 VFS 中,从而使内核可以读写这种文件系统

# 进入cgroup文件目录
cd /sys/fs/cgroup

image

这是 Linux 的 cgroup (控制组) 文件系统 挂载点,用于资源管理和隔离,该目录下所有文件的用途和功能如下表。

cgroup核心控制文件

文件名 功能描述
​cgroup.controllers 显示内核支持的、可用的资源控制器(如 cpu, memory, io 等)
​cgroup.subtree_control 设置在下级子 cgroup 中启用的控制器
​cgroup.procs 显示当前 cgroup 中包含的所有进程 ID (PID)
​cgroup.threads 显示当前 cgroup 中包含的所有线程 ID (TID)
​cgroup.stat 显示当前 cgroup 的基本状态信息
​cgroup.pressure 显示当前 cgroup 的 CPU、内存和 I/O 压力状态
​cgroup.max.depth 限制从当前 cgroup 开始的最大嵌套深度
​cgroup.max.descendants 限制从当前 cgroup 开始的最大子 cgroup 数量

CPU 资源管理

文件名 功能描述
​cpu.stat 显示 CPU 使用时间的详细统计(如用户态、系统态时间)
​cpu.stat.local 显示当前 cgroup 本地的 CPU 使用统计
​cpu.pressure 显示 CPU 资源压力的指标,反映任务等待 CPU 调度的情况
​cpuset.cpus.effective 显示当前 cgroup 实际可用的 CPU 核心列表
​cpuset.cpus.isolated 显示系统中被隔离(通常不用于普通任务)的 CPU 核心
​cpuset.mems.effective 显示当前 cgroup 实际可用的内存节点(NUMA)列表

内存资源管理

文件名 功能描述
​memory.stat 显示内存使用的极其详细的统计(缓存、RSS、交换区等)
​memory.pressure 显示内存资源压力的指标,反映内存回收和紧张状况
​memory.numa_stat 按 NUMA 节点显示内存统计信息
​memory.reclaim 可手动写入以触发当前 cgroup 的内存回收
​memory.zswap.writeback 显示从 zswap(压缩回写缓存)回写到交换区的数据量统计

I/O 资源管理

文件名 功能描述
​io.stat 显示每个块设备的 I/O 操作量(读取/写入的字节数、次数)
​io.pressure 显示 I/O 资源压力的指标,反映任务等待 I/O 完成的情况
​io.prio.class 用于设置 cgroup 的 I/O 调度优先级类别
​io.cost.model 用于配置 I/O 成本模型参数,以便进行权重控制
​io.cost.qos 用于配置 I/O 服务质量参数,以控制带宽分配

系统服务与进程分组

文件名/目录名 功能描述
​system.slice 包含所有系统服务(如 systemd 管理的服务)的 cgroup
​user.slice 包含所有用户登录会话和相关进程的 cgroup
​init.scope 包含系统初始化进程(如 systemd)的 cgroup

其他资源与挂载点

文件名 功能描述
​irq.pressure 显示中断(IRQ)处理压力的指标
​misc.capacity​ / misc.current 显示杂项资源的容量和当前使用量
​dmem.capacity​ / dmem.current 显示设备内存的容量和当前使用量
​*.mount 各种内核和特殊文件系统的挂载点(如大页内存、消息队列、调试跟踪等)

如何使用cgroup能力 @

通过将 cgroup 层级系统与 systemd 单位树捆绑,可以把资源管理设置从进程级别移至应用程序级别。

默认情况下,systemd 会自动创建 slice​、scope​ 和 service 单位的层级来为 cgroup 树提供统一结构。

所有资源默认会被划分为 3 个cgroup​: System​, User​ 和 Machine。

每一个 cgroup​都是一个 slice​,每个slice​ 都可以有自己的子slice​,每个子 slice​ 都用 User ID​ 来命名,可以通过 systemctl 命令进行配置。

  • system.slice —— 所有系统 service 的默认位置
  • user.slice —— 所有用户会话的默认位置。每个用户会话都会在该 slice 下面创建一个子 slice,如果同一个用户多次登录该系统,仍然会使用相同的子 slice。
  • machine.slice —— 所有虚拟机和 Linux 容器的默认位置
# 通过下面命令查看systemctl配置cgruop的命令文档
systemctl set-property -h

# 可以在/run/systemd/system/ 下面查看创建出来的文件

# 通过下面命令查看cgroup的层级结构(静态信息快照)
systemd-cgls --no-page

# 查看cgroup层级的动态信息
systemd-cgtop 

docker-compose如何配置cgruop @

在 docker-compose.yml​ 文件中,你可以在服务定义下的 deploy.resources.limits 部分为服务设置资源限制。

version: '3.8'  # 使用 3.8 或更高版本以支持 `deploy` 配置
services:
  your_service:
    image: your_image:latest
    deploy:
      resources:
        limits:
          cpus: '0.50'   # 限制容器最多使用 0.5 个 CPU 核心
          memory: 512M   # 限制容器最多使用 512MB 内存
        reservations:
          cpus: '0.25'   # 容器启动时保留 0.25 个 CPU 核心
          memory: 256M   # 容器启动时保留 256MB 内存

配置项:

  • ​​cpus​:指定容器可以使用的 CPU 核心数,可以是小数。
  • ​​memory​​:指定容器可以使用的内存大小,单位可以是 B​ (字节)、K​、M​、G)。
  • ​​reservations​​:指定资源预留值,确保容器至少能获得的资源量。

注意事项

  1. ​版本兼容性:确保你使用的 Docker Compose 文件版本和 Docker Engine 版本支持上述配置选项。
  2. cgroup v2 支持:现在许多较新的 Linux 发行版默认使用 cgroup v2。Docker 20.10 及更高版本对 cgroup v2 有很好的支持。你可以通过检查 /sys/fs/cgroup/cgroup.controllers 文件是否存在来确认系统是否使用 cgroup v2
  3. ​资源限制的生效​:通过 Compose 文件设置的资源限制主要是在容器运行时,由 Docker 通过对应的 cgroup 控制器(如 cpu​、memory)来强制执行。

参考链接 @

‍