linux cgroup学习总结

linux-cgroup使用

大纲

  • 概念
  • 安装与使用

概念

基础知识

cgroups 是Linux内核提供的一种可以限制,隔离单个进程或者多个进程组 (process groups)所使用物理资源的机制,可以对 cpu,内存,i/o等资源实现精细化的控制,cgroups 全称是Control Groups

Docker 就使用了 cgroups 提供的资源限制能力来完成cpu,内存等部分的资源控制。

Cgroups是从Linux内核版本2.6.24开始添加进去的,Cgroups最初是由Google的工程师在2006年开发的,起初的名字叫“process containers”,在2007年改名为“Control Groups”。(所以 Cgroups 是系统内置的只需使用即可)

Cgroups并不是全新创造的,而是将进程管理从 cpuset 中剥离出来。CGroups 是管理虚拟化资源手段。 CGroup 提供了一个虚拟文件系统,是进行分组管理和各子系统设置的接口。所以**要使用 CGroup,必须挂载 CGroup 文件系统。**通过挂载选项指定使用哪个子系统

使用 uname -r  查看当前系统内核版本

基础概念

Cgroups 中主要有以下几个关键概念名词

  • 控制组(control group)
  • 子系统(subsystem)
  • 层级(hierarchy)
  • 任务(task)

控制组(control group)

cgroup的资源控制是以控制组的方式实现,控制组指明了资源的配额限制。进程可以加入到某个控制组,也可以迁移到另一个控制组

子系统(subsystem)

一个子系统其实就是一种资源的控制器,比如memory子系统可以控制进程内存的使用。子系统需要加入到某个层级,然后该层级的所有控制组,均受到这个子系统的控制。

子系统功能说明

  • 1)blkio --为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等)。
  • 2)cpu – 使用调度程序提供对CPU的cgroup任务访问。
  • 3)cpuacct --自动生成cgroup中任务所使用的CPU资源报告。
  • 4)cpuset --为cgroup中的任务分配独立CPU(在多核系统)和内存节点。
  • 5)devices --可允许或者拒绝中的任务对设备的访问。
  • 6)freezer --挂起或者恢复cgroup中的任务。
  • 7)memory --设定 cgroup 中任务使用的内存限制,并自动生成任务使用的内存资源报告。
  • 8)net_cls–使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包。
  • 9)net_prio–允许管理员动态的通过各种应用程序设置网络传输的优先级,类似于socket 选项的SO_PRIORITY,但它有它自身的优势。
  • 10)HugeTLB–HugeTLB页的资源控制功能

注意:不同的linux内核版本支持的cgroup子系统数量不同,同时默认也不会全部挂载这些子系统 使用lssubsys -a 可以查看支持的子系统。在/sys/fs/cgroup文件夹下可以看到已经挂载的子系统

子系统类型

lssubsys --all 查看当前linux支持的cgroup 子系统

子系统配置项

blkio 控制选项

按比例分配块设备 IO 资源

blkio.weight:填写 100-1000 的一个整数值,作为相对权重比率,作为通用的设备分配比。
blkio.weight_device: 针对特定设备的权重比,写入格式为device_types:node_numbers weight,空格前的参数段指定设备,weight参数与blkio.weight相同并覆盖原有的通用分配比。{![查看一个设备的device_types:node_numbers可以使用:ls -l /dev/DEV,看到的用逗号分隔的两个数字就是。有的文章也称之为major_number:minor_number。]}

控制 IO 读写速度上限

blkio.throttle.read_bps_device:按每秒读取块设备的数据量设定上限,格式device_types:node_numbers bytes_per_second。
blkio.throttle.write_bps_device:按每秒写入块设备的数据量设定上限,格式device_types:node_numbers bytes_per_second。
blkio.throttle.read_iops_device:按每秒读操作次数设定上限,格式device_types:node_numbers operations_per_second。
blkio.throttle.write_iops_device:按每秒写操作次数设定上限,格式device_types:node_numbers operations_per_second

针对特定操作 (read, write, sync, 或 async) 设定读写速度上限

blkio.throttle.io_serviced:针对特定操作按每秒操作次数设定上限,格式device_types:node_numbers operation operations_per_second
blkio.throttle.io_service_bytes:针对特定操作按每秒数据量设定上限,格式device_types:node_numbers operation bytes_per_second

统计与监控 以下内容都是只读的状态报告,通过这些统计项更好地统计、监控进程的 io 情况。

blkio.reset_stats:重置统计信息,写入一个 int 值即可。
blkio.time:统计 cgroup 对设备的访问时间,按格式device_types:node_numbers milliseconds读取信息即可,以下类似。

blkio.io_serviced:统计 cgroup 对特定设备的 IO 操作(包括 read、write、sync 及 async)次数,格式device_types:node_numbers operation number
blkio.sectors:统计 cgroup 对设备扇区访问次数,格式 device_types:node_numbers sector_count
blkio.io_service_bytes:统计 cgroup 对特定设备 IO 操作(包括 read、write、sync 及 async)的数据量,格式device_types:node_numbers operation bytes
blkio.io_queued:统计 cgroup 的队列中对 IO 操作(包括 read、write、sync 及 async)的请求次数,格式number operation
blkio.io_service_time:统计 cgroup 对特定设备的 IO 操作(包括 read、write、sync 及 async)时间 (单位为 ns),格式device_types:node_numbers operation time
blkio.io_merged:统计 cgroup 将 BIOS 请求合并到 IO 操作(包括 read、write、sync 及 async)请求的次数,格式number operation
blkio.io_wait_time:统计 cgroup 在各设​​​备​​​中各类型​​​IO 操作(包括 read、write、sync 及 async)在队列中的等待时间​(单位 ns),格式device_types:node_numbers operation time
__blkio.__recursive_*:各类型的统计都有一个递归版本,Docker 中使用的都是这个版本。获取的数据与非递归版本是一样的,但是包括 cgroup 所有层级的监控数据。
memory 控制选项

限额类

memory.limit_bytes:强制限制最大内存使用量,单位有k、m、g三种,填-1则代表无限制。
memory.soft_limit_bytes:软限制,只有比强制限制设置的值小时才有意义。填写格式同上。当整体内存紧张的情况下,task 获取的内存就被限制在软限制额度之内,以保证不会有太多进程因内存挨饿。可以看到,加入了内存的资源限制并不代表没有资源竞争。
memory.memsw.limit_bytes:设定最大内存与 swap 区内存之和的用量限制。填写格式同上。

报警与自动控制

memory.oom_control:改参数填 0 或 1, 0表示开启,当 cgroup 中的进程使用资源超过界限时立即杀死进程,1表示不启用。默认情况下,包含 memory 子系统的 cgroup 都启用。当oom_control不启用时,实际使用内存超过界限时进程会被暂停直到有空闲的内存资源。

统计与监控类

memory.usage_bytes:报​​​告​​​该​​​ cgroup 中​​​进​​​程​​​使​​​用​​​的​​​当​​​前​​​总​​​内​​​存​​​用​​​量(以字节为单位)
memory.max_usage_bytes:报​​​告​​​该​​​ cgroup 中​​​进​​​程​​​使​​​用​​​的​​​最​​​大​​​内​​​存​​​用​​​量
memory.failcnt:报​​​告​​​内​​​存​​​达​​​到​​​在​​​ memory.limit_in_bytes设​​​定​​​的​​​限​​​制​​​值​​​的​​​次​​​数​​​
memory.stat:包含大量的内存统计数据。
cache:页​​​缓​​​存​​​,包​​​括​​​ tmpfs(shmem),单位为字节。
rss:匿​​​名​​​和​​​ swap 缓​​​存​​​,不​​​包​​​括​​​ tmpfs(shmem),单位为字节。
mapped_file:memory-mapped 映​​​射​​​的​​​文​​​件​​​大​​​小​​​,包​​​括​​​ tmpfs(shmem),单​​​位​​​为​​​字​​​节​​​
pgpgin:存​​​入​​​内​​​存​​​中​​​的​​​页​​​数​​​
pgpgout:从​​​内​​​存​​​中​​​读​​​出​​​的​​​页​​​数
swap:swap 用​​​量​​​,单​​​位​​​为​​​字​​​节​​​
active_anon:在​​​活​​​跃​​​的​​​最​​​近​​​最​​​少​​​使​​​用​​​(least-recently-used,LRU)列​​​表​​​中​​​的​​​匿​​​名​​​和​​​ swap 缓​​​存​​​,包​​​括​​​ tmpfs(shmem),单​​​位​​​为​​​字​​​节​​​
inactive_anon:不​​​活​​​跃​​​的​​​ LRU 列​​​表​​​中​​​的​​​匿​​​名​​​和​​​ swap 缓​​​存​​​,包​​​括​​​ tmpfs(shmem),单​​​位​​​为​​​字​​​节
active_file:活​​​跃​​​ LRU 列​​​表​​​中​​​的​​​ file-backed 内​​​存​​​,以​​​字​​​节​​​为​​​单​​​位
inactive_file:不​​​活​​​跃​​​ LRU 列​​​表​​​中​​​的​​​ file-backed 内​​​存​​​,以​​​字​​​节​​​为​​​单​​​位
unevictable:无​​​法​​​再​​​生​​​的​​​内​​​存​​​,以​​​字​​​节​​​为​​​单​​​位​​​
hierarchical_memory_limit:包​​​含​​​ memory cgroup 的​​​层​​​级​​​的​​​内​​​存​​​限​​​制​​​,单​​​位​​​为​​​字​​​节​​​
hierarchical_memsw_limit:包​​​含​​​ memory cgroup 的​​​层​​​级​​​的​​​内​​​存​​​加​​​ swap 限​​​制​​​,单​​​位​​​为​​​字​​​节​​​
cpu 控制选项

设定 CPU 使用周期使用时间上限

cpu.cfs_period_us:设定周期时间,必须与cfs_quota_us配合使用。
cpu.cfs_quota_us :设定周期内最多可使用的时间。这里的配置指 task 对单个 cpu 的使用上限,若cfs_quota_us是cfs_period_us的两倍,就表示在两个核上完全使用。数值范围为 1000 - 1000,000(微秒)。
cpu.stat:统计信息,包含nr_periods(表示经历了几个cfs_period_us周期)、nr_throttled(表示 task 被限制的次数)及throttled_time(表示 task 被限制的总时长)。

按权重比例设定 CPU 的分配

cpu.shares:设定一个整数(必须大于等于 2)表示相对权重,最后除以权重总和算出相对比例,按比例分配 CPU 时间。(如 cgroup A 设置 100,cgroup B 设置 300,那么 cgroup A 中的 task 运行 25% 的 CPU 时间。对于一个 4 核 CPU 的系统来说,cgroup A 中的 task 可以 100% 占有某一个 CPU,这个比例是相对整体的一个值。)

** RT 调度策略下的配置 实时调度策略与公平调度策略中的按周期分配时间的方法类似,也是在周期内分配一个固定的运行时间。**

cpu.rt_period_us :设定周期时间。
cpu.rt_runtime_us:设定周期中的运行时间。
cpuacct 控制选项

这个子系统的配置是cpu子系统的补充,提供 CPU 资源用量的统计,时间单位都是纳秒。

cpuacct.usage:统计 cgroup 中所有 task 的 cpu 使用时长
cpuacct.stat:统计 cgroup 中所有 task 的用户态和内核态分别使用 cpu 的时长
cpuacct.usage_percpu:统计 cgroup 中所有 task 使用每个 cpu 的时长
cpuset 控制选项

指定进程绑定cpu

cpuset.cpus:在这个文件中填写 cgroup 可使用的 CPU 编号,如0-2,16代表 0、1、2 和 16 这 4 个 CPU。
cpuset.mems:与 CPU 类似,表示 cgroup 可使用的memory node,格式同上
device 控制选项

** 设备黑 / 白名单过滤限制 task 对 device 的使用 **

devices.allow:允许名单,语法type device_types:node_numbers access type ;type有三种类型:b(块设备)、c(字符设备)、a(全部设备);access也有三种方式:r(读)、w(写)、m(创建)。
devices.deny:禁止名单,语法格式同上。
freezer 控制选项

暂停 / 恢复 cgroup 中的 task

层级(hierarchy)

控制组有层级关系,类似树的结构,子节点的控制组继承父控制组的属性(资源配额、限制等) 在父层级下创建文件夹就可以继承父层级的子系统,task除外

任务(task)

在cgroup中,任务就是一个进程。

安装与使用

注意:这里的总结都是基于ubuntu实现

基本使用方式

工具准备

cgroup是系统内核提供的功能无需额外安装但需要一些工具来方便操作

  • ubuntu cgroup工具安装: apt install cgroup-tools
  • CentOS7 cgroup工具安装:yum install libcgroup libcgroup-tools

安装完成后就可以使用以下命令 (后面详解)

  • cgclassify –将运行的任务移动到一个或者多个cgroup,例如:cgclassify -g cpu:yy [pid]
  • cgclear --删除层级中的所有cgroup。
  • cgconfigparser --解析cgconfig.conf文件和并挂载层级。
  • cgcreate – cgcreate在层级中创建新cgroup。
  • cgdelete – cgdelete命令删除指定的cgroup。
  • cgexec – 这个命令是cgroup启动的cgexec命令在指定的cgroup中运行任务。例如:cgexec -g “cpu:demo” ./mydocker 如果不使用那就手动把进程号写入到tasks中
  • cgget – cgget命令查看cgroup组里面设置的资源的限制。
  • cgrulesengd --在 cgroup 中发布任务。
  • cgset – cgset 命令为 cgroup 设定参数。路径相对于根的/cgroup,如果想设置根的参数使用gset命令。
  • lscgroup --命令列出层级中的 cgroup。
  • lssubsys --命令列出包含指定子系统的层级,使用-am参数可以看到未挂载的所有子系统

注意:后面的文章对以上命令详解

查看系统支持的cgroup

使用lssubsys --all 查看当前linux支持的cgroup 子系统 注意可能需要先安装 apt install cgroup-tools

linux cgroup学习总结_第1张图片

使用cgroup

1 使用默认挂载的cgroup

默认情况下linux会在启动后自动挂载group, 挂载的路径为/sys/fs/cgroup, docker就是直接使用的默认挂载的cgroup

linux cgroup学习总结_第2张图片

一个简单的例子 本例子使用stress 压力测试工具 来实现控制cpu使用率为50%

安装stress 
ubuntu apt-get install stress
centos yum install stress

**命令 stress -c 1 -t 60s **
开启一个进程不停做平方根60s 让cpu使用率飙升接近100%

在这里插入图片描述

linux cgroup学习总结_第3张图片

创建自己的cgroup 控制层 mytest (系统从启后mytest自动删除)

linux cgroup学习总结_第4张图片

测试使用刚才创建的mytest

  • 方法1 使用 cgexec
  • 方法2 直接写pid 到 tasks

方法1 使用 cgexec 命令指定进程使用cgroup

cgexec -g cpu:mytest stress -c 1 -t 60s
-g cpu:mytest  表示使用cpu子系统中的mytest

在这里插入图片描述

cpu使用率 在50%

linux cgroup学习总结_第5张图片

方法2 直接将pid 写入到 tasks

直接启动stress 程序 注意这次没有加cgexec

在这里插入图片描述

将stress 的pid 写入到 mytest文件夹下的 tasks

在这里插入图片描述

cpu使用率 在50%

linux cgroup学习总结_第6张图片

2 挂载自定义cgroup

注意:挂载自定义的cgroup 重启系统后就自动删除挂载的cgroup 层级

在挂载前先使用 lssubsys -a 查看当前cgroup可以使用的子系统

linux cgroup学习总结_第7张图片

注意:挂载cpu限制时需要使用 cpu,cpuacct 挂载网络限制的时候需要使用 net_cls,net_prio

Linux中可以使用mount命令挂载 cgroups 文件系统
格式为: mount -t cgroup -o 【cgroup子系统】【mount显示名称】【挂载的路径】

  • mount -t cgroup 固定格式表示挂载的文件系统类型是 cgroup
  • -o 后面是cgroup子系统名词 例如 -o cpu
  • 【mount显示名称】 使用mount命令可以展示出挂载信息, 会显示挂载时指定的名称 。 注意:使用umount 名称可以删除挂载
  • 【挂载的路径】将cgroup 层级挂载到硬盘哪个文件夹里
挂载自定义cgroup 流程

1 先规划好自定义挂载的文件夹路径
由于每个子系统只能挂载在一个文件夹下 所以先准备需要挂载子系统的文件夹

linux cgroup学习总结_第8张图片

2 将不同的子系统挂载到对应的文件夹下

linux cgroup学习总结_第9张图片

使用 mount | grep my 可以看到已经成功挂载
使用 mount my_cpu_mount 可以删除这个挂载

在这里插入图片描述

可以看到自定义挂载的cgroup 子系统层会继承父级的各种信息(包括在上一次测试中使用的mytest层级)

linux cgroup学习总结_第10张图片

3 可以使用mkdir 创建自定义的层级,或者使用cgcreate
mkdir 的方式在上次的测试中已经使用,这次使用cgcreate 命名创建一个层级

linux cgroup学习总结_第11张图片

4 测试使用控制进程cpu使用率为20%
将cpu使用率设为20% 并把stress运行时的进程号写入到tasks中 再使用top观察stress的cpu使用率

linux cgroup学习总结_第12张图片

cgroup-tools 工具总结

cgclassify

cgclassify 命令将进程移动到 cgroup 中

命令各式: cgclassify -g subsystems:my_cgroup 【进程ids】

  • subsystems 是用逗号分开的子系统列表,或者 * 启动与所有可用子系统关联的层级中的进程。请注意:如果在多个层级中有同名的 cgroup,则 -g 选项会将该进程移动到每个组群中。
  • my_cgroup 是到其层级中的 cgroup 的路径
  • 【进程ids】 是用空格分开的进程识别符(PID)列表 还可以在 pid 前面添加 – sticky 选项以保证所有子进程位于同一 cgroup 中。

linux cgroup学习总结_第13张图片

cgclassify 命令类似 echo pid > tasks

gexec

cgexec 命令在 cgroup 中启动进程

命令各式: cgexec -g subsystems:my_cgroup【操作命令】

  • subsystems 是用逗号分开的子系统列表,或者 * 启动与所有可用子系统关联的层级中的进程。请注意:如果在多个层级中有同名的 cgroup,则 -g 选项会将该进程移动到每个组群中。
  • my_cgroup 是到其层级中的 cgroup 的路径
  • 【操作命令】需要执行的程序
    在这里插入图片描述

cgcreate cgdelete

cgcreate -g subsystems:my_cgroup
cgdelete 命令,比如要删除上述的 test 节点,可以使用 cgdelete -r cpu:test命令进行删除

你可能感兴趣的:(一些杂文,linux,学习,运维)