Docker核心技术:Docker原理之Cgroups
云原生学习路线导航页(持续更新中)
本文是 Docker核心技术 系列文章:Docker原理之Cgroups,其他文章快捷链接如下:
- 应用架构演进
 - 容器技术要解决哪些问题
 - Docker的基本使用
 - Docker是如何实现的
 
- Docker核心技术:Docker原理之Namespace
 - Docker核心技术:Docker原理之Cgroups(本文)
 - Docker核心技术:Docker原理之Union文件系统
 
4.4.Cgroups:资源管控
4.4.1.Cgroups是什么

-  
Cgroups是谷歌Borg系统内部做资源管控的,后来将之提供到了Linux Kernel中
 -  
Linux内核中,Cgroups实现
- 在一个task中,还有另外一个属性 cgroups
 

 
4.4.2.Cgroups工作机制

-  
Cgroups实际上就是一个文件系统,在Linux的
/sys/fs/cgroup下 -  
Cgroup本身又有很多的子系统,包括cpu子系统
/sys/fs/cgroup/cpu、memory子系统/sys/fs/cgroup/memory等等,每个子系统中又包括各种配置文件,配置子系统的参数-  
比如cpu子系统中,包含多个配置文件,负责控制cpu绝对值、cpu相对值、cpu limit等等
 -  
如果想要控制一个进程的cpu绝对值,就修改cgroup目录下相应的文件,就可以立即做到cpu的限额

 
 -  
 -  
如果是容器,每个容器都有自己的cgroup
 -  
【🌟】cgroups的结构:树形结构
- /sys/fs/cgroup 
- cpu子系统 
- 当前子系统的cpu配置文件
 - 每个目录:又是关联到cpu子系统 的 子系统,目录内部又会包含当前子系统的cpu配置文件
 
 - memory子系统
 - …
 
 - cpu子系统 
 
 - /sys/fs/cgroup 
 
4.4.3.Cgroups包含哪些子系统

4.4.4.Cgroups CPU子系统
- cpu子系统下,有很多配置,常用的配置文件如下: 
- cpu.shares:设置cpu的相对值 
- 假设一个主机有3个CPU,创建了2个cgroup
 - Cgroup1 中 cpu.shares 写512,cgroup2 中 cpu.shares写1024
 - 意味着,这两个cgroup,可以按照 
512: 1024=1: 2的比例分摊cpu的时间,即Cgroup1 会分到1个CPU、Cgroup2 会分到2个CPU - 不过1:2只是一个相对值,如果Cgroup2 中压根没有进程,则 Cgroup1中的进程,就可以使用超过1个CPU
 
 - cpu.cfs_period_us、:cpu.cfs_quota_us:相互配合,设置cpu的绝对值 
- cpu.cfs_period_us:控制cpu时间周期的长度,默认是10万,100000
 - cpu.cfs_quota_us:控制当前cgroup能拿到一个cpu时间周期的多少。 
- 默认是-1,即不限制当前cgroups下进程可使用的cpu绝对值
 - 可如果你设置 cpu.cfs_period_us为 10万,cpu.cfs_quota_us为 1万,则表示 当前cgroup中的进程,一共可以得到 
1万/10万=0.1个CPU - 这是一个绝对值,当前cgroup下的 所有进程 占用cpu的总时间,不可超过0.1个CPU时间
 
 
 - cpuacct.usage:进行cgroup及其子cgroup下的,cpu使用情况的统计分析,可用做监控

 
 - cpu.shares:设置cpu的相对值 
 
4.4.5.拓展:Linux中多个进程如何共享cpu时间片
4.4.5.1.Linux内核的调度器
- Linux Kernel 2.6.23 以后,默认的是CFS(Completely Fair Scheduler)完全公平调度器
 

4.4.5.2.CFS调度器

4.4.5.3.vruntime红黑树
- 进程初始化时,为进程初始化它的vruntime值,插入树中,最小值放在左边,最大值放右边
 - 每次进程调度,都拿最左边的那个进程去运行。
 - 每次调度之后,时钟周期会为被调度进程重新计算一遍vruntime,公式:vruntime=实际运行时间*1024/进程权重 
- 进程权重相当于cpu_share的那个比例值
 - 被调度的进程,vruntime会一直涨;未被调度的进程,vruntime就不会变
 - 当被调度的进程,vruntime不再是最小的了,红黑树结构就会发生变化,将下次应该调度的进程放在最左边
 
 - 按照这样的模式,就可以 按照进程权重的设置,为每个进程分配 公平的cpu时间
 

4.4.5.4.CFS进程调度在Linux Kernel中的实现
- 感兴趣的可以深入
 

4.4.6.Cgroup Memory子系统
-  
memory子系统下,有很多配置,常用的配置文件如下:
- memory.soft_limit_in_bytes:内存软限制
 - memory.limit_in_bytes:内存硬限制,进程使用超过就会OOM
 - memory.oom_control:当发生OOM时,对进程执行什么操作,默认是 kill 进程。memory.oom_control中默认包含3个值: 
- oom_kill_disable 0:该参数表示是否禁用 OOM 杀死进程的功能。如果值为 0,则表示未禁用,即允许内核在 OOM 事件发生时杀死进程以释放内存。如果值为 1,则表示已禁用,即内核不会杀死进程
 - under_oom 0:该参数表示是否处于 OOM 状态。如果值为 0,则表示系统当前未处于 OOM 状态。如果值为 1,则表示系统当前处于 OOM 状态
 - oom_kill 0:该参数表示是否已经执行了 OOM 杀死进程的操作。如果值为 0,则表示尚未执行 OOM 杀死进程的操作。如果值为 1,则表示已经执行了 OOM 杀死进程的操作
 
 

 
4.4.7.Cgroup CPU 子系统练习
- 练习:使用Cgroups控制进程的资源开销
 

-  
进入主机的 /sys/fs/cgroup/cpu目录下,mkdir cpudemo
- 相当于我们创建了一个新的cgroup,并将其与 CPU 子系统相关联
 - linux会自动为cpudemo目录中,创建cpu的各种配置文件
 

 -  
准备一个死循环的程序,用来占用cpu资源
- 该程序会吃掉两个cpu
 
package mainfunc main(){// 协程1:死循环会吃掉一个cpugo func(){for {}}()// 主协程:死循环也会吃掉一个cpufor {} } -  
将上面的程序写入一个main.go,然后build一下
[root@VM-226-235-tencentos ~/zgy/code/test_cpu]# go build main.go [root@VM-226-235-tencentos ~/zgy/code/test_cpu]# ls main main.go -  
在终端前台执行一下这个程序,终端会卡住,因为是死循环,没有任何输出

 -  
另外打开一个终端,使用top命令查看现在的cpu使用情况
- 可以看到,main程序果然吃掉了2个CPU
 - main程序的pid为:19963
 

 -  
现在我们去cpudemo cgroup下,为这个进程设置CPU限额
[root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# cd /sys/fs/cgroup/cpu/cpudemo# 将main程序的pid,写入cgroup.procs,表示将main进程加入这个cgroup控制 [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# echo 19963 > cgroup.procs [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# cat cgroup.procs 19963# 使用绝对值控制cpu使用额度,cpu.cfs_period_us默认是10万,向cpu.cfs_quota_us写入1万,则main进程的cpu额度将会被限制在0.1个CPU [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# echo 10000 > cpu.cfs_quota_us [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# cat cpu.cfs_period_us 100000 [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# cat cpu.cfs_quota_us 10000 -  
再次top查看 main进程的cpu使用,果然被限制在0.1附近

 -  
可以用同样的方法,将cpu.cfs_quota_us值改成1.5万,则cpu将会被限制在0.15个

 -  
删除子系统
-  
注意,直接使用rm是删不掉cgroup子系统的
 -  
需要先安装cgroup-tools的工具,然后执行cgdelete命令,才可以删除子系统
# ubuntu下用apt,centos下用yum apt install cgroup-tools cd /sys/fs/cgroup/cpu cgdelete cpu:cpudemo 
 -  
 
4.4.8.Cgroup Memory子系统练习

-  
进入主机的 /sys/fs/cgroup/memory目录下,mkdir memorydemo
- 相当于我们创建了一个新的cgroup,并将其与 Memory 子系统相关联
 - linux会自动为memorydemo目录中,创建memory的各种配置文件

 
 -  
准备一个死循环的程序,用来占用memory资源。
-  
程序效果:
-  
该程序每隔1分钟就申请100MB内存,并将其填充为字符 ‘A’。共申请10次,最多申请1000MB。
 -  
可以通过 watch 命令,定期执行给定的命令并显示其输出,监视内存使用情况
watch 'ps -aux | grep malloc | grep -v grep'watch命令:watch是一个 Linux 命令,用于定期执行给定的命令并显示其输出。ps aux命令:ps是一个用于查看当前运行进程的命令。aux选项用于显示所有用户的所有进程,并以紧凑的格式显示进程的信息。grep malloc命令:grep是一个用于在文本中搜索指定模式的命令。在这里,它用于过滤出包含 “malloc” 字符串的行,即查找正在运行的进程中使用malloc函数进行内存分配的进程。grep -v grep命令:-v选项用于反向匹配,即排除包含 “grep” 字符串的行。这是为了避免在结果中显示grep命令本身的进程。
 -  
然后我们通过修改cgroup下的配置文件,将该进程的内存使用量,限制在100MB,超过时会OOM。
 

 -  
 -  
创建一个main.go文件
package main//#cgo LDFLAGS: //char* allocMemory(); import "C" import ("fmt""time" )func main() {// only loop 10 times to avoid exhausting the host memoryholder := []*C.char{}for i := 1; i <= 10; i++ {fmt.Printf("Allocating %dMb memory, raw memory is %d\n", i*100, i*100*1024*1025)// hold the memory, otherwise it will be freed by GCholder = append(holder, (*C.char)(C.allocMemory()))time.Sleep(time.Minute)} } -  
创建一个 malloc.c 文件
#include <stdlib.h> #include <stdio.h> #include <string.h>#define BLOCK_SIZE (100*1024*1024) char* allocMemory() {char* out = (char*)malloc(BLOCK_SIZE);memset(out, 'A', BLOCK_SIZE);return out; } -  
创建一个Makefile
build:CGO_ENABLED=1 GOOS=linux CGO_LDFLAGS="-static" go build 
 -  
 -  
程序写完,make build一下
[root@VM-226-235-tencentos ~/zgy/code/test_mem]# go mod init example.com/memory-test [root@VM-226-235-tencentos ~/zgy/code/test_mem]# go mod tidy [root@VM-226-235-tencentos ~/zgy/code/test_mem]# make build [root@VM-226-235-tencentos ~/zgy/code/test_mem]# ls go.mod main.go Makefile malloc.c memory-test -  
在终端前台执行一下这个程序,终端会卡住,因为进程每次循环都会sleep 1min

 -  
另外打开一个终端,使用
watch 'ps -aux | grep malloc | grep -v grep'命令查看现在的 malloc 内部的进程情况- 可以看到,有一个进程memory-test,果然malloc了100MB的内存
 - memory-test进程的pid为:13433
 

 -  
现在我们去memorydemo cgroup下,为这个进程设置Memory限额
[root@VM-226-235-tencentos /sys/fs/cgroup/memory/memorydemo]# cd /sys/fs/cgroup/memory/memorydemo# 将memory-test进程的pid,写入cgroup.procs,表示将 memory-test 进程加入这个cgroup控制 [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# echo 13433 > cgroup.procs [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# cat cgroup.procs 13433# 向 memory.limit_in_bytes 写入 104960000,大约是100MB [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# echo 104960000 > memory.limit_in_bytes [root@VM-226-235-tencentos /sys/fs/cgroup/cpu/cpudemo]# cat memory.limit_in_bytes 104960000 -  
在程序执行的终端可以看到,进程已经被kill掉了,因为申请内存超过了100MB,被执行OOM了。默认的OOM策略就是kill process

 
4.4.9.kubernetes Pod的cgroup怎么查看
- 方法一:进入pod内部查看 
- 进入pod内部,在 /sys/fs/cgroup下面,可以看到当前pod的所有 cgroup设置
 - 比如 /sys/fs/cgroup/cpu 中,
cpu.cfs_period_us、cpu.cfs_quota_us就以绝对值的方式,设置了pod的 cpu limit - 再比如,在 /sys/fs/cgroup/memory 中,
memory.limit_in_bytes就设置了pod的 memory limit 
 - 方法二:在pod所在主机上查看 
- 进入主机的 /sys/fs/cgroup,每一个子系统中,都有一个kubepods的目录,里面存储着所有pod的cgroup
 - kubepods里面,还有一个burstable目录,这就是所有pod cgroup的存储位置
 - 比如,查看一个pod的cpu cgroup,就应该进入:
/sys/fs/cgroup/cpu/kubepods/burstable/podxxxx-xxxx/- 其中 podxxxx-xxxx 表示pod的uid,可以使用kubectl get pods podxxx -oyaml找到
 
 
 
4.4.10.kubelet启动时,报错cgroup driver不一致

-  
因此,启动kubelet时,有时会报错:cgroup driver不一致,kubelet启动失败。原因如下:
- kubelet默认使用 systemd 作为 cgroup driver
 - 如果你本地还装了docker,且docker默认使用的是 cgroupfs 作为 cgroup driver。
 - 二者cgroup driver不同,kubelet出于保护,会禁止启动
 
 -  
解决方法:将docker的cgroup driver改成和kubelet一样,比如将docker的cgroup driver改成systemd,操作如下:

 
相关文章:
Docker核心技术:Docker原理之Cgroups
云原生学习路线导航页(持续更新中) 本文是 Docker核心技术 系列文章:Docker原理之Cgroups,其他文章快捷链接如下: 应用架构演进容器技术要解决哪些问题Docker的基本使用Docker是如何实现的 Docker核心技术:…...
union的特性和大小端
一、union在c和c语言中的特性 1.共享内存空间:union的所有成员共享同一块内存空间。意味着在同一时刻,union 只能存储其成员 中的一个值。当你修改了union中的一个成员,那么其它成员的值也会被改变,因为它们实际上都是指向同一块…...
个性化IT服务探索实践
探索和实践个性化IT服务,可以为用户提供更优质、定制化的解决方案,从而提升用户体验和满意度。以下是一些具体的步骤和建议,帮助自己在未来探索和实践个性化IT服务。 一、了解用户需求 用户调研和反馈: 进行用户调研,了解用户的需求和痛点。收集用户反馈,通过问卷、采访…...
UE4-打包游戏,游戏模式,默认关卡
一.打包游戏 注意windows系统无法打包苹果系统的执行包,只能使用苹果系统打包。 打包完之后是一个.exe文件。 打包要点: 1.确定好要操控的角色和生成位置。 2.设置默认加载的关卡和游戏模式。 在这个界面可以配置游戏的默认地图和游戏的模式,…...
Unity ShaderLab基础
[原文1] [参考2] 一 基础知识 1. 1 着色器语言分类: 语言说明HLSL基于 OpenGL 的 OpenGL Shading LanguageGLSL基于 DirectX 的 High Level Shading LanguageCGNVIDIA 公司的 C for GraphicShader LabUnity封装了CG,HLSL,GLSL的Unity专用着色器语言,具有跨平台,图形化编程,便…...
用代理IP会频繁掉线是什么原因?HTTP和SOCKS5协议优劣势是什么?
在使用代理IP的过程中,频繁掉线是一个常见且令人头痛的问题。要解决这一问题,我们需要先了解其原因,然后比较HTTP和SOCKS5两种代理协议的优劣势,以选择最适合的解决方案。 一、代理IP频繁掉线的原因 1. 代理服务器稳定性 代理服…...
MongoDB教程(十三):MongoDB覆盖索引
💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 文章目录 引言什么是覆盖…...
快速认识EA(Enterprise Architecture)
前言 企业架构,英文是:Enterprise Architecture,简称:EA,是承接企业战略规划与IT建设之间的桥梁,是企业信息化的核心,主要包括业务架构和IT架构。 架构的本质是管理和解决系统的复杂性&#x…...
词云图制作
词云图制作 一、什么是词云 这就是词云。 “词云”的概念最早是美国西北大学新闻学副教授、新媒体专业主任里奇•戈登( Rich Gordon )提出的。词云( Word Cloud ),又称文字云、标签云( Tag Cloud &#x…...
AndroidStudio与手机进行无线调试
(一)、前提条件 一部手机一条USB数据线一部电脑手机和电脑连接到同一个 Wifi开启手机的USB调试功能开启手机的无线调试功能 (二)、操作步骤 1、 将手机和电脑用USB数据线连接 2、 打开 终端,输入 adb devices ,查看手机和电脑是否连接成功。如下图: 2、…...
脉冲编码调制(PCM,Pulse Code Modulation)简介
脉冲编码调制(PCM,Pulse Code Modulation) 脉冲编码调制(PCM,Pulse Code Modulation)是一种将模拟信号转换为数字信号的技术。在音频处理、电话通信以及其他许多领域都有广泛应用。PCM通过采样、量化、编码等三个主要步骤将模拟信号转换为数…...
Pytorch transforms 的研究
绝对路径与相对路径差别 transforms的使用 from torchvision import transforms from PIL import Imageimg_path "dataset/train/bees/16838648_415acd9e3f.jpg" img Image.open(img_path) tensor_trans transforms.ToTensor() tensor_img tensor_trans(img) prin…...
一个C++模板工厂的编译问题的解决。针对第三方库的构造函数以及追加了的对象构造函数。牵扯到重载、特化等
一窥模板的替换和匹配方式:偏特化的参数比泛化版本的还要多:判断是不是std::pair<,>。_stdpair模板参数太多-CSDN博客 简介 在一个项目里,调用了第三封的库,这个库里面有个类用的很多,而且其构…...
《昇思 25 天学习打卡营第 20 天 | Pix2Pix实现图像转换 》
《昇思 25 天学习打卡营第 20 天 | Pix2Pix实现图像转换 》 活动地址:https://xihe.mindspore.cn/events/mindspore-training-camp 签名:Sam9029 Pix2Pix模型概述 Pix2Pix是一种基于条件生成对抗网络(cGAN)的图像转换模型&#x…...
关于c#的简单应用三题
#region 输入一个正整数,求1~这个数的阶乘 public static void Factorial(int a) { int result 1; for (int i 1; i < a; i) { result result * i; } Console.WriteLine(result); } #endregion #region 一个游戏&#…...
(十三)Spring教程——依赖注入之工厂方法注入
1.工厂方法注入 工厂方法是在应用中被经常使用的设计模式,它也是控制反转和单例设计思想的主要实现方法。由于Spring IoC容器以框架的方式提供工厂方法的功能,并以透明的方式开放给开发者,所以很少需要手工编写基于工厂方法的类。正是因为工厂…...
Redission中的Lua脚本写法、理解
对于Redission看门狗机制中的为了保证原子性的Lua脚本的写法规则是什么样的呢 ? 对于源码中的Lua脚本又是什么意思? 我们一起来看一下 首先,我们先基本的熟悉一下lua脚本的逻辑 在Lua脚本中,if (…) then … end 语句的执行过程…...
视频共享融合赋能平台LntonCVS视频监控管理平台视频云解决方案
LntonCVS是基于国家标准GB28181协议开发的视频监控与云服务平台,支持多设备同时接入。该平台能够处理和分发多种视频流格式,包括RTSP、RTMP、FLV、HLS和WebRTC。主要功能包括视频直播监控、云端录像与存储、检索回放、智能告警、语音对讲和平台级联&…...
GraphRAG + GPT-4o mini 低成本构建 AI 图谱知识库
更好的效果,更低的价格,听起来是不是像梦呓? 限制 首先,让我们来介绍一个词:RAG。 简单来说,RAG(Retrieval-Augmented Generation,检索增强生成) 的工作原理是将大型文档…...
全国区块链职业技能大赛第十套区块链产品需求分析与方案设计
任务1-1:区块链产品需求分析与方案设计 养老保险平台中涉及到参保人、社保局、公安局、工作单位等参与方,他们需要在区块链养老保险平台中完成账户注册、身份上链、社保代缴、信息核查等多种业务活动。通过对业务活动的功能分析,可以更好的服务系统的开发流程。基于养老保险…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
