cgroup 目录操作技巧
嵌套结构需要后序递归删除
[xiaochu.yh ~/tools/cgroup] $rmdir /sys/fs/cgroup/cpu/oceanbase/deadloop2
rmdir: failed to remove ‘/sys/fs/cgroup/cpu/oceanbase/deadloop2’: Device or resource busy
[xiaochu.yh ~/tools/cgroup] $
# 先删 child,才能删 parent
[xiaochu.yh ~/tools/cgroup] $rmdir /sys/fs/cgroup/cpu/oceanbase/deadloop2/child1
[xiaochu.yh ~/tools/cgroup] $rmdir /sys/fs/cgroup/cpu/oceanbase/deadloop2/child2
[xiaochu.yh ~/tools/cgroup] $rmdir /sys/fs/cgroup/cpu/oceanbase/deadloop2
继承属性:
# 初始化 cgroup 时检查 oceanbase/cpuset.cpus 是否设置,如果未设置,则执行
cat /sys/fs/cgroup/cpu/cpuset.cpus > /sys/fs/cgroup/cpu/oceanbase/cpuset.cpus
cat /sys/fs/cgroup/cpu/cpuset.mems > /sys/fs/cgroup/cpu/oceanbase/cpuset.mems
# 开启 oceanbase 这个组的继承属性
# 后面创建的任何子 group 都无需再设置 cpuset.mems 和 cpuset.cpus,简化操作
echo 1 > /sys/fs/cgroup/cpu/oceanbase/cgroup.clone_children
多个子系统,可以指向同一个目录。取决于 mount 命令。
A 机器上的 效果:
[xiaochu.yh ~/tools/cgroup] $ll /sys/fs/cgroup/
total 0
drwxr-xr-x 3 root root 0 May 7 18:59 blkio
lrwxrwxrwx 1 root root 33 May 7 18:59 cpu -> /sys/fs/cgroup/cpuset,cpu,cpuacct
lrwxrwxrwx 1 root root 33 May 7 18:59 cpuacct -> /sys/fs/cgroup/cpuset,cpu,cpuacct
lrwxrwxrwx 1 root root 33 May 7 18:59 cpuset -> /sys/fs/cgroup/cpuset,cpu,cpuacct
drwxr-xr-x 4 root root 0 Aug 20 18:04 cpuset,cpu,cpuacct
drwxr-xr-x 3 root root 0 May 7 18:59 devices
drwxr-xr-x 2 root root 0 May 7 18:59 freezer
drwxr-xr-x 2 root root 0 May 7 18:59 hugetlb
drwxr-xr-x 2 root root 0 Apr 19 15:44 intel_rdt
drwxr-xr-x 3 root root 0 May 7 18:59 memory
drwxr-xr-x 2 root root 0 May 7 18:59 net_cls
drwxr-xr-x 2 root root 0 May 7 18:59 perf_event
drwxr-xr-x 2 root root 0 May 7 18:59 pids
drwxr-xr-x 3 root root 0 May 7 18:59 systemd
$mount | grep cpu
cgroup on /sys/fs/cgroup/cpuset,cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu,cpuset)
B 机器上的效果:
$ll /sys/fs/cgroup/
total 0
drwxr-xr-x 5 root root 0 Jun 24 2019 blkio
lrwxrwxrwx 1 root root 11 Jun 24 2019 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 Jun 24 2019 cpuacct -> cpu,cpuacct
drwxr-xr-x 8 root root 0 Jun 24 2019 cpu,cpuacct
drwxr-xr-x 3 root root 0 Jun 24 2019 cpuset
drwxr-xr-x 4 root root 0 Jun 24 2019 devices
drwxr-xr-x 2 root root 0 Jun 24 2019 freezer
drwxr-xr-x 2 root root 0 Jun 24 2019 hugetlb
drwxr-xr-x 7 root root 0 Jun 24 2019 memory
drwxr-xr-x 2 root root 0 Jun 24 2019 net_cls
drwxr-xr-x 2 root root 0 Jun 24 2019 perf_event
drwxr-xr-x 4 root root 0 Jun 24 2019 systemd
$ll /sys/fs/cgroup/cpuset
total 0
drwxr-xr-x 3 root root 0 Aug 27 2019 agent
-rw-r--r-- 1 root root 0 Jun 24 2019 cgroup.clone_children
--w--w--w- 1 root root 0 Jun 24 2019 cgroup.event_control
-rw-r--r-- 1 root root 0 Jun 24 2019 cgroup.procs
-r--r--r-- 1 root root 0 Jun 24 2019 cgroup.sane_behavior
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.cpu_exclusive
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.cpus
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.mem_exclusive
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.mem_hardwall
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.memory_migrate
-r--r--r-- 1 root root 0 Jun 24 2019 cpuset.memory_pressure
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.memory_pressure_enabled
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.memory_spread_page
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.memory_spread_slab
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.mems
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.sched_load_balance
-rw-r--r-- 1 root root 0 Jun 24 2019 cpuset.sched_relax_domain_level
-rw-r--r-- 1 root root 0 Jun 24 2019 notify_on_release
-rw-r--r-- 1 root root 0 Jun 24 2019 release_agent
-rw-r--r-- 1 root root 0 Jun 24 2019 tasks
$mount | grep cpu
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
实验效果
# 分别启动 3 个 进程
./a.out deadloop2 100
./a.out deadloop2/child1 100
./a.out deadloop2/child2 100
背后对应了3组命令序列:
mkdir /sys/fs/cgroup/cpu/oceanbase/deadloop2/;
echo 5 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/cpuset.cpus
echo 0 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/cpuset.mems
echo 50000 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/cpu.cfs_quota_us
mkdir /sys/fs/cgroup/cpu/oceanbase/deadloop2/child1;
echo 5 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/child1/cpuset.cpus
echo 0 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/child1/cpuset.mems
echo 50000 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/child1/cpu.cfs_quota_us
mkdir /sys/fs/cgroup/cpu/oceanbase/deadloop2/child2;
echo 5 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/child2/cpuset.cpus
echo 0 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/child2/cpuset.mems
echo 50000 > /sys/fs/cgroup/cpu/oceanbase/deadloop2/child2/cpu.cfs_quota_us
这时,三个进程均占用 1/3 CPU,总大小为 50%。其中 50% 是由 cpu.cfs_quota_us 定义。
改进实验
如果我希望建立优先级,deadloop2 执行的时候, child1、child2 都不执行,当 deadloop2 退出时,child1、child2 分配 cpu 资源。
在 cgroup 下能否实现?用 cpu.shares 就行。
费解
87209 xiaochu. 20 0 9376 128 0 R 56.8 0.0 0:11.03 ./a.out deadloop/child1 4000
86104 xiaochu. 20 0 9376 128 0 R 28.6 0.0 1:04.57 ./a.out deadloop/child2 2000
87253 xiaochu. 20 0 9376 124 0 R 14.6 0.0 0:02.32 ./a.out deadloop 20000
顶层的 share 会优先分给 child,然后再满足顶层需求。
搞明白了
10932 xiaochu. 20 0 9376 120 0 R 66.8 0.0 3:14.17 ./a.out deadloop2 200
10696 xiaochu. 20 0 9376 128 0 R 20.9 0.0 1:32.62 ./a.out deadloop/child1 1900
9732 xiaochu. 20 0 9376 124 0 R 11.3 0.0 2:28.04 ./a.out deadloop 100
10609 xiaochu. 20 0 9376 124 0 R 1.0 0.0 0:05.83 ./a.out deadloop/child2 100
逻辑是这样的:
- 同层,按照同层的 shares 来分 cpu。比如:
deadloop2 占 66%; deadloop 33%。 - 比较费解的部分:deadloop 33% 怎么分给 child1, child2, deadloop 自己?
- 33% 3 个人分
- deadloop 上没有定义任何值(100 是用来和 200 比的,比完就作废)
- 算法是基准为 1024 即:parent 的 shares 总是 1024
- deadloop 占 1024, child1 占 1900, child2 占 100, total = 1024+1900+100 = 3024。
- 所以
deadloop = 33% * 1024 / 3024 = 11.2%
;child1 = 33% * 1900 / 3024 = 20.7%
;child2 = 1.1%
和 上面的截图相符合。
再来个例子:
10932 xiaochu. 20 0 9376 120 0 R 66.8 0.0 72:35.65 ./a.out deadloop2 200
9732 xiaochu. 20 0 9376 124 0 R 25.6 0.0 14:19.96 ./a.out deadloop 100
42711 xiaochu. 20 0 9376 120 0 R 5.0 0.0 0:02.20 ./a.out deadloop/child1 200
10609 xiaochu. 20 0 9376 124 0 R 2.7 0.0 1:15.36 ./a.out deadloop/child2 100
第一层,200:100,所以 cpu 是 66.8% : 32.3%
第二层,deadloop 是 1024;1024+200+100,然后分,得到 cpu 是 25.6%, 5%, 2.5%
尚存的疑惑
但是,这仅仅适用于单线程程序。如果程序变成多线程,又是一番景象! ./thread有20 个工作线程,shares 都设置为 1024,cpu 效果如下:
这个暂时没有找到合理的解释。
再举个栗子:把 ./thread 代码改一下,改成内部启动 4 个工作线程的版本,shares 依然都是 1024:
child 和 parent 的 cpu 比例是 1:4。难以解释把?
Best Practice
建议 cgroup 在 deadloop 那一层不要跑任何程序,上面配置的 shares 只用于和其它兄弟层级做 cpu 配比。
附录
程序如下,为自己在 cgroup 中创建一个目录,并开始死循环压 CPU。
// [xiaochu.yh ~/tools/cgroup] $cat main.c
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#define STACK_SIZE (1024 * 1024)
int pipefd[2];
static char container_stack[STACK_SIZE];
int container_main(void* arg)
{
char ch;
int i = 0;
close(pipefd[1]);
read(pipefd[0], &ch, 1);
printf("start\n");
for(;;)i++;
return 1;
}
int main(int argc, char** argv)
{
if (argc != 3) {
printf("Wrong Arg. specify hierachy\n");
return 1;
}
char *h = argv[1];
char *quota = argv[2];
char cmd[128];
printf("Parent - start a container!\n");
/* 设置CPU利用率为50% */
sprintf(cmd, "/sys/fs/cgroup/cpu/oceanbase/%s/", h);
mkdir(cmd, 0755);
sprintf(cmd, "echo 5 > /sys/fs/cgroup/cpu/oceanbase/%s/cpuset.cpus", h);
printf("run cmd:%s!\n", cmd);
system(cmd);
sprintf(cmd, "echo 0 > /sys/fs/cgroup/cpu/oceanbase/%s/cpuset.mems", h);
printf("run cmd:%s!\n", cmd);
system(cmd);
// sprintf(cmd, "echo %s > /sys/fs/cgroup/cpu/oceanbase/%s/cpu.cfs_quota_us", quota, h);
sprintf(cmd, "echo %s > /sys/fs/cgroup/cpu/oceanbase/%s/cpu.shares", quota, h);
printf("run cmd:%s!\n", cmd);
system(cmd);
pipe(pipefd);
/* 调用clone函数,其中传出一个函数,还有一个栈空间的(为什么传尾指针,因为栈是反着的) */
int container_pid = clone(container_main, container_stack+STACK_SIZE, SIGCHLD ,NULL);
sprintf(cmd, "echo %d >> /sys/fs/cgroup/cpu/oceanbase/%s/tasks",container_pid, h);
printf("PID:%d!\n", container_pid);
system(cmd);
close(pipefd[1]);
waitpid(container_pid, NULL, 0);
printf("Parent - container stopped!\n");
return 0;
}
参考
https://www.infoq.cn/article/docker-kernel-knowledge-cgroups-resource-isolation