linux cgroup 限制cpu、memory、iops使用率
linux 环境下进程对资源的使用通常是不受控制的,极端情况下进程将主机所有资源耗尽,导致系统 hang 住,运维人员无法登录主机,即使能够登录上去,操作也无响应。通过 linux cgroup 机制可以限制进程的资源使用率,进程与进程之间进行资源隔离,这里的资源主要包括 cpu、memory、iops。
1. 安装依赖包(root用户)
yum install libcgroup-tools
2. 修改配置文件(root用户)
vim /etc/cgconfig.conf
group pg_resource_limit { perm { task { uid = pg; gid = pg; fperm = 774; } admin { uid = pg; gid = pg; dperm = 775; fperm = 774; } } cpu { cpu.cfs_period_us = 100000; cpu.cfs_quota_us = 10000; } memory { memory.limit_in_bytes = 10M; memory.memsw.limit_in_bytes = 10M; } blkio { blkio.throttle.read_iops_device = "253:0 1048576"; blkio.throttle.write_iops_device = "253:0 1048576"; } }
上述配置文件的 uid 和 gid 为启动程序的用户,非 root,配置信息格式一定要保证正确,不能有多余的空格或制表符,否则会报错。
(1)CPU 使用率限制
- cpu.cfs_period_us,用来配置时间周期长度,单位是 us,取值范围 1000~1000000,即 1ms ~ 1s
- cpu.cfs_quota_us:用来配置当前 cgroup 在设置的周期长度内所能使用的 CPU 时间数,单位 us,最小值为 1000 即 1ms
cfs 是完全公平调度策略,cpu.cfs_period_us 和 cpu.cfs_quota_us 值根据主机 CPU 数量进行设置。对于多核 CPU,假设主机有 100 个 CPU 核心,限制使用 CPU 总能力的 10%(每 100ms 能使用 1000ms 的 CPU 时间,即使用 10 个 CPU 核心),如下:
cpu.cfs_period_us = 100000 cpu.cfs_quota_us = 1000000
(2)Memory 使用率限制
- memory.limit_in_bytes 参数限制了可以使用的内存大小,单位为字节
- memory.memsw.limit_in_bytes 参数限制了可以使用的 swap 交换内存的大小,单位为字节
(3)IO 使用率限制
- blkio.throttle.read_iops_device 表示限制读 IO 的使用率,253:0 表示设备编号,可以通过 ls -l /dev/dm-0 命令获取磁盘设备编号,1048576 表示 IO 读取速度 1MB/s
- blkio.throttle.write_iops_device 表示限制写 IO 的使用率
(4)使配置生效
配置生效: /usr/sbin/cgconfigparser -l /etc/cgconfig.conf -s 1664
开机自动启动 cgconfig 服务: systemctl enable cgconfig
启动 cgconfig 服务: systemctl start cgconfig
生效后确认以下目录属主为用户 pg:
- /sys/fs/cgroup/cpu/pg_resource_limit
- /sys/fs/cgroup/memory/pg_resource_limit
- /sys/fs/cgroup/blkio/pg_resource_limit
3. 测试 cgroup 限制资源使用率
切换到 pg 用户,执行以下测试:
(1)cpu 使用率测试
写个简单的 C 程序,无限循环,如下:
#include <stdio.h> int main(int argc, char *argv[]) { while(1); return 0; }
使用 cgexec 执行执行以上程序,查看 CPU 使用率,值为 10%,如下:
cgexec -g cpu:pg_resource_limit ./a.out
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 2160 pg 20 0 4212 352 276 R 10.3 0.0 0:02.46 ./a.out
(2)memory 使用率测试
写个简单的 C 程序,不断的分配内存,测试 memory 使用率,如下:
#include <stdio.h> int main(int argc, char *argv[]) { int all = 0; while(1) { char *p = malloc(1024); all += 1024; printf("memory size:%d\n",all); } return 0; }
使用 cgexec 启动程序:
cgexec -g memory:pg_resource_limit ./a.out
运行一段时间,程序被 kill,最后一次输出的申请的内存总大小为 10MB,如下:
memory size:10230784 Killed
(3)io 使用率测试
使用 cgexec 执行 dd 命令,测试 iops 使用率。
cgexec -g blkio:pg_resource_limit dd if=/tmp/1.log of=/tmp/2.log
在测试环境貌似 io 使用率限制没有成功,查找相关资料,了解到 blkio 只支持 Direct I/O 的场景,对于 Buffered I/O 的文件读写无法限制。因此不能使用
dd 加上 direct 参数,再次测试,IO 速度从正常的 11.9 MB/s 降到 559 kB/s:
[pg@centos ~]$ dd oflag=direct if=/tmp/1.log of=/tmp/2.log 1000000+0 records in 1000000+0 records out 512000000 bytes (512 MB) copied, 43.1928 s, 11.9 MB/s [pg@centos ~]$ cgexec -g blkio:pg_resource_limit dd oflag=direct if=/tmp/1.log of=/tmp/2.log 1000000+0 records in 1000000+0 records out 512000000 bytes (512 MB) copied, 915.501 s, 559 kB/s