本文主要记录 Linux Cgroup V2 版本基本使用操作,包括 cpu、memory 子系统演示。

1. 开启 Cgroup V2

版本检查

通过下面这条命令来查看当前系统使用的 Cgroups V1 还是 V2

stat -fc %T /sys/fs/cgroup/

如果输出是cgroup2fs 那就是 V2,就像这样

root@tezn:~# stat -fc %T /sys/fs/cgroup/
cgroup2fs

如果输出是tmpfs 那就是 V1,就像这样

[root@docker cgroup]# stat -fc %T /sys/fs/cgroup/
tmpfs

启用 cgroup v2

如果当前系统未启用 Cgroup V2,也可以通过修改内核 cmdline 引导参数在你的 Linux 发行版上手动启用 cgroup v2。

如果你的发行版使用 GRUB,则应在 /etc/default/grub 下的 GRUB_CMDLINE_LINUX 中添加 systemd.unified_cgroup_hierarchy=1, 然后执行 sudo update-grub

具体如下:

1)编辑 grub 配置

vi /etc/default/grub

内容大概是这样的:

GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT=0
GRUB_DISTRIBUTOR=`lsb_release -i -s 2> /dev/null || echo Debian`
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX=""

对最后一行GRUB_CMDLINE_LINUX进行修改

GRUB_CMDLINE_LINUX="quiet splash systemd.unified_cgroup_hierarchy=1"

2)然后执行以下命令更新 GRUB 配置

sudo update-grub

3)最后查看一下启动参数,确认配置修改上了

cat /boot/grub/grub.cfg | grep "systemd.unified_cgroup_hierarchy=1"

4)然后就是重启

reboot

重启后查看,不出意外切换到 cgroups v2 了

root@cgroupv2:~# stat -fc %T /sys/fs/cgroup/
cgroup2fs

发行版推荐

不过,推荐的方法仍是使用一个默认已启用 cgroup v2 的发行版。

有关使用 cgroup v2 的 Linux 发行版的列表,

  • Container-Optimized OS(从 M97 开始)
  • Ubuntu(从 21.10 开始,推荐 22.04+)
  • Debian GNU/Linux(从 Debian 11 Bullseye 开始)
  • Fedora(从 31 开始)
  • Arch Linux(从 2021 年 4 月开始)
  • RHEL 和类似 RHEL 的发行版(从 9 开始)

2. 基本使用

cgroup v2 使用上和 v1 版本基本一致,v2 版本也是默认在/sys/fs/cgroup/目录。

root@mydocker:~# ls /sys/fs/cgroup/
cgroup.controllers cgroup.subtree_control init.scope system.slice
cgroup.max.depth cgroup.threads io.cost.model user.slice
cgroup.max.descendants cpu.pressure io.cost.qos
cgroup.procs cpuset.cpus.effective io.pressure
cgroup.stat cpuset.mems.effective memory.pressure
  • 创建 sub-cgroup: 只需要创建一个子目录
cd /sys/fs/cgroup
mkdir $CGROUP_NAME
  • 将进程移动到指定 cgroup:将 PID 写入到相应 cgroup 的 cgroup.procs 文件即可,就像这样:
echo 1001 > /sys/fs/cgroup/test/cgroup.procs
  • 删除 cgroup/sub-cgroup: 也是直接删除对应目录即可

    • 如果一个cgroup 已经没有任何children或活进程,那直接删除对应的文件夹就删除该cgroup了
    • 如果一个cgroup已经没有children,但是还有僵尸进程,也认为这个cgroup是空的,可以直接删除
rmdir /sys/fs/cgroup/test
  • 修改 cpu、memory 限制:往对应配置文件写入配置内容即可

    • cpu.max 用于配置 cpu 使用限制
    • memory.max 则用于配置 内存使用限制
    • ...

创建 cgroup

接下来,以 cpu、memory 为例,简单演示一下 cgroup v2 版本使用

root@mydocker:~# cd /sys/fs/cgroup/
root@mydocker:/sys/fs/cgroup# mkdir test
root@mydocker:/sys/fs/cgroup# cd test
root@mydocker:/sys/fs/cgroup/test# ls
cgroup.controllers cpu.uclamp.max memory.current
cgroup.events cpu.uclamp.min memory.events
cgroup.freeze cpu.weight memory.events.local
cgroup.max.depth cpu.weight.nice memory.high
cgroup.max.descendants cpuset.cpus memory.low
cgroup.procs cpuset.cpus.effective memory.max
cgroup.stat cpuset.cpus.partition memory.min
cgroup.subtree_control cpuset.mems memory.oom.group
cgroup.threads cpuset.mems.effective memory.pressure
cgroup.type io.max memory.stat
cpu.max io.pressure pids.current
cpu.pressure io.stat pids.events
cpu.stat io.weight pids.max

CPU

启动一个死循环

root@mydocker:/sys/fs/cgroup/test# while : ; do : ; done &
[1] 90482

不出意外的话,应该占用了 100% cpu

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
90482 root 20 0 10160 1772 0 R 99.3 0.1 0:05.01 bash

接下来使用 cgroup v2 限制该进程只能使用 20% cpu

1)修改配置

echo 2000 10000 > cpu.max

含义是在 10000 微秒的 CPU 时间周期内,有 2000 微秒是分配给本 cgroup 的,也就是本 cgroup 管理的进程在单核 CPU 上的使用率不会超过 20%。

2)将进程加入当前 cgroup

echo 90482 > cgroup.procs

再次查看

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
90482 root 20 0 10160 1772 0 R 20.2 0.1 2:07.78 bash

可以看到,已经被限制到了 20%

Memory

接下来演示内存限制,使用以下代码来模拟内存消耗,

cat <<EOF > ~/mem-allocate.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #define MB (1024 * 1024) int main(int argc, char *argv[])
{
char *p;
int i = 0;
while(1) {
p = (char *)malloc(MB);
memset(p, 0, MB);
printf("%dM memory allocated\n", ++i);
sleep(1);
} return 0;
}
EOF

编译

gcc ~/mem-allocate.c -o ~/mem-allocate

然后启动该文件

root@mydocker:/sys/fs/cgroup/test# ~/mem-allocate
1M memory allocated
2M memory allocated
3M memory allocated
4M memory allocated
5M memory allocated
6M memory allocated
7M memory allocated
8M memory allocated
9M memory allocated
10M memory allocated
11M memory allocated
12M memory allocated
^C

可以看到,每秒会消耗 1M 内存,若不停止会一直运行直到 OOM。

接下来使用 cgroup v2 限制最多消耗 10M 内存。

1)修改配置

单位为字节 10485760= 10 * 1024 * 1024

echo 10485760 > memory.max

也就是本 cgroup 管理的进程内存使用不会超过 10M

2)将进程加入当前 cgroup

#将当前bash加入到test中,这样这个bash创建的所有进程都会自动加入到test中
sh -c "echo $$ >> cgroup.procs"

再次查看

root@mydocker:/sys/fs/cgroup/test# ~/mem-allocate
1M memory allocated
2M memory allocated
3M memory allocated
4M memory allocated
5M memory allocated
6M memory allocated
7M memory allocated
8M memory allocated
9M memory allocated
Killed

可以看到,到 10M 时就因为达到内存上限而被 Kill 了。

删除 cgroup

演示完成,把 cgroup 删除。

首先把进程 kill 一下

root@mydocker:/sys/fs/cgroup# cat test/cgroup.procs
90444
90630
root@mydocker:/sys/fs/cgroup# kill -9 90630
root@mydocker:/sys/fs/cgroup# kill -9 90444

然后删除目录

root@mydocker:/sys/fs/cgroup# rmdir test

这样 cgroup 就删除了。

3. v1 v2 对比

v1 的 cgroup 为每个控制器都使用独立的树(目录)

[root@docker cgroup]# ls /sys/fs/cgroup/
blkio cpu cpuacct cpuacct,cpu cpu,cpuacct cpuset devices freezer hugetlb memory net_cls net_cls,net_prio net_prio perf_event pids rdma systemd

每个目录就代表了一个 cgroup subsystem,比如要限制 cpu 则需要到 cpu 目录下创建子目录(树),限制 memory 则需要到 memory 目录下去创建子目录(树)。

比如 Docker 就会在 cpu、memory 等等目录下都创建一个名为 docker 的目录,在 docker 目录下在根据 containerID 创建子目录来实现资源限制。

各个 Subsystem 各自为政,看起来比混乱,难以管理

因此最终的结果就是:

  1. 用户空间最后管理着多个非常类似的 hierarchy
  2. 在执行 hierarchy 管理操作时,每个 hierarchy 上都重复着相同的操作

v2 中对 cgroups 的最大更改是将重点放在简化层次结构上

  • v1 为每个控制器使用独立的树(例如 /sys/fs/cgroup/cpu/GROUPNAME /sys/fs/cgroup/memory/GROUPNAME)。
  • v2 将统一/sys/fs/cgroup/GROUPNAME中的树,如果进程 X 加入/sys/fs/cgroup/test,则启用 test 的每个控制器都将控制进程 X。

更多 v1 和 v2 差异见 v1 存在的问题及 v2 的设计考虑


【从零开始写 Docker 系列】持续更新中,搜索公众号【探索云原生】订阅,阅读更多文章。


4. 小结

本文主要分享了 Linux cgroup v2 版本的基本使用,以及 v1 和 v2 版本的差异。

更多 cgroup v2 信息推荐阅读:Control Group v2 及其译文 Control Group v2(cgroupv2 权威指南)(KernelDoc, 2021)

Linux-Cgroup V2 初体验的更多相关文章

  1. Kali Linux 2016.2初体验使用总结

    Kali Linux 2016.2初体验使用总结 Kali Linux官方于8月30日发布Kali Linux 2016的第二个版本Kali Linux 2016.2.该版本距离Kali Linux  ...

  2. Linux on window初体验

    参照来源: https://www.cnblogs.com/enet01/p/7458767.html 1:liunx on window 的配置不多说(百度网上很多)启动开发这模式,在应用和程序中勾 ...

  3. Kali Linux 2016.2初体验

    前言 Kali Linux官 方于8月30日发布Kali Linux 2016的第二个版本Kali Linux 2016.2.该版本距离Kali Linux 2016.1版本发布,已经有7个月.在这期 ...

  4. 【Linux】CentOS8 初体验

    一.部署CentOS8虚拟机 1.下载Centos8镜像 下载地址: https://www.centos.org/download/ 可以选择国内的下载源,比较快,这里推荐清华的和阿里的 2.下载完 ...

  5. 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验

    在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...

  6. Linux之初体验

    预备作业03--我的Linux初体验 学习基于VirtualBox虚拟机安装Ubuntu图文教程在自己笔记本上安装Linux操作系统 一开始以为这个项目很简单,以往也在自己的笔记本上看教程安装过软件, ...

  7. 第三次随笔--安装虚拟机及学习linux系统初体验

    第三次随笔--安装虚拟机及学习linux系统初体验 ·学习基于VirtualBox虚拟机安装Ubuntu图文教程在自己笔记本上安装Linux操作系统 首先按照老师的提示步骤进行VirtualBox虚拟 ...

  8. 20155226-虚拟机与Linux之初体验

    虚拟机与Linux之初体验 虚拟机的安装 虚拟机对我来说不是很了解,但今天在安装过程中加深了我的理解.虚拟机是一个在原来系统基础上进行的又一个系统安装,可以在不影响前者的情况下完成一些其不能解决的问题 ...

  9. 20155315庄艺霖第三次作业之Linux初体验

    Linux初体验 安装Linux三两事 老师的作业要求基于VirtualBox安装Linux系统,我一开始下载了VB但是电脑运行不了,后来看网上的教程下载了VMware,才算开始了我的Linux之旅. ...

  10. 虚拟机与Linux的初体验

    很早的时候就知道虚拟机这个神奇东西的存在,但也仅仅是只闻其名,未见其身.后来在信息安全素质教育的这门课程上,为了做木马实验.暴力破解实验以及邮件窃取实验,这才比较直接的接触到了虚拟机.当我看着在另一个 ...

随机推荐

  1. Centos7安装openJdk17

    yum 安装 安装 EPEL 软件源:使用以下命令安装 EPEL 软件源,它包含了 OpenJDK 17 的安装包. sudo yum install epel-release sudo yum in ...

  2. PaliGemma 正式发布 — Google 最新发布的前沿开放视觉语言模型

    PaliGemma 是 Google 推出的新一代视觉语言模型家族,能够接收图像与文本输入并生成文本输出. Google 团队已推出三种类型的模型:预训练(PT)模型.混合模型和微调(FT)模型,这些 ...

  3. centos安装kvm博客

    一 centos如何安装kvm https://blog.csdn.net/yulsh/article/details/91790804

  4. 【winform】【Socket】实现你画我猜一:核心功能开发

    我认为得核心:是把客户端画的图画实时传递给其他的客户端.   我的思路是: 1.GDI+绘图加鼠标事件,实现客户端绘图. 2.每记录鼠标有效绘图10个点,就把这10个点通过socket传递给服务器. ...

  5. Intel HDSLB 高性能四层负载均衡器 — 基本原理和部署配置

    前言 在上一篇<Intel HDSLB 高性能四层负载均衡器 - 快速入门和应用场景>中,我们着重介绍了 HDSLB(High Density Scalable Load Balancer ...

  6. WPF+Emgucv实现在图像上画出感兴趣的区域 并进行掩膜获取 得到图像均值 和简单的 漫水填充

    <Grid.RowDefinitions></Grid.RowDefinitions> <Grid> <UniformGrid Columns="2 ...

  7. 将.net core api 部署成windows服务

    将.net core api 部署成windows服务   参考 https://blog.csdn.net/qq_38762313/article/details/103311944 将NSSM解压 ...

  8. CENTOS6.8 修改主机名

    1.临时修改主机名   显示主机名:spark@master:~$ hostnamemaster修改主机名:spark@master:~$ sudo hostname hadoopspark@mast ...

  9. 小米路由器4c刷入openwrt并成功进行锐捷认证

    小米路由器4C 刷入openwrt 并成功进行锐捷认证 前言: 在大学中,宿舍有个路由器当然是刚需,然而,我们学校的校园网需要进行锐捷认证,常规的路由器还用不了,需要自己刷路由器或是从奸商处购买.初入 ...

  10. Atlas快速入门

    先说一些废话 之前的公司在数据中台的项目上调研决定启用了Atlas作为我们数据血缘管理的工具,让我给大家写了一份Atlas快速入门的文档,所以在这里我将这篇文档以一个纯新手视角的方式再一次优化,希望能 ...