cgroups是linux内核资源隔离机制,容器通过其控制cpu、内存、io;监控需读取对应cgroup路径下统计文件,注意v1/v2路径差异、字段累计性、单位及时机,并校验容器存活状态。

cgroups 是 Linux 内核提供的资源隔离与限制机制,容器(如 Docker、containerd)底层正是通过 cgroups 控制 CPU、内存、IO 等资源使用。要准确监控容器资源消耗,本质就是读取对应 cgroup 路径下的统计文件,并正确解析其语义。
定位容器对应的 cgroup 路径
容器运行时会为每个容器创建独立的 cgroup 子树。路径通常位于 /sys/fs/cgroup/ 下,具体位置取决于 cgroup 版本(v1 或 v2)和资源类型:
- cgroup v1:按子系统分目录,例如 /sys/fs/cgroup/cpu/docker/
、/sys/fs/cgroup/memory/docker/ - cgroup v2:统一挂载点(如 /sys/fs/cgroup),容器路径为 /sys/fs/cgroup/
/ ,常见 slice 如 docker-.scope 或 libpod-.scope - 可通过 cat /proc/
/cgroup 查看某进程所属的 cgroup 路径,快速确认容器实际归属
关键资源指标及读取方式
不同资源对应不同统计文件,需关注其单位与更新时机:
- CPU 使用量:cgroup v1 中读 cpuacct.stat(含 user 和 system 毫秒数);v2 中读 cpu.stat(含 usage_usec、user_usec、system_usec);注意需周期采样做差值计算使用率
- 内存使用:v1 读 memory.usage_in_bytes(当前 RSS + cache),配合 memory.limit_in_bytes 判断是否接近上限;v2 读 memory.current 和 memory.max;若启用了 memory.pressure,还可读 memory.pressure 获取内存压力信号
- IO 统计:blkio 子系统下(v1)读 blkio.io_service_bytes 或 blkio.io_serviced;v2 统一由 io.stat 提供,格式为 “major:minor rbytes=… wbytes=…”
解析注意事项与常见陷阱
直接 cat 文件看似简单,但容易误读数据:
- 部分字段是**累计值**(如 cpu.usage_usec、io.stat 的字节数),不能直接当作瞬时值使用,必须两次采样求差并除以时间间隔
- memory.usage_in_bytes 在 v1 中包含 page cache,不代表真实内存压力;建议结合 memory.stat 中的 rss 和 cache 字段拆分分析
- cgroup v2 的 memory.current 默认不含内核内存(kmem),若容器启用 kmem accounting,需额外关注 memory.kmem.current
- 容器退出后 cgroup 目录可能残留,读取前应校验对应容器是否仍在运行(如检查 cgroup.procs 是否为空或进程是否存在)
轻量集成建议
无需依赖完整监控栈,可快速落地基础统计:
- 用 shell + awk 定期采集关键字段,写入本地日志或推送至 Prometheus Node Exporter 的 textfile collector
- 在 Go/Python 中调用 os.ReadDir + ioutil.ReadFile,避免 exec cat 带来的开销;注意文件权限(通常需 root 或 cgroup read 权限)
- 对 Kubernetes 场景,优先使用 kubelet 的 /metrics/cadvisor 接口,它已封装 cgroup 解析逻辑并标准化指标名(如 container_cpu_usage_seconds_total)










