引言

本文为docker学习过程中深度了解容器化资源隔离学习笔记,Linux Cgroups学习笔记,简单记录cgroups中的部分原理以及cgroups操作,了解cgroup工作原理更能深入理解docker工作原理

Linux kernel Cgroups

  • Cgroups (Control Groups)是 Linux 下用于对一个或一组进程进行资源控制和监控的机制;
  • 可以对诸如 CPU 使用时间、内存、磁盘 I/O 等进程所需的资源进行限制;
  • 不同资源的具体管理工作由相应的 Cgroup 子系统(Subsystem)来实现 ;
  • 针对不同类型的资源限制,只要将限制策略在不同的的子系统上进行关联即可 ;
  • Cgroups 在不同的系统资源管理子系统中以层级树(Hierarchy)的方式来组织管理:每个Cgroup 都可以包含其他的子 Cgroup,因此子 Cgroup 能使用的资源除了受本 Cgroup 配置的资源参数限制,还受到父Cgroup 设置的资源限制

Linux kernel中 Cgroups 的实现

  • 进程数据结构
  1. struct task_struct
  2. {
  3. struct css_set *cgroups;
  4. struct list_head cg_list;
  5. ......
  6. }

每个进程对应一个css_set结构,css_set存储了与进程相关的cgropus信息。cg_list是一个嵌入的 list_head 结构,用于将连到同一个 css_set 的进程组织成一个链表。进程和css_set的关系是多对一关系

  • css_set 是 cgroup_subsys_state 对象的集合数据结构
  1. struct css_set {
  2. /*
  3. * Set of subsystem states, one for each subsystem. This array is
  4. * immutable after creation apart from the init_css_set during
  5. * subsystem registration (at boot time).
  6. */
  7. struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
  8. ......
  9. }

subsys 是一个指针数组,存储一组指向 cgroup_subsys_state 的指针,通过这个指针进程可以获取到对应的cgroups信息,一个 cgroup_subsys_state 就是进程与一个特定子系统相关的信息

  • cgroup_subsys_state结构体如下
  1. struct cgroup_subsys_state {
  2. struct cgroup *cgroup;
  3. ......
  4. };

cgroup 指针指向了一个 cgroup 结构,也就是进程属于的 cgroup

数据结构指向图

image.png

cgroups 对资源的分配

  • blkio: 这个子系统设置限制每个块设备的输入输出控制。例如:磁盘,光盘以及 USB 等等
  • cpu: 这个子系统使用调度程序为 cgroup 任务提供 CPU 的访问
  • cpuacct: 产生 cgroup 任务的 CPU 资源报告
  • cpuset: 如果是多核心的 CPU,这个子系统会为 cgroup 任务分配单独的 CPU 和内存
  • devices: 允许或拒绝 cgroup 任务对设备的访问
  • freezer: 暂停和恢复 cgroup 任务
  • memory: 设置每个 cgroup 的内存限制以及产生内存资源报告
  • net_cls: 标记每个网络包以供 cgroup 方便使用
  • ns: 名称空间子系统
  • pid: 进程标识子系统

CPU 子系统

  • cpu.shares: 可出让的能获得 CPU 使用时间的相对值(时间片比例,权重)。使用cpu.shares设置的cpu时间片,进程之间可以相互挤压资源(一边进程空闲时,另一个进程可以挤压CPU时间片)

image.png

  • cpu.cfs_period_us:cfs_period_us 用来配置时间周期长度,单位为 us(微秒)。
    cpu.cfs_quota_us:cfs_quota_us 用来配置当前 Cgroup 在 cfs_period_us 时间内最多能使用的 CPU 时间数,单位为 us(微秒)。<默认时间周期长度为100000us>(以绝对比例控制CPU使用时间)
    image.png
  • cpu.stat : Cgroup 内的进程使用的 CPU 时间统计。
  • nr_periods : 经过 cpu.cfs_period_us 的时间周期数量。
  • nr_throttled : 在经过的周期内,有多少次因为进程在指定的时间周期内用光了配额时间而受到限制。
  • throttled_time : Cgroup 中的进程被限制使用 CPU 的总用时,单位是 ns(纳秒)。

cpuacct 子系统

用于统计 Cgroup 及其子 Cgroup 下进程的 CPU 的使用情况。

  • cpuacct.usage
    包含该 Cgroup 及其子 Cgroup 下进程使用 CPU 的时间,单位是 ns(纳秒)。
  • cpuacct.stat
    包含该 Cgroup 及其子 Cgroup 下进程使用的 CPU 时间,以及用户态和内核态的时间。

Memory 子系统

  • memory.usage_in_bytes
    cgroup 下进程使用的内存,包含 cgroup 及其子 cgroup 下的进程使用的内存
  • memory.max_usage_in_bytes
    cgroup 下进程使用内存的最大值,包含子 cgroup 的内存使用量。
  • memory.limit_in_bytes
    设置 Cgroup 下进程最多能使用的内存。如果设置为 -1,表示对该 cgroup 的内存使用不做限制。
  • memory.oom_control
    设置是否在 Cgroup 中使用 OOM(Out of Memory)Killer,默认为使用。当属于该 cgroup 的进程使用的内存超过最大的限定值时,会立刻被 OOM Killer 处理。

通过CPU来控制一个进程的资源开销

  • Linux对于CPU的控制文件一般默认在/sys/fs/cgroup/cpu/文件下,我们可以看到CPU配置文件,其中cgroup.procs存储该cgroup控制的进程号
    image.png
  • 创建一个控制cpu测试的文件 mkdir cputest
    进入到我们创建的目录,可以看到自动生成了相关cpu配置文件
    image.png
  • 查看文件,可以看到cpu.shares默认为1024,意思是使用一个逻辑CPU
    cpu.cfs_period_us 默认100000 us ,cpu.cfs_quota_us 默认不限制
    image.png
  • 我们在服务器上开启一个新的无限循环进程使之消耗CPU,记录下他的pid
    image.png
  • 将线程加入cgroup.procs中
    image.png
  • 更改cfs_quota_us为50000
    image.png
    此时CPU使用率被强制降到50%(50000/100000)
    image.png

    通过memory来控制一个进程的资源开销

    原理和cpu相同本文不做过多介绍