橘子学K8S02之容器中所谓的限制

news2024/12/26 10:36:00

前面我们知道了关于隔离在Linux中的实现是通过一组NameSpace做到的,而且实际上他只是修改了应用进程看到计算机的视图,对他的视野做了限制,只能看到某些特定的内容,但是当你把视角切换到宿主机的操作系统来看的时候,这些所谓的容器和被隔离的进程其实和其他进程没有区别。
这使得他作为一个容器就很便捷的实现了一些隔离功能,但是这个优点也不是很牛逼的,他和虚拟化技术相比有很多不足之处,就是隔离的不彻底。

首先既然容器只是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的其实还就是一个宿主机的操作系统内核。
尽管你可以在容器中通过前面说的Mount Namespae单独挂载其他不同版本的操作系统文件,但是这也不能改变他共享宿主机内核的事实,这就意味着,如果你在win的宿主机上运行Linux容器,或者在低版本上的Linux宿主机上运行高版本的linux容器都是行不通的,因为他们的宿主机的内核版本不一样,这肯定无法共享。而相比之下,拥有硬件虚拟化技术和独立Guest OS 的虚拟机就要方便得多了,最极端的例子就是Microsoft 的云计算平台Azure ,实际上就是运行在win服务器集群上的,但这并不妨碍你在它上面创建各种Linux虚拟机出来。

其次,在Linux内核中,很多资源和对象是不能Namespacce化的,最典型的例子就是:时间。
这就意味着,如果你的容器中的程序使用settimeofday(2)系统调用修改了时间,整个宿主机的时间都会被随之修改,这显然不符合用户的预期,想比在虚拟机里面这种里面完全的虚拟化,甚至连硬件资源都是能虚拟化的,你可以随意折腾,啥都能做。但是容器里部署应用的时候,什么能做,什么不能做,就得是用户必须考虑的一个问题。
所以我们现在可以了解一下关于限制的问题了。

一、关于限制

前面我们通过Namespace技术成功的把容器隔离在自己的一个视角下,现在你的容器进程成功被隔离开了。但是为什么还是需要限制呢?
我们说过,隔离的各个容器之间虽然是看不到其他的进程的,但是他们之间还是共享的宿主机的内核资源。换言之你多个容器之间其实还是在一起使用内核资源。比如cpu 比如内存,你的隔离进程自己就可以占用到百分之百,吃尽所有的资源。当然你的资源也可能被其他的隔离进程抢占。这种模式下的沙盒显然和我们理解的那种隔离不是一个概念,所以就需要做到限制每个沙盒的资源。

而 Linux Cgroups 就是 Linux 内核中用来为进程设置资源限制的一个重要功能。Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。此外,Cgroups 还能够对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。拥有控制这些资源的能力,不仅仅是限制,当然我们这里只研究一下限制,毕竟这是容器的一个核心概念。

二、Cgroups的使用

在 Linux 中,Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。简单来说他是一组文件,通过文件暴露给用户,供你使用功能,他的功能就封装在这组文件中,在 我的机器里,我可以用 mount 指令把它们展示出来,这条命令是:

mount -t cgroup
显示出所有挂载类型为cgroup的文件。我的内容为:
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_prio,net_cls)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)

在这里插入图片描述
它的输出结果,是一系列文件系统目录。如果你在自己的机器上没有看到这些目录,那你就需要自己去挂载 Cgroups。
可以看到,在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。这些都是我这台机器当前可以被 Cgroups 进行限制的资源种类。比如说/sys/fs/cgroup/cpu这个就表示我的系统可以限制cpu,因为group挂载文件里面包含cpu的限制类型。

而在子系统对应的资源种类下,你就可以看到该类资源具体可以被限制的方法。比如,对 CPU 子系统来说,我们就可以看到如下几个配置文件,这个指令是:

列出所有的cpu限制资源的限制方法:
ls /sys/fs/cgroup/cpu

在这里插入图片描述
你会在它的输出里注意到 cfs_period 和 cfs_quota 这样的关键词。这两个参数需要组合使用,可以用来限制进程在长度为 cfs_period 的一段时间内,只能被分配到总量为 cfs_quota 的 CPU 时间。也就是说他能够限制你的进程对cpu的使用,在一段时间内系统分配给你这个进程的时间长度。我们就可以通过操作这个参数来限制我们的容器对于cpu的占用率。

1、cgroups限制cpu资源

而这样的配置文件又如何使用呢?你需要在对应的子系统下面创建一个目录,比如,我们现在进入 /sys/fs/cgroup/cpu 目录下,然后创建一个叫做levi的目录:mkdir levi

[root@iZ2ze1q2h6sy9dblhemmhmZ cpu]# ls ./levi/
cgroup.clone_children  cgroup.event_control  cgroup.procs  cpuacct.stat  cpuacct.usage  cpuacct.usage_percpu  cpu.cfs_period_us  cpu.cfs_quota_us  cpu.rt_period_us  cpu.rt_runtime_us  cpu.shares  cpu.stat  notify_on_release  tasks

此时我们发现在我创建好levi目录之后,系统会为我们在这个目录下自动建立一系列的文件,其实就是我们在cpu的限制目录下建立了一个目录,自动就创建了一堆可以用来限制cpu的文件。此时我们的这个levi文件夹就被称之为一个控制组,自动生成该子系统(cpu子系统)对应的一组资源限制文件。
然后,我们在后台执行这样一条脚本:该脚本的含义就是死循环,把cup拉到百分百。

$ while : ; do : ; done &

在这里插入图片描述
执行之后我们看到我们这个shell脚本的进程就被启动了,他的进程号是11792(记住这个数字)。然后我们打开top观察一下cpu的使用情况。我们看到11792这个进程把cpu拉的很高。
在这里插入图片描述
而此时,我们可以通过查看 levi 目录下的文件,看到 levi 控制组里的 CPU quota 还没有任何限制(即:-1),CPU period 则是默认的 100 ms(100000 us):

[root@iZ2ze1q2h6sy9dblhemmhmZ cpu]# cat /sys/fs/cgroup/cpu/levi/cpu.cfs_quota_us
-1
[root@iZ2ze1q2h6sy9dblhemmhmZ cpu]# cat /sys/fs/cgroup/cpu/levi/cpu.cfs_period_us
100000
~~~shell
因为此时我们啥也没干,我们这个levi控制组就是个摆设,谁也没控制,于是我们现在就用这个控制组来控制一下我们这个11792进程。让他不要这么肆无忌惮的使用我的资源。
1、向 levi组里的 cfs_quota 文件写入 20 ms(20000 us):
~~~shell
$ echo 20000 > /sys/fs/cgroup/cpu/levi/cpu.cfs_quota_us

它意味着在每 100 ms 的时间里,被该控制组限制的进程只能使用 20 ms 的 CPU 时间,也就是说这个进程只能使用到 20% 的 CPU 带宽。

但是此时我们只是修改了这个控制组,你这个控制组要控制谁呢,也就说你的控制组要和你要控制的进程关联起来。才能做到指定控制。
2、我们把被限制的进程的 PID 写入 container 组里的 tasks 文件,上面的设置就会对该进程生效了:

echo 11792 > /sys/fs/cgroup/cpu/levi/tasks

此时我们就完成了控制,按照我们的预期,我们希望刚才那个拉满cpu的进程,现在在限制下只能使用百分之20的cpu资源,那么我们用top来看一下。
在这里插入图片描述
我们看到监控下的占用和我们的预期一样的。这就表示我们的限制是成功的。

2、如何理解docker的限制

除 CPU 子系统外,Cgroups 的每一个子系统都有其独有的资源限制能力,比如:
blkio,为​​​块​​​设​​​备​​​设​​​定​​​I/O 限​​​制,一般用于磁盘等设备;
cpuset,为进程分配单独的 CPU 核和对应的内存节点;
memory,为进程设定内存使用的限制。
Linux Cgroups 的设计还是比较易用的,它就是一个子系统目录加上一组资源限制文件的组合。而对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。
而至于在这些控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定了,比如这样一条命令:

$ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash

在启动这个容器后,我们可以通过查看 Cgroups 文件系统下,CPU 子系统中,“docker”这个控制组里的资源限制文件的内容来确认:

$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_period_us 
100000
$ cat /sys/fs/cgroup/cpu/docker/5d5c9f67d/cpu.cfs_quota_us 
20000

这就意味着这个 Docker 容器,只能使用到 20% 的 CPU 带宽。
我们通过一个对cpu占用的方式模拟了docker限制的规则,其实你就可以自己简单实现docker的这个小功能了。

三、总结

所以,一个正在运行的 Docker 容器,其实就是一个启用了多个 Linux Namespace 的应用进程,而这个进程能够使用的资源量,则受 Cgroups 配置的限制。
这也是容器技术中一个非常重要的概念,即:容器是一个“单进程”模型。由于一个容器的本质就是一个进程,用户的应用进程实际上就是容器里 PID=1 的进程,也是其他后续创建的所有进程的父进程。这就意味着,在一个容器中,你没办法同时运行两个不同的应用,因为docker的理念就是容器就是应用,通过监控应用来表达容器的状态,所以一对一的这种最能达到效果,如果你运行两个进程,但是只有一个能表达PID=1,那么就存在另一个进程挂了,但是docker不知道,因为他是和PID=1的进程挂钩的。
除非你能事先找到一个公共的 PID=1 的程序来充当两个不同应用的父进程,这样当子进程挂了会发给父进程(PID=1)一个信号,这样对于父进程也是能感知的,父进程能感知,dockler也就能感知了,这也是为什么很多人都会用 systemd 或者 supervisord 这样的软件来代替应用本身作为容器的启动进程。
这是因为容器本身的设计,就是希望容器和应用能够同生命周期,这个概念对后续的容器编排非常重要。否则,一旦出现类似于“容器是正常运行的,但是里面的应用早已经挂了”的情况,编排系统处理起来就非常麻烦了。
另外,跟 Namespace 的情况类似,Cgroups 对资源的限制能力也有很多不完善的地方,被提及最多的自然是 /proc 文件系统的问题。
众所周知,Linux 下的 /proc 目录存储的是记录当前内核运行状态的一系列特殊文件,用户可以通过访问这些文件,查看系统以及当前正在运行的进程的信息,比如 CPU 使用情况、内存占用率等,这些文件也是 top 指令查看系统信息的主要数据来源。但是,你如果在容器里执行 top 指令,就会发现,它显示的信息居然是宿主机的 CPU 和内存数据,而不是当前容器的数据。造成这个问题的原因就是,/proc 文件系统并不知道用户通过 Cgroups 给这个容器做了什么样的资源限制,即:/proc 文件系统不了解 Cgroups 限制的存在。在生产环境中,这个问题必须进行修正,否则应用程序在容器里读取到的 CPU 核数、可用内存等信息都是宿主机上的数据,这会给应用的运行带来非常大的困惑和风险。这也是在企业中,容器化应用碰到的一个常见问题,也是容器相较于虚拟机另一个不尽如人意的地方。后面我会补充这个解决方案的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1306942.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JIT即时编译器深度解析——Java性能提升利器

文章目录 一、JIT概述1、为什么要用JIT即时编译器2、C1、C2与Graal编译器3、分层编译4、热点代码5、热点探测(1)方法调用计数器(2)回边计数器 二、编译优化技术1、方法内联(1)什么是方法内联(2&…

银行数据分析指标篇:最全银行数据指标体系打包送给你!

前两天分享了银行业数据分析的案例,今天呢,老李把金融行业的指标体系和典型分析场景完整分享给大家!做地通俗易懂,条理清晰,很快就能上手。 银行指标体系 “指标”作为业务和数据的结合,它使得业务目标可…

Vue 2.0源码分析-update

Vue 的 _update 是实例的一个私有方法,它被调用的时机有 2 个,一个是首次渲染,一个是数据更新的时候;由于我们这一章节只分析首次渲染部分,数据更新部分会在之后分析响应式原理的时候涉及。_update 方法的作用是把 VNo…

聚焦本田XR-V和福特领睿:两大SUV综合实力对比,谁更胜一筹?

在当今的SUV市场中,家庭用户的选择变得越来越多样化。特别是对于那些追求时尚、功能性以及技术先进性的用户来说,选择正确的SUV显得尤为重要。本文将重点对比福特领睿和本田XR-V这两款SUV,探讨它们在各方面的表现,做一个综合实力的…

艾江山:你好好养生,我带你去看海

有多少人,还没好好看过这个世界; 有多少人,因为不够健康缺少走出来的勇气。 艾江山第二届平凡人的养生故事大赛暨北海游学,在一片依依不舍中圆满闭幕。 游学博闻,盖谓其因游学所以能博闻也 传统上,游学是…

Power BI - 5分钟学习增加条件列

每天5分钟,今天介绍Power BI增加条件列。 什么是增加条件列? 简单理解,可以根据表中某列设置一个或者多个条件,判定的结果会生成一个新列。 举例: 首先,导入一张【Sales】样例表(Excel数据源导入请参考每…

将自己的django项目部署到云服务器(腾讯云centos)

最近自己买了个云服务玩,突然就想把自己写的小项目部署到云服务器上,这样就可以实现公网访问了。以下是整个部署过程和遇到的各种问题的解决方案,有想自己部署自己功能的,可以参考着进行哦。 1、设置好腾讯云的远程登录代码 先给…

智能座舱架构与芯片- (9) 音频篇 上

一、音频总线 音频是智能座舱的核心功能,涵盖车载音响、语音识别、e-Call、消噪及回声消除等应用,随着汽车智能网联化的发展,对音频的开发要求也越来越高。传统的车载音频系统采用模拟并行音频信号传输方式,难以在功能增加与整车…

[足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-1开环系统与闭环系统Open/Closed Loop System

本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-自动控制原理Ch1-1开环系统与闭环系统Open/Closed Loop System EG1: 烧水与控温水壶EG2: 蓄水与最终水位闭环控制系统 EG1: 烧水与控温水壶 EG2: 蓄水与最终水位 h ˙ q i n A − g h A R \dot{…

总结了人工智能领域,能源领域,电气领域比较好中的一些sci期刊!!仅供参考

文章目录 前言一、总结了人工智能领域,能源领域,电气领域比较好中的一些sci期刊 总结 前言 期刊查询网站: https://www.letpub.com.cn/index.php?pagejournalapp&viewsearch 链接: 点我跳转期刊查询网站 一、总结了人工智能领域&#…

许战海战略文库|美国品牌实践:从品类品牌向产业品牌转变

引言:《品类战略》是上世纪70年代特劳特和里斯所推崇的定位理论,强调“品类聚焦是唯一正确的战略“新品类要使用新品牌”等战略思想,并对品牌延伸等多元化品牌进行批判,并由中国代理人传入中国,从2002年至今滋生了众多品类品牌,阻碍中国经济发展。 在今天…

图生视频AI技术,1张图零提示词,让静态照片动起来

AI时代的发展速度比我们想象中的快多了,当大部分人刚学会AI生成图片时,现在又开始流行AI生成视频了,正式从图片、文字升级到短视频时代。 最近一段时间,AI生成视频的技术正在突飞猛进。Pika、Runway等大家熟知的海外工具都在不断…

android studio flutter启动一直卡在“ Running gradle task ‘assembledebug‘ “的解决问题

解决问题: 1、修改项目中android/build.gradle文件 将buildscript.repositories下面的 //google() //mavenCentral()注释掉,改成maven {allowInsecureProtocol trueurl https://maven.aliyun.com/repository/google } maven {allowInsecureProtocol t…

Chrome安装插件出现CRX-HEADER-INVALID解决方法

1 Chrome浏览器安装离线插件时出现了“CRX-HEADER-INVALID”错误。 2将插件包的后缀名改成.zip格式。 3点击右侧三点按钮后点击【更多工具】--》【扩展程序】界面。 4在【扩展程序】将ZIP包拉入并安装。 5这样就安装成功了,虽然图标上有红色图标…

HarmonyOS4.0从零开始的开发教程14Web组件的使用

HarmonyOS(十二)Web组件的使用 1 概述 相信大家都遇到过这样的场景,有时候我们点击应用的页面,会跳转到一个类似浏览器加载的页面,加载完成后,才显示这个页面的具体内容,这个加载和显示网页的…

数据库——安全性

智能2112杨阳 一、目的与要求: 1、设计用户子模式 2、根据实际需要创建用户角色及用户,并授权 3、针对不同级别的用户定义不同的视图,以保证系统的安全性 二、内容: 先创建四类用户角色: 管理员角色Cusm、客户角…

YashanDB亮相2023年深圳市高校教育信息化学会学术年会,加码高校数字基座建设

12月3日,“2023年深圳市高校教育信息化学会学术年会”在深圳顺利召开。深圳计算科学研究院(简称:深算院)YashanDB团队受邀出席,同来自深圳高校、政府教育部门、教育信息化专家学者等共同探讨教育信息化前沿技术与应用的…

06线性回归衍生算法

目录: ridge算法 lasso算法 elastic-Net算法 from sklearn.linear_model import Ridge from sklearn.linear_model import SGDRegressor, LinearRegression from sklearn.linear_model import Lasso import numpy as np# 1. Ridge 岭回归# 生成随机数据 X np.…

linux 调试工具 GDB 使用

gdb是linux下常用的代码调试工具,本文记录常用命令。 被调试的应用需要使用 -g 参数进行编译,如不确定可使用如下命令查看是否支持debug readelf -S filename | grep "debug" 启动调试 gdb binFile 例如要调试sshd: 调试带参数…

汉诺塔(函数递归)

前言 汉诺塔问题是一个经典的数学谜题,也是函数递归的一个经典问题,起源于印度。问题的设定是有三个柱子,第一个柱子上有一组不同大小的圆盘,按照从上到下依次变大的顺序摆放。目标是将所有的圆盘从第一个柱子移动到第三个柱子上&…