linux cgroup

  • 了解cgroup

1.cgroup描述

官方描述:

   DESCRIPTION   
       Control groups, usually referred to as cgroups, are a Linux kernel
       feature which allow processes to be organized into hierarchical
       groups whose usage of various types of resources can then be limited
       and monitored.  The kernel's cgroup interface is provided through a
       pseudo-filesystem called cgroupfs.  Grouping is implemented in the
       core cgroup kernel code, while resource tracking and limits are
       implemented in a set of per-resource-type subsystems (memory, CPU,
       and so on).
   
   Terminology
       A cgroup is a collection of processes that are bound to a set of
       limits or parameters defined via the cgroup filesystem.

       A subsystem is a kernel component that modifies the behavior of the
       processes in a cgroup.  Various subsystems have been implemented,
       making it possible to do things such as limiting the amount of CPU
       time and memory available to a cgroup, accounting for the CPU time
       used by a cgroup, and freezing and resuming execution of the
       processes in a cgroup.  Subsystems are sometimes also known as
       resource controllers (or simply, controllers).

       The cgroups for a controller are arranged in a hierarchy.  This
       hierarchy is defined by creating, removing, and renaming
       subdirectories within the cgroup filesystem.  At each level of the
       hierarchy, attributes (e.g., limits) can be defined.  The limits,
       control, and accounting provided by cgroups generally have effect
       throughout the subhierarchy underneath the cgroup where the
       attributes are defined.  Thus, for example, the limits placed on a
       cgroup at a higher level in the hierarchy cannot be exceeded by
       descendant cgroups

  Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU、内存、磁盘输入输出等)。这个项目最早是由Google的工程师在2006年发起(主要是Paul Menage和Rohit Seth),最早的名称为进程容器(process containers)。在2007年时,因为在Linux内核中,容器(container)这个名词太过广泛,为避免混乱,被重命名为cgroup,并且被合并到2.6.24版的内核中去。

  Linux Cgroup ​​​系​​​统​​​中​​​所​​​运​​​行​​​任​​​务​​​(进​​​程​​​)的​​​用​​​户​​​定​​​义​​​组​​​群​​​分​​​配​​​资​​​源​​​ — 比​​​如​​​ CPU 时​​​间​​​、​​​系​​​统​​​内​​​存​​​、​​​网​​​络​​​带​​​宽​​​或​​​者​​​这​​​些​​​资​​​源​​​的​​​组​​​合​​​。​​​可​​​以​​​监​​​控​​​配​​​置​​​的​​​ cgroup,拒​​​绝​​​ cgroup 访​​​问​​​某​​​些​​​资​​​源​​​,甚​​​至​​​在​​​运​​​行​​​的​​​系​​​统​​​中​​​动​​​态​​​配​​​置​​​cgroup。

  cgroup 是 Linux 下的一种将进程按组进行管理的机制,在用户层看来,cgroup 技术就是把系统中的所有进程组织成一颗一颗独立的树,每棵树都包含系统的所有进程,树的每个节点是一个进程组,而每颗树又和一个或者多个 subsystem 关联,树的作用是将进程分组,而 subsystem 的作用就是对这些组进行操作。cgroup 主要包括下面两部分:

  • subsystem : 一个 subsystem 就是一个内核模块,它被关联到一颗 cgroup 树之后,就会在树的每个节点(进程组)上做具体的操作。subsystem 经常被称作 resource controller,因为它主要被用来调度或者限制每个进程组的资源,但是这个说法不完全准确,因为有时我们将进程分组只是为了做一些监控,观察一下他们的状态,比如 perf_event subsystem。到目前为止,Linux 支持 12 种 subsystem,比如限制 CPU 的使用时间,限制使用的内存,统计 CPU 的使用情况,冻结和恢复一组进程等。

  • hierarchy : 一个 hierarchy 可以理解为一棵 cgroup 树,树的每个节点就是一个进程组,每棵树都会与零到多个 subsystem 关联。在一颗树里面,会包含 Linux 系统中的所有进程,但每个进程只能属于一个节点(进程组)。系统中可以有很多颗 cgroup 树,每棵树都和不同的 subsystem 关联,一个进程可以属于多颗树,即一个进程可以属于多个进程组,只是这些进程组和不同的 subsystem 关联。目前 Linux 支持 12 种 subsystem,如果不考虑不与任何 subsystem 关联的情况(systemd 就属于这种情况),Linux 里面最多可以建 12 颗 cgroup 树,每棵树关联一个 subsystem,当然也可以只建一棵树,然后让这棵树关联所有的 subsystem。当一颗 cgroup 树不和任何 subsystem 关联的时候,意味着这棵树只是将进程进行分组,至于要在分组的基础上做些什么,将由应用程序自己决定,systemd 就是一个这样的例子。

2.原理

  cgroups的实现本质上是给系统进程挂上钩子(hooks),当task运行的过程中涉及到某个资源时就会触发钩子上所附带的subsystem进行检测,最终根据资源类别的不同使用对应的技术进行资源限制和优先级分配。

  cgroups的目的是将任意进程进行分组化管理。

  cgroups本身提供将进程进行分组化管理的功能,而IO或内存的分配等具体的资源管理功能则是通过subsystem来实现的。可以通过/proc/cgroup查看可以使用的subsystem。

  cgroups提供了一个名为cgroup的虚拟文件系统,作为进行分组管理和各子系统设置的用户接口.要使用cgroups,必须挂载cgroup文件系统,此时可以通过挂载参数指定使用的subsystem。

  在linux中,cgroups默认挂载在/sys/fs/cgroup目录,其中包含了所有的子系统以及每个子系统的层级。

3.cgroups相关概念

  cgroups主要由task,cgroup,subsystem以及hierarchy组成.

  • Task(任务) : 在 linux 系统中,内核本身的调度和管理并不对进程和线程进行区分,只是根据 clone 时传入的参数的不同来从概念上区分进程和线程。这里使用 task 来表示系统的一个进程或线程。
  • cgroup(控制族群): 控制族群是一组按照某种标准划分的进程.cgroups中的资源控制都是以控制族群为单位实现的.一个进程可以加入某个控制族群,也可以迁移至另一个控制族群。
  • Hierarchy(层级) :层级有一系列 cgroup 以一个树状结构排列而成,每个层级通过绑定对应的子系统进行资源控制。层级中的 cgroup 节点可以包含零个或多个子节点,子节点继承父节点挂载的子系统。一个操作系统中可以有多个层级。
  • subsystem(子系统): 通常是一个资源控制器.例如CPU子系统可以控制CPU时间分配.一个子系统必须附加到控制族群树上才能起作用,该树上的所有控制族群都受到该子系统的控制

3.1.子系统简介

  subsystem实际上就是cgroups的资源控制系统,每种subsystem独立地控制一种资源

  • blkio (since Linux 2.6.33; CONFIG_BLK_CGROUP): 这个subsystem可以为块设备设定输入/输出限制,比如物理驱动设备(包括磁盘,固态硬盘,USB等),限制cgroup访问块设备的IO速度。
  • cpu (since Linux 2.6.24; CONFIG_CGROUP_SCHED): 这个subsystem使用调度程序控制task对CPU的使用,用来限制cgroup的CPU使用率。
  • cpuacct (since Linux 2.6.24; CONFIG_CGROUP_CPUACCT): 这个subsystem自动生成cgroup中task对CPU资源使用情况的报告,统计cgroup的CPU的使用率
  • cpuset (since Linux 2.6.24; CONFIG_CPUSETS): 这个subsystem可以为cgroup中的task分配独立的CPU(此处针对多处理器系统)和内存,绑定cgroup到指定CPUs和NUMA节点。
  • devices (since Linux 2.6.26; CONFIG_CGROUP_DEVICE) : 这个subsystem可以开启或关闭cgroup中task对设备的访问,限制cgroup创建(mknod)和访问设备的权限。
  • freezer (since Linux 2.6.28; CONFIG_CGROUP_FREEZER): 这个subsystem可以挂起或恢复cgroup中的task,suspend和restore一个cgroup中的所有进程。
  • memory (since Linux 2.6.25; CONFIG_MEMCG): 这个subsystem可以设定cgroup中task对内存使用量的限定,并且自动生成这些task对内存资源使用情况的报告,统计和限制cgroup的内存的使用率,包括process memory, kernel memory, 和swap。
  • perf_event (since Linux 2.6.39; CONFIG_CGROUP_PERF): 这个subsystem使用后使得cgroup中的task可以进行统一的性能测试,对cgroup进行性能监控。
  • net_cls (since Linux 2.6.29; CONFIG_CGROUP_NET_CLASSID) : 将一个cgroup中进程创建的所有网络包加上一个classid标记,用于tc和iptables。 只对发出去的网络包生效,对收到的网络包不起作用。
  • net_prio (since Linux 3.3; CONFIG_CGROUP_NET_PRIO) : 针对每个网络接口设置cgroup的访问优先级。
  • hugetlb (since Linux 3.5; CONFIG_CGROUP_HUGETLB) : 限制cgroup的huge pages的使用量。
  • pids (since Linux 4.3; CONFIG_CGROUP_PIDS) : 限制一个cgroup及其子孙cgroup中的总进程数。

  上面这些subsystem,有些需要做资源统计,有些需要做资源控制,有些即不统计也不控制。对于cgroup树来说,有些subsystem严重依赖继承关系,有些subsystem完全用不到继承关系,而有些对继承关系没有严格要求。

xxx:$ cat /proc/cgroups
#subsys_name    hierarchy       num_cgroups     enabled
cpuset  3       1       1
cpu     2       70      1
cpuacct 2       70      1
blkio   9       70      1
memory  7       127     1
devices 8       70      1
freezer 10      1       1
net_cls 6       1       1
perf_event      4       1       1
net_prio        6       1       1
hugetlb 11      1       1
pids    5       71      1

3.2.cgroups规则

  在任务,控制族群,层级,子系统间有着一些规则:

  • 同一个hierarchy能够附加一个或多个subsystem
  • 一个subsystem只能附加到一个hierarchy上
  • 每次在系统中创建新层级时,该系统中的所有任务都是那个层级的默认cgroup(我们称之为root cgroup,此cgroup在创建层级时自动创建,后面在该层级中创建的cgroup都是此cgroup的后代)的初始成员
  • 一个任务可以是多个cgroup的成员,但是这些cgroup必须在不同的层级
  • 进程创建子进程时,该子进程自动成为其父进程所在的cgroup的成员.可根据需要将其移至其它cgroup中

3.3.cgroups 的主要作用

  实现 cgroups 的主要目的是为不同用户层面的资源管理提供一个统一化的接口。从单个任务的资源控制到操作系统层面的虚拟化,cgroups 提供了四大功能:

  • 资源限制:cgroups 可以对任务是要的资源总额进行限制。比如设定任务运行时使用的内存上限,一旦超出就发 OOM。
  • 优先级分配:通过分配的 CPU 时间片数量和磁盘 IO 带宽,实际上就等同于控制了任务运行的优先级。
  • 资源统计:cgoups 可以统计系统的资源使用量,比如 CPU 使用时长、内存用量等。这个功能非常适合当前云端产品按使用量计费的方式。
  • 任务控制:cgroups 可以对任务执行挂起、恢复等操作。

3.4.cgroups 的文件系统接口

  cgroups 以文件的方式提供应用接口,我们可以通过 mount 命令来查看 cgroups 默认的挂载点:

$ mount | grep cgroup
>tmpfs on /sys/fs/cgroup type tmpfs (rw,mode=755)
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset,clone_children)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event,release_agent=/run/cgmanager/agents/cgm-release-agent.perf_event)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids,release_agent=/run/cgmanager/agents/cgm-release-agent.pids)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb,release_agent=/run/cgmanager/agents/cgm-release-agent.hugetlb)
  • 第一行的 tmpfs 说明 /sys/fs/cgroup 目录下的文件都是存在于内存中的临时文件。
  • 第二行的挂载点 /sys/fs/cgroup/systemd 用于 systemd 系统对 cgroups 的支持。
  • 其余的挂载点则是内核支持的各个子系统的根级层级结构。

Note: 在使用 systemd 系统的操作系统中,/sys/fs/cgroup 目录都是由 systemd 在系统启动的过程中挂载的,并且挂载为只读的类型。换句话说,系统是不建议在 /sys/fs/cgroup 目录下创建新的目录并挂载其它子系统的。

4.如何查看当前进程属于哪些cgroup

  可以通过查看/proc/[pid]/cgroup知道指定进程属于哪些cgroup。

dev@ubuntu:~$ cat /proc/777/cgroup
11:cpuset:/
10:freezer:/
9:memory:/system.slice/cron.service
8:blkio:/system.slice/cron.service
7:perf_event:/
6:net_cls,net_prio:/
5:devices:/system.slice/cron.service
4:hugetlb:/
3:cpu,cpuacct:/system.slice/cron.service
2:pids:/system.slice/cron.service
1:name=systemd:/system.slice/cron.service

每一行包含用冒号隔开的三列:

  • cgroup树的ID, 和/proc/cgroups文件中的ID一一对应。

  • 和cgroup树绑定的所有subsystem,多个subsystem之间用逗号隔开。这里name=systemd表示没有和任何subsystem绑定,只是给他起了个名字叫systemd。

  • 进程在cgroup树中的路径,即进程所属的cgroup,这个路径是相对于挂载点的相对路径。

以 memory 子系统为例

xxx:/sys/fs/cgroup/memory$ ls
cgroup.clone_children           memory.kmem.tcp.failcnt             memory.soft_limit_in_bytes
cgroup.event_control            memory.kmem.tcp.limit_in_bytes      memory.stat
cgroup.procs                    memory.kmem.tcp.max_usage_in_bytes  memory.swappiness
cgroup.sane_behavior            memory.kmem.tcp.usage_in_bytes      memory.usage_in_bytes
init.scope                      memory.kmem.usage_in_bytes          memory.use_hierarchy
memory.failcnt                  memory.limit_in_bytes               notify_on_release
memory.force_empty              memory.max_usage_in_bytes           release_agent
memory.kmem.failcnt             memory.move_charge_at_immigrate     system.slice
memory.kmem.limit_in_bytes      memory.numa_stat                    tasks
memory.kmem.max_usage_in_bytes  memory.oom_control                  user.slice
memory.kmem.slabinfo            memory.pressure_level

Brief summary of control files.


 tasks				 # attach a task(thread) and show list of threads
 cgroup.procs			 # show list of processes
 cgroup.event_control		 # an interface for event_fd()
 memory.usage_in_bytes		 # show current usage for memory
				 (See 5.5 for details)
 memory.memsw.usage_in_bytes	 # show current usage for memory+Swap
				 (See 5.5 for details)
 memory.limit_in_bytes		 # set/show limit of memory usage
 memory.memsw.limit_in_bytes	 # set/show limit of memory+Swap usage
 memory.failcnt			 # show the number of memory usage hits limits
 memory.memsw.failcnt		 # show the number of memory+Swap hits limits
 memory.max_usage_in_bytes	 # show max memory usage recorded
 memory.memsw.max_usage_in_bytes # show max memory+Swap usage recorded
 memory.soft_limit_in_bytes	 # set/show soft limit of memory usage
 memory.stat			 # show various statistics
 memory.use_hierarchy		 # set/show hierarchical account enabled
 memory.force_empty		 # trigger forced page reclaim
 memory.pressure_level		 # set memory pressure notifications
 memory.swappiness		 # set/show swappiness parameter of vmscan
				 (See sysctl's vm.swappiness)
 memory.move_charge_at_immigrate # set/show controls of moving charges
 memory.oom_control		 # set/show oom controls.
 memory.numa_stat		 # show the number of memory usage per numa node

 memory.kmem.limit_in_bytes      # set/show hard limit for kernel memory
 memory.kmem.usage_in_bytes      # show current kernel memory allocation
 memory.kmem.failcnt             # show the number of kernel memory usage hits limits
 memory.kmem.max_usage_in_bytes  # show max kernel memory usage recorded

 memory.kmem.tcp.limit_in_bytes  # set/show hard limit for tcp buf memory
 memory.kmem.tcp.usage_in_bytes  # show current tcp buf memory allocation
 memory.kmem.tcp.failcnt            # show the number of tcp buf memory usage hits limits
 memory.kmem.tcp.max_usage_in_bytes # show max tcp buf memory usage recorded

refer to

  • https://lwn.net/Articles/604609/
  • https://www.cnblogs.com/sparkdev/p/8296063.html
  • Documentation/admin-guide/cgroup-v2.rst
  • https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/cgroup-v1/cgroups.txt?h=v4.18-rc1
  • https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt
  • https://man7.org/linux/man-pages/man7/cgroups.7.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值