一、理解Cgroups
-
什么是Cgroups?
cgroups - 内核控制组- 一个内核特性,允许对任务(进程)进行聚合或划分
- 任务被组织成层次化的组
- cgroups 可以被配置以表现出特定的行为
- 用于帮助调整系统,以最佳方式利用可用的硬件和网络资源
它(指systemd)解决了某些服务(如Apache)产生大量第三方进程(例如CGI或Java进程)的问题,而这些第三方进程又会继续产生更多的进程。这使得明确分配变得困难甚至不可能。此外,服务可能无法正确终止,导致一些子进程仍然存活。
systemd通过为每个服务分配一个自己的cgroup来解决这个问题。cgroups是内核的一个特性,允许将进程及其所有子进程聚合成层次化组织的组。systemd以服务的名称来命名每个cgroup。由于非特权进程不允许离开其cgroup,这为使用服务名称标记服务产生的所有进程提供了一种有效的方法。
要列出属于某个服务的所有进程,可以使用命令systemd-cgls。 -
cgroups术语
- cgroup:将一组任务与一个或多个子系统的参数集相关联
- subsystem:一个模块,它利用cgroup提供的任务分组功能,以特定方式处理任务组
- hierarchy:以树形结构排列的一组cgroup
- task:系统上运行的进程
二、理解cgroup模型
-
linux进程模型
- 在Linux系统中使用systemd的所有进程都共有一个父进程:systemd进程。
- Linux进程模型是单层次的——所有进程都源自一个单一的父进程。
- Linux进程会继承其父进程的环境以及某些其他属性。
在Linux系统中,所有进程都源自一个共同的父进程:systemd进程。该进程在系统启动时由内核执行,并启动其他进程(这些进程又可能启动它们自己的子进程)。所有进程都源自单一的父进程,这使得Linux进程模型成为一个单层次结构。
除了systemd之外,每个Linux进程都会继承其父进程的环境(如PATH变量)以及某些其他属性(如打开的文件描述符)。 -
cgroup模型
-
cgroups(控制组)与进程相似之处在于:
- 它们具有层次结构
- 子cgroups会从其父cgroup继承某些属性。
-
它们之间的根本区别在于:
- 在一个系统上,可以同时存在许多不同的cgroups层次结构。
-
需要多个独立的cgroups层次结构,因为每个层次结构都关联到一个或多个子系统。
-
一个子系统代表单一资源,例如:
- CPU时间
- 内存
-
-
cgroup设计概述
-
该设计使得cgroups的使用变得简单
- 只需在单个层次结构中为特定任务设置少量参数
- 例如,一个仅包含CPU和内存子系统的cgroup。
-
该设计还允许进行高度特定的配置
- 系统上的每个任务(进程)都可以成为每个层次结构的成员,而每个层次结构都只有一个附加的子系统
- 这样的配置将使系统管理员能够绝对控制每个任务的所有参数。
-
-
cgroup子系统
子系统分为两种类型:-
隔离和特殊控制
- cpuset(CPU集)
- namespace(命名空间)
- freezer(冻结器,用于暂停和恢复进程)
- device(设备,控制对设备的访问)
- checkpoint/restart(检查点和重启,用于保存和恢复进程状态)
-
资源控制
- cpu(调度器),用于控制CPU的使用
- memory(内存),用于控制内存的使用
- disk i/o(磁盘输入/输出),用于控制磁盘读写操作
- network(网络),用于控制网络流量和资源
-
-
cgroup文件系统层次结构
-
cgroup子系统
列出有效的cgroup子系统:
有多个cgroup子系统可供选择。要查看可用的子系统,请运行以下命令:
cat /proc/mounts | grep cgroup
在SUSE Linux Enterprise(SLE)上,列表将包括:
blkio — 此子系统对块设备(如物理驱动器(磁盘、固态硬盘或USB))的输入/输出访问设置限制。
cpu — 此子系统利用调度程序为cgroup任务提供CPU访问权限。
cpuacct — 此子系统自动生成关于cgroup中任务所使用的CPU资源的报告。
cpuset — 此子系统将多核系统中的单个CPU和内存节点分配给cgroup中的任务。
devices — 此子系统允许或拒绝cgroup中的任务访问设备。
freezer — 此子系统挂起或恢复cgroup中的任务。
memory — 此子系统对cgroup中任务所使用的内存设置限制,并自动生成关于这些任务所使用的内存资源的报告。
net_cls — 此子系统为网络数据包添加类标识符(classid),使得Linux流量控制器(tc)能够识别来自特定cgroup任务的数据包。
net_prio — 此子系统提供了一种方法,可以按网络接口动态设置网络流量的优先级。
ns — 命名空间子系统。
三、了解cgroup规则
-
子系统之间的关系,控制组和任务的层次结构
-
请记住—在系统术语中,进程被称为cgroup中的任务
-
控制子系统、cgroup层次结构和任务之间关系的规则有四条
-
rule1
一个单一的层次结构可以附加一个或多个子系统- 只要每个子系统没有附加到已经附加有其他任何子系统的任何其他层次结构上,那么CPU和内存子系统(或任何数量的子系统)都可以附加到一个单一的层次结构上。
- 只要每个子系统没有附加到已经附加有其他任何子系统的任何其他层次结构上,那么CPU和内存子系统(或任何数量的子系统)都可以附加到一个单一的层次结构上。
-
rule2
如果其中一个层级已经连接了不同的子系统,那么任何单一子系统都不能连接到多个层级上。
-
rule3
- 一个任务不能成为同一层级中两个控制组的成员。
- 只要它们位于不同的层级,一个单一任务可以属于多个控制组。
-
rule4
- 子任务会自动继承其父任务的控制组成员身份。
- 之后,子任务变为独立,可以根据需要移动到不同的控制组中。
-
-
-
cgroup功能概述
- 一个任务在任何单一层级中只能属于一个控制组(cgroup)
- 因此,任何一个子系统对任务的限制或影响只有一种方式。
- 可以将多个子系统组合在一起,使它们影响单个层级中的所有任务。
- 可以重构层级结构
- 例如,从包含多个子系统的层级中移除一个子系统,并将其附加到一个新的、独立的层级上。
- 如果减少在独立层级之间拆分子系统的需求,可以移除一个层级并将其子系统附加到现有的层级上。
- 一个任务在任何单一层级中只能属于一个控制组(cgroup)
四、管理cgroups
- 管理cgroups
- 控制组(cgroups)的管理是通过:
- 在子系统目录中创建子目录。
- 修改这些子目录中的文件来实现的。
- systemd会将每个服务放入其自己的控制组中。
- 在SUSE Linux Enterprise 15(SLE 15)中,管理控制组的主要工具是mount和systemctl命令。
- 要查看属于某个服务的进程,可以使用以下命令:systemd-cgls。
- 控制组(cgroups)的管理是通过:
- 使用mount管理cgroups
- mount命令用于创建控制组(cgroups)并定义受影响的子系统。
#mount -t cgroup group_name /sys/fs/cgroup - 可以通过mount命令单独调用子系统(其中“none”是控制组的名称):
# mkdir /cpuset /cpu # mount -t cgroup -o cpuset none /cpuset # mount -t cgroup -o cpu,cpuacct none /cpu
- mount命令用于创建控制组(cgroups)并定义受影响的子系统。
- 使用systemctl管理cgroup
systemctl命令可以用于为控制组(cgroups)设置限制:
#systemctl set-property [--runtime] NAME PROPERTY1=VALUE [PROPERTY2=VALUE]
示例:
systemctl set-property user.slice CPUAccounting=yes
为user.slice设置CPU会计功能为启用。
systemctl set-property user.slice CPUQuota=50%
为user.slice设置CPU配额限制为50%。
systemctl set-property user.slice MemoryAccounting=yes
为user.slice设置内存统计功能为启用。
systemctl set-property nginx.service MemoryLow=512M
为nginx.service服务设置最低内存阈值为512MB。
systemctl set-property nginx.service MemoryHigh=2G
为nginx.service服务设置较高内存阈值为2GB。
systemctl set-property nginx.service MemoryMax=4G
为nginx.service服务设置最大内存限制为4GB。
systemctl set-property system.slice DeviceAllow=“/dev/sdb1 r”
为system.slice设置设备访问权限,允许读取(r)/dev/sdb1设备。
使用–runtime选项会使限制在下次重启后不再持续生效,即默认行为是持久性的。
CPUAccounting=[yes|no] – 启用CPU使用情况统计。
CPUQuota=PERCENTAGE – 为进程分配CPU时间百分比。
MemoryAccounting=[yes|no] – 启用内存使用情况统计。
MemoryLow=BYTES – 低于此限制的进程所使用的未用内存不会被回收用于其他用途。
MemoryHigh=BYTES – 如果使用的内存超过此限制,则会积极从进程中收回内存。
MemoryMax=BYTES – 设置使用的内存的最大限制。
DeviceAllow= – 允许读取(r)、写入(w)和创建特殊文件(mknod,m)访问。
DevicePolicy=[auto|closed|strict] – 当设置为strict时,只允许访问在DeviceAllow中列出的设备。closed另外还允许访问标准伪设备,包括/dev/null、/dev/zero、/dev/full、/dev/random和/dev/urandom。如果DeviceAllow中没有定义特定规则,auto允许访问所有设备。auto是默认设置。
- 子系统
blkio:对块设备的输入/输出访问设置限制。
cpu:此子系统使用调度程序为控制组(cgroup)中的任务提供CPU访问权限。
cpuacct:自动生成关于控制组中任务所使用的CPU资源的报告。
cpuset:将特定的CPU和内存节点分配给控制组中的任务。
devices:允许或拒绝控制组中的任务访问设备。
freezer:挂起或恢复控制组中的任务。