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

文章评论

0条评论