南京市建设委员会网站/搜索引擎优化是指
云原生学习路线导航页(持续更新中)
本文是 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:区块链产品需求分析与方案设计 养老保险平台中涉及到参保人、社保局、公安局、工作单位等参与方,他们需要在区块链养老保险平台中完成账户注册、身份上链、社保代缴、信息核查等多种业务活动。通过对业务活动的功能分析,可以更好的服务系统的开发流程。基于养老保险…...

分布式Apollo配置中心搭建实战
文章目录 环境要求第一步、软件下载第二步、创建数据库参考文档 最近新项目启动,采用Apollo作为分布式的配置中心,在本地搭建huanj 实现原理图如下所示。 环境要求 Java版本要求:JDK1.8 MySql版本要求:5.6.5 Apollo版本要求&…...

Android monkey命令和monkey脚本详解
Monkey命令 monkey 是 Android 平台上一个非常有用的工具,它可以帮助开发者在设备上生成随机的用户事件流,如按键输入、触摸屏手势等,以此来测试应用的稳定性。这对于发现应用中的崩溃、异常和性能问题特别有用。 基本语法 adb shell monk…...

vue 实现对图片的某个区域点选, 并在该区域上方显示该部分内容
目录 1、通义灵码实现: 2、csdn的C知道: 3、百度comate: 1、通义灵码实现: 在 Vue 中实现对图片某个区域的点选并显示该区域属于哪一部分,通常涉及到几个关键步骤: 图片区域划分: 首先&#…...

配置文件格式 INI 快速上手
文章目录 1.简介2.语法节键值对注释大小写空白行数据类型字符串 (String)整数 (Integer)浮点数 (Float)布尔值 (Boolean)列表 (List) 3.示例4.解析参考文献 1.简介 INI 的全称是 Initialization,即为初始化文件,最早是 Windows 系统配置文件所采用的格式…...

基于WebGoat平台的SQL注入攻击
目录 引言 一、安装好JAVA 二、下载并运行WebGoat 三、注册并登录WebGoat 四、模拟攻击 1. 第九题 2. 第十题 3. 第十一题 4. 第十二题 5. 第十三题 五、思考体会 1. 举例说明SQL 注入攻击发生的原因。 2. 从信息的CIA 三要素(机密性、完整性、可用性&…...

SpringMvc有几个上下文
你好,我是柳岸花明。 SpringMVC作为Spring框架的重要组成部分,其启动流程和父子容器机制是理解整个框架运行机制的关键。本文将通过一系列详细的流程图,深入剖析SpringMVC的启动原理与父子容器的源码结构。 SpringMVC 父子容器 父容器的创建 …...

k8s部署rabbitmq集群
1 部署集群 1.1 安装 # 创建一个中间件的命名空间 kubectl create namespace middleware # 创建ConfigMap,包含RabbitMQ的配置文件内容 kubectl apply -f rabbitmq-configmap.yaml # 配置用于存储RabbitMQ数据的PersistentVolume(PV)和PersistentVolum…...

Python利用包pypinyin汉字转拼音(处理多音字)
一、汉字转拼音 在python中将汉字的拼音输出可以采用pypinyin包,一下是简单的demo示例: 默认调用pinyin方法转换时时默认时带声调的,不带声调需要添加“styleStyle.NORMAL”参数。 from pypinyin import pinyin, Styledef pinyin_transfer…...

推荐系统三十六式学习笔记:工程篇.常见架构24|典型的信息流架构是什么样的
目录 整体框架数据模型1.内容即Activity2.关系即连接 动态发布信息流排序数据管道总结 从今天起,我们不再单独介绍推荐算法的原理,而是开始进入一个新的模块-工程篇。 在工程实践的部分中,我首先介绍的内容是当今最热门的信息流架构。 信息…...

解决QEMU无法从非0x80000000处开始执行
解决QEMU无法从非0x80000000处开始执行 1 背景介绍2 问题描述3 原因分析4 解决办法5 踩坑回忆5.1 坑1 - 怀疑设备树有问题5.2 坑2 - 怀疑QEMU中内存未写入成功5.3 QEMU地址空间分析过程 1 背景介绍 在使用NEMU与QEMU做DiffTest的场景下,运行的固件为《RISC-V体系结…...