玩转 Cgroup 系列之四:使用 systemd 管理 Cgroup

作为这个系列文章的最后一篇,作者将介绍 systemd 以及它如何帮助管理 Cgroup(点击参考原文)。

在开始之前,建议先读完本系列的前三篇文章,便于更好地理解。

使用 systemd 管理 Cgroup

在默认情况下,systemd 会为其监控的每个服务在 system.slice 下创建一个新的 Cgroup。回到 OpenShift 控制平面主机,运行 systemd-cglsshows 命令,可以看到(简洁起见,这里只展示其中一部分输出):

plain 复制代码
└─system.slice
  ├─sssd.service
  ├─lvm2-lvmetad.service
  ├─rsyslog.service
  ├─systemd-udevd.service
  ├─systemd-logind.service
  ├─systemd-journald.service
  ├─crond.service
  ├─origin-node.service
  ├─docker.service
  ├─dnsmasq.service
  ├─tuned.service
  ├─sshd.service
  ├─NetworkManager.service
  ├─dbus.service
  ├─polkit.service
  ├─chronyd.service
  ├─auditd.service
    └─getty@tty1.service

我们可以通过编辑 systemd service 文件来进行更改,一共有三种方法:

  • 编辑 service 文件本身;
  • 使用 drop-in 文件;
  • 使用 systemctl set-property 命令。这个过程与手动编辑文件相同,但 systemctl 会为我们创建所需要的条目。

下面来详细介绍这三种方法。

编辑 Service 文件本身

我先创建一个非常简单的单元文件,运行脚本:

bash 复制代码
[Service]
Type=oneshot
ExecStart=/root/generate_load.sh
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

它的 bash 脚本只有两行:

bash 复制代码
#!/bin/bash
/usr/bin/cat /dev/urandom > /dev/null &

检查 systemd-cgls 输出,发现新服务嵌套在 system.slice 下(只展示其中一部分输出):

bash 复制代码
└─system.slice
  ├─cat.service
  ├─tuned.service
  ├─sshd.service
  ├─NetworkManager.service
  ├─sssd.service
  ├─dbus.service
  │ └─getty@tty1.service
  └─systemd-logind.service

如果在 systemd service 文件中添加下列语句,会发生什么?

bash 复制代码
Slice=my-beautiful-slice.slice

systemd-cgls 的输出有些出人意料,而且 cat.service 文件也被深层嵌套着:

bash 复制代码
Control group /:
├─my.slice
│ └─my-beautiful.slice
│   └─my-beautiful-slice.slice
│     └─cat.service
│       └─4010 /usr/bin/cat /dev/urandom

为什么会这样?

这与 systemd 的 Cgroup 嵌套方式有关。通常来说,子项以 -.slice 的方式声明。如果父项本身不存在,那么 systemd 会自动进行创建。如果刚刚我使用的是下划线 _,而不是破折号 -,那么结果就是您所想的那样了:

plaintext 复制代码
Control group /:
├─my_beautiful_slice.slice
│ └─cat.service
│   └─4123 /usr/bin/cat /dev/urandom

使用 drop-in 文件

在 systemd 中设置 drop-in 文件非常简单。首先,在 /etc/systemd/system 目录下根据服务名称创建一个合适的目录。以 cat 为例,运行以下命令:

bash 复制代码
# mkdir -p /etc/systemd/system/cat.service.d/

我们可以任意组织这些文件。鉴于它们是按照数字顺序依次执行的,可以将配置文件命名为类似 10-CPUSettings.conf 这样的形式。此目录中的所有文件都使用 .conf 文件扩展名。每次调整这些文件时,都需要运行 systemctl daemon-reload 命令。

我创建了两个 drop-in 文件来展示如何分离配置。第一个文件是 00-slice.conf。如下所示,它为 cat 服务设置了单独切片的默认选项:

bash 复制代码
[Service]
Slice=AWESOME.slice
MemoryAccounting=yes
CPUAccounting=yes

另一个文件设置了 CPUShares 的数量,我把它命名为 10-CPUSettings.conf

bash 复制代码
[Service]
CPUShares=256

我在同一个切片中创建了第二个服务。为了更容易区分进程,第二个脚本会略有不同:

bash 复制代码
#!/bin/bash
/usr/bin/sha256sum /dev/urandom > /dev/null &

然后我简单创建了 cat 文件的副本,替换了脚本,并更改了 CPUShares 的值:

bash 复制代码
# sed 's/load\.sh/load2\.sh/g' cat.service > sha256sum.service
# cp -r cat.service.d sha256sum.service.d
# sed -i 's/256/2048/g' sha256sum.service.d/10-CPUSettings.conf

最后重新加载 daemon 并启动服务:

bash 复制代码
# systemctl daemon-reload
# systemctl start cat.service
# systemctl start sha256sum.service

这里我先不展示 top 的输出,而是想介绍一下 systemd-cgtop。它的工作方式与常规的 top 类似,但它会按切片和切片中的服务提供细分后的信息。这可以帮助我们了解是否在系统上充分利用了 Cgroup。

如下所示,systemd-cgtop 显示了特定切片中所有服务的聚合情况,以及切片中每个服务的资源利用情况:

使用 systemctl set-property 命令

最后一个方法是使用 systemctl set-property 命令配置 Cgroup。下面从一个基本的 service 文件 md5sum.service 开始:

bash 复制代码
[Service]
Type=oneshot
ExecStart=/root/generate_load3.sh
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes
Slice=AWESOME.slice

[Install]
WantedBy=multi-user.target

使用 systemctl set-property 命令,把文件放置在 /etc/systemd/system.control 目录中。这些文件不用手动编辑。因为 set-property 命令不能识别到所有属性,所以 Slice 定义被放在了 service 文件中。

设置好单元文件并重新加载 daemon 后,使用 systemctl 命令:

bash 复制代码
# systemctl set-property md5sum.service CPUShares=1024

它创建了一个位于 /etc/systemd/system.control/md5sum.service.d/50-CPUShares.conf 的 drop-in 文件,可以随意查看。因为这些文件本不是用来手动编辑的,所以暂且不论。

运行命令,测试更改是否生效:

shell 复制代码
systemctl start md5sum.service cat.service sha256sum.service

如图所示,更改应该成功了。sha256sum.service 的 CPUShares 为 2048,md5sum.service 为 1024,cat.service 为 256。

总结

到此,我们也只是涉及了 Cgroup 的一点皮毛,实际应用的过程会更加复杂。Cgroup 除了能够保持系统健康运行,还能帮助实施"深度防御"策略。此外,它们也是现代 Kubernetes 工作负载的关键组件之一,有助于正确运行容器化进程,主要负责:

  • 限制进程的资源;
  • 在存在争用时决定优先级;
  • 控制对读/写和 mknod 设备的访问;
  • 对系统上运行的进程进行高级别资源统计。

可以说,如果没有 Cgroup,容器化和 Kubernetes 等很多关键业务都不可能实现。

这个系列教程到这里就告一段落了,希望能对大家有所启发。

参考资料

  1. 0xax.gitbooks.io/linux-insid...
  2. sysadmincasts.com/episodes/14...
  3. itnext.io/chroot-cgro...
  4. www.certdepot.net/rhel7-get-s...
  5. access.redhat.com/documentati...
  6. oakbytes.wordpress.com/2012/09/02/...
  7. www.redhat.com/en/blog/wor...
  8. www.redhat.com/en/blog/wor...
  9. youtu.be/z7mgaWqiV90
  10. youtu.be/el7768BNUPw
  11. youtu.be/sK5i-N34im8
  12. youtu.be/_AODvcO5Q_8
  13. youtu.be/x1npPrzyKfs
  14. youtu.be/yZpNsDe4Qzg
  15. access.redhat.com/solutions/4...
相关推荐
ShiinaKaze7 天前
用图说明 CPU、MCU、MPU、SoC 的区别
mcu·cpu·mpu·soc·计算机架构
谷公子的藏经阁20 天前
RISC-V笔记——内存模型总结
cpu·risc-v·内存模型·memory model·ztso
Crossoads20 天前
【汇编语言】寄存器(内存访问)(七)—— CPU提供的栈机制
android·java·tcp/ip·机器学习·cpu··汇编语言
谷公子的藏经阁23 天前
RISC-V笔记——基础
cpu·risc-v·isa
utmhikari1 个月前
【DIY小记】新手小白超频i9-12900kf和3070ti经验分享
cpu·显卡·nvidia·超频·微星
修行者xxl1 个月前
Intel Xeon(至强) 服务器 CPU
服务器·cpu
华为云开发者联盟1 个月前
总奖金高达10万元!华为算法精英实战营“亲和任务调度系统”来啦!
ai·cpu·芯片设计·任务调度
编码时空的诗意行者1 个月前
动手测试:CPU的L1~L3级缓存和内存的读取速度测试
缓存·cpu·性能
寅双木1 个月前
如何选购笔记本电脑?要看哪些参数?
笔记·笔记本电脑·cpu·显卡·内存条·固态硬盘·机械硬盘
Sindweller55301 个月前
CPU中也应用到了缓存:CPU3层高速缓存,以及它的缓存一致性问题、MESI协议和Java的一些应用
缓存·cpu·计算机基础