跳转到内容跳转到页面导航:上一页 [访问键 p]/下一页 [访问键 n]
适用于 openSUSE Leap 15.6

10 Kernel control groups 编辑源文件

摘要

Kernel Control Groups(“cgroups”)是内核特性,用于分配和限制进程的硬件和系统资源。进程也可以组织成层次树结构。

10.1 概述 编辑源文件

每个进程都被分配一个且仅分配一个管理 cgroup。cgroups 以层次树结构排序。您可以为单个进程或层次树的整个分支设置资源限制,例如 CPU、内存、磁盘 I/O 或网络带宽使用量。

openSUSE Leap 上,systemd 使用 cgroups 将所有进程组织到组中,systemd 将其称为 slices。 systemd 还提供了一个接口来设置 cgroup 属性。

命令 systemd-cgls 显示层次树。

内核 cgroup API 有两种变体——v1 和 v2。此外,可能存在多个 cgroup 层次结构,暴露不同的 API。在众多可能的组合中,有两种实际选择

  • 统一:具有 controllers 的 v2 层次结构

  • 混合:没有 controllers 的 v2 层次结构,以及位于 v1 层次结构上的 controllers(已弃用)

默认模式是统一。存在一种混合模式,为需要它的应用程序提供向后兼容性。

您只能设置一种模式。

10.1.1 混合 cgroup 层次结构 编辑源文件

Note
注意:弃用通知

cgroup v1 已被弃用,并且可能在未来的版本中被删除。

要启用混合控制组层次结构,请将 systemd.unified_cgroup_hierarchy=0 作为内核命令行参数附加到 GRUB 2 启动加载程序。有关配置 GRUB 2 的更多详细信息,请参阅 “参考”手册,第 12 章“启动加载程序 GRUB 2”

10.2 资源会计 编辑源文件

将进程组织到不同的 cgroups 可以用来获取每个 cgroup 的资源消耗数据。

会计具有相对较小但非零的开销,其影响取决于工作负载。为一个单元激活会计,也隐式地为同一 slice 中的所有单元以及其父 slice 中的所有单元激活它。

可以使用诸如 MemoryAccounting= 之类的指令在每个单元的基础上设置会计,或者使用指令 DefaultMemoryAccounting=/etc/systemd/system.conf 中全局为所有单元设置会计。有关可能的指令的详尽列表,请参阅 man systemd.resource-control

10.3 设置资源限制 编辑源文件

Note
注意:隐式资源消耗

请注意,资源消耗隐式地取决于您的工作负载执行的环境(例如,库/内核中数据结构的尺寸,实用程序的 fork 行为,计算效率)。因此,如果环境发生变化,建议(重新)校准您的限制。

可以使用 systemctl set-property 命令设置 cgroups 的限制。语法是

# systemctl set-property [--runtime] NAME PROPERTY1=VALUE [PROPERTY2=VALUE]

配置的值会立即应用。可选地,使用 --runtime 选项,以便新的值在重新启动后不会持久存在。

NAME 替换为 systemd 服务、scope 或 slice 名称。

有关完整的属性列表和更多详细信息,请参阅 man systemd.resource-control

10.4 使用 TasksMax 防止 fork 炸弹 编辑源文件

systemd 支持为每个单独的 leaf 单元或聚合在 slices 上配置任务计数限制。上游 systemd 附带的默认值限制了每个单元中的任务数量(内核全局限制的 15%,运行 /usr/sbin/sysctl kernel.pid_max 查看总限制)。每个用户的 slice 限制为内核限制的 33%。但是,这对于 openSUSE Leap 而言有所不同。

10.4.1 查找当前的默认 TasksMax 编辑源文件

实践表明,没有一个默认值适用于所有用例。 openSUSE Leap 附带两个自定义配置,这些配置会覆盖系统单元和用户 slice 的上游默认值,并将它们都设置为 infinity/usr/lib/systemd/system.conf.d/__20-defaults-SUSE.conf 包含这些行

[Manager]
DefaultTasksMax=infinity

/usr/lib/systemd/system/user-.slice.d/10-defaults.conf 包含这些行

[Slice]
TasksMax=infinity

使用 systemctl 验证 DefaultTasksMax 值

> systemctl show --property DefaultTasksMax
DefaultTasksMax=infinity

infinity 表示没有限制。更改默认值不是必需的,但设置某些限制可能有助于防止系统因失控进程而崩溃。

10.4.2 覆盖 DefaultTasksMax 编辑源文件

通过创建一个新的覆盖文件 /etc/systemd/system.conf.d/90-system-tasksmax.conf 来更改全局 DefaultTasksMax 值,并写入以下行以设置新的默认系统单元限制为 256 个任务

[Manager]
DefaultTasksMax=256

加载新设置,然后验证它是否已更改

> sudo systemctl daemon-reload
> systemctl show --property DefaultTasksMax
DefaultTasksMax=256

调整此默认值以适应您的需求。您可以根据需要为单个服务设置不同的限制。以下示例适用于 MariaDB。首先检查当前活动值

> systemctl status mariadb.service
  ● mariadb.service - MariaDB database server
   Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset>
   Active: active (running) since Tue 2020-05-26 14:15:03 PDT; 27min ago
     Docs: man:mysqld(8)
           https://mariadb.com/kb/en/library/systemd/
 Main PID: 11845 (mysqld)
   Status: "Taking your SQL requests now..."
    Tasks: 30 (limit: 256)
   CGroup: /system.slice/mariadb.service
           └─11845 /usr/sbin/mysqld --defaults-file=/etc/my.cnf --user=mysql

Tasks 行显示 MariaDB 当前正在运行 30 个任务,并且具有默认的 256 上限,这对于数据库而言不足。以下示例演示如何将 MariaDB 的限制提高到 8192。

> sudo systemctl set-property mariadb.service TasksMax=8192
> systemctl status mariadb.service
● mariadb.service - MariaDB database server
   Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disab>
  Drop-In: /etc/systemd/system/mariadb.service.d
           └─50-TasksMax.conf
   Active: active (running) since Tue 2020-06-02 17:57:48 PDT; 7min ago
     Docs: man:mysqld(8)
           https://mariadb.com/kb/en/library/systemd/
  Process: 3446 ExecStartPre=/usr/lib/mysql/mysql-systemd-helper upgrade (code=exited, sta>
  Process: 3440 ExecStartPre=/usr/lib/mysql/mysql-systemd-helper install (code=exited, sta>
 Main PID: 3452 (mysqld)
   Status: "Taking your SQL requests now..."
    Tasks: 30 (limit: 8192)
   CGroup: /system.slice/mariadb.service
           └─3452 /usr/sbin/mysqld --defaults-file=/etc/my.cnf --user=mysql

systemctl set-property 应用新的限制并创建一个 drop-in 文件以实现持久性,/etc/systemd/system/mariadb.service.d/50-TasksMax.conf,其中仅包含您想要应用于现有单元文件的更改。该值不必为 8192,但应为适合您工作负载的任何限制。

10.4.3 用户的默认 TasksMax 限制 编辑源文件

用户的默认限制应较高,因为用户会话需要更多资源。通过创建一个新文件,例如 /etc/systemd/system/user-.slice.d/40-user-taskmask.conf,为任何用户设置您自己的默认值。以下示例设置默认值为 16284

[Slice]
TasksMax=16284
Note
注意:数字前缀引用

请参阅 “参考”手册,第 10 章“systemd 守护程序”,第 10.5.3 节“手动创建 drop-in 文件”,以了解 drop-in 文件需要哪些数字前缀。

然后重新加载 systemd 以加载新值,并验证更改

> sudo systemctl daemon-reload
> systemctl show --property TasksMax user-1000.slice
TasksMax=16284

您如何知道使用哪些值?这因您的工作负载、系统资源和其他资源配置而异。当您的 TasksMax 值过低时,您可能会看到错误消息,例如 Failed to fork (Resources temporarily unavailable)Can't create thread to handle new connectionError: Function call 'fork' failed with error code 11, 'Resource temporarily unavailable'

有关配置 systemd 中系统资源的更多信息,请参阅 systemd.resource-control (5)

10.5 使用 cgroups 进行 I/O 控制 编辑源文件

本节介绍使用 Linux 内核的块 I/O 控制器来优先处理或限制 I/O 操作。这利用了 systemd 提供的手段来配置 cgroups,并讨论了在处理比例 I/O 控制时可能遇到的陷阱。

10.5.1 先决条件 编辑源文件

以下子部分描述了您在设计和配置系统时必须采取的步骤,因为这些方面无法在运行时更改。

10.5.1.1 文件系统 编辑源文件

您应该使用支持 cgroup writeback 的文件系统(否则无法进行 writeback 计费)。推荐的 openSUSE Leap 文件系统在以下上游版本中添加了支持

  • Btrfs (v4.3)

  • Ext4 (v4.3)

  • XFS (v5.3)

截至 openSUSE Leap 15.3,可以使用上述任何文件系统。

10.5.1.2 块 I/O 调度器 编辑源文件

节流策略在堆栈中更高层实现,因此不需要进行任何额外的调整。比例 I/O 控制策略有两种不同的实现:BFQ 控制器和基于成本的模型。我们在此描述 BFQ 控制器。要为特定设备施加其比例实现,我们必须确保 BFQ 是所选调度器。检查当前调度器

> cat /sys/class/block/sda/queue/scheduler
mq-deadline kyber bfq [none]

将调度器切换到 BFQ

 # echo bfq > /sys/class/block/sda/queue/scheduler

您必须指定磁盘设备(而不是分区)。设置此属性的最佳方法是特定于设备的 udev 规则。 openSUSE Leap 附带的 udev 规则已经为旋转磁盘驱动器启用了 BFQ。

10.5.1.3 Cgroup 层次结构布局 编辑源文件

通常,所有任务都位于根 cgroup 中,并且它们相互竞争。当任务分布到 cgroup 树中时,竞争仅发生在同级 cgroup 之间。这适用于比例 I/O 控制;吞吐量按层次方式聚合所有后代(参见下图)。

r
`-  a      IOWeight=100
    `- [c] IOWeight=300
    `-  d  IOWeight=100
`- [b]     IOWeight=200

I/O 仅来自 cgroup c 和 b。即使 c 具有更高的权重,由于它与 b 在同一级别竞争,因此其优先级较低。

10.5.2 配置控制量 编辑源文件

您可以永久地将值应用于(长期运行的)服务。

> sudo systemctl set-property fast.service IOWeight=400
> sudo systemctl set-property slow.service IOWeight=50
> sudo systemctl set-property throttled.service IOReadBandwidthMax="/dev/sda 1M"

或者,您可以将 I/O 控制应用于单个命令,例如

> sudo systemd-run --scope -p IOWeight=400 high_prioritized_command
> sudo systemd-run --scope -p IOWeight=50 low_prioritized_command
> sudo systemd-run --scope -p IOReadBandwidthMax="/dev/sda 1M" dd if=/dev/sda of=/dev/null bs=1M count=10

10.5.3 I/O 控制行为和设置期望 编辑源文件

以下列表项描述了 I/O 控制行为,以及在不同条件下您应该期望的结果。

  • I/O 控制最适用于直接 I/O 操作(绕过页面缓存),在实际 I/O 与调用者分离的情况下(通常通过页面缓存进行写回),可能会表现出各种情况。例如,延迟的 I/O 控制,甚至没有观察到的 I/O 控制(考虑小的突发或同时发生且永远不会 相遇, 同时提交 I/O 的竞争工作负载)。出于这些原因,结果的吞吐量比率并不严格遵循配置权重的比率。

  • systemd 会缩放配置的权重(以调整较窄的 BFQ 权重范围),因此结果的吞吐量比率也不同。

  • 写回活动取决于脏页的数量,以及全局 sysctl 旋钮(vm.dirty_background_ratiovm.dirty_ratio)。当脏限制在 cgroup 之间分发时,单个 cgroup 的内存限制会发挥作用,这反过来可能会影响受影响 cgroup 的 I/O 强度。

  • 并非所有存储都是一样的。I/O 控制发生在 I/O 调度器层,这会对堆叠在其之上的设备产生影响,这些设备不执行实际的调度。考虑设备映射器逻辑卷跨多个物理设备,MD RAID,甚至 Btrfs RAID。对这些设置进行 I/O 控制可能具有挑战性。

  • 没有为读写分别设置比例 I/O 控制的单独设置。

  • 比例 I/O 控制只是可以相互影响的策略之一(但负责任的资源设计或许可以避免这种情况)。

  • I/O 设备带宽并非 I/O 路径上唯一的共享资源。全局文件系统结构也参与其中,这与 I/O 控制旨在保证特定带宽有关;它并不能保证,甚至可能导致优先级反转(优先级较高的 cgroup 等待优先级较低的 cgroup 的事务)。

  • 到目前为止,我们一直在讨论文件系统数据的显式 I/O,但交换(swap-in)和换出(swap-out)也可以被控制。虽然如果出现这种需求,则表明内存配置不当(或内存限制)。

10.5.4 用户会话中的资源控制 编辑源文件

为了在用户会话中应用 cgroup 资源控制,必须将控制器委托给 systemd 的用户实例。 openSUSE Leap 默认配置的 systemd 不会委托任何控制器。

您可以使用 drop-in 文件来更改委托的控制器集合。例如,/etc/systemd/system/user@.service.d/60-delegate.conf 将控制器添加到所有用户,而 /etc/systemd/system/user@uid.service.d/60-delegate.conf 仅将控制器添加到特定用户。该文件的内容应如下所示

[Service]
Delegate=pids memory

必须通知 systemd 实例和受影响的用户实例以重新加载新的配置。

> sudo systemctl daemon-reload
> systemctl --user daemon-reexec

或者,受影响的用户可以注销并重新登录,而不是第二行来重启他们的用户实例。

10.6 更多信息 编辑源文件

打印此页面