使用 systemd 限制系统资源的使用
source link: https://arstercz.com/使用-systemd-限制系统资源的使用/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
简单介绍
在基于 Linux-3.x 内核版本的很多发行版都提供了 Systemd 来管理系统和服务. 同时也将 cgroup 功能加到了 slice, scope 和 service 三个单元中, 详见 sec-Default_Cgroup_Hierarchies . 基于这些特性我们可以很方便的通过 systemd 来限制服务或者进程对系统资源的使用, 这在单主机多服务的场景下会很有用. 下面则以 MySQL 服务为例介绍如何使用 systemd 限制资源的使用, 其它服务的限制和此等同.
示例使用
以 Centos7 系统为例, 从 redhat-resource-control 的文档来看, 官方建议通过 service 来实现资源的限制, 所以这里我们增加可以带端口参数(如果单台主机有多个 MySQL 实例的话)启动的 mysql 服务:
# cat /usr/lib/systemd/system/[email protected] [Unit] Description=MySQL Server node%i [Service] Type=forking Environment="PORT_ARGS=%I" PermissionsStartOnly=true ExecStart=/usr/local/mysqlnode/bin/node ${PORT_ARGS} start ExecStop=/usr/local/mysqlnode/bin/node ${PORT_ARGS} stop [Install] WantedBy=multi-user.target
上述服务以 fork 方式启动服务, @
符号之后的端口号即为相应的端口参数, 启动后查看对应服务状态:
# systemctl start mysql@3327 # systemctl status mysql@3327 ● [email protected] - MySQL Server node3327 Loaded: loaded (/usr/lib/systemd/system/[email protected]; disabled; vendor preset: disabled) Active: active (running) since Fri 2018-12-07 21:31:32 CST; 4s ago Process: 58084 ExecStart=/usr/local/mysqlnode/bin/node ${PORT_ARGS} start (code=exited, status=0/SUCCESS) Main PID: 58159 (mysqld_safe) CGroup: /system.slice/system-mysql.slice/[email protected] ├─58159 /bin/sh /opt/Percona-Server-5.6.38-rel83.0-Linux.x86_64.ssl101//bin/mysqld_safe --defaults-file=/export/mysql/node3327/my.node.cnf ├─59489 /opt/Percona-Server-5.6.38-rel83.0-Linux.x86_64.ssl101/bin/mysqld --defaults-file=/export/mysql/node3327/my.node.cnf --basedir=/opt/Percona-Server-5.6.38-rel83.0-Linux.x86_64.ssl101 --datadir=/export/mysql/node3327/... └─59490 logger -t mysqld-3327 -p daemon.error
通过 systemd 增加 cgroup 限制,可以一次设置单项属性值, 也可以一次设置多项:
# systemctl set-property [email protected] MemoryLimit=5G # 5G 内存 # systemctl set-property [email protected] CPUQuota=150% # 150% cpu 使用率 # systemctl set-property [email protected] BlockIOWeight=1000 # IO 权重 # systemctl status mysql@3327 ● [email protected] - MySQL Server node3327 Loaded: loaded (/usr/lib/systemd/system/[email protected]; disabled; vendor preset: disabled) Drop-In: /etc/systemd/system/[email protected] └─50-MemoryLimit.conf Active: active (running) since Fri 2018-12-07 21:31:32 CST; 1min 18s ago Process: 58084 ExecStart=/usr/local/mysqlnode/bin/node ${PORT_ARGS} start (code=exited, status=0/SUCCESS) Main PID: 58159 (mysqld_safe) Memory: 1.3M (limit: 5G) # 内存限制 5G CGroup: /system.slice/system-mysql.slice/[email protected] ├─58159 /bin/sh /opt/Percona-Server-5.6.38-rel83.0-Linux.x86_64.ssl101//bin/mysqld_safe --defaults-file=/export/mysql/node3327/my.node.cnf ├─59489 /opt/Percona-Server-5.6.38-rel83.0-Linux.x86_64.ssl101/bin/mysqld --defaults-file=/export/mysql/node3327/my.node.cnf --basedir=/opt/Percona-Server-5.6.38-rel83.0-Linux.x86_64.ssl101 --datadir=/export/mysql/node3327/... └─59490 logger -t mysqld-3327 -p daemon.error
更多属性参见 man systemd.resource-control
, 不过一些参数没有对应的属性, 需要手动单独设置, 比如设置单独某个服务的 memory + swap
限制, 可以使用以下命令将限制的字节数写到对应的参数文件中:
echo xxxxxx > memory.memsw.limit_in_bytes
查看 MySQL 进程 cgroup 信息, 可以看到 memory, blkid, cpuacct 三个条目对应的信息:
# cat /proc/59489/cgroup 11:memory:/system.slice/system-mysql.slice/[email protected] 10:devices:/system.slice/system-mysql.slice 9:cpuset:/ 8:blkio:/system.slice/system-mysql.slice/[email protected] 7:perf_event:/ 6:hugetlb:/ 5:freezer:/ 4:cpuacct,cpu:/system.slice/system-mysql.slice 3:pids:/system.slice/system-mysql.slice 2:net_prio,net_cls:/ 1:name=systemd:/system.slice/system-mysql.slice/[email protected]
查看进程相关的限制值:
# cat /sys/fs/cgroup/memory/system.slice/system-mysql.slice/mysql\@3327.service/memory.limit_in_bytes 5368709120 # cat /sys/fs/cgroup/blkio/system.slice/system-mysql.slice/mysql\@3327.service/blkio.weight 1000 # cat /sys/fs/cgroup/cpu/system.slice/system-mysql.slice/mysql\@3327.service/cpu.cfs_quota_us 150000
简单验证
这里仅以不同的 CPUQuota 为例说明, 如下所示可以看到, MySQL 进程在不同 CPUQuota 限制下的不同表现, benchyou 的压测结果也相差较大.
限制进程 CPUQuota 为 150% 的情况下:
# top -p 59489 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 59489 mysql 20 0 3412052 1.468g 8784 S 149.5 2.3 7:08.22 mysqld # benchyou --oltp-tables-count=256 --read-threads=30 --update-threads 8 --write-threads 6 --delete-threads=5 --mysql-table-engine=innodb .. time thds tps wtps rtps rio rio/op wio wio/op rMB rKB/op wMB wKB/op cpu/op freeMB cacheMB w-rsp(ms) r-rsp(ms) total-number [13s] [r:30,w:6,u:8,d:5] 3323 304 3019 0 0.00 0 0.00 0.00 0.00 0.00 0.00 0.00 0 0 62.56 9.92 40765 time thds tps wtps rtps rio rio/op wio wio/op rMB rKB/op wMB wKB/op cpu/op freeMB cacheMB w-rsp(ms) r-rsp(ms) total-number [14s] [r:30,w:6,u:8,d:5] 3319 325 2994 0 0.00 0 0.00 0.00 0.00 0.00 0.00 0.00 0 0 57.21 9.99 44084
限制进程 CPUQuota 为 400% 情况下:
# top -p 59489 PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 59489 mysql 20 0 3416472 1.474g 8796 S 400.0 2.4 7:47.42 mysqld # benchyou --oltp-tables-count=256 --read-threads=30 --update-threads 8 --write-threads 6 --delete-threads=5 --mysql-table-engine=innodb .. time thds tps wtps rtps rio rio/op wio wio/op rMB rKB/op wMB wKB/op cpu/op freeMB cacheMB w-rsp(ms) r-rsp(ms) total-number [10s] [r:30,w:6,u:8,d:5] 10547 967 9580 0 0.00 0 0.00 0.00 0.00 0.00 0.00 0.00 0 0 19.49 3.12 96270 time thds tps wtps rtps rio rio/op wio wio/op rMB rKB/op wMB wKB/op cpu/op freeMB cacheMB w-rsp(ms) r-rsp(ms) total-number [11s] [r:30,w:6,u:8,d:5] 10829 1036 9793 0 0.00 0 0.00 0.00 0.00 0.00 0.00 0.00 0 0 18.23 3.04 107099
会话级别限制
如果没有以 service 启动, 可以按照 pid 查看会话级别的信息:
# systemctl status 303 # 303 为 mysql 进程 id ● session-31208.scope - Session 31208 of user root
session-31208.scope
即为会话级别的信息, 一个会话可能包含多个 MySQL 进程, 使用上述的 systemctl set-property session-31208.scope XXXX
即可对整个会话的进程进行相关的限制. 当然使用这种方式即是对多个进程总体使用情况的限制.
其它限制
如果要单独限制 1 个进程 id, 则需要借助 libcgroup 提供的工具, 具体的使用同 Centos6 的设置, 不过 Centos7 已经弃用了 libgcgroup-tools, 不再建议使用, 如果要对单独进程进行限制, 最好使用 service 进行启动. 另外从 systemd 提供的 ControlGroupInterface
来看, 其提供的控制选项还不够精细, 比如没有 memsw, cpuset 等设置的属性, 这种情况下如果有限制的需求, 还需要靠和以前一样的 libcgroup-tool 方式来设置, 比如以下设置, 限制 pid 为 59489 的进程仅使用 cpu 0 ~ 5, mem 可以是 cpu node0 或 node1, cgclassify 没有指定 --sticky
选项的话则 tasks 会包含指定进程的子进程信息:
# cgcreate -g cpuset:[email protected] # cgset -r cpuset.cpus=0-5 [email protected] # cgset -r cpuset.mems=0-1 [email protected] # cgclassify -g cpuset:[email protected] 59489
当然也可以使用红帽知识库的方式在启动进程的时候就限制相应的 cpuset 等选项, 详见 redhat-1445073
参考
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK