linux 内核资源配置--cgroups详解以及在docker中的应用

news/2024/11/23 0:47:15/

一、Cgroup 概述

1.1、cgroups 是什么

Linux cgroup (Control Groups)是 Linux 内核提供的一种机制,用于限制进程组使用的资源(如 CPU、内存、磁盘 I/O 等)。通过将进程组划分为层次结构,并将资源限制应用于不同层次的组,可以实现对系统资源的统一管理和限制。

cgroup 提供了一套 API,用于创建、管理和监控进程组。通过这些 API,可以将进程组划分为不同的层次结构,并为每个层次结构设置不同的资源限制。在实际使用中,可以使用 cgroup 来限制某些进程组的资源使用,以确保系统资源的公平分配和有效使用。

1.2、cgroup 四大功能

  • 资源限制(Resource Limiting):cgroup 可以限制进程组的资源使用,如 CPU、内存、磁盘 I/O 等,以保证系统的稳定性和可靠性。通过配置 cgroup,可以为每个进程组分配合适的资源,并防止某个进程组的资源占用过多影响其他进程组的正常运行。

  • 优先级管理(Priority Management):cgroup 可以控制进程组的运行优先级(CPU shares),以确保系统中每个进程组都有足够的 CPU 时间片,从而避免 CPU 资源的浪费和系统的不稳定性。

  • 资源统计(Accounting):cgroup 可以对进程组使用的资源进行统计,包括 CPU、内存、磁盘 I/O 等,从而帮助系统管理员了解系统资源的使用情况,并进行资源规划和优化。

  • 控制访问(Access Control):cgroup 可以对任务执行挂起,恢复等操作,从而实现对系统资源的统一管理和控制。通过配置 cgroup,可以限制某些用户或进程组的资源使用,保证系统资源的公平分配和有效使用。

1.3、cgroup 架构

在这里插入图片描述

1.3.1、css_set

css_set 是一个用于管理 cgroup 层次结构的结构体。它是一个代表 cgroup 集合的数据结构,用于存储每个 cgroup 在层次结构中的位置和控制器信息。

css_set 保存了一个 cgroup 集合的状态,包括每个 cgroup 所属的父节点、子节点等信息。它将 cgroup 组织成层次结构,并按照不同的控制器对 cgroup 进行管理和限制资源使用。每个 css_set 都包含一个指向其父 css_set 的指针,这样就可以形成一个树状结构的 cgroup 层次结构。

css_set 中包含了一组指向 cgroup 控制器(如 CPU 权限、内存限制等)的指针,这些控制器用于限制进程组使用的资源。通过配置这些控制器,可以为每个 cgroup 分配不同的资源限制,从而确保系统的稳定性和可靠性。

在 cgroup 中,每个 cgroup 都关联着一个 css_set,它保存着 cgroup 的状态信息以及与其他 cgroup 之间的关系。因此,css_set 是 cgroup 中非常重要的一个数据结构,它负责管理和组织 cgroup 的层次结构,并提供了一组 API,允许用户对 cgroup 进行管理和监控,同时也管理和限制 cgroup 的资源使用。

1.3.2、subsys

在 cgroup 中,subsys(Subsystem)是指一个负责管理 cgroup 中某个资源的模块。每个 subsys 管理着 cgroup 中的一组资源,并提供了一组 API,用于配置和管理这些资源。

常见的 subsys 包括 CPU、内存、磁盘 I/O 等。每个 subsys 可以为 cgroup 分配不同的资源限制,从而限制进程组使用的资源。

在 cgroup 中,每个 cgroup 都可以使用一个或多个 subsys。每个 subsys 都具有以下功能:

  • 提供 API:subsys 提供了一组 API,用于配置和管理 cgroup 中的资源。这些 API 允许用户为每个 cgroup 分配不同的资源限制,从而限制进程组使用的资源。

  • 管理资源:subsys 管理 cgroup 中的资源,如 CPU、内存、磁盘 I/O 等。通过配置不同的 subsys,可以为每个 cgroup 分配不同的资源限制,从而确保系统的稳定性和可靠性。

  • 统计资源:subsys 可以统计 cgroup 中每个资源的使用情况,如 CPU 使用率、内存使用量等。这些统计数据可以帮助系统管理员更好地了解系统资源的使用情况,并进行资源规划和优化。

1.3.3、subsys 和css_set 的关系

subsys 是针对某个资源的管理模块,而 css_set 则是针对 cgroup 层次结构的管理结构。每个 cgroup 可以使用一个或多个 subsys。每个 css_set 中包含了一组指向 cgroup 控制器(即 subsys)的指针,这些控制器用于限制进程组使用的资源。通过配置这些控制器,可以为每个 cgroup 分配不同的资源限制,从而确保系统的稳定性和可靠性。

1.4、主要术语

  • 任务(Tasks):就是系统的一个进程。
  • 控制组(Control Group):一组按照某种标准划分的进程,比如官方文档中的Professor和Student,或是WWW和System之类的,其表示了某进程组。Cgroups中的资源控制都是以控制组为单位实现。一个进程可以加入到某个控制组。而资源的限制是定义在这个组上,就像上面示例中我用的 hello 一样。简单点说,cgroup的呈现就是一个目录带一系列的可配置文件。
  • 层级(Hierarchy):控制组可以组织成hierarchical的形式,既一颗控制组的树(目录结构)。控制组树上的子节点继承父结点的属性。简单点说,hierarchy就是在一个或多个子系统上的cgroups目录树。
  • 子系统(Subsystem):一个子系统就是一个资源控制器,比如CPU子系统就是控制CPU时间分配的一个控制器。子系统必须附加到一个层级上才能起作用,一个子系统附加到某个层级以后,这个层级上的所有控制族群都受到这个子系统的控制。Cgroup的子系统可以有很多,也在不断增加中。

二、Cgroups子系统

2.1、查看环境中的子系统

mount -t cgroup

$ mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/cpuset,cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset,cpu,cpuacct)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
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/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)

lssubsys -m

# 要使用lssubsys 命令,需要安装包
$ yum install libcgroup-tools
$ lssubsys -m
cpuset,cpu,cpuacct /sys/fs/cgroup/cpuset,cpu,cpuacct
blkio /sys/fs/cgroup/blkio
memory /sys/fs/cgroup/memory
devices /sys/fs/cgroup/devices
freezer /sys/fs/cgroup/freezer
net_cls,net_prio /sys/fs/cgroup/net_cls,net_prio
perf_event /sys/fs/cgroup/perf_event
hugetlb /sys/fs/cgroup/hugetlb
pids /sys/fs/cgroup/pids
rdma /sys/fs/cgroup/rdma

cat /proc/cgroups

$ cat /proc/cgroups
#subsys_name	hierarchy	num_cgroups	enabled
cpuset	6	124	1
cpu	6	124	1
cpuacct	6	124	1
blkio	7	113	1
memory	9	185	1
devices	8	111	1
freezer	5	83	1
net_cls	4	83	1
perf_event	10	83	1
net_prio	4	83	1
hugetlb	11	83	1
pids	2	111	1
rdma	3	2	1

cat /proc/[pid]/cgroup 查看进程所属的 cgroups

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

2.2、子系统名称及其作用

名称作用
blkio限制进程组对块设备的访问,确保磁盘 I/O 的公平使用和稳定性
cpu使用调度程序控制任务对CPU的使用
cpuacct自动生成cgroups中任务对cpu资源使用情况报告
cpuset为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点
devices允许或者拒绝 cgroup 中的任务访问设备
freezer挂起或者恢复 cgroup 中的任务
memory设定 cgroup 中任务使用的内存限制,并自动生成由那些任务使用的内存资源报告
net_cls使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包,配合 tc(traffic controller)限制网络带宽
net_prio设置进程的网络流量优先级
hugetlb限制 HugeTLB 的使用
perf_event允许 Perf 工具基于 Cgroup 分组做性能检测
rdma将 RDMA 资源(如 HCA、QPs、CQs 等)分配给 cgroup,并限制 cgroup 使用这些资源的数量,RDMA 设备通常包括网卡、主机适配器和交换机等
pids限制 cgroup 中能够运行的进程数量
ns允许用户将不同的命名空间分配给 cgroup,并限制 cgroup 中的进程仅能访问特定的命名空间

2.3、各个子系统主要配置

2.3.1、blkio配置

blkio 子系统是 cgroup 提供的一种用于控制块设备(如硬盘、SSD 等)输入/输出(I/O)带宽的子系统。通过 blkio 子系统,用户可以为每个 cgroup 分配不同的磁盘 I/O 带宽限制,并确保不同进程组之间的磁盘 I/O 不会互相干扰和冲突。

下面是 blkio 子系统的一些常用配置(如下mygroup为示例,具体根据环境中确定):

blkio.weight:用于设置 cgroup 的 I/O 权重,它是一个相对值,默认值为 500。较高的权重值表示更高的 I/O 优先级。

# 设置 cgroup 的 I/O 权重为 1000
echo 1000 > /sys/fs/cgroup/blkio/mygroup/blkio.weight

blkio.weight_device:用于设置某个块设备的 I/O 权重,例如:

# 为设备 /dev/sda 设置 I/O 权重为 1000
echo "1000:253:*" > /sys/fs/cgroup/blkio/mygroup/blkio.weight_device

blkio.throttle.read_bps_deviceblkio.throttle.write_bps_device:用于限制读和写操作的 I/O 带宽,例如:

# 限制设备 /dev/sda 的读操作带宽为 10 MB/s
echo "10:253:rw" > /sys/fs/cgroup/blkio/mygroup/blkio.throttle.read_bps_device# 限制设备 /dev/sda 的写操作带宽为 5 MB/s
echo "5:253:rw" > /sys/fs/cgroup/blkio/mygroup/blkio.throttle.write_bps_device

blkio.throttle.read_iops_deviceblkio.throttle.write_iops_device:用于限制读和写操作的 I/O 操作数,例如:

# 限制设备 /dev/sda 的读操作 IOPS 为 1000
echo "1000:253:rw" > /sys/fs/cgroup/blkio/mygroup/blkio.throttle.read_iops_device# 限制设备 /dev/sda 的写操作 IOPS 为 500
echo "500:253:rw" > /sys/fs/cgroup/blkio/mygroup/blkio.throttle.write_iops_device

2.3.2、cpu配置

cpu 子系统是 cgroup 提供的一种用于控制 CPU 使用率的子系统。通过 cpu 子系统,用户可以限制 cgroup 中进程的 CPU 使用率,并确保不同进程组之间的 CPU 使用率不会互相干扰和冲突。

以下是 cpu 子系统的一些常用配置:

cpu.cfs_quota_uscpu.cfs_period_us:用于限制 cgroup 中的进程使用 CPU 时间的比例。其中 cpu.cfs_quota_us 表示时间配额,单位为微秒,cpu.cfs_period_us 表示时间周期,单位为微秒。例如:

# 限制 cgroup 中的进程使用 50% 的 CPU 时间
echo 50000 > /sys/fs/cgroup/cpu/mygroup/cpu.cfs_quota_us
echo 100000 > /sys/fs/cgroup/cpu/mygroup/cpu.cfs_period_us

这个配置将 cgroup 中的进程 CPU 使用率限制为 50%。如果希望取消限制,可以将 cpu.cfs_quota_us 的值设置为 -1。

cpu.shares:用于设置 cgroup 中进程的 CPU 使用权重,它是一个相对值,默认值为 1024。较高的权重值表示更高的 CPU 使用优先级。例如:

# 设置 cgroup 的 CPU 使用权重为 2048
echo 2048 > /sys/fs/cgroup/cpu/mygroup/cpu.shares

cpu.rt_period_uscpu.rt_runtime_us:用于限制实时进程在 cgroup 中的 CPU 使用时间。其中 cpu.rt_period_us 表示时间周期,单位为微秒,cpu.rt_runtime_us 表示时间配额,单位为微秒。例如:

# 限制实时进程在 cgroup 中使用 10ms 的 CPU 时间
echo 10000 > /sys/fs/cgroup/cpu/mygroup/cpu.rt_period_us
echo 1000 > /sys/fs/cgroup/cpu/mygroup/cpu.rt_runtime_us

2.3.3、cpuacct 常用参数

cpuacct 子系统是 cgroup 提供的一种用于统计 cgroup 中进程 CPU 使用情况的子系统。以下是 cpuacct 子系统的一些常用参数:

cpuacct.usage:用于获取 cgroup 中所有进程的 CPU 使用时间,以纳秒为单位。

# 获取 cgroup 中所有进程的 CPU 使用时间
cat /sys/fs/cgroup/cpuacct/mygroup/cpuacct.usage

cpuacct.usage_percpu:用于获取 cgroup 中每个 CPU 核心的 CPU 使用时间,以纳秒为单位。

# 获取 cgroup 中每个 CPU 核心的 CPU 使用时间
cat /sys/fs/cgroup/cpuacct/mygroup/cpuacct.usage_percpu

cpuacct.stat:用于获取 cgroup 中进程的 CPU 使用时间和资源消耗情况的统计信息,包括用户态时间、内核态时间、等待时间等。

# 获取 cgroup 中进程的 CPU 使用时间和资源消耗情况的统计信息
cat /sys/fs/cgroup/cpuacct/mygroup/cpuacct.stat

这些参数可以根据实际需求进行调整和修改。需要注意的是,cpuacct 子系统只用于统计进程的 CPU 使用情况,不限制进程的 CPU 使用率。如果需要限制进程的 CPU 使用率,应该使用 cpu 子系统

2.3.4、cpuset 配置

cpuset 子系统是 cgroup 提供的一种用于控制进程 CPU 核心和内存使用的子系统。通过 cpuset 子系统,用户可以将进程限制在特定的 CPU 核心或者 NUMA 节点上,以及限制进程的内存使用。

以下是 cpuset 子系统的一些常用配置:

cpuset.cpus:用于设置 cgroup 中允许使用的 CPU 核心。该参数可以使用类似 “0-3,6,8-10” 的格式,表示允许使用编号为 0-3、6、8-10 的 CPU 核心。例如:

# 设置 cgroup 中允许使用的 CPU 核心为 0-3 和 6
echo "0-3,6" > /sys/fs/cgroup/cpuset/mygroup/cpuset.cpus

cpuset.mems:用于设置 cgroup 中允许使用的 NUMA 节点。该参数可以使用类似 “0,1” 的格式,表示允许使用编号为 0 和 1 的 NUMA 节点。例如:

# 设置 cgroup 中允许使用的 NUMA 节点为 0 和 1
echo "0,1" > /sys/fs/cgroup/cpuset/mygroup/cpuset.mems

cpuset.memory_migrate:用于设置是否允许 cgroup 中的进程迁移内存。可以将该参数设置为 1,表示允许内存迁移,或者将其设置为 0,表示禁止内存迁移。例如:

# 允许 cgroup 中的进程迁移内存
echo 1 > /sys/fs/cgroup/cpuset/mygroup/cpuset.memory_migrate

2.3.5、devices 配置

devices 子系统是 cgroup 提供的一种用于控制进程对系统设备访问权限的子系统。通过 devices 子系统,用户可以限制 cgroup 中进程对指定设备的访问权限,防止恶意程序或者误操作对系统设备造成损害。

devices 子系统的配置涉及以下三个参数:

devices.allow:用于设置允许访问的设备列表。该参数可以使用类似 “c 1:3 rwm” 的格式,其中 “c” 表示字符设备,“1:3” 表示设备的主次编号,“rwm” 表示允许的访问权限(读、写、执行)。例如:

# 允许 cgroup 中的进程访问 /dev/null 和 /dev/zero 设备
echo "c 1:3 rwm, c 1:5 rwm" > /sys/fs/cgroup/devices/mygroup/devices.allow

上面的示例中,设置了允许 cgroup 中的进程访问 /dev/null 和 /dev/zero 设备,并且设置了读、写、执行权限。

devices.deny:用于设置禁止访问的设备列表。该参数可以使用类似 “c 1:3 rwm” 的格式,其中 “c” 表示字符设备,“1:3” 表示设备的主次编号,“rwm” 表示禁止的访问权限(读、写、执行)。例如:

# 禁止 cgroup 中的进程访问 /dev/pts 和 /dev/tty 设备
echo "c 5:2 rwm, c 4:0 rwm" > /sys/fs/cgroup/devices/mygroup/devices.deny

上面的示例中,设置了禁止 cgroup 中的进程访问 /dev/pts 和 /dev/tty 设备,并且设置了读、写、执行权限。

devices.list:用于获取当前 cgroup 中允许访问的设备列表。例如:

# 获取当前 cgroup 中允许访问的设备列表
cat /sys/fs/cgroup/devices/mygroup/devices.list

2.3.6、freezer 配置

freezer 子系统是 cgroup 提供的一种用于暂停和恢复进程的子系统。通过 freezer 子系统,用户可以暂停 cgroup 中的所有进程或者某个进程,以便进行调试、备份或者迁移等操作。

以下是 freezer 子系统的一些常用配置:

freezer.state:用于设置或获取 cgroup 的状态。该参数可以设置为以下几个值:

FROZEN:冻结 cgroup 中的所有进程,包括子 cgroup 中的进程。
THAWED:解冻 cgroup 中的所有进程,包括子 cgroup 中的进程。
FREEZING:正在冻结 cgroup 中的进程。
FROZEN:正在解冻 cgroup 中的进程。
UNKNOWN:cgroup 的状态未知。

例如:

# 冻结 cgroup 中的所有进程
echo "FROZEN" > /sys/fs/cgroup/freezer/mygroup/freezer.state

freezer.parent_freezing:用于设置子 cgroup 是否继承父 cgroup 的冻结状态。该参数可以设置为 0 或 1,分别表示不继承和继承。例如:

# 子 cgroup 不继承父 cgroup 的冻结状态
echo 0 > /sys/fs/cgroup/freezer/mygroup/freezer.parent_freezing

freezer.self_freezing:用于设置进程退出时是否将自己冻结。该参数可以设置为 0 或 1,分别表示不冻结和冻结。例如:

# 进程退出时将自己冻结
echo 1 > /sys/fs/cgroup/freezer/mygroup/freezer.self_freezing

2.3.7、memory 配置

memory 子系统是 cgroup 提供的一种用于控制进程内存使用的子系统。通过 memory 子系统,用户可以限制 cgroup 中进程的内存使用,防止进程耗尽系统内存,导致系统崩溃或变得不可用。

以下是 memory 子系统的一些常用配置:

memory.limit_in_bytes:用于设置 cgroup 中进程的内存限制。该参数可以设置一个整数值,表示允许使用的最大内存量(以字节为单位)。例如:

# 设置 cgroup 中进程的内存限制为 1 GB
echo "1073741824" > /sys/fs/cgroup/memory/mygroup/memory.limit_in_bytes

memory.soft_limit_in_bytes:用于设置 cgroup 中进程的软内存限制。软限制是当系统内存不足时,内核会尝试回收该 cgroup 中进程的内存。该参数可以设置一个整数值,表示软限制的最大内存量(以字节为单位)。例如:

# 设置 cgroup 中进程的软内存限制为 800 MB
echo "838860800" > /sys/fs/cgroup/memory/mygroup/memory.soft_limit_in_bytes

memory.swappiness:用于设置 cgroup 中进程的交换空间使用比例。该参数可以设置一个整数值,表示在物理内存不足时,内核将会将多少进程内存移动到交换空间中。例如:

# 设置 cgroup 中进程的交换空间使用比例为 50%
echo "50" > /sys/fs/cgroup/memory/mygroup/memory.swappiness

memory.kmem.limit_in_bytes:用于设置 cgroup 中进程使用内核内存的限制。该参数可以设置一个整数值,表示 cgroup 中进程允许使用的内核内存的最大量(以字节为单位)。例如:

# 设置 cgroup 中进程使用内核内存的限制为 100 MB
echo "104857600" > /sys/fs/cgroup/memory/mygroup/memory.kmem.limit_in_bytes

2.3.8、net_cls 配置

net_cls 子系统是 cgroup 提供的一种用于控制网络流量的子系统。通过 net_cls 子系统,用户可以将 cgroup 中的网络流量标记为特定的类别,以便网络设备或者 QoS(Quality of Service)系统根据标记来进行流量控制。

以下是 net_cls 子系统的一些常用配置:

net_cls.classid:用于设置 cgroup 中网络流量的分类标识符。该参数可以设置一个整数值,表示网络流量的分类标识符。例如:

# 设置 cgroup 中网络流量的分类标识符为 0x10001
echo "0x10001" > /sys/fs/cgroup/net_cls/mygroup/net_cls.classid

/sys/class/net/<interface>/queues/tx-<queue>/xps_cpus:用于设置网络接口队列中流量的处理器亲和性。该参数可以设置一个 CPU 核心的位图,表示哪些 CPU 核心可以处理该队列中的网络流量。例如:

# 设置 eth0 接口队列 0 中网络流量的处理器亲和性为 CPU 0 和 CPU 1
echo "3" > /sys/class/net/eth0/queues/tx-0/xps_cpus

2.3.9、net_prio 配置

net_prio 子系统是 cgroup 提供的一种用于控制网络流量优先级的子系统。通过 net_prio 子系统,用户可以将 cgroup 中的网络流量设置为不同的优先级,以便优化网络性能和资源利用。

以下是 net_prio 子系统的一些常用配置:

net_prio.ifpriomap:用于设置网络接口的优先级映射。该参数可以设置一个字符串,表示网络接口和优先级之间的映射关系。例如:

# 设置 eth0 接口的优先级为 1,eth1 接口的优先级为 2
echo "eth0 1, eth1 2" > /sys/fs/cgroup/net_prio/mygroup/net_prio.ifpriomap

net_prio.prioidx:用于设置优先级索引。该参数可以设置一个整数值,表示 cgroup 中网络流量的优先级。例如:

# 设置 cgroup 中网络流量的优先级为 1
echo "1" > /sys/fs/cgroup/net_prio/mygroup/net_prio.prioidx

net_prio.default:用于设置默认的网络流量优先级。该参数可以设置一个整数值,表示当流量没有被映射到具体接口时的默认优先级。例如:

# 设置默认的网络流量优先级为 2
echo "2" > /sys/fs/cgroup/net_prio/mygroup/net_prio.default

2.3.10、hugetlb 配置

hugetlb 子系统是 cgroup 提供的一种用于控制大页面内存(Huge Page)使用的子系统。大页面内存是一种更大的内存页,可以提高内存访问效率和性能。通过 hugetlb 子系统,用户可以限制 cgroup 中进程使用的大页面内存的数量和大小。

以下是 hugetlb 子系统的一些常用配置:

hugetlb.<pagesize>.limit_in_bytes:用于设置 cgroup 中进程使用指定大小的大页面内存的限制。该参数可以设置一个整数值,表示 cgroup 中进程允许使用的指定大小的大页面内存的最大量(以字节为单位)。其中 表示大页面的大小,例如 hugetlb.2MB.limit_in_bytes 表示 2MB 大页面内存的限制。例如:

# 设置 cgroup 中进程使用 2MB 大页面内存的限制为 1 GB
echo "1073741824" > /sys/fs/cgroup/hugetlb/mygroup/hugetlb.2MB.limit_in_bytes

hugetlb.<pagesize>.max_usage_in_bytes:用于设置 cgroup 中进程使用指定大小的大页面内存的最大使用量。该参数可以设置一个整数值,表示 cgroup 中进程使用指定大小的大页面内存的最大使用量(以字节为单位)。例如:

# 设置 cgroup 中进程使用 2MB 大页面内存的最大使用量为 512 MB
echo "536870912" > /sys/fs/cgroup/hugetlb/mygroup/hugetlb.2MB.max_usage_in_bytes

hugetlb.<pagesize>.current_usage_in_bytes:用于获取 cgroup 中进程使用指定大小的大页面内存的当前使用量。该参数可以查询 cgroup 中进程使用指定大小的大页面内存的当前使用量(以字节为单位)。例如:

# 查询 cgroup 中进程使用 2MB 大页面内存的当前使用量
cat /sys/fs/cgroup/hugetlb/mygroup/hugetlb.2MB.current_usage_in_bytes

2.3.11、perf_event 配置

perf_event 子系统是 cgroup 提供的一种用于控制进程性能计数器(Performance Counter)的子系统。通过 perf_event 子系统,用户可以对 cgroup 中的进程进行性能分析和调优。

以下是 perf_event 子系统的一些常用配置:

perf_event.<event_name>.enable:用于启用或禁用指定的性能计数器事件。该参数可以设置一个整数值,表示是否启用指定的性能计数器事件(1 表示启用,0 表示禁用)。其中 <event_name> 表示性能计数器事件的名称,例如 cycles 表示 CPU 周期计数器事件。例如:

# 启用 cgroup 中进程的 CPU 周期计数器事件
echo "1" > /sys/fs/cgroup/perf_event/mygroup/perf_event.cycles.enable

perf_event.<event_name>.config:用于设置指定的性能计数器事件的配置参数。该参数可以设置一个整数值,表示性能计数器事件的配置参数。例如:

# 设置 cgroup 中进程的 CPU 周期计数器事件的配置参数为 0x412e
echo "0x412e" > /sys/fs/cgroup/perf_event/mygroup/perf_event.cycles.config

perf_event.<event_name>.count:用于获取 cgroup 中进程指定性能计数器事件的计数值。该参数可以查询 cgroup 中进程指定性能计数器事件的计数值。例如:

# 查询 cgroup 中进程 CPU 周期计数器事件的计数值
cat /sys/fs/cgroup/perf_event/mygroup/perf_event.cycles.count

2.3.12、rdma 配置

rdma 子系统是 cgroup 提供的一种用于控制 RDMA(Remote Direct Memory Access)资源使用的子系统。RDMA 是一种高性能网络传输技术,可以实现低延迟、高吞吐量的数据传输。通过 rdma 子系统,用户可以限制 cgroup 中进程使用 RDMA 资源的数量和大小。

以下是 rdma 子系统的一些常用配置:

rdma.max_qp:用于设置 cgroup 中进程在每个 RDMA 设备上可以创建的最大 QP(Queue Pair)数。该参数可以设置一个整数值,表示 cgroup 中进程在每个 RDMA 设备上可以创建的最大 QP 数。例如:

# 设置 cgroup 中进程在每个 RDMA 设备上可以创建的最大 QP 数为 128
echo "128" > /sys/fs/cgroup/rdma/mygroup/rdma.max_qp

rdma.max_mr:用于设置 cgroup 中进程在每个 RDMA 设备上可以注册的最大 MR(Memory Region)数。该参数可以设置一个整数值,表示 cgroup 中进程在每个 RDMA 设备上可以注册的最大 MR 数。例如:

# 设置 cgroup 中进程在每个 RDMA 设备上可以注册的最大 MR 数为 256
echo "256" > /sys/fs/cgroup/rdma/mygroup/rdma.max_mr

rdma.max_pd:用于设置 cgroup 中进程在每个 RDMA 设备上可以创建的最大 PD(Protection Domain)数。该参数可以设置一个整数值,表示 cgroup 中进程在每个 RDMA 设备上可以创建的最大 PD 数。例如:

# 设置 cgroup 中进程在每个 RDMA 设备上可以创建的最大 PD 数为 16
echo "16" > /sys/fs/cgroup/rdma/mygroup/rdma.max_pd

rdma.max_cq:用于设置 cgroup 中进程在每个 RDMA 设备上可以创建的最大 CQ(Completion Queue)数。该参数可以设置一个整数值,表示 cgroup 中进程在每个 RDMA 设备上可以创建的最大 CQ 数。例如:

# 设置 cgroup 中进程在每个 RDMA 设备上可以创建的最大 CQ 数为 64
echo "64" > /sys/fs/cgroup/rdma/mygroup/rdma.max_cq

2.3.13、pids 配置

pids 子系统是 cgroup 提供的一种用于控制进程数量的子系统。通过 pids 子系统,用户可以控制 cgroup 中运行的进程数量,以避免系统过载或进程耗尽系统资源。

以下是 pids 子系统的一些常用配置:

pids.max:用于限制 cgroup 中进程的最大数量。该参数可以设置一个整数值,表示 cgroup 中允许运行的最大进程数量。例如:

# 设置 cgroup 中允许运行的最大进程数量为 1000
echo "1000" > /sys/fs/cgroup/pids/mygroup/pids.max

pids.current:用于查询 cgroup 中当前运行的进程数量。该参数可以查询 cgroup 中当前运行的进程数量。例如:

# 查询 cgroup 中当前运行的进程数量
cat /sys/fs/cgroup/pids/mygroup/pids.current

pids.max_depth:用于限制 cgroup 的层级深度。该参数可以设置一个整数值,表示 cgroup 可以创建的最大层级深度。例如:

# 设置 cgroup 可以创建的最大层级深度为 3
echo "3" > /sys/fs/cgroup/pids/mygroup/pids.max_depth

2.3.14、ns 配置

ns 子系统是 cgroup 提供的一种用于控制 Linux 命名空间(Namespace)的子系统。通过 ns 子系统,用户可以限制 cgroup 中进程使用特定命名空间的数量和类型。

以下是 ns 子系统的一些常用配置:

ns.<namespace_type>.max:用于限制 cgroup 中进程使用特定类型命名空间的数量。该参数可以设置一个整数值,表示 cgroup 中允许运行的最大特定类型命名空间的数量。其中 <namespace_type> 表示命名空间的类型,例如 pid 表示进程 ID 命名空间。例如:

# 设置 cgroup 中允许运行的最大 PID 命名空间数量为 5
echo "5" > /sys/fs/cgroup/ns/mygroup/ns.pid.max

ns.<namespace_type>.current:用于查询 cgroup 中当前运行特定类型命名空间的进程数量。该参数可以查询 cgroup 中当前运行特定类型命名空间的进程数量。例如:

# 查询 cgroup 中当前运行的 PID 命名空间的进程数量
cat /sys/fs/cgroup/ns/mygroup/ns.pid.current

ns.current:用于查询 cgroup 中进程使用的所有命名空间的数量。该参数可以查询 cgroup 中进程使用的所有命名空间的数量。例如:

# 查询 cgroup 中进程使用的所有命名空间的数量
cat /sys/fs/cgroup/ns/mygroup/ns.current

2.4、创建子系统

在 Linux 中,可以使用 cgroupfs 文件系统来创建和管理 Cgroups 子系统。cgroupfs 文件系统通常挂载在 /sys/fs/cgroup 目录下,您可以在该目录下创建子目录,来创建 Cgroups 子系统。

2.4.1、创建子目录

/sys/fs/cgroup 目录下创建一个子目录,用于存放控制组。例如,要创建一个 CPU 控制组,可以执行以下命令:

 mkdir /sys/fs/cgroup/cpu/mygroup

该命令会在 /sys/fs/cgroup/cpu 目录下创建一个名为 mygroup 的子目录,用于存放 CPU 控制组。

创建后目录中自动生成以下文件:

cgroup.clone_children         cpuacct.usage              cpu.cfs_init_buffer_us  cpuset.group_balancer            cpuset.soft_cpus
cgroup.procs                  cpuacct.usage_all          cpu.cfs_period_us       cpuset.mem_exclusive             cpu.shares
cgroup.rich_container_source  cpuacct.usage_percpu       cpu.cfs_quota_us        cpuset.mem_hardwall              cpu.stat
cpuacct.block_latency         cpuacct.usage_percpu_sys   cpu.identity            cpuset.memory_migrate            notify_on_release
cpuacct.cgroup_wait_latency   cpuacct.usage_percpu_user  cpu.rt_period_us        cpuset.memory_pressure           pool_size
cpuacct.enable_sli            cpuacct.usage_sys          cpu.rt_runtime_us       cpuset.memory_spread_page        tasks
cpuacct.ioblock_latency       cpuacct.usage_user         cpuset.cpu_exclusive    cpuset.memory_spread_slab
cpuacct.proc_stat             cpuacct.wait_latency       cpuset.cpus             cpuset.mems
cpuacct.sched_cfs_statistics  cpu.bvt_warp_ns            cpuset.effective_cpus   cpuset.sched_load_balance
cpuacct.stat                  cpu.cfs_burst_us           cpuset.effective_mems   cpuset.sched_relax_domain_level

除了每个cgroup独特的资源控制文件,还有一些通用的文件。

  • tasks:当前 cgroup 包含的任务(task)pid 列表,把某个进程的 pid 添加到这个文件中就等于把进程交由到该cgroup控制。
  • cgroup.procs:使用逻辑和tasks相同。
  • notify_on_release:0或者1,该文件的内容为1时,当cgroup退出时(不再包含任何进程和子cgroup),将调用release_agent里面配置的命令。
  • release_agent:需要执行的命令。

另外在docker中无法创建,报错:

$ mkdir /sys/fs/cgroup/cpu/mygroup
mkdir: cannot create directory ‘/sys/fs/cgroup/cpu/mygroup’: Read-only file system

2.4.2、指定控制组参数

在创建控制组的子目录下,可以创建一些文件来指定控制组的参数,例如 CPU 使用率、内存限制等。例如,要限制 mygroup 控制组中的进程使用 50% 的 CPU,可以执行以下命令:

echo 50000 > /sys/fs/cgroup/cpu/mygroup/cpu.cfs_quota_us
echo 100000 > /sys/fs/cgroup/cpu/mygroup/cpu.cfs_period_us

该命令会将 mygroup 控制组中的进程限制为最多占用 50% 的 CPU 使用率。

2.4.3、将进程加入控制组

将需要受到控制的进程加入到相应的控制组中。例如,要将进程 PID 为 12345 的进程加入到 mygroup 控制组中,可以执行以下命令:

sudo echo 12345 > /sys/fs/cgroup/cpu/mygroup/tasks

一次只能添加一个任务进程ID。如果有多个任务ID,需分多次添加。

cgroup各个子系统初始化时,默认把系统中所有进程都纳管了,将一个进程的pid添加到新建的cgroup tasks文件的操作,实际是从一个cgroup移入到另一个cgroup的操作。所以要将进程从某个cgroup中删除,只能通过将其移出到另一个cgroup来实现,或者将进程终止。

2.4.4、删除cgroup 子系统

删除子资源,就是删除对应的目录:

# 删除失败
$ rm -rf /sys/fs/cgroup/cpu/mygroup/
rm: cannot remove ‘mygroup/cpu.cfs_burst_us’: Operation not permitted
rm: cannot remove ‘mygroup/cgroup.procs’: Operation not permitted
rm: cannot remove ‘mygroup/cpu.cfs_period_us’: Operation not permitted
rm: cannot remove ‘mygroup/cpuset.memory_pressure’: Operation not permitted
rm: cannot remove ‘mygroup/cpu.identity’: Operation not permitted
rm: cannot remove ‘mygroup/cpu.stat’: Operation not permitted
rm: cannot remove ‘mygroup/cpuset.memory_migrate’: Operation not permitted
rm: cannot remove ‘mygroup/cpuacct.cgroup_wait_latency’: Operation not permitted
rm: cannot remove ‘mygroup/cpuacct.usage_percpu_sys’: Operation not permitted
...# 删除成功
$ rmdir /sys/fs/cgroup/cpu/mygroup/# 验证删除干净
$ find /sys/fs/cgroup  -name mygroup

三、层级(Hierarchy)

Hierarchy 是指 Cgroups 控制组的层级结构,是一种树形结构,由多个 Cgroups 控制组组成。每个层级都有一个根控制组,可以包含多个子控制组,每个子控制组又可以包含多个子子控制组,以此类推,形成了一棵树形结构。

由于 Cgroups 控制组可以包含其他子控制组,因此 Cgroups 控制组的层级结构可以表现为进程间的层级关系。例如,一个父进程可以创建多个子进程,每个子进程可以绑定到不同的 Cgroups 控制组中,形成一个层级结构。

每个 Cgroups 控制组都有自己的资源限制和控制参数,例如 CPU 使用率、内存限制、IO 限制等。这些资源限制和控制参数可以在 Cgroups 控制组层级中进行继承和覆盖。当一个进程被绑定到一个 Cgroups 控制组中时,它会受到该控制组及其父控制组的所有资源限制和控制参数的影响。如果一个子控制组需要覆盖父控制组的某个参数,可以在子控制组中重新指定该参数。

每个hierarchy都对应一个cgroup虚拟文件系统,每个hierarchy都有系统上的所有task,此外低level的hierarchy不能超过高level设定的资源上限

架构图如下:
在这里插入图片描述

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

层级的组成规则有四个:

3.1、规则一

单个层次结构可以具有一个或多个子系统。如图所示,/cpu_memory_cg这个层级对cgroup1,cgroup2设置了cpu和memory两个子系统。

在这里插入图片描述

3.2、规则二

如果任何一个子系统已经附加到了一个层次,则不能将他们附加到另一个层次的结构中。如图所示,层级A的cpu_cg首先管理cpu子系统,那么层级B的cpu_mem_cg就无法管理cpu子系统。
在这里插入图片描述

3.3、规则三

每次在系统上创建新的层次结构时,系统上的所有任务最初都是该层次结构的默认cgroup(称为根cgroup)成员。对于创建的任何单个层次结构,系统上的每个任务都可以是该层次结构中的一个cgroup成员。一个任务可以位于多个cgroup中,只要这些cgroup中的每个处于不同的子系统层次结构中即可。任务一旦成为同一层次结构中的第二个cgroup成员,就会将其从该层次结构中的第一个cgroup中删除,即在同一层次结构中的两个不通cgroup,绝不会有同一任务,也即是对某进程某类cgroup子系统的限制方式只能有一种。创建第一个层次结构时,系统上的每个任务都是至少一个cgroup(根cgroup)的成员,因此,在使用cgroup时,每个系统任务始终至少位于一个cgroup中,如图所示
在这里插入图片描述

3.3、规则四

系统上派生的任何进程都会创建一个子进程(或线程)。子进程自动继承其父级的cgroup成员资格,但可以根据需要移动到其他cgroup中,移动后父子进程完全独立,如图所示

在这里插入图片描述

四、cgroups 在docker 中的应用

4.1、对cpu 使用率控制

在启动容器时使用docker run --cpu等参数可以控制容器CPU 使用率和分配比例,避免因为某个容器过度使用 CPU 资源而影响其他服务的正常运行。常见参数及其作用如下:

--cpus

限制容器使用的 CPU 核心数量。例如,–cpus=2 表示限制容器最多只能使用 2 个 CPU 核心。

--cpu-period 和 --cpu-quota

用于限制容器可以使用的 CPU 时间。--cpu-period 参数用于指定时间周期,单位为微秒,默认为 100,000 微秒。--cpu-quota 参数用于指定每个时间周期容器可以使用的 CPU 时间,单位为微秒,默认为 -1,表示不限制。

--cpu-shares

指定容器的 CPU 分配比例。例如,--cpu-shares=512 表示容器分配到的 CPU 资源权重是 512。

--cpu-rt-period

docker run --cpu-rt-period是 Docker 的一个 CPU 实时调度相关的参数。它用于指定在实时控制组中运行的容器的 CPU 时间周期,单位为微秒,默认值为 1000000 微秒(即 1 秒)。

实时控制组(RT Cgroups) 是一种针对实时任务的 Cgroups 控制组。当一个容器属于实时控制组时,容器可以有更高的 CPU 优先级,并且可以使用更多的 CPU 资源。

通过在 docker run 命令中使用 --cpu-rt-period 参数,可以为容器指定自己的 CPU 时间周期。例如,使用以下命令创建一个实时控制组的容器:

docker run --cpu-rt-period=50000 --cpu-rt-runtime=10000 myimage

该命令会创建一个名为 myimage 的容器,将容器绑定到一个实时控制组中,并指定容器的 CPU 时间周期为 50000 微秒,CPU 运行时间为 10000 微秒。这样,容器可以使用更多的 CPU 资源,并提高容器内部应用程序的性能。

需要注意的是,实时控制组的使用需要谨慎。不当使用实时控制组可能会影响其他服务的正常运行。建议在使用实时控制组时仅为真正需要实时性的服务使用,并根据系统实际情况进行适当的调优和管理。

--cpu-rt-runtime

docker run --cpu-rt-runtime 是 Docker 的一个 CPU 实时调度相关的参数。它用于指定在实时控制组中运行的容器的 CPU 运行时间,单位为微秒,默认值为 -1,表示不限制。

--cpuset-cpus

docker run --cpuset-cpus 是 Docker 的一个 CPU 调度相关的参数。它用于指定容器可使用的 CPU 核心编号,可以用逗号分隔多个 CPU 核心编号。例如,--cpuset-cpus=0,2,4 表示容器只能使用编号为 0、2、4 的 CPU 核心。

通过在 docker run 命令中使用 --cpuset-cpus 参数,可以限制容器只能使用指定的 CPU 核心,避免容器过度使用 CPU 资源而影响系统性能。例如,使用以下命令创建一个限制容器使用 CPU 核心的容器:

docker run --cpuset-cpus=0,2,4 myimage

该命令会创建一个名为 myimage 的容器,将容器限制为只能使用编号为 0、2、4 的 CPU 核心。

--cpuset-mems

docker run --cpuset-mems 是 Docker 的一个 CPU 调度相关的参数。它用于指定容器可使用的内存节点,可以用逗号分隔多个内存节点编号。例如,--cpuset-mems=0,1 表示容器只能使用节点 0 和节点 1 上的内存资源。

通过在 docker run 命令中使用 --cpuset-mems 参数,可以限制容器只能使用指定的内存节点,避免容器过度使用内存资源而影响系统性能。例如,使用以下命令创建一个限制容器使用内存节点的容器:

docker run --cpuset-mems=0,1 myimage

该命令会创建一个名为 myimage 的容器,将容器限制为只能使用节点 0 和节点 1 上的内存资源。

4.2、对内存限额

与操作系统类似,容器可使用的内存包括两部分:物理内存和 Swap,默认情况下,容器可以使用主机上的所有空闲内存,docker可以使用一些参数来限制容器使用的内存资源,避免因为某个容器过度使用内存资源而影响其他服务的正常运行。常见参数如下:

--memory 和 --memory-swap

限制容器可以使用的内存和交换空间的大小。
--memory 参数用于指定内存限制,
--memory-swap 参数用于指定交换空间限制。
默认情况下,--memory-swap 的值等于 --memory 的值加上主机上可用的交换空间大小。例如,--memory=1g --memory-swap=2g 表示限制容器最多只能使用 1GB 的内存和 2GB 的交换空间。

--memory-reservation

指定容器的内存保证,即为容器预留一定的内存空间。例如, --memory-reservation=500m 表示为容器预留至少 500MB 的内存空间。

--memory-swappiness

指定容器对交换空间的使用倾向性。该参数的值范围为 0 到 100,表示对内存的使用倾向性。值越大,容器越倾向于使用交换空间。

4.3、对-Block IO的限制

对于容器使用的块 IO 资源,可以使用以下参数进行限制

--blkio-cost-weight-device

docker run --blkio-cost-weight-device 是 Docker 的一个 IO 调度相关的参数。它用于指定容器在指定块设备上使用 IO 资源的权重。该参数在使用 IO 资源时会影响容器的 IO 资源使用情况,从而保证容器磁盘 IO 的质量。

使用 --blkio-cost-weight-device 参数可以为容器指定在指定块设备上使用 IO 资源的权重。例如,使用以下命令创建一个限制容器在 /dev/sda 上的磁盘 IO 资源使用权重为 400 的容器:

docker run --blkio-cost-weight-device=/dev/sda:400 myimage

该命令会创建一个名为 myimage 的容器,并为容器指定在 /dev/sda 块设备上使用 IO 资源的权重为 400。

--blkio-weight

docker run --blkio-weight 是 Docker 的一个 IO 调度相关的参数。它用于为容器指定 IO 资源的权重,从而影响容器在 IO 调度时的优先级。该参数在使用 IO 资源时会影响容器的 IO 资源使用情况,从而保证容器磁盘 IO 的质量。

使用 --blkio-weight 参数可以为容器指定在 IO 调度时的权重。默认情况下,容器没有 IO 限制。使用 --blkio-weight 可以设置容器的 IO 权重,值越大,容器的 IO 资源使用优先级越高。例如,使用以下命令创建一个 IO 权重为 500 的容器:

docker run --blkio-weight=500 myimage

该命令会创建一个名为 myimage 的容器,并为容器指定 IO 权重为 500。

--blkio-cost-weight-device--blkio-weight 区别

作用不同:--blkio-cost-weight-device 参数是针对指定的块设备设置容器在该设备上的 IO 资源使用权重,而 --blkio-weight 参数是为容器指定 IO 调度时的总权重。
适用范围不同:--blkio-cost-weight-device 参数只能限制容器在指定的块设备上使用的 IO 资源,而 --blkio-weight 参数可以影响容器在所有块设备上的 IO 调度。
举个例子,如果一个容器使用多个块设备,那么使用 --blkio-cost-weight-device 参数只能针对某个指定的设备设置 IO 资源的使用限制,而使用 --blkio-weight 参数可以为整个容器设置 IO 调度的权重,从而影响容器在多个块设备上的 IO 资源使用情况。

--blkio-weight-device

docker run --blkio-weight-device 是 Docker 的一个 IO 调度相关的参数。它用于为容器在指定块设备上使用 IO 资源的权重,从而影响容器在 IO 调度时的优先级。该参数在使用 IO 资源时会影响容器的 IO 资源使用情况,从而保证容器磁盘 IO 的质量。

使用 --blkio-weight-device 参数可以为容器在指定块设备上使用 IO 资源的权重。例如,使用以下命令创建一个限制容器在 /dev/sda 块设备上的 IO 资源使用权重为 400 的容器:

docker run --blkio-weight-device=/dev/sda:400 myimage

该命令会创建一个名为 myimage 的容器,并为容器在 /dev/sda 块设备上使用 IO 资源的权重为 400。

--blkio-cost-weight-device--blkio-weight-device 区别

作用不同:--blkio-cost-weight-device 参数是针对指定的块设备设置容器在该设备上的 IO 资源使用权重,而 --blkio-weight-device 参数是为容器指定在所有块设备上使用 IO 资源的权重。
适用范围不同:--blkio-cost-weight-device 参数只能限制容器在指定的块设备上使用的 IO 资源,而 --blkio-weight-device 参数可以影响容器在所有块设备上的 IO 调度。
举个例子,如果一个容器使用多个块设备,那么使用 --blkio-cost-weight-device 参数只能针对某个指定的设备设置 IO 资源的使用限制,而使用 --blkio-weight-device 参数可以为整个容器设置在所有块设备上的 IO 调度的权重,从而影响容器在多个块设备上的 IO 资源使用情况。

--blkio-weight--blkio-weight-device 区别

作用不同:--blkio-weight 参数是为容器指定 IO 调度时的总权重,而 --blkio-weight-device 参数是为容器在指定块设备上使用 IO 资源的权重。
适用范围不同:--blkio-weight 参数可以影响容器在所有块设备上的 IO 调度,而 --blkio-weight-device 参数只能限制容器在指定的块设备上使用的 IO 资源。
举个例子,如果一个容器使用多个块设备,那么使用 --blkio-weight 参数可以为整个容器设置 IO 调度时的权重,从而影响容器在多个块设备上的 IO 资源使用情况,而使用 --blkio-weight-device 参数只能针对某个指定的设备设置容器在该设备上的 IO 资源的使用限制。

4.4、devices 的限制

bps 是byte per second,每秒读写的数据量。iops是io per second,每秒IO的次数。常见参数如下:

--device

docker run --device选项用于将主机上的特定设备映射到容器中,以便容器内的进程可以访问这些设备。这是Docker中的一个高级选项,通常用于需要访问主机上的硬件设备的应用程序,例如音频设备、摄像头、串口等。

例如,如果您想在Docker容器中运行一个使用USB设备连接的应用程序,那么您可以使用以下命令运行容器:

docker run --device=/dev/ttyUSB0 myapp

其中,/dev/ttyUSB0是USB设备的路径,myapp是您要运行的应用程序的名称。这个命令将会将主机上的/dev/ttyUSB0设备映射到容器中,以便您的应用程序可以使用它。这样,在容器中运行的应用程序就可以像在主机上一样访问USB设备了。

此外,还可以指定多个设备,例如:

docker run --device=/dev/ttyUSB0 --device=/dev/video0 myapp

这个命令将会将主机上的/dev/ttyUSB0设备和/dev/video0设备映射到容器中,以便myapp应用程序可以使用这些设备。

--device-cgroup-rule

docker run --device-cgroup-rule选项用于在容器内设置控制组规则,以限制容器中进程对指定硬件设备的访问。通常,这个选项与docker run --device选项一起使用,以控制容器中进程对硬件设备的访问。

例如,以下命令限制了容器中所有进程对/dev/snd设备的访问:

docker run --device=/dev/snd --device-cgroup-rule='c 116:* rwm' myapp

其中,--device=/dev/snd将主机上的/dev/snd设备映射到容器中,--device-cgroup-rule='c 116:* rwm'设置了控制组规则,以允许容器中进程对设备/dev/snd的读、写和映射操作。

--device-read-bps

docker run --device-read-bps选项用于限制容器内的进程从指定设备读取数据的速度。它限制了设备的读取速度,以保护设备不会被过度使用。这个选项仅在使用–device选项映射设备时生效。

例如,以下命令将限制容器中的进程从/dev/sda设备每秒读取不超过1MB的数据:

docker run --device=/dev/sda --device-read-bps=/dev/sda:1mb myapp

其中,--device=/dev/sda将主机上的/dev/sda设备映射到容器中,--device-read-bps=/dev/sda:1mb设置了限制,以限制容器中的进程每秒最多从/dev/sda设备读取1MB的数据。

--device-read-iops

docker run --device-read-iops选项用于限制容器内的进程从指定设备读取数据的IOPS(每秒输入/输出操作数)。它限制了设备的读取速度,以保护设备不会被过度使用。这个选项仅在使用–device选项映射设备时生效。

例如,以下命令将限制容器中的进程从/dev/sda设备每秒执行不超过100个读取操作:

docker run --device=/dev/sda --device-read-iops=/dev/sda:100 myapp

其中,--device=/dev/sda将主机上的/dev/sda设备映射到容器中, --device-read-iops=/dev/sda:100设置了限制,以限制容器中的进程每秒最多从/dev/sda设备执行100个读取操作。

--device-write-bps

docker run --device-write-bps选项用于限制容器内的进程向指定设备写入数据的速度。它限制了设备的写入速度,以保护设备不会被过度使用。这个选项仅在使用–device选项映射设备时生效。

例如,以下命令将限制容器中的进程向/dev/sda设备每秒写入不超过1MB的数据:

docker run --device=/dev/sda --device-write-bps=/dev/sda:1mb myapp

其中,--device=/dev/sda将主机上的/dev/sda设备映射到容器中,--device-write-bps=/dev/sda:1mb设置了限制,以限制容器中的进程每秒最多向/dev/sda设备写入1MB的数据。

--device-write-iops

docker run --device-write-iops选项用于限制容器内的进程向指定设备写入数据的IOPS(每秒输入/输出操作数)。它限制了设备的写入速度,以保护设备不会被过度使用。这个选项仅在使用–device选项映射设备时生效。

例如,以下命令将限制容器中的进程向/dev/sda设备每秒执行不超过100个写入操作:

docker run --device=/dev/sda --device-write-iops=/dev/sda:100 myapp

其中,--device=/dev/sda将主机上的/dev/sda设备映射到容器中,--device-write-iops=/dev/sda:100设置了限制,以限制容器中的进程每秒最多向/dev/sda设备执行100个写入操作。

参考文档

1、https://blog.csdn.net/weixin_41402069/article/details/125886286

2、https://www.cnblogs.com/rdchenxi/p/10464386.html

3、https://www.cnblogs.com/lioa/p/12664912.html

4、https://www.modb.pro/db/233701

5、https://blog.frognew.com/2021/05/relearning-container-06.html

6、https://www.modb.pro/db/233701

7、https://ggaaooppeenngg.github.io/zh-CN/2017/05/07/cgroups-%E5%88%86%E6%9E%90%E4%B9%8B%E5%86%85%E5%AD%98%E5%92%8CCPU/

8、https://www.php.cn/faq/556561.html

9、https://blog.csdn.net/m0_71931851/article/details/128132467


http://www.ppmy.cn/news/503058.html

相关文章

java手机号、身份证号脱敏

废话不多说&#xff0c;直接上代码了 // 手机号码前三后四脱敏public static String mobileDesensitize(String mobile) {if (StringUtils.isEmpty(mobile) || (mobile.length() ! 11)) {return mobile;}return mobile.replaceAll("(\\w{3})\\w*(\\w{4})", "$1*…

PHP 身份证号验证是否是真实的

已测试&#xff0c;90%左右的身份证号都可以检验出来是否是真实的身份证号&#xff0c;如果要求不高的话&#xff0c;可以不用在使用第三方的身份证号验证了封装的model 可以直接使用的 大家可以借鉴看一下&#xff0c;有问题可以及时指出<?php namespace app\backend\cont…

身份证号判断是否合法(具体代码)

通过身份证号判断是否合法、省份、性别、出生日期、生肖、星座的具体代码&#xff1a; import java.util.Calendar; import java.util.Scanner;public class Idcard {public static void main(String[] args) {yixuewen();}/*根据〖中华人民共和国国家标准 GB 11643-1999〗中有…

身份证号的奥秘

第1关:判断性别 通过身份证的第17位也就是倒数第二位的数字可以辨别该身份证所属人的性别,奇数为男性,偶数为女性。 本关任务:输入身份证号,第17位若是偶数,输出男性,否则输出女性 if eval(sfzh[16])%2==0: print("女性") else: print

身份证号码的校验

身份证号码的校验的计算方法: 1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7、9、10、5、8、4、2、1、6、3、7、9、10、5、8、4、2; 2、将这17位数字和系数相乘的结果相加; 3、用加出来和除以11&#xff0c;看余数是多少; 4、余数只可能有…

python-身份证号处理

18位身份证号码&#xff1a;第7、8、9、10位为出生年份(四位数)&#xff0c;第11、第12位为出生月份&#xff0c;第13、14位代表出生日期&#xff0c;第17位代表性别&#xff0c;奇数为男&#xff0c;偶数为女。 用户输入一个合法的身份证号&#xff0c;请输出用户的出生年月日…

python基础经典问题-判断身份证号码是否有效

输入一个身份证号&#xff0c;判断其是否有效&#xff1a; 若不为18位&#xff0c;提示“长度错误”&#xff1b; 若前17位不为数字&#xff0c;提示“有无效字符”&#xff1b; 最后一位为校验码&#xff0c;若错误&#xff0c;提示”校验码错误”&#xff0c; 若校验码正确&a…

php 判断身份证号是否正确

public function validateIDCard($idcard) {if(empty($idcard)){return 错误身份证;}else{$idcard strtoupper($idcard); # 如果是小写x,转化为大写Xif(strlen($idcard) ! 18 && strlen($idcard) ! 15){return 错误身份证;}# 如果是15位身份证&#xff0c;则转化为18位…