• 关于Linux中如何使用 systemd-run创建临时Cgroup来限制ad-hoc的资源消耗


    写在前面


    • 分享一些临时命令资源限制的笔记
    • 博文内容涉及:
      • systemd-run 限制 ad-hoc 资源消耗基本原理
      • 前后台ad-hoc资源限制demo
    • 理解不足小伙伴帮忙指正

    地球上人的博爱将只可能以媚俗作态为基础--------《生命中不能承受之轻》


    简单介绍

    通过 systemd-run 命令我们可以创建一个临时的cgroup并且可以在这个cgroup中运行临时命令。从而达到对资源的限制。

    这里其实是把临时命令封装为一个service 或者 scope 单元(systemd 的资源单位类型为:service、scope、slice),然后单元放到了 创建的 cgroup层级下(slice)用于资源管理。

    • service : 一个或一组进程,由 systemd 依据单位配置文件启动。service 对指定进程进行封装,这样进程可以作为一个整体被启动或终止。
    • scope : 一组外部创建的进程。由强制进程通过 fork() 函数启动和终止、之后被 systemd 在运行时注册的进程,scope 会将其封装。例如:用户会话、 容器和虚拟机被认为是 scope。
    • slice : 一组按层级排列的单位。slice 并不包含进程,但会组建一个层级,并将 scope 和 service 都放置其中。真正的进程包含在 scope 或 service 中。在这一被划分层级的树中,每一个 slice 单位的名字对应通向层级中一个位置的路径。小横线(“-”)起分离路径组件的作用。

    Servicescope 单元做资源限制,也就是我们的临时命令,是通过指定单元中的属性来实现的。通过 -p 来传递

    systemd-run -p MemoryLimit=5M --unit=name --scope --slice=slice_name command

    当指定为 scope 的时候,作为前台进程存在的。命令如果有输出,会直接打印出来,即换句话讲,它是同步的,直接从 systemd-run 进程中启动。

    systemd-run -p MemoryLimit=5M --unit=name --slice=slice_name command

    当不指定为 scope ,默认是作为 service 存在。即后台非同步启动进程。它们从 systemd 进程中被调用

    • --unit=name 为单元生成的名字
    • --slice=slice_name: 为生成的 cgroup 层级的名字

    -p MemoryLimit=5M 即向对应单元传递一个内存限制的参数,它等价于下面的操作

    # 如需使用命令列来限定 httpd.service 的 CPU 和内存占用量,请输入:
    systemctl set-property httpd.service CPUShares=600 MemoryLimit=500M
    # 如希望此更改为临时更改,请添加 --runtime 选项:
    systemctl set-property --runtime httpd.service CPUShares=600 MemoryLimit=500M
    
    • 1
    • 2
    • 3
    • 4

    其他的参数可以通过帮忙文档 查看 man systemd-run

    因为是临时生成,所以 通过上面的方式生成的 单元文件,默认在 API文件系统 /run 下, 生命周期和临时的进程周期相同。

    前台进程

    同步进程

    前台进程一种是需要设置 --scope,指定为一个scope资源,除非命令运行结束或者强制执行,否则会一直挂在前台

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemd-run -p  MemoryLimit=5M  -p CPUShares=100 --unit=sleep-10  --scope  --slice=test  sleep 10
    Running scope as unit sleep-10.scope.
    ┌──[root@liruilongs.github.io]-[~]
    └─$
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上面为 执行一个 sleep 10 的临时命令。对内存限制为5M。CPU限制为100m.,当前的 scope 资源单元为
    sleep-10.scope. ,分配的 slice 为 test

    上面 的命令会这10秒后结束 ,对应的他的单元文件也会随之消失

    允许被运行的命令访问终端

    另一种是通过-t 命令将当前 bash 放到 service 单元中,

    以临时服务的方式运行 /bin/bash 命令, 并将其标准输入、标准输出、标准错误连接到当前的 TTY 设备上:

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemd-run  -p  MemoryLimit=5M  -p CPUShares=100 --unit=bash-limit   --slice=bash-test -t /bin/bash
    Running as unit bash-limit.service.
    Press ^] three times within 1s to disconnect TTY.
    
    • 1
    • 2
    • 3
    • 4

    在生成的 bash Service 中我们可以运行交互命令,查看当前 Service 的单元文件

    ┌──[root@liruilongs.github.io]-[/]
    └─$ systemctl cat bash-limit.service
    # /run/systemd/system/bash-limit.service
    # Transient stub
    
    # /run/systemd/system/bash-limit.service.d/50-CPUShares.conf
    [Service]
    CPUShares=100
    # /run/systemd/system/bash-limit.service.d/50-Description.conf
    [Unit]
    Description=/bin/bash
    # /run/systemd/system/bash-limit.service.d/50-Environment.conf
    [Service]
    Environment="TERM=xterm-256color"
    # /run/systemd/system/bash-limit.service.d/50-ExecStart.conf
    [Service]
    ExecStart=
    ExecStart=@/bin/bash "/bin/bash"
    # /run/systemd/system/bash-limit.service.d/50-MemoryLimit.conf
    [Service]
    MemoryLimit=5242880
    # /run/systemd/system/bash-limit.service.d/50-Slice.conf
    [Service]
    Slice=bash-test.slice
    # /run/systemd/system/bash-limit.service.d/50-StandardError.conf
    [Service]
    StandardError=tty
    # /run/systemd/system/bash-limit.service.d/50-StandardInput.conf
    [Service]
    StandardInput=tty
    # /run/systemd/system/bash-limit.service.d/50-StandardOutput.conf
    [Service]
    StandardOutput=tty
    # /run/systemd/system/bash-limit.service.d/50-TTYPath.conf
    [Service]
    TTYPath=/dev/pts/2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    通过 systemctl status bash-limit.service 我们可以看到cgroup的相关信息

    ┌──[root@liruilongs.github.io]-[/]
    └─$ systemctl status bash-limit.service
    ● bash-limit.service - /bin/bash
       Loaded: loaded (/run/systemd/system/bash-limit.service; static; vendor preset: disabled)
      Drop-In: /run/systemd/system/bash-limit.service.d
               └─50-CPUShares.conf, 50-Description.conf, 50-Environment.conf, 50-ExecStart.conf, 50-MemoryLimit.conf, 50-Slice.conf, 50-StandardError.conf, 50-StandardInput.conf, 50-StandardOutput.conf, 50-TTYPath.conf
       Active: active (running) since 六 2022-10-29 13:40:19 CST; 31s ago
     Main PID: 136529 (bash)
       Memory: 1.7M (limit: 5.0M)
       CGroup: /bash.slice/bash-test.slice/bash-limit.service
               ├─136529 /bin/bash
               └─136607 systemctl status bash-limit.service
    
    1029 13:40:19 liruilongs.github.io systemd[1]: Started /bin/bash.
    ┌──[root@liruilongs.github.io]-[/]
    └─$ bash
    ┌──[root@liruilongs.github.io]-[/]
    └─$ bash
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    ┌──[root@liruilongs.github.io]-[/]
    └─$  systemctl status bash-limit.service
    ● bash-limit.service - /bin/bash
       Loaded: loaded (/run/systemd/system/bash-limit.service; static; vendor preset: disabled)
      Drop-In: /run/systemd/system/bash-limit.service.d
               └─50-CPUShares.conf, 50-Description.conf, 50-Environment.conf, 50-ExecStart.conf, 50-MemoryLimit.conf, 50-Slice.conf, 50-StandardError.conf, 50-StandardInput.conf, 50-StandardOutput.conf, 50-TTYPath.conf
       Active: active (running) since 六 2022-10-29 13:40:19 CST; 48s ago
     Main PID: 136529 (bash)
       Memory: 4.3M (limit: 5.0M)
       CGroup: /bash.slice/bash-test.slice/bash-limit.service
               ├─136529 /bin/bash
               ├─136613 bash
               ├─136630 bash
               └─136667 systemctl status bash-limit.service
    
    1029 13:40:19 liruilongs.github.io systemd[1]: Started /bin/bash.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

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

    ┌──[root@liruilongs.github.io]-[/]
    └─$ systemctl disable bash-limit.service --now
    已终止
    
    • 1
    • 2
    • 3

    后台进程

    后台非守护进程

    后台非守护进程不需要 --scope 参数,在后台执行,默认是一个 service

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemd-run -p  MemoryLimit=5M  -p CPUShares=100 --unit=sleep-50 --slice=test sleep 50
    Running as unit sleep-50.service.
    ┌──[root@liruilongs.github.io]-[~]
    └─$
    
    • 1
    • 2
    • 3
    • 4
    • 5

    我们可以通过命令查看状态

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemctl status sleep-50.service
    ● sleep-50.service - /usr/bin/sleep 50
       Loaded: loaded (/run/systemd/system/sleep-50.service; static; vendor preset: disabled)
      Drop-In: /run/systemd/system/sleep-50.service.d
               └─50-CPUShares.conf, 50-Description.conf, 50-ExecStart.conf, 50-MemoryLimit.conf, 50-Slice.conf
       Active: active (running) since 六 2022-10-29 01:29:29 CST; 10s ago
     Main PID: 33234 (sleep)
       Memory: 92.0K (limit: 5.0M)
       CGroup: /test.slice/sleep-50.service
               └─33234 /usr/bin/sleep 50
    
    1029 01:29:29 liruilongs.github.io systemd[1]: Started /usr/bin/sleep 50.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    通过 systemdctl cat 命令可以看到当前资源的配置文件,

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemctl cat sleep-50.service
    # /run/systemd/system/sleep-50.service
    # Transient stub
    
    # /run/systemd/system/sleep-50.service.d/50-CPUShares.conf
    [Service]
    CPUShares=100
    # /run/systemd/system/sleep-50.service.d/50-Description.conf
    [Unit]
    Description=/usr/bin/sleep 50
    # /run/systemd/system/sleep-50.service.d/50-ExecStart.conf
    [Service]
    ExecStart=
    ExecStart=@/usr/bin/sleep "/usr/bin/sleep" "50"
    # /run/systemd/system/sleep-50.service.d/50-MemoryLimit.conf
    [Service]
    MemoryLimit=5242880
    # /run/systemd/system/sleep-50.service.d/50-Slice.conf
    [Service]
    Slice=test.slice
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    超过50秒。Service 正常退出

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemctl status sleep-50.service
    Unit sleep-50.service could not be found.
    ┌──[root@liruilongs.github.io]-[~]
    └─$
    
    • 1
    • 2
    • 3
    • 4
    • 5

    后台守护进程

    后台守护进程,需要一个一直运行的临时命令。不会死掉

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemd-run -p  MemoryLimit=5M  -p CPUShares=100 --unit=top-print --slice=test top -b
    
    • 1
    • 2

    查看状态

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemctl status top-print.service
    ● top-print.service - /usr/bin/top -b
       Loaded: loaded (/run/systemd/system/top-print.service; static; vendor preset: disabled)
      Drop-In: /run/systemd/system/top-print.service.d
               └─50-CPUShares.conf, 50-Description.conf, 50-ExecStart.conf, 50-MemoryLimit.conf, 50-Slice.conf
       Active: active (running) since 六 2022-10-29 00:48:54 CST; 1min 28s ago
     Main PID: 27206 (top)
       Memory: 824.0K (limit: 5.0M)
       CGroup: /test.slice/top-print.service
               └─27206 /usr/bin/top -b
    
    1029 00:50:15 liruilongs.github.io top[27206]: 20108 etcd      20   0   57692   7352   4444 S...res
    1029 00:50:15 liruilongs.github.io top[27206]: 21323 pcp       20   0   96024   4220   2592 S...ger
    1029 00:50:15 liruilongs.github.io top[27206]: 22386 postfix   20   0   89892   4116   3092 S...kup
    1029 00:50:15 liruilongs.github.io top[27206]: 23131 root      20   0       0      0      0 S.../5+
    1029 00:50:15 liruilongs.github.io top[27206]: 23139 root      20   0       0      0      0 S.../0+
    1029 00:50:15 liruilongs.github.io top[27206]: 23158 root      20   0    4492    644    560 S...lo+
    1029 00:50:15 liruilongs.github.io top[27206]: 24193 etcd      20   0   60024  10420   5532 S...res
    1029 00:50:15 liruilongs.github.io top[27206]: 24938 root      20   0    4364    360    292 S...eep
    1029 00:50:15 liruilongs.github.io top[27206]: 25475 root      20   0       0      0      0 S.../2+
    1029 00:50:15 liruilongs.github.io top[27206]: 25853 root      20   0       0      0      0 S.../1+
    Hint: Some lines were ellipsized, use -l to show in full.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    对应的资源文件

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemctl cat top-print.service
    # /run/systemd/system/top-print.service
    # Transient stub
    
    # /run/systemd/system/top-print.service.d/50-CPUShares.conf
    [Service]
    CPUShares=100
    # /run/systemd/system/top-print.service.d/50-Description.conf
    [Unit]
    Description=/usr/bin/top -b
    # /run/systemd/system/top-print.service.d/50-ExecStart.conf
    [Service]
    ExecStart=
    ExecStart=@/usr/bin/top "/usr/bin/top" "-b"
    # /run/systemd/system/top-print.service.d/50-MemoryLimit.conf
    [Service]
    MemoryLimit=5242880
    # /run/systemd/system/top-print.service.d/50-Slice.conf
    [Service]
    Slice=test.slice
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    查看归属,不同的Service。但是在一个同一个slice

    ┌──[root@liruilongs.github.io]-[~]
    └─$ systemd-cgls | head -n 7
    ├─1 /usr/lib/systemd/systemd --system --deserialize 13
    ├─test.slice
    │ ├─sleep-50.service
    │ │ └─67803 /usr/bin/sleep 50
    │ └─top-print.service
    │   └─27206 /usr/bin/top -b
    ├─docker
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    关于 如何使用 systemd-run 创建临时 Cgroup 来限制ad-hoc(临时命令)的资源消耗就和小伙伴分享到这里,更多参数特性请查看手册了解

    man systemd-run | cat
    
    • 1

    博文引用资源


    http://www.jinbuguo.com/systemd/systemd-run.html#

    https://access.redhat.com/documentation/zh-cn/red_hat_enterprise_linux/7/html-single/resource_management_guide/index

    https://liruilong.blog.csdn.net/article/details/120735766

    https://liruilong.blog.csdn.net/article/details/123941400

  • 相关阅读:
    网络协议--RARP:逆地址解析协议
    QSOP24封装的语音芯片优势列举
    推荐《咒术回战》
    【计算机视觉面经二】卷积神经网络中的理解:通道(channel)和空间(spatial)信息
    SpringFramework:Spring 概述
    kafka安装部署详解
    Linux下redis单机安装、主从搭建及哨兵模式搭建及springboot整合测试
    详细步骤记录:持续集成Jenkins自动化部署一个Maven项目
    标准输入流
    教程九 在Go中使用Energy创建跨平台GUI应用 - Go绑定变量JS调用
  • 原文地址:https://blog.csdn.net/sanhewuyang/article/details/127522198