本文主要记录 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. C数据结构:KMP算法详解(呕心沥血)

    KMP算法 作者心声 了解暴力求解(必需会) KMP算法详解 记住我这段话(你会爱上它的)← : ①前后缀及其用处 ②求出前后缀的next数组 求出next数组的代码 开始实现KMP算法 结尾 附上源 ...

  2. 【开源】2024最新python豆瓣电影数据爬虫+可视化分析项目

    项目介绍 [开源]项目基于python+pandas+flask+mysql等技术实现豆瓣电影数据获取及可视化分析展示,觉得有用的朋友可以来个一键三连,感谢!!! 项目演示 [video(video- ...

  3. 2024-05-22:用go语言,你有一个包含 n 个整数的数组 nums。 每个数组的代价是指该数组中的第一个元素的值。 你的目标是将这个数组划分为三个连续且互不重叠的子数组。 然后,计算这三个子数

    2024-05-22:用go语言,你有一个包含 n 个整数的数组 nums. 每个数组的代价是指该数组中的第一个元素的值. 你的目标是将这个数组划分为三个连续且互不重叠的子数组. 然后,计算这三个子数 ...

  4. Dubbo SPI扩展机制源码详解(基于2.7.10)

    Dubbo SPI 一. 概述 本文主要分享 Dubbo 的拓展机制 SPI. 想要理解 Dubbo ,理解 Dubbo SPI 是非常必须的.在 Dubbo 中,提供了大量的拓展点,基于 Dubbo ...

  5. 修改java版本环境变量不生效

    修改java版本环境变量不生效 起因 先上图说明问题(电脑含有多个java版本,因为需要维护很老的项目,需要切换至以前的java版本,当然也可以不用修改环境变量,直接指定) 环境变量配置 正常 jav ...

  6. 痞子衡嵌入式:不同J-Link版本对于i.MXRT1170连接复位后处理行为有所不同

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是不同J-Link版本对于i.MXRT1170连接复位后处理行为. 痞子衡之前写过一篇旧文 <i.MXRT1170上用J-Link连 ...

  7. containerd 源码分析:创建 container(三)

    文接 containerd 源码分析:创建 container(二) 1.2.2.2 启动 task 上节介绍了创建 task,task 创建之后将返回 response 给 ctr.接着,ctr 调 ...

  8. JavaSE的运算符

    [Top] 算术运算 分类 运算符 算数运算符 * / + - % ++ -- 赋值运算符 +=, -=, /=, *=, %=(扩展赋值运算符), = 比较(关系)运算符 == != > &l ...

  9. docker使用Open Policy Agent(OPA)进行访问控制

    目录 一.系统环境 二.前言 三.Open Policy Agent 简介 四.Rego 语言简介 五.配置基本环境 六.docker安装OPA插件 6.1 安装docker 6.2 docker安装 ...

  10. HiveSQL 工作实战总结

    记录一些工作中有意思的统计指标,做过一些简化方便大家阅读,记录如有错误,欢迎在评论区提问讨论~ 问题类型 连续问题 两种思路 第一种:日期减去一列数字得出日期相同,主要是通过row_number窗口函 ...