Linux cgroups是Linux内核中的一项强大功能,允许用户对进程进行**资源限制、优先级控制、监控和隔离。它主要用于管理和控制计算资源的分配,特别是在容器技术(如 Docker 和 LXC)中得到了广泛应用。
1. Cgroups的基本概念和原理
1.1 资源控制和管理
cgroups的基本功能是将一组进程划分为一个组(控制组),并对这个组分配特定的资源。这些资源主要包括:
- CPU(处理器时间)
- 内存(RAM 和 swap 空间)
- I/O(磁盘和网络带宽)
- 进程数(控制同时运行的进程/线程数量)
- 设备访问控制(控制进程可以访问的设备)
每个cgroup可以对进程的这些资源进行限制和控制,内核会根据cgroup的配置在运行时对资源进行调度。
1.2 cgroup 的层次结构
cgroups具有层次结构,类似于文件系统的层次树。每个cgroup可以包含多个子cgroup,资源控制是自上而下继承的:
- 根cgroup:系统的默认组,包含所有进程。
- 子cgroup:可以从根cgroup创建子控制组,并继承上层组的资源限制。
进程可以分配到任何层次的cgroup中,每个子cgroup可以进一步对资源进行细化限制。
2. cgroups的组成部分
cgroups由以下两个主要组成部分构成:
2.1 cgroup控制器
控制器是cgroups的核心部分,负责实际管理不同类型的资源。常见的控制器包括:
- cpu:控制进程的CPU时间使用。
- cpuacct:对进程的CPU使用情况进行统计。
- memory:限制进程使用的内存大小。
- blkio:控制进程对块设备(磁盘)的 I/O 操作。
- devices:控制进程可以访问哪些设备。
- freezer:挂起或恢复cgroup中的所有进程。
每个控制器都可以单独挂载并使用不同的限制方式。
2.2 Linux cgroup内存子系统
cgroups通过一个虚拟文件系统来暴露接口,称为cgroupfs。这个虚拟文件系统通常挂载在 `/sys/fs/cgroup/`,通过这个文件系统,用户可以:
- 创建、修改和删除cgroup。
- 设置资源限制。
- 监控cgroup的资源使用情况。
在cgroupfs中,每个资源控制器会以不同的子目录存在,例如:
/sys/fs/cgroup/cpu/
每个子目录会包含一些特殊文件,这些文件用来配置和管理资源限制,比如 `cpu.shares` 文件用来定义 CPU 共享比例。
3. Cgroups 的基本操作
3.1 创建cgroup
通过在 cgroupfs 中创建一个新目录,可以创建一个新的 cgroup。这个目录中的文件用来表示资源限制和当前的资源使用情况。例如:
mkdir /dev/memcg/mygroup
这将创建一个名为 `mygroup` 的新控制组,详情如下:
解释:
1. cgroup.clone_children
说明:是否自动将子进程添加到与父进程相同的 cgroup。如果设置为 1,子进程将自动继承父进程的 cgroup 设置。
值:0 或 1。
2. cgroup.event_control
说明:用于控制和管理 cgroup 事件通知机制的文件,通常用于与外部监控系统进行事件触发交互。
3. cgroup.procs
说明:列出当前 cgroup 中所有进程的 PID。可以通过写入 PID 来将某个进程移入该 cgroup。
4. cgroup.sane_behavior
说明:用于指示是否启用了更合理的行为配置(通常与 cgroup v2 或内核的一些新特性有关)。
内存子系统参数
5. memory.failcnt
说明:记录自启动以来,因超出内存限制而失败的内存分配次数。
6. memory.force_empty
说明:写入该文件会尝试释放该 cgroup 中所有不再需要的内存,通常用于手动回收内存。
7. memory.kmem.failcnt
说明:记录内核内存(kmem)分配失败的次数。
8. memory.kmem.limit_in_bytes
说明:限制该 cgroup 可用的内核内存(包括 slab 分配)的上限。
9. memory.kmem.max_usage_in_bytes
说明:自启动以来该 cgroup 中内核内存使用的峰值。
10. memory.kmem.slabinfo
说明:提供内核 slab 分配器的信息,帮助诊断和分析内核内存的使用情况。
11. memory.kmem.tcp.failcnt
说明:记录 TCP 缓存内存分配失败的次数。
12. memory.kmem.tcp.limit_in_bytes
说明:限制该 cgroup 中 TCP 缓存的最大内存使用量。
13. memory.kmem.tcp.max_usage_in_bytes
说明:自启动以来该 cgroup 中 TCP 缓存使用的峰值内存。
14. memory.kmem.tcp.usage_in_bytes
说明:当前该 cgroup 中 TCP 缓存的内存使用量。
15. memory.kmem.usage_in_bytes
说明:当前该 cgroup 中使用的内核内存大小。
16. memory.limit_in_bytes
说明:设置该 cgroup 可使用的物理内存上限(不包括 swap)。超出此值时,内存分配将失败,进程可能会被 OOM 杀死。
17. memory.max_usage_in_bytes
说明:记录自启动以来该 cgroup 的最大物理内存使用量。
18. memory.memsw.failcnt
说明:记录该 cgroup 中物理内存加 swap 内存的分配失败次数。
19. memory.memsw.limit_in_bytes
说明:设置该 cgroup 可使用的物理内存和 swap 的总和上限。
20. memory.memsw.max_usage_in_bytes
说明:自启动以来该 cgroup 使用的最大物理内存加 swap 内存。
21. memory.memsw.usage_in_bytes
说明:当前该 cgroup 中物理内存和 swap 的使用总量。
22. memory.move_charge_at_immigrate
说明:控制当进程迁移到一个新的 cgroup 时是否将其当前的内存使用量一起迁移。可用于控制内存计费策略。
23. memory.numa_stat
说明:显示该 cgroup 中内存的 NUMA(非一致性内存访问)节点的使用统计信息。
24. memory.oom_control
说明:控制是否启用 OOM(Out Of Memory)保护。当设置为启用时,可以避免 cgroup 中的进程被 OOM 杀死。
25. memory.pressure_level
说明:显示内存压力的水平,用于调节系统在内存紧张时的响应行为。
26. memory.soft_limit_in_bytes
说明:设置该 cgroup 的内存软限制,允许 cgroup 在有剩余内存时使用更多的内存,但当系统内存紧张时会首先回收超出部分。
27. memory.stat
说明:提供该 cgroup 的详细内存使用统计信息,包括匿名内存、缓存、RSS 和 slab 等。
28. memory.swappiness
说明:控制该 cgroup 的内存换出到 swap 的倾向,值在 0 到 100 之间,数值越大表示更倾向于将内存换出到 swap。
29. memory.usage_in_bytes
说明:当前该 cgroup 的物理内存使用量(不包括 swap)。
30. memory.use_hierarchy
说明:控制是否启用内存 cgroup 的层次结构行为。如果启用,子 cgroup 会继承父 cgroup 的内存限制。
其他控制文件
1. notify_on_release
说明:当该 cgroup 中的最后一个任务退出时,是否发送通知。如果设置为 1,当所有进程退出时,系统会发出释放通知。
2. release_agent
说明:定义一个可执行文件的路径,当所有进程从 cgroup 中移除时执行该文件。
3. tasks
说明:列出当前 cgroup 中所有进程的 PID,并可以通过向其中写入 PID 将某个进程移入该 cgroup。
常用操作如下介绍:
3.2 将进程加入cgroup
通过将进程的PID写入 cgroup.procs文件,可以将该进程分配到对应的cgroup中:
echo PID号 > /dev/memcg/mygroup/cgroup.procs
这将PID的进程加入到 `mygroup` 中。
3.3 设置内存限制
通过写入文件,可以对 cgroup 设置资源限制。例如,为 `mygroup` 设置 CPU 使用权重:
echo 50M > /dev/memcg/mygroup/memory.limit_in_bytes
监控到的进程,如果使用的内存超过50M,就会触发swap交换(如果有配置)
4. cgroups v1 和 cgroups v2
Linux cgroups有两个版本:cgroups v1和cgroups v2。大多数Linux发行版仍然支持cgroups v1,但新系统通常推荐使用cgroups v2,它引入了一些重要改进:
- 统一层次结构:cgroups v2采用了统一的层次结构,将所有控制器放在同一个层级下,而不是像 v1 那样分散在不同的子系统中。
- 更好的资源隔离和控制:v2具有更强的资源控制能力,减少了v1中的一些设计缺陷。
在cgroups v2中,虚拟文件系统通常挂载在`/sys/fs/cgroup/`,并且不同控制器的文件不再分散,而是统一到一个cgroup目录下。
5. cgroups 的应用场景
- 容器管理:在容器技术中,cgroups 用来为每个容器设置资源配额,确保容器间的资源隔离。
- 虚拟化:通过 cgroups,可以在虚拟化环境中对虚拟机进行资源控制。
- 多租户环境:在云计算环境中,cgroups 可以为每个租户分配适当的资源,确保不同用户的隔离。
- 系统资源管理:cgroups 可以用于限制和监控本地系统中的进程资源使用,防止进程过度使用系统资源导致宕机。
总结
Linux cgroups 提供了一种强大的机制,用于限制、监控和隔离系统中不同进程组的资源使用。通过 cgroups,管理员可以确保系统资源的合理分配,并防止单个进程或进程组占用过多资源。