Linux 内核容器技术:CGroups 资源限制核心技术(第一部分)

文档信息

  • 系列: Linux 内核容器技术深度解析
  • 第二篇: CGroups 资源限制
  • 版本: V1.0
  • 创建日期: 2026 年 3 月 10 日
  • 预计阅读时间: 4-5 小时
  • 技术难度: ⭐⭐⭐⭐⭐ (专家级)
  • 前置知识: Linux 进程管理、内存管理、调度器基础

目录

  1. [CGroups 技术概述](#cgroups 技术概述)
  2. CGroups v1 核心子系统详解
  3. CGroups v2 统一架构
  4. [Docker 与 Kubernetes 中的 CGroups 应用](#docker 与 kubernetes 中的 cgroups 应用)
  5. 资源限制实战与性能调优
  6. 故障排查与最佳实践

CGroups 技术概述

什么是 CGroups?

CGroups 定义:
Control Groups (控制组) 是 Linux 内核功能,用于:
├─ 限制进程组的资源使用
├─ 监控资源消耗
├─ 控制资源分配
└─ 实现 QoS 保障

核心价值:
├─ 防止资源耗尽:单个进程不影响系统
├─ 资源隔离:多租户环境下的公平分配
├─ 性能保障:关键业务优先
└─ 成本优化:提升资源利用率

与 Namespace 对比:

Namespace (隔离):
├─ 解决"看不见"问题
├─ 系统视图隔离
├─ 进程、网络、文件隔离
└─ 各看各的

CGroups (限制):
├─ 解决"用多少"问题
├─ 资源使用限制
├─ CPU、内存、I/O 控制
└─ 定量分配

CGroups 发展历史

CGroups v1 (2008):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Linux 2.6.24 引入

特点:
├─ 18 个子系统 (资源控制器)
├─ 树状层级结构
├─ 每个子系统独立层级
└─ 配置复杂

问题:
├─ 层级嵌套复杂
├─ 线程问题
├─ 内存回收不可控
└─ 配置繁琐

CGroups v2 (2016):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Linux 4.5 引入

改进:
├─ 统一层级结构
├─ 单个树管理所有资源
├─ 线程安全
├─ 内存压力事件
├─ IO 控制增强
└─ 配置简化

优势对比:

特性          CGroups v1      CGroups v2
层级结构      多树 (每子系统)   单树 (统一)
线程支持      部分支持        完全支持
内存回收      不可控         可控
IO 控制       较弱           增强
配置复杂度    高             低
内核版本      2.6.24+        4.5+

CGroups 核心概念

层级结构 (Hierarchy):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
root/
├── system/
│   ├── user.slice/          # 用户会话
│   ├── system.slice/        # 系统服务
│   └── machine.slice/       # 虚拟机
├── docker/                   # Docker 容器
│   ├── container1/
│   └── container2/
└── kubernetes/               # K8s Pod
    ├── pod1/
    └── pod2/

控制组 (Control Group):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
定义: 层级树中的节点
特点:
├─ 包含一组进程
├─ 继承父组配置
├─ 可设置资源限制
└─ 可监控资源使用

子系统 (Subsystem):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGroups v1 的子系统:
├─ cpu: CPU 调度
├─ cpuacct: CPU 记账
├─ cpuset: CPU 亲和性
├─ memory: 内存控制
├─ blkio: 块设备 I/O
├─ devices: 设备访问
├─ net_cls: 网络分类
├─ net_prio: 网络优先级
├─ hugetlb: 大页内存
├─ pids: 进程数限制
├─ freezer: 进程冻结
├─ perf_event: 性能监控
├─ debug: 调试
└─ ... (共 18 个)

CGroups v2 的资源控制器:
├─ cpu: CPU 权重和带宽
├─ memory: 内存限制
├─ io: I/O 带宽和 IOPS
├─ pids: 进程数
├─ hugetlb: 大页内存
├─ rdma: RDMA 资源
└─ misc: 其他资源

CGroups 文件系统接口

CGroups v1 文件系统:

挂载点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
$ mount | grep cgroup
cgroup on /sys/fs/cgroup/cpu type cgroup (rw,cpu)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,memory)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,blkio)

目录结构:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/sys/fs/cgroup/memory/
├── cgroup.procs              # 进程列表
├── tasks                     # 线程列表
├── memory.limit_in_bytes     # 内存限制
├── memory.usage_in_bytes     # 内存使用
├── memory.stat               # 详细统计
├── memory.soft_limit_in_bytes # 软限制
├── memory.oom_control        # OOM 控制
└── docker/                   # 子控制组
    ├── cgroup.procs
    └── memory.limit_in_bytes

CGroups v2 文件系统:

挂载点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
$ mount | grep cgroup2
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime)

目录结构:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/sys/fs/cgroup/
├── cgroup.controllers         # 可用控制器
├── cgroup.subtree_control     # 子树控制
├── cgroup.procs               # 进程列表
├── cgroup.threads             # 线程列表
├── cpu.max                    # CPU 限制
├── cpu.weight                 # CPU 权重
├── memory.max                 # 内存限制
├── memory.current             # 当前使用
├── io.max                     # I/O 限制
└── pids.max                   # 进程数限制

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 创建控制组
$ sudo mkdir /sys/fs/cgroup/mygroup

# 启用控制器
$ echo "+memory +cpu" > /sys/fs/cgroup/cgroup.subtree_control

# 设置内存限制 (512MB)
$ echo "536870912" > /sys/fs/cgroup/mygroup/memory.max

# 设置 CPU 限制 (50% = 50000ms/100000ms)
$ echo "50000 100000" > /sys/fs/cgroup/mygroup/cpu.max

# 添加进程到控制组
$ echo "12345" > /sys/fs/cgroup/mygroup/cgroup.procs

CGroups v1 核心子系统详解

1. CPU 子系统

功能:控制 CPU 时间分配

核心参数:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cpu.cfs_quota_us:     CPU 配额 (微秒)
cpu.cfs_period_us:    CPU 周期 (微秒,默认 100000)
cpu.shares:           CPU 权重 (默认 1024)
cpu.rt_runtime_us:    实时运行时间
cpu.rt_period_us:     实时周期

配置示例:

场景 1: 限制容器使用 50% CPU
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 创建控制组
$ sudo cgcreate -g cpu:/docker/container1

# 设置 50% CPU (50000us / 100000us)
$ echo 50000 > /sys/fs/cgroup/cpu/docker/container1/cpu.cfs_quota_us
$ echo 100000 > /sys/fs/cgroup/cpu/docker/container1/cpu.cfs_period_us

# 添加进程
$ echo 12345 > /sys/fs/cgroup/cpu/docker/container1/cgroup.procs

# 验证
$ cgget -g cpu:docker/container1
cpu.cfs_quota_us = 50000
cpu.cfs_period_us = 100000

场景 2: CPU 权重分配
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 容器 A: 权重 2048 (2 倍)
$ echo 2048 > /sys/fs/cgroup/cpu/docker/containerA/cpu.shares

# 容器 B: 权重 1024 (1 倍)
$ echo 1024 > /sys/fs/cgroup/cpu/docker/containerB/cpu.shares

# 容器 C: 权重 512 (0.5 倍)
$ echo 512 > /sys/fs/cgroup/cpu/docker/containerC/cpu.shares

# CPU 竞争时分配比例: A:B:C = 2:1:0.5

场景 3: 绑定到特定 CPU 核心
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 使用 cpuset 子系统
$ sudo cgcreate -g cpuset:/docker/container1

# 设置 CPU 核心 (0-3)
$ echo "0-3" > /sys/fs/cgroup/cpuset/docker/container1/cpuset.cpus

# 设置内存节点
$ echo "0" > /sys/fs/cgroup/cpuset/docker/container1/cpuset.mems

# 添加进程
$ echo 12345 > /sys/fs/cgroup/cpuset/docker/container1/cgroup.procs

性能监控:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 查看 CPU 使用统计
$ cat /sys/fs/cgroup/cpu/docker/container1/cpuacct.usage
1234567890  # 纳秒

# 查看每个 CPU 核心的使用
$ cat /sys/fs/cgroup/cpu/docker/container1/cpuacct.usage_percpu
123456 234567 345678 456789

# 使用 cgtop 查看实时 CPU 使用
$ cgtop -g cpu

2. Memory 子系统

功能:控制内存使用,防止 OOM

核心参数:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
memory.limit_in_bytes:        硬限制
memory.soft_limit_in_bytes:   软限制 (回收阈值)
memory.memsw.limit_in_bytes:  内存 +Swap 限制
memory.oom_control:           OOM 控制
memory.oom_kill_disable:      禁用 OOM Kill
memory.use_hierarchy:         层级统计
memory.stat:                  详细统计

配置示例:

场景 1: 设置内存硬限制
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 创建控制组
$ sudo cgcreate -g memory:/docker/container1

# 设置 512MB 限制
$ echo "536870912" > /sys/fs/cgroup/memory/docker/container1/memory.limit_in_bytes

# 添加进程
$ echo 12345 > /sys/fs/cgroup/memory/docker/container1/cgroup.procs

# 查看使用情况
$ cat /sys/fs/cgroup/memory/docker/container1/memory.usage_in_bytes
268435456  # 256MB

场景 2: 配置软限制
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 硬限制:1GB
$ echo "1073741824" > /sys/fs/cgroup/memory/docker/container1/memory.limit_in_bytes

# 软限制:512MB (内存紧张时优先回收)
$ echo "536870912" > /sys/fs/cgroup/memory/docker/container1/memory.soft_limit_in_bytes

# 效果:
# - 正常使用:可以使用到 1GB
# - 内存紧张:回收超过 512MB 的部分

场景 3: 禁用 OOM Killer
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 禁用 OOM Kill (进程会睡眠而不是被杀死)
$ echo "1" > /sys/fs/cgroup/memory/docker/container1/memory.oom_kill_disable

# 查看 OOM 状态
$ cat /sys/fs/cgroup/memory/docker/container1/memory.oom_control
oom_kill_disable 1
under_oom 0
oom_kill 0

场景 4: 内存+Swap 限制
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 内存限制:512MB
$ echo "536870912" > /sys/fs/cgroup/memory/docker/container1/memory.limit_in_bytes

# 内存+Swap 限制:1GB
$ echo "1073741824" > /sys/fs/cgroup/memory/docker/container1/memory.memsw.limit_in_bytes

# 效果:
# - 最多使用 512MB 物理内存
# - 超出部分使用 Swap
# - 总计不超过 1GB

详细统计信息:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
$ cat /sys/fs/cgroup/memory/docker/container1/memory.stat
cache 104857600        # 页面缓存
rss 209715200          # 匿名内存
mapped_file 52428800   # 映射文件
pgpgin 123456          # 读入页数
pgpgout 65432          # 写出页数
pgfault 78901          # 缺页中断
pgmajfault 234         # 主缺页中断
inactive_anon 104857600
active_anon 104857600
inactive_file 52428800
active_file 52428800
unevictable 0
hierarchical_memory_limit 536870912
hierarchical_memsw_limit 1073741824
total_cache 104857600
total_rss 209715200

OOM 事件监控:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 查看 OOM 杀死次数
$ cat /sys/fs/cgroup/memory/docker/container1/memory.oom_kill
0

# 查看是否处于 OOM 状态
$ cat /sys/fs/cgroup/memory/docker/container1/memory.oom_control | grep under_oom
under_oom 0

3. Block I/O 子系统

功能:控制块设备 I/O 带宽和 IOPS

核心参数:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
blkio.weight:           权重 (10-1000, 默认 500)
blkio.weight_device:    按设备设置权重
blkio.throttle.read_bps_device:    读带宽限制 (B/s)
blkio.throttle.write_bps_device:   写带宽限制 (B/s)
blkio.throttle.read_iops_device:   读 IOPS 限制
blkio.throttle.write_iops_device:  写 IOPS 限制

配置示例:

场景 1: I/O 权重分配
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 容器 A: 高优先级 (权重 800)
$ echo 800 > /sys/fs/cgroup/blkio/docker/containerA/blkio.weight

# 容器 B: 低优先级 (权重 200)
$ echo 200 > /sys/fs/cgroup/blkio/docker/containerB/blkio.weight

# I/O 竞争时分配比例:A:B = 4:1

场景 2: 限制读带宽
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 限制从 /dev/sda 读取速度为 10MB/s
$ echo "8:0 10485760" > /sys/fs/cgroup/blkio/docker/container1/blkio.throttle.read_bps_device

# 设备号查询
$ ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 Mar 10 10:00 /dev/sda
# 主设备号 8, 次设备号 0

场景 3: 限制写 IOPS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 限制向 /dev/sdb 写入 IOPS 为 100
$ echo "8:16 100" > /sys/fs/cgroup/blkio/docker/container1/blkio.throttle.write_iops_device

场景 4: 多设备限制
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 限制 /dev/sda 读 10MB/s
$ echo "8:0 10485760" > /sys/fs/cgroup/blkio/docker/container1/blkio.throttle.read_bps_device

# 限制 /dev/sda 写 5MB/s
$ echo "8:0 5242880" > /sys/fs/cgroup/blkio/docker/container1/blkio.throttle.write_bps_device

# 限制 /dev/sdb 读 20MB/s
$ echo "8:16 20971520" > /sys/fs/cgroup/blkio/docker/container1/blkio.throttle.read_bps_device

# 限制 /dev/sdb 写 10MB/s
$ echo "8:16 10485760" > /sys/fs/cgroup/blkio/docker/container1/blkio.throttle.write_bps_device

I/O 统计监控:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 查看 I/O 统计
$ cat /sys/fs/cgroup/blkio/docker/container1/blkio.io_service_bytes
8:0 Read 104857600
8:0 Write 52428800
8:0 Sync 157286400
8:0 Async 0
8:0 Total 157286400
8:16 Read 209715200
8:16 Write 104857600
8:16 Sync 314572800
8:16 Async 0
8:16 Total 314572800

# 查看 IOPS 统计
$ cat /sys/fs/cgroup/blkio/docker/container1/blkio.io_serviced
8:0 Read 1000
8:0 Write 500
8:0 Sync 1500
8:0 Async 0
8:0 Total 1500

4. PIDs 子系统

功能:限制进程数量,防止 fork 炸弹

核心参数:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
pids.max:     最大进程数
pids.current: 当前进程数
pids.events:  事件统计

配置示例:

场景 1: 限制进程数
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 创建控制组
$ sudo cgcreate -g pids:/docker/container1

# 限制最多 100 个进程
$ echo "100" > /sys/fs/cgroup/pids/docker/container1/pids.max

# 添加进程
$ echo 12345 > /sys/fs/cgroup/pids/docker/container1/cgroup.procs

# 查看当前进程数
$ cat /sys/fs/cgroup/pids/docker/container1/pids.current
23

# 尝试 fork 超过限制
$ while :; do fork() & done
-bash: fork: retry: Resource temporarily unavailable

场景 2: 无限制
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 设置为 max (无限制)
$ echo "max" > /sys/fs/cgroup/pids/docker/container1/pids.max

场景 3: 监控 fork 失败事件
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 查看事件统计
$ cat /sys/fs/cgroup/pids/docker/container1/pids.events
max 0  # fork 失败次数

实时监控:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 查看当前进程数
$ cat /sys/fs/cgroup/pids/docker/container1/pids.current

# 查看最大限制
$ cat /sys/fs/cgroup/pids/docker/container1/pids.max

# 列出所有进程
$ cat /sys/fs/cgroup/pids/docker/container1/cgroup.procs
12345
12346
12347
...

5. Devices 子系统

功能:控制设备访问权限

设备类型:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
b: 块设备 (block device)
c: 字符设备 (character device)
u: 任意设备

权限:
r: 读 (read)
w: 写 (write)
m: 创建设备节点 (mknod)

配置示例:

场景 1: 禁止访问所有设备 (默认)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 默认情况下,CGroups 禁止访问所有设备
# 需要显式允许

场景 2: 允许访问 /dev/null
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 允许读写 /dev/null (主设备号 1, 次设备号 3)
$ echo "c 1:3 rw" > /sys/fs/cgroup/devices/docker/container1/devices.allow

场景 3: 允许访问 /dev/zero
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 允许读写 /dev/zero (主设备号 1, 次设备号 5)
$ echo "c 1:5 rw" > /sys/fs/cgroup/devices/docker/container1/devices.allow

场景 4: 允许访问所有终端设备
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 允许访问 /dev/tty (主设备号 5, 次设备号 0)
$ echo "c 5:0 rw" > /sys/fs/cgroup/devices/docker/container1/devices.allow

场景 5: 允许访问 GPU 设备
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# NVIDIA GPU (主设备号 195)
$ echo "c 195:* rw" > /sys/fs/cgroup/devices/docker/container1/devices.allow

Docker 默认配置:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Docker 容器默认允许的设备:
├─ /dev/null (1:3)
├─ /dev/zero (1:5)
├─ /dev/full (1:7)
├─ /dev/random (1:8)
├─ /dev/urandom (1:9)
├─ /dev/tty (5:0)
├─ /dev/ptmx (5:2)
└─ /dev/fuse (10:229)

6. Net_cls 和 Net_prio 子系统

Net_cls: 为网络包添加 classid 标记

功能:配合 tc (traffic control) 进行流量控制

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 创建控制组
$ sudo cgcreate -g net_cls:/docker/container1

# 设置 classid (0x10001)
$ echo "0x10001" > /sys/fs/cgroup/net_cls/docker/container1/net_cls.classid

# 配置 tc 规则
$ sudo tc qdisc add dev eth0 root handle 1: htb
$ sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 10mbit
$ sudo tc filter add dev eth0 parent 1:0 handle 1: cgroup

# 效果:容器所有网络包都标记为 0x10001,应用 tc 规则

Net_prio: 设置网络优先级

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 创建控制组
$ sudo cgcreate -g net_prio:/docker/container1

# 设置 eth0 接口优先级为 10
$ echo "eth0 10" > /sys/fs/cgroup/net_prio/docker/container1/net_prio.ifpriomap

# 设置多个接口
$ echo "eth0 10" > /sys/fs/cgroup/net_prio/docker/container1/net_prio.ifpriomap
$ echo "eth1 5" > /sys/fs/cgroup/net_prio/docker/container1/net_prio.ifpriomap

CGroups v2 统一架构

CGroups v2 核心改进

统一层级结构:

CGroups v1:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/sys/fs/cgroup/
├── cpu/          # CPU 层级
│   └── docker/
├── memory/       # 内存层级
│   └── docker/
├── blkio/        # I/O 层级
│   └── docker/
└── ...           # 每个子系统独立层级

问题:
├─ 配置复杂:需要在多个层级操作
├─ 线程问题:线程不能跨层级
└─ 资源冲突:不同子系统配置不一致

CGroups v2:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
/sys/fs/cgroup/
└── docker/
    ├── container1/    # 统一控制组
    │   ├── cpu.max
    │   ├── memory.max
    │   ├── io.max
    │   └── pids.max
    └── container2/

优势:
├─ 单一层级:所有资源在一个树中
├─ 配置简单:一次设置所有资源
├─ 线程安全:支持线程粒度控制
└─ 资源协调:统一 QoS 策略

CGroups v2 资源控制器详解

1. CPU 控制器

核心文件:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
cpu.max:           CPU 带宽限制
cpu.weight:        CPU 权重
cpu.pressure:      CPU 压力统计

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 创建控制组
$ sudo mkdir /sys/fs/cgroup/docker/container1

# 启用 CPU 控制器
$ echo "+cpu" > /sys/fs/cgroup/cgroup.subtree_control

# 设置 CPU 限制 (50% = 50000/100000)
$ echo "50000 100000" > /sys/fs/cgroup/docker/container1/cpu.max

# 设置 CPU 权重 (默认 100)
$ echo "200" > /sys/fs/cgroup/docker/container1/cpu.weight

# 查看 CPU 压力
$ cat /sys/fs/cgroup/docker/container1/cpu.pressure
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

2. Memory 控制器

核心文件:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
memory.max:          硬限制
memory.high:         软限制 (回收阈值)
memory.current:      当前使用
memory.stat:         详细统计
memory.oom.group:    OOM 组标志
memory.pressure:     内存压力

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 启用内存控制器
$ echo "+memory" > /sys/fs/cgroup/cgroup.subtree_control

# 设置硬限制 (512MB)
$ echo "536870912" > /sys/fs/cgroup/docker/container1/memory.max

# 设置软限制 (256MB)
$ echo "268435456" > /sys/fs/cgroup/docker/container1/memory.high

# 查看当前使用
$ cat /sys/fs/cgroup/docker/container1/memory.current
134217728  # 128MB

# 查看统计
$ cat /sys/fs/cgroup/docker/container1/memory.stat
anon 104857600
file 20971520
kernel_stack 524288
slab 262144
sock 131072
shmem 65536
file_mapped 10485760
file_dirty 0
file_writeback 0
inactive_anon 52428800
active_anon 52428800
inactive_file 10485760
active_file 10485760
unevictable 0
slab_reclaimable 131072
slab_unreclaimable 131072
pgfault 12345
pgmajfault 234
pgrefill 567
pgscan 890
pgsteal 123
pgactivate 456
pgdeactivate 789

# OOM 组设置 (进程组一起被 OOM kill)
$ echo "1" > /sys/fs/cgroup/docker/container1/memory.oom.group

# 查看内存压力
$ cat /sys/fs/cgroup/docker/container1/memory.pressure
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

3. I/O 控制器

核心文件:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
io.max:            I/O 限制
io.weight:         I/O 权重
io.pressure:       I/O 压力

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 启用 I/O 控制器
$ echo "+io" > /sys/fs/cgroup/cgroup.subtree_control

# 限制读带宽 (10MB/s)
$ echo "8:0 rbps=10485760" > /sys/fs/cgroup/docker/container1/io.max

# 限制写带宽 (5MB/s)
$ echo "8:0 wbps=5242880" > /sys/fs/cgroup/docker/container1/io.max

# 限制读 IOPS (100)
$ echo "8:0 riops=100" > /sys/fs/cgroup/docker/container1/io.max

# 限制写 IOPS (50)
$ echo "8:0 wiops=50" > /sys/fs/cgroup/docker/container1/io.max

# 设置 I/O 权重 (默认 100)
$ echo "200" > /sys/fs/cgroup/docker/container1/io.weight

# 查看 I/O 压力
$ cat /sys/fs/cgroup/docker/container1/io.pressure
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

4. PID 控制器

核心文件:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
pids.max:          最大进程数
pids.current:      当前进程数
pids.events:       事件统计

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 启用 PID 控制器
$ echo "+pids" > /sys/fs/cgroup/cgroup.subtree_control

# 限制 100 个进程
$ echo "100" > /sys/fs/cgroup/docker/container1/pids.max

# 查看当前进程数
$ cat /sys/fs/cgroup/docker/container1/pids.current
23

# 查看事件
$ cat /sys/fs/cgroup/docker/container1/pids.events
max 0

5. Hugetlb 控制器

核心文件:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
hugetlb.<size>.max:     大页内存限制
hugetlb.<size>.current: 当前使用

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 限制 2MB 大页内存为 64MB
$ echo "67108864" > /sys/fs/cgroup/docker/container1/hugetlb.2MB.max

# 限制 1GB 大页内存为 1GB
$ echo "1073741824" > /sys/fs/cgroup/docker/container1/hugetlb.1GB.max

# 查看使用
$ cat /sys/fs/cgroup/docker/container1/hugetlb.2MB.current
33554432  # 32MB

CGroups v2 PSI (Pressure Stall Information)

PSI 压力停滞信息:

功能:监控资源压力导致的性能停滞

三种资源压力:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CPU: 等待 CPU 调度的时间
Memory: 等待内存回收的时间
I/O: 等待 I/O 完成的时间

两种模式:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
some: 部分任务停滞的时间占比
full: 所有任务都停滞的时间占比

配置示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 查看 CPU 压力
$ cat /sys/fs/cgroup/docker/container1/cpu.pressure
some avg10=5.00 avg60=3.50 avg300=2.00 total=123456
full avg10=0.00 avg60=0.00 avg300=0.00 total=0

解读:
├─ some avg10=5.00: 过去 10 秒,5% 的时间有任务等待 CPU
├─ full avg10=0.00: 过去 10 秒,0% 的时间所有任务都在等待
└─ total=123456: 累积停滞时间 (微秒)

# 查看内存压力
$ cat /sys/fs/cgroup/docker/container1/memory.pressure
some avg10=10.00 avg60=8.50 avg300=5.00 total=234567
full avg10=2.00 avg60=1.50 avg300=0.50 total=12345

解读:
├─ some avg10=10.00: 10% 时间有任务等待内存
├─ full avg10=2.00: 2% 时间所有任务都在等待内存
└─ full > 0 表示内存严重不足

# 查看 I/O 压力
$ cat /sys/fs/cgroup/docker/container1/io.pressure
some avg10=15.00 avg60=12.00 avg300=8.00 total=345678
full avg10=5.00 avg60=3.00 avg300=1.00 total=23456

告警阈值:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# 设置 PSI 告警 (需要内核支持)
$ echo "some 60000 500000" > /sys/fs/cgroup/docker/container1/memory.pressure_threshold

# 当 some 压力超过 50% 持续 60 秒时触发
# 可用于自动扩缩容或告警

由于篇幅限制,让我继续创建文档的第二部分,包含 Docker/K8s 应用、实战调优和最佳实践:

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐