玩转 Cgroup 系列之四:使用 systemd 管理 Cgroup
  UPHL7SqojIc3 2023年11月24日 20 0

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

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

使用 systemd 管理 Cgroup

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

└─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 文件本身

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

[Service]
Type=oneshot
ExecStart=/root/generate_load.sh
TimeoutSec=0
StandardOutput=tty
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

它的 bash 脚本只有两行:

#!/bin/bash
/usr/bin/cat /dev/urandom > /dev/null &

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

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

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

Slice=my-beautiful-slice.slice

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

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

为什么会这样?

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

Control group /:
├─my_beautiful_slice.slice
│ └─cat.service
│   └─4123 /usr/bin/cat /dev/urandom

使用 drop-in 文件

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

# mkdir -p /etc/systemd/system/cat.service.d/

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

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

[Service]
Slice=AWESOME.slice
MemoryAccounting=yes
CPUAccounting=yes

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

[Service]
CPUShares=256

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

#!/bin/bash
/usr/bin/sha256sum /dev/urandom > /dev/null &

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

# 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 并启动服务:

# systemctl daemon-reload
# systemctl start cat.service
# systemctl start sha256sum.service

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

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

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

使用 systemctl set-property 命令

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

[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 命令:

# systemctl set-property md5sum.service CPUShares=1024

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

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

systemctl start md5sum.service cat.service sha256sum.service

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

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

总结

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

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

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

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

参考资料

  1. https://0xax.gitbooks.io/linux-insides/content/Cgroups/linux-cgroups-1.html
  2. https://sysadmincasts.com/episodes/14-introduction-to-linux-control-groups-cgroups
  3. https://itnext.io/chroot-cgroups-and-namespaces-an-overview-37124d995e3d
  4. https://www.certdepot.net/rhel7-get-started-cgroups/
  5. https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/resource_management_guide/chap-introduction_to_control_groups
  6. https://oakbytes.wordpress.com/2012/09/02/cgroup-cpu-allocation-cpu-shares-examples/
  7. https://www.redhat.com/en/blog/world-domination-cgroups-part-1-cgroup-basics
  8. https://www.redhat.com/en/blog/world-domination-cgroups-rhel-8-welcome-cgroups-v2
  9. https://youtu.be/z7mgaWqiV90
  10. https://youtu.be/el7768BNUPw
  11. https://youtu.be/sK5i-N34im8
  12. https://youtu.be/_AODvcO5Q_8
  13. https://youtu.be/x1npPrzyKfs
  14. https://youtu.be/yZpNsDe4Qzg
  15. https://access.redhat.com/solutions/4489171
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月24日 0

暂无评论

UPHL7SqojIc3