关于Linux中控制群组(cgroup)的一些笔记

网友投稿 932 2022-05-30

不加思考地滥读或无休止地读书,所读过的东西无法刻骨铭心,其大部分终将消失殆尽。——叔本华

写在前面

学习遇到容器资源限制的处理问题,所以研究下。

博文内容涉及:

容器中cgroup的应用

不加思考地滥读或无休止地读书,所读过的东西无法刻骨铭心,其大部分终将消失殆尽。——叔本华

容器使用cgroup对资源进行限制

容器内存限制:-m 200M

┌──[root@liruilongs.github.io]-[/] └─$ docker run -itd --name=c2 -m 200M centos 3b2df1738e84159f4fa02dadbfc285f6da8ddde4d94cb449bc775c9a70eaa4ea ┌──[root@liruilongs.github.io]-[/] └─$ docker stats CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS 3b2df1738e84 c2 0.00% 528KiB / 200MiB 0.26% 648B / 0B 0B / 0B 1 55e45b34d93d c1 0.00% 8.684MiB / 3.843GiB 0.22% 648B / 0B 30.5MB / 11.5MB 2

对容器CPU的限制:-cpuset-cpus 0

┌──[root@liruilongs.github.io]-[/] └─$ ps mo pid,psr $(pgrep cat) ┌──[root@liruilongs.github.io]-[/] └─$ docker run -itd --name=c3 --cpuset-cpus 0 -m 200M centos a771eed8c7c39cd410bd6f43909a67bfcf181d87fcafffe57001f17f3fdff408

第 1 章 控制群组简介

1.1. 什么是控制群组

控制群组(control group) 是Linux kernel(Linux内核)的一项功能:

在一个系统中运行的层级制进程组,您可对其进行资源分配(如CPU时间、系统内存、网络带宽或者这些资源的组合)。

通过使用cgroup ,

系统管理员在分配、排序、拒绝、管理和监控系统资源等方面,可以进行精细化控制。硬件资源可以在应用程序和用户间智能分配,从而增加整体效率。

关于Linux中控制群组(cgroup)的一些笔记

控制群组可对进程进行层级式分组并标记,并对其可用资源进行限制。

传统情况下,所有的进程分得的系统资源数量相近,管理员用进程niceness值进行调节。

用niceness值进行调节,包含大量进程的应用程序可以比包含少量进程的应用程序获得更多资源,这与应用程序的重要程度无关。

通过将cgroup层级系统与systemd单位树捆绑, Linux 可以把资源管理设置从进程级别移至应用程序级别。

可以使用systemctl指令,或者通过修改systemd单位文件来管理系统资源。

在 Linux 7之前的版本中,系统管理员使用libcgroup软件包中的cgconfig指令来建立自定义cgroup层级。但现在,这个软件包已经过时也不被推荐使用,因为它很容易与默认的cgroup层级产生冲突。然而,在一些特定情况下, libcgroup仍然可用,如systemd不可用时,或使用net-prio子系统时。

上述工具提供了高阶接口,用与Linux kernel中的cgroup管控器(也称为子系统)互动。用于资源管理的主要cgroup管控器是cpu, memory和blkio

1.2. cgroup的默认层级

默认情况下, systemd会自动创建slice, scope和service单位的层级,来为cgroup树提供统一结构。使用systemctl指令,您可以通过创建自定义slice进一步修改此结构,

systemd也自动为/sys/fs/cgroup/目录中重要的kernel资源管控器挂载层级。

在系统的开机阶段,systemd 会把支持的 controllers (subsystem 子系统)挂载到默认的 /sys/fs/cgroup/ 目录下面:

┌──[root@liruilongs.github.io]-[~] └─$ ls /sys/fs/cgroup/ blkio cpuacct cpuset freezer memory net_cls,net_prio perf_event systemd cpu cpu,cpuacct devices hugetlb net_cls net_prio pids ┌──[root@liruilongs.github.io]-[~] └─$ ll /sys/fs/cgroup/

除了systemd目录外,其它目录都是对应的subsystem。/sys/fs/cgroup/systemd目录是systemd维护的自己使用的非subsystem的 cgroups层级结构。

systemd 的单位类型

系统中运行的所有进程,都是 systemd init 进程的子进程。在资源管控方面,systemd提供了三种单位类型:

service :

一个或一组进程,由 systemd 依据单位配置文件启动。service 对指定进程进行封装,这样进程可以作为一个整体被启动或终止。service 参照以下方式命名:

name.service # 其中,name 代表服务名称。 Undefined

scope :

一组外部创建的进程。由强制进程通过 fork() 函数启动和终止、之后被 systemd 在运行时注册的进程,scope 会将其封装。例如:用户会话、 容器和虚拟机被认为是 scope。scope 的命名方式如下:

name.scope #其中,name 代表 scope 名称。 Undefined

slice :

一组按层级排列的单位。slice 并不包含进程,但会组建一个层级,并将 scope 和 service 都放置其中。真正的进程包含在 scope 或 service 中。在这一被划分层级的树中,每一个 slice 单位的名字对应通向层级中一个位置的路径。小横线("-")起分离路径组件的作用。例如,如果一个 slice 的名字是:

parent-name.slice Undefined

这说明 parent-name.slice 是 parent.slice 的一个子 slice。这一子 slice 可以再拥有自己的子 slice,被命名为:parent-name-name2.slice,以此类推。

-.slice Undefined

service、scope 和 slice单位直接映射到 cgroup 树中的对象。当这些单位被激活,它们会直接一一映射到由单位名建立的 cgroup路径中。例如,ex.service 属于 test-waldo.slice,会直接映射到 cgroup test.slice/test-waldo.slice/ex.service/ 中。

service、scope 和slice是由系统管理员手动创建或者由程序动态创建的。默认情况下, 操作系统会定义一些运行系统必要的内置 service。另外,默认情况下,系统会创建四种 slice:

请注意,所有的用户会话、虚拟机和容器进程会被自动放置在一个单独的 scope 单元中。而且,所有的用户会分得一个隐含子 slice(implicit subslice)。除了上述的默认配置,系统管理员可能会定义新的 slice,并将 service 和 scope 置于其中。

systemd-cgls

service 和 scope 包含进程,但被放置在不包含它们自身进程的 slice 里。唯一例外是位于特殊 systemd.slice 中的 PID 1。请注意,-.slice 未被显示,因为它被整体树的根隐性识别。

`service 和 slice 单位可通过永久单位文件来配置;或者对 PID 1 进行 API 调用,在运行时动态创建。scope 单位只能以第一种方式创建。API 调用动态创建的单位是临时的,并且仅在运行时存在。一旦结束、被关闭或者系统重启,临时单位会被自动释放。

1.3. Linux Kernel 的资源管控器

资源管控器(也称为cgroup子系统)代表一种单一资源:如 CPU 时间或者内存。Linux kernel提供一系列资源管控器,由 systemd自动挂载。如需参考目前已挂载的资源管控器列表,请参见 /proc/cgroups,或使用 lssubsys 监控工具。在 Linux 7 中,systemd 默认挂载以下管控器:

Linux 7 中可用的管控器

Linux Kernel 展示了一系列可用 systemd 配置的资源管控器可调参数。参数的详细描述请参阅 kernel 文档(kernel 管控器专项介绍 的参考列表)。

第 2 章 使用控制群组

概述与创建、管理控制群组相关的任务。systemd是管理cgroup的推荐方式并会在将来版本中被支持,

2.1. 创建控制群组

从 systemd的角度来看,cgroup会连接到一个系统单位,此单位可用单位文件进行配置、用systemd命令列实用工具进行管理。根据应用的类型,您的资源管理设定可以是

transient(临时的) 或者 persistent(永久的)

要为服务创建 transient cgroup(临时 cgroup),请使用 systemd-run 指令启动此服务。如此,可以限制此服务在运行时所用资源。对 systemd 进行 API 调用,应用程序可以动态创建临时 cgroup。服务一旦停止,临时单位就会被自动移除。

要给服务分配 persistent cgroup(永久 cgroup),请对其单位配置文件进行编写。系统重启后,此项配置会被保留,所以它可以用于管理自动启动的服务。请注意,scope 单位不能以此方式创建。

2.1.1. 用 systemd-run 创建临时 cgroup

systemd-run指令用于

创建、启动临时 service 或 scope 单位,并在此单位中运行自定义指令

在 service 单位中执行的指令在后台非同步启动,它们从 systemd 进程中被调用。在 scope 单位中运行的指令直接从 systemd-run 进程中启动,因此从调用方继承执行状态。此情况下的执行是同步的。

在一个指定 cgroup 中运行指令,请以 root 身份输入

systemd-run --unit=name --scope --slice=slice_name command Undefined

上述选项外,systemd-run 也有一些其它可用参数。例如,–description 可以创建对单位的描述;service 进程结束后,–remain-after-exit 可以收集运行时信息;–machine 选项可以在密闭容器中执行指令

┌──[root@liruilongs.github.io]-[~] └─$ systemd-run --unit=toptest --slice=test top -b Running as unit toptest.service. #现在,toptest.service 名称可以与 systemctl 指令结合,以监控或修改 cgroup。 ┌──[root@liruilongs.github.io]-[~] └─$ systemctl status toptest.service ● toptest.service - /usr/bin/top -b Loaded: loaded (/run/systemd/system/toptest.service; static; vendor preset: disabled) Drop-In: /run/systemd/system/toptest.service.d └─50-Description.conf, 50-ExecStart.conf, 50-Slice.conf Active: active (running) since Wed 2021-10-13 01:12:43 CST; 50s ago Main PID: 27671 (top) CGroup: /test.slice/toptest.service └─27671 /usr/bin/top -b Oct 13 01:13:31 liruilongs.github.io top[27671]: 24025 root 20 0 145704 5332 4072 S 0.0 0.1 0:0... sshd Oct 13 01:13:31 liruilongs.github.io top[27671]: 24027 root 20 0 116024 2812 1784 S 0.0 0.1 0:0... bash Oct 13 01:13:31 liruilongs.github.io top[27671]: 24926 root 20 0 0 0 0 S 0.0 0.0 0:0...er/u+ Oct 13 01:13:31 liruilongs.github.io top[27671]: 25314 root 20 0 0 0 0 S 0.0 0.0 0:0...er/0+ Oct 13 01:13:31 liruilongs.github.io top[27671]: 25790 root 20 0 145704 5328 4072 S 0.0 0.1 0:0... sshd Oct 13 01:13:31 liruilongs.github.io top[27671]: 25792 root 20 0 115784 2440 1636 S 0.0 0.1 0:0... bash Oct 13 01:13:31 liruilongs.github.io top[27671]: 26067 root 20 0 0 0 0 S 0.0 0.0 0:0...er/0+ Oct 13 01:13:31 liruilongs.github.io top[27671]: 26337 postfix 20 0 89648 4028 3016 S 0.0 0.1 0:0...ickup Oct 13 01:13:31 liruilongs.github.io top[27671]: 27425 root 20 0 0 0 0 S 0.0 0.0 0:0...er/1+ Oct 13 01:13:31 liruilongs.github.io top[27671]: 27530 root 20 0 0 0 0 S 0.0 0.0 0:0...er/1+ Hint: Some lines were ellipsized, use -l to show in full. ┌──[root@liruilongs.github.io]-[~] └─$ ┌──[root@liruilongs.github.io]-[~] └─$ systemd-cgls ├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21 ├─test.slice │ └─toptest.service │ └─27671 /usr/bin/top -b ├─docker │ ├─3254bcd54a7b2b1a5ece2ca873ab18c3215484e6b4f83617a522afe4e853c378 │ │ ├─11885 /home/weave/runsvinit │ │ ├─11902 /sbin/runsvdir /etc/service │ │ ├─11903 runsv probe ........

2.1.2. 创建永久 cgroup

若要在系统启动时,配置一个自动启动的单位,请执行 systemctl enable 指令。自动运行此指令会在 /usr/lib/systemd/system/ 目录中创建单位文件。如要对cgroup做出永久改变,请添加或修改其单位文件中的配置参数。更多信息,请参阅〈第 2.3.2 节 “修改单位文件”〉。

2.2. 删除控制群组

临时cgroup所包含的进程一旦结束,临时cgroup就会被自动释放。通过将--remain-after-exit选项传递给systemd-run,您可以在其进程结束后,让单位继续运行来收集运行时的信息。如要单位停止运行,请输入:

systemctl stop name.service Undefined

如果您希望一个service停止运行,请将name替换成此service的名字。如要终止一个或多个单位中的进程,请以root身份输入:

systemctl kill name.service --kill-who=PID,... --signal=signal Undefined

用单位名(如 httpd.service)替代name。使用 --kill-who从 cgroup中挑选您希望结束的进程。如要同时终止多项进程,请传送一份 PID的逗号分隔列表。用您希望发送至指定进程的POSIX信号类型替代signal。默认情况下是 SIGTERM。

当单位被禁用并且其配置文件通过运行(下列行)被删除,永久 cgroup 会被释放:

systemctl disable name.service #name 代表您希望禁用的 service 名字。 Undefined

2.3. 修改 cgroup

所有被systemd监管的永久单位都在/usr/lib/systemd/system/目录中有一个单位配置文件。如要修改service单位的参数,请修改此配置文件。可以手动完成或者从命令列界面使用systemctl set-property指令。

# 用您希望修改的 systemd 名字来替代 name,希望改动的参数名称来替代 parameter,希望分配给此参数的新值来替代 value。 systemctl set-property name parameter=value Undefined

并非所有单位参数都能在运行时被修改,但是大多数与资源管控相关的参数是可以的,systemctl set-property指令让您可以同时修改多项属性,所以相较于单独设定每项属性,推荐您使用此指令。

改动会立即生效并被写入单位文件,并在重启后保留。您可以传递--runtime 选项,让设定变成临时设定。

systemctl set-property --runtime name property=value Undefined

2.3.1. 在命令列界面设定参数

systemctl set-property指令让您可以在

应用程序运行时,持续修改资源管控设置

。请以root身份使用下列句法来完成此项操作:

# 如需使用命令列来限定 httpd.service 的 CPU 和内存占用量,请输入: systemctl set-property httpd.service CPUShares=600 MemoryLimit=500M # 如希望此更改为临时更改,请添加 --runtime 选项: systemctl set-property --runtime httpd.service CPUShares=600 MemoryLimit=500M ###################### ┌──[root@liruilongs.github.io]-[~] └─$ cat /usr/lib/systemd/system/httpd.service [Unit] Description=The Apache HTTP Server After=network.target remote-fs.target nss-lookup.target Documentation=man:httpd(8) Documentation=man:apachectl(8) [Service] Type=notify EnvironmentFile=/etc/sysconfig/httpd ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND ExecReload=/usr/sbin/httpd $OPTIONS -k graceful ExecStop=/bin/kill -WINCH ${MAINPID} # We want systemd to give httpd some time to finish gracefully, but still want # it to kill httpd after TimeoutStopSec if something went wrong during the # graceful stop. Normally, Systemd sends SIGTERM signal right after the # ExecStop, which would kill httpd. We are sending useless SIGCONT here to give # httpd time to finish. KillSignal=SIGCONT PrivateTmp=true [Install] WantedBy=multi-user.target ┌──[root@liruilongs.github.io]-[~] └─$ systemctl set-property httpd.service BlockIOAccounting=true ┌──[root@liruilongs.github.io]-[~] └─$ systemctl set-property httpd.service CPUShares=600 MemoryLimit=500M ┌──[root@liruilongs.github.io]-[~] └─$ cat /etc/systemd/system/httpd.service.d/50-CPUShares.conf [Service] CPUShares=600 ┌──[root@liruilongs.github.io]-[~] └─$ cat /etc/systemd/system/httpd.service.d/50-MemoryLimit.conf [Service] MemoryLimit=524288000 ┌──[root@liruilongs.github.io]-[~] └─$ cat /etc/systemd/system/httpd.service.d/50-BlockIOAccounting.conf [Service] BlockIOAccounting=yes ┌──[root@liruilongs.github.io]-[~] └─$

2.3.2. 修改单位文件

systemd service单位文件提供一系列对资源管理有帮助的高级配置参数。这些参数与必须在kernel中启用的Linux cgroup管控器通讯。您可以使用这些参数管理CPU、内存使用量、block IO和更多精细单位的属性。

cpu 管控器在 kernel 中被默认启动,这可使所有系统 service 的可用 CPU 量相同,而与其所包含进程数量无关。此项默认设定可以使用/etc/systemd/system.conf配置文件中的 DefaultControllers参数来修改。如需管理 CPU 的分配,请使用单位配置文件[Service]部分中的下列指令:

`CPUShares=value`

请用CPU share的数量代替value。默认值为1024,您可以增加此数值来给单位分配更多CPU。此参数默认:CPUAccounting 已在单位文件中启用。

CPUShares参数可以控制cpu.shares控制群组参数。

┌──[root@liruilongs.github.io]-[~] └─$ cat /etc/systemd/system.conf | grep -i BlockIOAccounting #DefaultBlockIOAccounting=no ┌──[root@liruilongs.github.io]-[~] └─$ cat /etc/systemd/system.conf | grep -i CPUAccounting #DefaultCPUAccounting=no

#若要为 Apache service 分配 1500 个 CPU share 而不是 1024 个,请修改 /usr/lib/systemd/system/httpd.service 单位文件中的 CPUShares 设置: [Service] CPUShares=1500 # 要应用此项修改,请重新载入 systemd 的配置并重启 Apache 来让修改过的 service 文件生效: systemctl daemon-reload systemctl restart httpd.service

为限定单位可用内存大小,请使用单位配置文件[Service]部分中的下列指令:

MemoryLimit=value

对cgroup中执行的进程设定其可用内存的最大值,并用此值替代value。请以千字节(Kilobyte)、兆字节(Megabyte)、千兆字节(Gigabyte)、太字节(Terabyte)为计量单位并使用 K、M、G、T 后缀来表示。同样,MemoryAccounting 参数必须在同一单元中启用。

MemoryLimit 参数可以控制 memory.limit_in_bytes 控制群组参数。

#若要限定 Apache service 的最大可用内存为 1GB,请修改 /usr/lib/systemd/system/httpd.service 单位文件中的 MemoryLimit 设定: [Service] MemoryLimit=1G #要应用此项修改,请重新载入 systemd 的配置并重启 Apache 来让修改过的 service 文件生效: systemctl daemon-reload systemctl restart httpd.service

如要管理Block IO,请使用单位配置文件[Service]部分中的下列指令。下列指令假设 BlockIOAccounting 参数已启动:

BlockIOWeight=value

为已执行进程选取一个新的整体 block IO 权重,并以此替代 value。权重需在 10 到 1000 之间选择,默认值是 1000。

BlockIODeviceWeight=device_name value

请为 device_name 所指的设备选取 block IO 权重,并以此代替 value。用名称或者通向此设备的路径来代替 device_name。因为有 BlockIOWeight,您可以在 10 到 1000 之间选取权重值。

BlockIOReadBandwidth=device_name value

此指令可以为一个单位限定具体带宽。用设备名称或通向块设备节点的路径替换 device_name,value 代表带宽率。使用 K、M、G、T 后缀作为计量单位。没有后缀的值默认单位为 “字节/秒”。

BlockIOWriteBandwidth=device_name value

此指令可以给指定设备限定可写带宽。参数与可与 BlockIOReadBandwidth 一致。

# 如要降低 Apache service 存取 /home/jdoe/ 目录 block IO 的权重,请将下列字符添加至 /usr/lib/systemd/system/httpd.service 单位文件: [Service] BlockIODeviceWeight=/home/jdoe 750 #如要设定 Apache 从 /var/log/ 目录读取的最大带宽为 5MB/秒,请使用下列句法: [Service] BlockIOReadBandwith=/var/log 5M #如要应用此项修改,请重新载入 systemd 的配置并重启 Apache,这样所修改的 service 文件会生效: systemctl daemon-reload systemctl restart httpd.service Undefined

另有几种指令,可在单位文件中使用以协助管理资源。

DeviceAllow=device_name options #此选项可以控制存取指定设备节点的次数。此处,device_name 代表通向设备节点的路径, # 或者是 /proc/devices 中特定的设备组名称。用 r、w 和 m 的组合来替换 options, # 以便单位读取、写入或者创建设备节点。 DevicePolicy=value #此处,value 是以下三种之一。 # - strict :仅允许 DeviceAllow 指定的存取类型; # - closed:允许对标准伪设备的存取,如:/dev/null、/dev/zero、/dev/full、/dev/random 和 /dev/urandom; # - auto:如果不显示 DeviceAllow,则允许对所有设备进行存取,此设定为默认设置。 Slice=slice_name # 请用存放单位的 slice 名称替换 slice_name。默认名称是 system.slice。scope 单位不能以此方式排列,因为它们已与其父 slice 绑定。 ControlGroupAttribute=attribute value # 此选项可以设定 Linux cgroup 管控器公开的多项控制群组参数。用您希望修改的低级别 cgroup 参数来替换 attribute,用此参数的新值来替换 value。

#如果您希望更改 memory.swappiness 设置来重新设定 kernel 替换 cgroup 任务所用进程内存的趋势,请参阅〈Kernel 管控器专项介绍〉对内存管控器的介绍。如要将 Apache service 的 memory.swappiness 设为 70,请添加下列信息至 /usr/lib/systemd/system/httpd.service: [Service] ControlGroupAttribute=memory.swappiness 70 #要应用此项修改,请重新载入 systemd 的配置并重启 Apache 来让修改过的 service 文件生效: systemctl daemon-reload systemctl restart httpd.service Undefined

2.4. 获得关于控制群组的信息

使用systemctl指令将系统单位列表并检查它们的状态。systemd-cgls指令可以检查控制群组的层级,systemd-cgtop可以监控控制群组的实时资源消耗。

2.4.1. 将单位列表

使用下列指令将系统中所有被激活单位列表:

┌──[root@liruilongs.github.io]-[~] └─$ systemctl list-units UNIT LOAD ACTIVE SUB DESCRIPTION proc-sys-fs-binfmt_misc.automount loaded active waiting Arbitrary Executable File Formats File System Au sys-devices-pci0000:00-0000:00:10.0-host2-target2:0:0-2:0:0:0-block-sda-sda1.device loaded active ................

以上所列结果包含四项:

默认情况下,systemctl 只会列出被激活的单位

(依据 ACTIVE 域中的高级激活状态)。使用--all选项可以查看未被激活的单位。如要限制结果列表中的信息量,请使用--type (-t)参数,此参数需要单位类型的逗号分隔列表,如:service 和 slice或者单位装载状态,如:loaded 和 masked。

┌──[root@liruilongs.github.io]-[~] └─$ systemctl -t slice UNIT LOAD ACTIVE SUB DESCRIPTION -.slice loaded active active Root Slice system-getty.slice loaded active active system-getty.slice system-selinux\x2dpolicy\x2dmigrate\x2dlocal\x2dchanges.slice loaded active active system-selinux\x2dpolicy\x2dmigrate\x system.slice loaded active active System Slice user-0.slice loaded active active User Slice of root user.slice loaded active active User and Session Slice LOAD = Reflects whether the unit definition was properly loaded. ACTIVE = The high-level unit activation state, i.e. generalization of SUB. SUB = The low-level unit activation state, values depend on unit type. 6 loaded units listed. Pass --all to see loaded but inactive units, too. To show all installed unit files use 'systemctl list-unit-files'. ┌──[root@liruilongs.github.io]-[~] └─$ systemctl -t service,masked Unknown unit type or load state 'masked'. Use -t help to see a list of allowed values. ┌──[root@liruilongs.github.io]-[~] └─$ systemctl -t masked 0 loaded units listed. Pass --all to see loaded but inactive units, too. To show all installed unit files use 'systemctl list-unit-files'. ┌──[root@liruilongs.github.io]-[~] └─$ systemctl list-unit-files UNIT FILE STATE proc-sys-fs-binfmt_misc.automount static dev-hugepages.mount static dev-mqueue.mount static proc-sys-fs-binfmt_misc.mount static sys-fs-fuse-connections.mount static sys-kernel-config.mount static sys-kernel-debug.mount static tmp.mount .......

2.4.2. 查看控制群组的层级

上述指令不会超越单位水平来显示 cgroup 中运行的真正进程。systemctl结果也不会显示单位的层级。您可以使用 systemd-cgls指令,根据cgroup将运行的进程分组来同时实现两者。 要显示您系统中的全部cgroup层级,请输入:

systemd-cgls # 如要减少 systemd-cgls 的输出并查看层级的特定一部分,请执行: systemd-cgls name systemctl status httpd.service

除了上述工具,systemd 也提供了专门监控 Linux 的 machinectl 指令。

2.4.3. 查看资源管控器

上述的systemctl指令可以监控高级单位层级,但是不能显示Linux kernel的资源管控器被哪项进程使用。这些信息存储在专门的进程文件中,如要查阅这些文件,请以root身份输入:

# PID 代表您希望查看的进程 ID。 cat proc/PID/cgroup ┌──[root@liruilongs.github.io]-[~] └─$ ps -ef | grep httpd | grep -v grep root 1231 1 0 02:00 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND apache 1232 1231 0 02:00 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND apache 1233 1231 0 02:00 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND apache 1234 1231 0 02:00 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND apache 1235 1231 0 02:00 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND apache 1236 1231 0 02:00 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND ┌──[root@liruilongs.github.io]-[~] └─$ cat /proc/1231/cgroup # 默认情况下,此列表对所有 systemd 启动的单位一致,因为它自动挂载所有默认管控器 11:blkio:/system.slice/httpd.service 10:memory:/system.slice/httpd.service 9:freezer:/ 8:perf_event:/ 7:cpuacct,cpu:/system.slice/httpd.service 6:devices:/system.slice/httpd.service 5:pids:/ 4:hugetlb:/ 3:net_prio,net_cls:/ 2:cpuset:/ 1:name=systemd:/system.slice/httpd.service ┌──[root@liruilongs.github.io]-[~] └─$

2.4.4. 监控资源消耗量

systemd-cgls指令给cgroup层级提供了静态数据快照。要查看按资源使用量(CPU、内存和 IO)排序的、正在运行的 cgroup 动态描述请使用:

systemd-cgtop # systemd-cgtop 提供的统计数据和控制选项与 top 实用工具所提供的相近 ┌──[root@liruilongs.github.io]-[~] └─$ systemd-cgtop

第 4 章 控制群组应用示例

4.1. 定义数据库 I/O 的优先级

在数据库服务器专用的虚拟机内部运行数据库服务器实例,让您可以根据数据库的优先级来为其分配资源。

系统在两个 KVM 虚拟机内部运行两个数据库服务器。一个数据库的优先级较高,另一个较低。当两个数据库服务器同时运行,I/O 吞吐量会降低来均等地容纳两个数据库的请求;

一旦优先级低的数据库启动(约在时间轴的 45 处),分配给两个服务器的 I/O 吞吐量是相同的。

为能优先处理来自优先级高的数据库服务器请求,可将此服务器分配给一个 I/O 操作预留量高的 cgroup

而优先级低的数据库服务器可以分配给一个 I/O 操作预留量少的 cgroup

。可按照以下步骤过程 4.1, “I/O 吞吐量优先化”来完成此操作,这些步骤将全部在主机系统上执行。

4.1.1 I/O 吞吐量优先化

# 请确保两项服务的所用资源统计功能,处于开启状态: systemctl set-property db1.service BlockIOAccounting=true systemctl set-property db2.service BlockIOAccounting=true # 如果将高优先级和低优先级服务的比率设定为 10:1 ,那么在这些服务单位中运行的进程将只能使用可用资源: systemctl set-property db1.service BlockIOWeight=1000 systemctl set-property db2.service BlockIOWeight=100

显示了优先处理优先级高的数据库请求,而限制优先级低的数据库的情况。一旦数据库服务器移至恰当的 cgroup(约在时间轴的 75 处),I/O 吞吐量就会在两个服务器间按照 10:1 的比率分配。

4.2. 定义网络流量的优先级

在单一服务器系统中运行多项与网络相关的服务时,定义这些服务的网络优先级是很重要的。定义优先级可以保证源自特定服务的数据包比源自其它服务的数据包享有更高优先级。

例如,当一台服务器系统同时起到 NFS 服务器和 Samba 服务器的作用时,优先级就显得尤为重要。NFS 必须享有高优先权,因为用户会预期较高吞吐量。Samba 的优先级可以较低,以确保 NFS 服务器有更佳表现。

net_prio 管控器可以用来为cgroup中的进程设定网络优先级。之后,优先级会被转译为Type Of Service(TOS,服务类型)比特,并嵌入每一个数据包中。

4.2.1 为共享服务的文件设定网络优先级

net_prio 管控器并未编译进 kernel,它是一个必须手动装载的模块。如需装载,请输入:

modprobe netprio_cgroup

请将 net_prio 子系统附加到 /cgroup/net_prio cgroup 中:

mkdir sys/fs/cgroup/net_prio mount -t cgroup -o net_prio none sys/fs/cgroup/net_prio

请为各项服务创建其 cgroup:

mkdir sys/fs/cgroup/net_prio/nfs_high mkdir sys/fs/cgroup/net_prio/samba_low

如希望nfs服务被自动移至nfs_high cgroup,请将下列行添至/etc/sysconfig/nfs文件:

CGROUP_DAEMON="net_prio:nfs_high"

此配置可确保nfs服务启动或重启时,nfs服务进程已被移至nfs_high cgroup。

smbd后台驻留程序在/etc/sysconfig目录中没有配置文件。为实现将 smbd 后台驻留程序自动移至 samba_low cgroup,请添加下列行至/etc/cgrules.conf文件:

*:smbd net_prio samba_low

请注意:此规则会将每一个smbd后台驻留程序(不仅仅是/usr/sbin/smbd)移至samba_low cgroup 。

您可以用相似的方式为nmbd和winbindd后台驻留程序定义规则,将它们移至samba_low cgroup。

请启动cgred服务,以载入之前步骤的配置:Cgred 是 一 个 守 护 进 程 ,它 可 根 据 在 etc/cgrules.conf 文 件 中 设 定 的 参 数 将 任 务 移 动 到 cgroup 中 。

systemctl start cgred Starting CGroup Rules Engine Daemon: [ OK ]

至于此示例的目的,让我们假设两项服务都使用 eth1 网络接口;给每一个 cgroup 定义优先级:1 表示优先级低,10 表示优先级高:

echo "eth1 1" > /sys/fs/cgroup/net_prio/samba_low/net_prio.ifpriomap echo "eth1 10" > /sys/fs/cgroup/net_prio/nfs_high/net_prio.ifpriomap

请启动 nfs 和 smb 服务以检查各自的进程是否已被移至正确的 cgroup:

~]# systemctl start smb Starting SMB services: [ OK ] ~]# cat /sys/fs/cgroup/net_prio/samba_low/tasks 16122 16124 ~]# systemctl start nfs Starting NFS services: [ OK ] Starting NFS quotas: [ OK ] Starting NFS mountd: [ OK ] Stopping RPC idmapd: [ OK ] Starting RPC idmapd: [ OK ] Starting NFS daemon: [ OK ] ~]# cat sys/fs/cgroup/net_prio/nfs_high/tasks 16321 16325 16376

Docker Linux

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:【活动结束】【内容共创系列】感恩有你,一路同行,参与签约作者征集令,赢高达500元礼包!
下一篇:我来告诉你,一个草根程序员如何进入BAT
相关文章