玩转 Cgroup 系列之三:挑战手动管理 Cgroup

在前面的文章中,作者讨论了 Cgroup 和 CPUShare 如何用于系统管理和性能调优。

在这一篇文章中,作者将重点介绍 Cgroup 的手动管理任务。虽然手动管理 Cgroup 不是一件容易的事,但了解其中的过程可以帮助我们更好地认识 Cgroup 和资源管理(点击参考原文)。

挑战手动管理 Cgroup

来看看如何在没有相关工具支持的情况下创建 Cgroup。

本质上, Cgroup 只是一个挂载有 cgroups 的目录结构,可以位于文件系统的任何位置。在默认情况下,我们可以在 /sys/fs/cgroup 中找到系统创建的 Cgroup。而如果想手动创建 Cgroup 该怎么做呢?首先,需要创建一个顶级目录:

bash 复制代码
# mkdir -p /my_cgroups

创建后,需要决定使用哪些控制器。注意,Cgroup v1 版本的结构大致如下:

bash 复制代码
/my_cgroups
├── <controller type>
│   ├── <group 1>
│   ├── <group 2>
│   ├── <group 3>

要创建的所有组都单独嵌套在每个控制器下。因此,控制器 memory 下的 group1 与控制器 blkio 下的 group1 是完全独立的。在这个基础上,我们创建一个基本的 CPUShares 示例。 简单起见,我先在系统上生成一些负载:

bash 复制代码
# cat /dev/urandom

这一步会在系统中产生一些人为负载,以便进行简单测算。它不是一个真实的负载示例,但是突出了 CPUShares 的主要特点。我还设置了一台运行 CentOS 8 的虚拟机,只有一个 vCPU,以便进行非常简单的数学计算。做好这些准备之后,第一步就是为我们的 Cgroup 控制器创建一些目录:

bash 复制代码
# mkdir -p /my_cgroups/{memory,cpusets,cpu}

接下来,将 Cgroup 挂载到这些文件夹中:

bash 复制代码
# mount -t cgroup -o memory none /my_cgroups/memory
# mount -t cgroup -o cpu,cpuacct none /my_cgroups/cpu
# mount -t cgroup -o cpuset none /my_cgroups/cpusets

如果想创建自己的 Cgroup,只需在您想要使用的控制器下创建一个新的目录就可以了。在这个例子中,我处理的是位于 cpu 目录中的文件 cpu.shares。下面我们在 cpu 控制器下创建一些 Cgroup:

bash 复制代码
# mkdir -p /my_cgroups/cpu/{user1,user2,user3}

请注意,这些目录是由控制器自动填充的:

bash 复制代码
ls -l /my_cgroup/cpu/user1/
-rw-r--r--. 1 root root 0 Sep  5 10:26 cgroup.clone_children
-rw-r--r--. 1 root root 0 Sep  5 10:26 cgroup.procs
-r--r--r--. 1 root root 0 Sep  5 10:26 cpuacct.stat
-rw-r--r--. 1 root root 0 Sep  5 10:26 cpuacct.usage
-r--r--r--. 1 root root 0 Sep  5 10:26 cpuacct.usage_all
-r--r--r--. 1 root root 0 Sep  5 10:26 cpuacct.usage_percpu
-r--r--r--. 1 root root 0 Sep  5 10:26 cpuacct.usage_percpu_sys
-r--r--r--. 1 root root 0 Sep  5 10:26 cpuacct.usage_percpu_user
-r--r--r--. 1 root root 0 Sep  5 10:26 cpuacct.usage_sys
-r--r--r--. 1 root root 0 Sep  5 10:26 cpuacct.usage_user
-rw-r--r--. 1 root root 0 Sep  5 10:26 cpu.cfs_period_us
-rw-r--r--. 1 root root 0 Sep  5 10:26 cpu.cfs_quota_us
-rw-r--r--. 1 root root 0 Sep  5 10:26 cpu.rt_period_us
-rw-r--r--. 1 root root 0 Sep  5 10:26 cpu.rt_runtime_us
-rw-r--r--. 1 root root 0 Sep  5 10:20 cpu.shares
-r--r--r--. 1 root root 0 Sep  5 10:26 cpu.stat
-rw-r--r--. 1 root root 0 Sep  5 10:26 notify_on_release
-rw-r--r--. 1 root root 0 Sep  5 10:23 tasks

现在我已经设置了一些 Cgroup,然后就可以生成负载了。打开三个 SSH 会话,并在前台运行以下命令:

bash 复制代码
# cat /dev/urandom

可以在 top 中看到结果:

注意: CPUShares 是基于顶级 Cgroup 的。默认情况下,顶级 Cgroup 是无约束的,这意味着一旦上层进程需要 CPUShares,系统将优先考虑该进程。是不是感觉有点绕?所以我们最好在系统上对 Cgroup 的布局进行可视化,以避免混淆,这一点非常重要。

从上面的截图中可以看到,所有的 cat 进程几乎都接收到了相同数量的 CPU 时间。这是因为默认情况下 Cgroup 在 cpu.shares 文件中的赋值是 1024。如前所述,这个份额是由父级与其他 Cgroup 的关系决定的。在本例中,我没有调整任何父级的权重。因此,如果所有父级 Cgroup 同时需要资源的话,它们将以默认的 1024 CPUShares 的权重进行分配。

回过头来,我在这里创建了带有默认值的 Cgroup,每个组的默认权重为 1024。如果要更改这个值,只需更改 cpu.shares 文件即可:

bash 复制代码
# echo 2048 > user1/cpu.shares
# echo 768 > user2/cpu.shares
# echo 512 > user3/cpu.shares

现在,权重计算会变得更复杂。但因为我还没有将任何进程添加到 Cgroup 中,它还处于未激活状态。如果要将进程添加到 Cgroup 中,将所需的 PID 添加到 tasks 文件中就可以:

bash 复制代码
# echo 2023 > user1/tasks

同样,可以在 top 中看到结果:

如图所示,新 Cgroup 中的进程大致接收到了一半的 CPU 时间。这是因为按照之前的等式,可以计算出:

我们继续将其他两个进程添加到各自的 Cgroup 中并观察结果:

bash 复制代码
# echo 2024 > user2/tasks
# echo 2025 > user3/tasks

可以看到权重已经生效,user1 占用了大约 61% 的 CPU 时间。剩余的时间分配给了 user2user3

不过,我们的示例也存在几个问题:

  1. 这些设置都是手动创建的,如果放入 Cgroup 中的进程的 PID 发生改变,会怎么样?
  2. 自定义的文件和文件夹在重启后不会保存,怎么办?
  3. 大部分工作都需要手动完成,有哪些工具可用?

我知道你很急,但是你先别急,systemd 为我们提供了很好的解决方案。我们在下一篇文章中会涉及。

总结

现在我们已经知道如何手动管理 Cgroup 了,因此后面大家能够更好地体会 Cgroup 和 systemd 协同使用的价值。

我将在本系列的第四篇,也就是完结篇中,深入探讨这个想法。

相关推荐
RemainderTime31 分钟前
Spring Boot脚手架集成Sa-Token实现生产级RBAC权限管理
java·spring boot·后端·系统架构
llz_1124 小时前
web-第二次课后作业
前端·后端·web
红尘散仙10 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
卷毛的技术笔记11 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
会编程的土豆11 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
喵个咪11 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
basketball61612 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
qq_25183645712 小时前
SpringBoot+Vue 共享电池柜管理系统 完整实现 前后端分离项目实战 完整代码
vue.js·spring boot·后端
zhangxingchao12 小时前
AI 大模型核心六:量化、Workflow 与 Agent、多轮 RAG
前端·人工智能·后端
IT_陈寒13 小时前
Vite打包时遇到的坑,原来问题出在这里
前端·人工智能·后端