Docker底层-Cgroup

Cgroup 是什么?

一、基本概念

Cgroup(Control Groups)是 Linux 内核的一个功能,用于限制、记录和隔离进程组的资源使用。

简单理解:

  • Cgroup = Control Groups = 控制组
  • 作用:限制和管理进程的资源使用
  • 位置:Linux 内核功能,通过 /sys/fs/cgroup 文件系统访问

二、Cgroup 的作用

Cgroup 可以限制和管理:

资源类型 可以限制什么 实际例子
CPU CPU 使用率、CPU 时间片 限制容器最多使用 50% CPU
Memory 内存使用量、Swap 限制容器最多使用 512MB 内存
Block IO 磁盘读写速度 限制容器磁盘 IO 为 10MB/s
Network 网络带宽 限制容器网络带宽为 100Mbps
Process 进程数量 限制容器最多 100 个进程
Device 设备访问权限 允许/禁止访问特定设备

三、Cgroup 的工作原理

1. 文件系统接口

Cgroup 通过虚拟文件系统暴露:

/sys/fs/cgroup/

├── cpu/ # CPU 控制器

│ ├── docker/ # Docker 容器的 cgroup

│ └── ...

├── memory/ # 内存控制器

│ ├── docker/

│ └── ...

├── blkio/ # 块 IO 控制器

│ └── ...

└── pids/ # 进程数控制器

└── ...

2. 层次结构

Cgroup 是树形结构:

/sys/fs/cgroup/cpu/

├── docker/ # Docker 的父 cgroup

│ ├── <container-id-1>/ # 容器 1 的 cgroup

│ │ ├── cpu.cfs_quota_us # CPU 配额

│ │ └── tasks # 属于这个组的进程

│ └── <container-id-2>/ # 容器 2 的 cgroup

└── system.slice/ # systemd 服务的 cgroup

复制代码
root@LAPTOP-LU4HDAFV:/sys/fs/cgroup# tree -L 1
.
├── cgroup.controllers
├── cgroup.max.depth
├── cgroup.max.descendants
├── cgroup.pressure
├── cgroup.procs
├── cgroup.stat
├── cgroup.subtree_control
├── cgroup.threads
├── cpu.pressure
├── cpu.stat
├── cpu.stat.local
├── cpuset.cpus.effective
├── cpuset.mems.effective
├── dev-hugepages.mount
├── dev-mqueue.mount
├── init.scope
├── io.pressure
├── io.stat
├── memory.numa_stat
├── memory.pressure
├── memory.reclaim
├── memory.stat
├── sys-fs-fuse-connections.mount
├── sys-kernel-config.mount
├── sys-kernel-debug.mount
├── sys-kernel-tracing.mount
├── system.slice
└── user.slice

10 directories, 19 files
root@LAPTOP-LU4HDAFV:/sys/fs/cgroup# 
复制代码
=== cgroup.controllers 文件说明 ===

这个文件列出了系统可用的 Cgroup 资源控制器

=== 各个控制器的含义 ===

1. cpuset - CPU 核心和内存节点分配
2. cpu - CPU 使用限制和调度
3. io - 块设备 IO 限制
4. memory - 内存使用限制
5. hugetlb - 大页内存管理
6. pids - 进程数量限制
7. rdma - RDMA 资源限制

二、各分类详细说明

1. Cgroup 核心文件(8 个)- 管理 Cgroup 本身

作用:管理 Cgroup 系统本身,不直接限制资源

类比:公司总部的组织架构管理

文件 作用 类比
cgroup.controllers 列出有哪些控制器可用 公司有哪些部门
cgroup.procs 记录哪些进程在这个组 哪些员工在这个部门
cgroup.subtree_control 控制子组能用哪些控制器 子部门能用哪些工具
cgroup.max.depth 限制 Cgroup 树的深度 部门层级最多几层
cgroup.stat Cgroup 统计信息 部门统计报表

关键点:这些文件管理"谁在哪个组",不直接限制资源。

2. CPU 控制器文件(3 个)- 控制 CPU 资源

作用:限制和管理 CPU 使用

类比:CPU 部门的规则和统计

文件 作用 实际内容
cpu.stat 记录 CPU 用了多少时间 usage_usec 5624888000(用了 5624 秒)
cpu.pressure 告诉你 CPU 是否紧张 CPU 压力信息
cpu.stat.local 本地 CPU 统计 本地 CPU 使用情况

关键点:这些文件限制和统计 CPU 使用,类似"电表"。

3. CPUset 控制器文件(2 个)- 控制 CPU 核心分配

作用:决定进程能用哪些 CPU 核心

类比:分配座位

文件 作用 实际内容
cpuset.cpus.effective 实际能用的 CPU 核心 0-11(能用所有 12 个核心)
cpuset.mems.effective 实际能用的内存节点 内存节点编号

关键点:这些文件限制"能用哪些 CPU 核心",不是限制"用多少 CPU"。

4. IO 控制器文件(2 个)- 控制磁盘 IO

作用:限制和管理磁盘读写

类比:限速标志和流量统计

文件 作用 实际内容
io.stat 记录磁盘读写了多少 rbytes=2492019712(读了 2.3GB)
io.pressure 告诉你磁盘是否繁忙 IO 压力信息

关键点:这些文件限制和统计磁盘 IO,类似"限速标志"。

5. 内存控制器文件(4 个)- 控制内存资源

作用:限制和管理内存使用

类比:水表和限流阀

文件 作用 实际内容
memory.stat 记录内存用了多少 anon 1314009088(匿名页用了 1.2GB)
memory.pressure 告诉你内存是否紧张 内存压力信息
memory.reclaim 可以手动回收内存 内存回收接口
memory.numa_stat NUMA 内存统计 NUMA 节点内存使用

关键点:这些文件限制和统计内存使用,类似"水表"。

6. Cgroup 组目录(9 个)- 实际的 Cgroup 组

作用:实际的 Cgroup 组,包含进程和资源限制

类比:实际的部门

目录 类型 包含什么
system.slice/ slice 所有 systemd 系统服务
docker-<id>.scope/ scope Docker 容器的进程
init.scope/ scope init 进程(PID 1)
*.mount/ mount 各种挂载点的进程

关键点:

  • 目录 = 实际的组,里面有进程
  • 目录里也有控制文件(cpu.max、memory.current 等)
  • 这些文件控制目录里的进程

三、关键区别

文件 vs 目录
类型 是什么 作用 例子
文件 工具/规则 设置限制、查看统计 cpu.max, memory.current
目录 部门/组织 包含进程和资源限制 system.slice/, docker-<id>.scope/
根目录 vs 子目录

/sys/fs/cgroup/ # 根目录

├── cpu.stat # 整个系统的 CPU 统计

├── memory.stat # 整个系统的内存统计

└── system.slice/ # 子目录

├── cpu.stat # system.slice 的 CPU 统计

├── memory.stat # system.slice 的内存统计

└── docker-<id>.scope/ # 子子目录

├── cpu.stat # 容器的 CPU 统计

└── memory.stat # 容器的内存统计

四、实际例子

例子 1:查看整个系统的 CPU 使用

cat /sys/fs/cgroup/cpu.stat

输出: usage_usec 5624888000 (整个系统用了 5624 秒 CPU)

例子 2:查看容器的 CPU 使用

cat /sys/fs/cgroup/system.slice/docker-<id>.scope/cpu.stat

输出: usage_usec 134142 (这个容器用了 0.13 秒 CPU)

例子 3:限制容器的 CPU

写入限制到容器的 cpu.max 文件

复制代码
echo "50000 100000" > /sys/fs/cgroup/system.slice/docker-<id>.scope/cpu.max

cpu.max 文件格式

格式:<quota> <period>

含义 CPU 使用率
max 100000 无限制 100%
100000 100000 限制 100% 100%
50000 100000 限制 50% 50%
25000 100000 限制 25% 25%

说明:

  • period(周期):通常是 100000 微秒 = 100ms
  • quota(配额):在这个周期内可以使用的时间(微秒)
  • CPU 使用率 = quota / period

五、总结

各分类的含义:

  1. Cgroup 核心文件 = 管理员
  • 管理"谁在哪个组",不直接限制资源
  1. CPU/内存/IO 控制器文件 = 资源管理员
  • 限制和统计资源使用(CPU、内存、IO)
  1. Cgroup 组目录 = 实际的部门
  • 包含进程和资源限制
  • 目录里也有控制文件

关系:

  • 文件 = 工具(用来设置限制)
  • 目录 = 组织(包含进程和限制)
  • 目录里的文件 = 控制目录里的进程

这就是这些分类的含义。

Cgroup 可以设置的所有资源限制

除了 CPU 使用时间,Cgroup 还可以设置以下限制:

一、所有可设置的资源限制

1. CPU 相关限制(4 种)
文件 作用 设置示例
cpu.max CPU 使用时间限制 echo "50000 100000" > cpu.max (50% CPU)
cpu.weight CPU 权重(公平调度) echo "100" > cpu.weight (默认权重)
cpu.idle CPU 空闲时间 echo "0" > cpu.idle (禁用空闲)
cpu.max.burst CPU 突发限制 echo "10000" > cpu.max.burst
2. 内存相关限制(5 种)
文件 作用 设置示例
memory.max 最大内存使用量 echo "536870912" > memory.max (512MB)
memory.high 内存警告阈值 echo "268435456" > memory.high (256MB)
memory.low 内存保护阈值 echo "134217728" > memory.low (128MB)
memory.swap.max Swap 限制 echo "268435456" > memory.swap.max (256MB)
memory.min 最小内存保证 echo "67108864" > memory.min (64MB)
3. IO 限制(1 种)
文件 作用 设置示例
io.max 磁盘读写速度限制 echo "8:48 rbps=10485760 wbps=10485760" > io.max (10MB/s)
4. 进程数限制(1 种)
文件 作用 设置示例
pids.max 最大进程数 echo "100" > pids.max
5. CPU 核心分配(2 种)
文件 作用 设置示例
cpuset.cpus 指定可用的 CPU 核心 echo "0-3" > cpuset.cpus (只用 CPU 0-3)
cpuset.mems 指定可用的内存节点 echo "0" > cpuset.mems (只用内存节点 0)

二、实际设置示例

示例 1:限制 CPU 为 50%

echo "50000 100000" > /sys/fs/cgroup/system.slice/docker-<id>.scope/cpu.max

含义: 限制使用 50% CPU

示例 2:限制内存为 512MB

echo "536870912" > /sys/fs/cgroup/system.slice/docker-<id>.scope/memory.max

536870912 = 512 * 1024 * 1024 (字节)

示例 3:限制进程数为 100

echo "100" > /sys/fs/cgroup/system.slice/docker-<id>.scope/pids.max

示例 4:限制只能使用 CPU 0-3

echo "0-3" > /sys/fs/cgroup/system.slice/docker-<id>.scope/cpuset.cpus

示例 5:限制磁盘读写速度为 10MB/s

先找到设备号

lsblk

假设设备是 8:48

echo "8:48 rbps=10485760 wbps=10485760" > /sys/fs/cgroup/system.slice/docker-<id>.scope/io.max

10485760 = 10 * 1024 * 1024 (10MB/s)

示例 6:设置内存警告阈值

echo "268435456" > /sys/fs/cgroup/system.slice/docker-<id>.scope/memory.high

256MB,超过这个值会触发警告但不会杀死进程

示例 7:设置 CPU 权重

echo "200" > /sys/fs/cgroup/system.slice/docker-<id>.scope/cpu.weight

权重越高,CPU 分配越多(默认 100)

三、Docker 命令对应的 Cgroup 设置

Docker 命令 对应的 Cgroup 文件 设置的值
--cpus="0.5" cpu.max 50000 100000
--memory="512m" memory.max 536870912
--memory-swap="1g" memory.swap.max 1073741824
--pids-limit=100 pids.max 100
--cpuset-cpus="0-3" cpuset.cpus 0-3
--device-read-bps="/dev/sda:10mb" io.max 8:48 rbps=10485760
--device-write-bps="/dev/sda:10mb" io.max 8:48 wbps=10485760

四、完整的资源限制列表

Cgroup 可以设置的资源限制:

  1. CPU 限制

✓ cpu.max - CPU 使用时间(主要限制)

✓ cpu.weight - CPU 权重(公平调度)

✓ cpu.idle - CPU 空闲时间

✓ cpu.max.burst - CPU 突发限制

  1. 内存限制

✓ memory.max - 最大内存(主要限制)

✓ memory.high - 内存警告阈值

✓ memory.low - 内存保护阈值

✓ memory.min - 最小内存保证

✓ memory.swap.max - Swap 限制

  1. IO 限制

✓ io.max - 磁盘读写速度(主要限制)

  1. 进程数限制

✓ pids.max - 最大进程数(主要限制)

  1. CPU 核心分配

✓ cpuset.cpus - 可用的 CPU 核心

✓ cpuset.mems - 可用的内存节点

五、总结

除了设置 CPU 使用时间(cpu.max),Cgroup 还可以设置:

  1. CPU 权重(cpu.weight)- 公平调度
  1. 内存限制(memory.max)- 最大内存
  1. 内存阈值(memory.high/low)- 警告和保护
  1. Swap 限制(memory.swap.max)- Swap 使用
  1. IO 限制(io.max)- 磁盘读写速度
  1. 进程数限制(pids.max)- 最大进程数
  1. CPU 核心分配(cpuset.cpus)- 指定可用 CPU
  1. 内存节点分配(cpuset.mems)- 指定可用内存节点

这些限制共同控制容器的资源使用。

相关推荐
卜锦元2 小时前
Golang后端性能优化手册(第四章:异步处理与消息队列)
开发语言·后端·docker·容器·性能优化·golang·团队开发
汪碧康2 小时前
【k8s-1.34.2安装部署】二.kubernets软件、证书、配置、脚本等文件准备
云原生·容器·kubernetes·xkube·k8s管理平台·k8s安装部署·k8s dashboard
赋创小助手2 小时前
超微SYS-821GE-TNHR深度测评:8卡 NVIDIA H200 风冷 AI 服务器
运维·服务器·人工智能·深度学习·计算机视觉·语言模型·自然语言处理
ldj20202 小时前
docker-compose对比k8s
云原生·容器·kubernetes
被生活耽误的旅行者2 小时前
由于没有远程桌面授权服务器可以提供许可证,远程会话连接已断开
运维·服务器
一介书生 `2 小时前
轻量级服务器监 Beszel
运维·服务器
随祥2 小时前
windows下搭建MQTT测试环境(服务器/客户端)
运维·服务器
北龙云海2 小时前
全栈护航科研信息化:北龙云海驻场运维服务——为前沿探索提供稳定、安全的数字基座
运维·安全·运维服务·驻场运维
JHC0000002 小时前
推特(X)平台推文自动保存(支持保存所有推文相关数据到服务器)
运维·服务器·爬虫·python·dreamweaver