35.4. 使用 cgroups-v1 为应用程序设置 CPU 限制

要使用 控制组版本 1 ( cgroups-v1)配置对应用程序的 CPU 限制,请使用 /sys/fs/ 虚拟文件系统。

先决条件

  • 有 root 权限。
  • 您有一个要限制其 CPU 消耗的应用程序。
  • 您将系统配置为,在系统引导过程中,默认由 systemd 系统和服务管理器挂载 cgroups-v1

    # grubby --update-kernel=/boot/vmlinuz-$(uname -r) --args="systemd.unified_cgroup_hierarchy=0 systemd.legacy_systemd_cgroup_controller"

    这会在当前引导条目中添加所需的内核命令行参数。

流程

  1. 识别您要限制 CPU 消耗的应用程序的进程 ID (PID):

    # top
    top - 11:34:09 up 11 min,  1 user,  load average: 0.51, 0.27, 0.22
    Tasks: 267 total,   3 running, 264 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 49.0 us,  3.3 sy,  0.0 ni, 47.5 id,  0.0 wa,  0.2 hi,  0.0 si,  0.0 st
    MiB Mem :   1826.8 total,    303.4 free,   1046.8 used,    476.5 buff/cache
    MiB Swap:   1536.0 total,   1396.0 free,    140.0 used.    616.4 avail Mem
    
      PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     6955 root      20   0  228440   1752   1472 R  99.3   0.1   0:32.71 sha1sum
     5760 jdoe      20   0 3603868 205188  64196 S   3.7  11.0   0:17.19 gnome-shell
     6448 jdoe      20   0  743648  30640  19488 S   0.7   1.6   0:02.73 gnome-terminal-
        1 root      20   0  245300   6568   4116 S   0.3   0.4   0:01.87 systemd
      505 root      20   0       0      0      0 I   0.3   0.0   0:00.75 kworker/u4:4-events_unbound
    ...

    这个 top 程序的示例输出显示, PID 6955 的说明性应用程序 sha1sum 消耗了大量 CPU 资源。

  2. cpu 资源控制器目录中创建子目录:

    # mkdir /sys/fs/cgroup/cpu/Example/

    此目录代表控制组,您可以在其中放置特定进程,并向进程应用某些 CPU 限制。同时,目录中将创建多个 cgroups-v1 接口文件和 cpu 特定于控制器的文件。

  3. 可选 :检查新创建的控制组:

    # ll /sys/fs/cgroup/cpu/Example/
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cgroup.clone_children
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cgroup.procs
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.stat
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_all
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu_sys
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_percpu_user
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_sys
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpuacct.usage_user
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.cfs_period_us
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.cfs_quota_us
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.rt_period_us
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.rt_runtime_us
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 cpu.shares
    -r—​r—​r--. 1 root root 0 Mar 11 11:42 cpu.stat
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 notify_on_release
    -rw-r—​r--. 1 root root 0 Mar 11 11:42 tasks

    这个示例输出显示文件,如 cpuacct.usagecpu.cfs._period_us,它们代表特定的配置和/或限值,可以为 Example 控制组中的进程设置。请注意,对应的文件名以它们所属的控制组控制器的名称为前缀。

    默认情况下,新创建的控制组继承对系统整个 CPU 资源的访问权限,且无限制。

  4. 为控制组群配置 CPU 限制:

    # echo "1000000" > /sys/fs/cgroup/cpu/Example/cpu.cfs_period_us
    # echo "200000" > /sys/fs/cgroup/cpu/Example/cpu.cfs_quota_us
    • cpu.cfs_period_us 文件表示以微秒为单位(这里表示为"us")的时段,用于控制组对 CPU 资源的访问权限应重新分配的频率。上限为 1 000 000 微秒,下限为 1 000 微秒。
    • cpu.cfs_quota_us 文件表示以微秒为单位的总时间量,控制组中的所有进程都可以在一个期间(如 cpu.cfs_period_us 定义)。当控制组中的进程在单个期间内使用完配额指定的所有时间时,在周期的剩余时间内,它们将被节流,并且不允许在下一个期间前运行。较低限制为 1 000 微秒。

      上面的示例命令设定 CPU 时间限值,使得 Example 控制组中的所有进程仅能每 1 秒( cpu.cfs_quota_us 定义)每 1 秒(由 cpu.cfs_period_us 定义)运行 0.2 秒。

  5. 可选 :验证限制:

    # cat /sys/fs/cgroup/cpu/Example/cpu.cfs_period_us /sys/fs/cgroup/cpu/Example/cpu.cfs_quota_us
    1000000
    200000
  6. 将应用程序的 PID 添加到 Example 控制组群中:

    # echo "6955" > /sys/fs/cgroup/cpu/Example/cgroup.procs

    此命令确保特定应用成为 Example 控制组的一员,因此不超过为 Example 控制组配置的 CPU 限值。PID 应该代表系统中的一个已存在的进程。这里的 PID 6955 分配给进程 sha1sum /dev/zero &,用于说明 cpu 控制器的用例。

验证

  1. 验证应用程序是否在指定的控制组群中运行:

    # cat /proc/6955/cgroup
    12:cpuset:/
    11:hugetlb:/
    10:net_cls,net_prio:/
    9:memory:/user.slice/user-1000.slice/user@1000.service
    8:devices:/user.slice
    7:blkio:/
    6:freezer:/
    5:rdma:/
    4:pids:/user.slice/user-1000.slice/user@1000.service
    3:perf_event:/
    2:cpu,cpuacct:/Example
    1:name=systemd:/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service

    此示例输出显示在 Example 控制组中运行的所需应用程序的进程,后者将 CPU 限制应用到应用程序的进程。

  2. 确定节流应用程序的当前 CPU 消耗:

    # top
    top - 12:28:42 up  1:06,  1 user,  load average: 1.02, 1.02, 1.00
    Tasks: 266 total,   6 running, 260 sleeping,   0 stopped,   0 zombie
    %Cpu(s): 11.0 us,  1.2 sy,  0.0 ni, 87.5 id,  0.0 wa,  0.2 hi,  0.0 si,  0.2 st
    MiB Mem :   1826.8 total,    287.1 free,   1054.4 used,    485.3 buff/cache
    MiB Swap:   1536.0 total,   1396.7 free,    139.2 used.    608.3 avail Mem
    
      PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
     6955 root      20   0  228440   1752   1472 R  20.6   0.1  47:11.43 sha1sum
     5760 jdoe      20   0 3604956 208832  65316 R   2.3  11.2   0:43.50 gnome-shell
     6448 jdoe      20   0  743836  31736  19488 S   0.7   1.7   0:08.25 gnome-terminal-
      505 root      20   0       0      0      0 I   0.3   0.0   0:03.39 kworker/u4:4-events_unbound
     4217 root      20   0   74192   1612   1320 S   0.3   0.1   0:01.19 spice-vdagentd
    ...

    请注意,PID 6955 的 CPU 消耗从 99% 减少到 20%。

注意

cpu.cfs_period_uscpu.cfs_quota_uscgroups-v2 的对应部分是 cpu.max 文件。cpu.max 文件可以通过 cpu 控制器获得。

其他资源