[k8s理论知识]3.docker基础(二)隔离技术

容器其实是一种沙盒技术,其核心是通过约束和修改进程的动态表现,为其创建一个边界。这个边界确保了应用与应用之间不会相互干扰,同时可以方便在不同的环境中迁移,这是PaaS最理想的状态。

程序是代码的可执行镜像,通常以二进制文件的形式存储在磁盘上。但是当程序被执行时,操作系统会将程序的数据加载到内存中,读取计算指令并指示CPU执行。CPU与内存协作进行计算,使用寄存器存放数值,内存堆栈保存执行的命令和变量,此外,程序还可能打开文件和调用IO设备。所有这些状态信息和数据信息的集合,构成了进程的动态表现。

进程可以理解为是 动态的程序,但更准确地说,进程是程序在计算机系统中的一个 执行实例。程序本身只是静态的代码文件(通常指由源代码编译得到的可执行文件),而进程则是该程序的一个活动状态,它包含了程序的执行上下文和资源。

那么,如果给进程之间确立边界,也就是给程序创建了边界。而容器技术的核心,就是通过约束和修改进程的动态表现,从而为其创造一个边界。

Nampespace技术

启动一个busybox容器,通过以下操作让我们更好的理解进程隔离。

[root@master ~]# docker run -it busybox:v1 /bin/sh
/ # pid
/bin/sh: pid: not found
/ # ps
PID   USER     TIME  COMMAND1 root      0:00 /bin/sh6 root      0:00 ps

可以看到,我们在 Docker 里最开始执行的 /bin/sh,就是这个容器内部的第 1 号进程(PID=1),而这个容器里一共只有两个进程在运行。这就意味着,前面执行的 /bin/sh,以及我们刚刚执行的 ps,已经被 Docker 隔离在了一个跟宿主机完全不同的世界当中。

当我们不要关闭这个命令行(否则容器会销毁),而打开另一个窗口,查看这个容器的pid,可以看到这个容器的PID实际为16043。

[root@master ~]# docker ps | grep busybox
e45240f24ffb   busybox:v1                                          "/bin/sh"                 12 seconds ago   Up 11 seconds             epic_moser
[root@master ~]# docker inspect --format '{{.State.Pid}}' e45240f24ffb 
16043

以上表述实际上是非常不严谨的,因为容器本身没有PID,容器只是为程序提供一个隔离的视图,而运行在容器里的程序(在我们的例子中是/bin/bash)才拥有PID。也就是说在查看容器的PID的时候,查看的实际上是它内部程序的PID。

所以我们可以理解,这个bin/bash本身的PID是16043,而容器实施了一个障眼法,让前面的所有PID都看不见了,这个程序的PID也就成了1。

事实上,以上只是将进程空间进行了Namespace隔离,容器还需要进行文件系统、IO设备等的隔离。这些在后面会一一演示。

在理解了 Namespace 的工作方式之后,你就会明白,跟真实存在的虚拟机不同,在使用 Docker 的时候,并没有一个真正的“Docker 容器”运行在宿主机里面。Docker 项目帮助用户启动的,还是原来的应用进程,只不过在创建这些进程时,Docker 为它们加上了各种各样的 Namespace 参数。

Cgroups

从上面例子可以看出,Namespace技术改变了进程看待计算机的视图,但是计算机并没有改变看待进程的视图,对于底层操作系统而言,容器里的进程和直接运行的进程没有区别。也就是说,虽然上面例子中的bin/bash进程表面上被隔离了起来,但是实际上它能得到的内存和cpu资源,却可以随意的被其他进程占用。而这个进程本身也可以吃掉别的进程的资源,这不符合一个沙盒的行为表现。而且,在linux内核中,有很多的资源是不能namespace化的,比如时间。

Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。通过以下命令可以看到cgroup在系统中挂载的位置。

[root@master ~]# mount -t 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/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/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/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
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/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)

可以看到,在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统。这些都是我这台机器当前可以被 Cgroups 进行限制的资源种类。我们进入CPU目录,可以看到有很多cpu的配置文件。在这些文件中,文件夹container是我们后来创建的。

当我们进入container文件夹,会看到里面已经创建了完整的cgoups文件系统。 这是因为当你在cgroups的某个子系统(比如cpu或者sys等),你实际上在创建一个新的控制组,控制组允许你为该组内的进程设置资源限制或监控资源使用情况。因此Linux内核会在这个子目录下生成一系列与该子系统相关的文件。

 但是这些文件实际上是虚拟的,并不是存储载物理磁盘上的文件,只是为用户提供的与内核交互的接口。

 随后打开另一个终端,执行以下命令。这条命令是一个死循环,会吃光所有cpu资源。

可以看到这个进程PID是47975。

接下来进入container目录, 看到 container 控制组里的 CPU quota 还没有任何限制(即:-1),CPU period 则是默认的 100  ms(100000  us)

[root@master container]# cat cpu.cfs_period_us 
100000
[root@master container]# cat cpu.cfs_quota_us 
-1

接下来我们进行控制组的限制操作,向container组里的cfs_quota和cfs_period文件写入参数进行限制。

以下的操作意思是100000us(100ms)里面有20000us(20ms)可以给这个控制组使用。

接下来要将这个PID(47975)放入这个控制组。

重新用top命令查看,发现 它虽然是一个死循环,但是只占用了20%的cpu资源。

控制组 

不是每一个Linux进程都有自己的控制组,但是每个进程都会属于某一个资源控制组。在没有配置自定义 cgroups 的情况下,所有进程都会被分配到系统的默认控制组,这些默认的 cgroups 通常是由 init 系统(如 systemd)或直接由内核管理的。多个进程也可以被放置在同一个控制组中。

比如说我们查看cgroup/cpu里的user.slice文件夹,可以看到里面有一个procs文件,打开可以看到这个资源控制组的所有进程。

假设有一个进程PID是12345,我们可以将它加入控制组中。

echo 12345 > /sys/fs/cgroup/cpu/user.slice/cgroup.procs

创建一个docker,并规定了他的cpu资源限制。可以看到docker ID是b47efc8e7d29,cgroup目录是system.slice下的以b47efc8e7d29开头的文件夹。

[root@master ~]# docker run  -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
root@b47efc8e7d29:/# cat /proc/self/cgroup
11:pids:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
10:memory:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
9:perf_event:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
8:cpuset:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
7:net_prio,net_cls:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
6:devices:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
5:blkio:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
4:cpuacct,cpu:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
3:hugetlb:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
2:freezer:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope
1:name=systemd:/system.slice/docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope

进入文件夹,可以看到他的cpu资源限制。 也就是说docker可以在创建容器的时候进行资源限制。

[root@master system.slice]# cd docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope/
[root@master docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope]# ls
cgroup.clone_children  cgroup.procs  cpuacct.usage         cpu.cfs_period_us  cpu.rt_period_us   cpu.shares  notify_on_release
cgroup.event_control   cpuacct.stat  cpuacct.usage_percpu  cpu.cfs_quota_us   cpu.rt_runtime_us  cpu.stat    tasks
[root@master docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope]# cat cpu.rt_period_us 
1000000
[root@master docker-b47efc8e7d291be37292fdf8edb160947e2bfa413595f90d6d4960f7b22a3edf.scope]# cat cpu.cfs_quota_us 
20000
echo操作 

 /sys/fs/cgroup/cpu/container/cgroup.procs 和 /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us 这两个文件的行为是不同的,所以当我们进行echo操作的时候,写入cpu.cfs_quota_us 文件的行为是覆盖式的。当你使用 echo 写入一个新的值时,它会替换掉之前的值。cgroup.procs 是一个特殊的文件,它的目的是让用户通过写入进程 ID 来动态管理进程所属的控制组。因此它的行为不是像普通文件那样追加或覆盖内容,而是执行一个动作(将进程加入到该控制组)。

文件系统

如果不进行单的文件系统挂载,容器内的进程的文件系统视图就是整个物理主机的视图。所以在容器创建之前,docker通过重新挂载根目录,从而让容器进程看到的是一个独立的隔离环境。为了能够让容器的这个根目录看起来更“真实”,Docker会在这个容器的根目录下挂载一个完整操作系统的文件系统,比如 Ubuntu16.04 的 ISO。这样,在容器启动之后,我们在容器里通过执行 "ls /" 查看根目录下的内容,就是 Ubuntu 16.04 的所有目录和文件。而挂载在容器根目录上,用来为进程提供隔离后环境的文件的操作系统,就是所谓的容器镜像。它还有一个更为专业的名字,叫作:rootfs(根文件系统)。

值得注意的是,rootfs只是一个操作系统所包含的文件、配置和目录,并不包含操作系统的内核。Linux操作系统分为两部分,内核和用户态。

内核:这是操作系统的核心,负责与硬件交互、调度进程、管理内存、网络、文件系统等。无论是ubuntu、centos还是其他linux发行版的内核,他们的核心功能是相同的。

用户态:这是操作系统中用户可以直接接触的部分,比如程序、库、配置文件等等。不同的linux发行版(linux/ubuntu/debian)在用户态可能有很大不同,包括包管理、配置文件等。

对于容器来讲,操作系统就是宿主机的操作系统内核。所以说,当你拉取一个 CentOS 容器镜像时,实际上你只是拉取了 CentOS 的用户态部分(包括系统工具、库、配置文件等),而不包含 CentOS 的内核。容器中的进程依然使用的是宿主机的内核来运行。因此,无论宿主机运行的是 Ubuntu 还是其他发行版的内核,只要它是 Linux 内核,容器中的 CentOS 文件系统都可以正常工作。

Docker和VM对比

但是事实上,宿主机不可能光有一个内核态,他也是有用户态的。当你在一个 Ubuntu 宿主机上运行一个 CentOS 容器时,容器中的进程会使用 CentOS 的用户态工具和库。比如,容器中的 yum(CentOS 的包管理器)可以正常运行,而不会使用 Ubuntu 的 apt(Ubuntu 的包管理器)。因此,容器就像是一个独立的系统,拥有自己的文件系统、程序、配置等,不依赖宿主机的用户态。你可以把它想象为容器本身有一个“虚拟的用户态”,但它并不运行在宿主机的用户态环境中。

当你在一个 Ubuntu 宿主机上运行了一个 CentOS 虚拟机,虚拟机内的 CentOS 系统会像在物理机上一样启动,它将加载自己的 CentOS 内核,并启动 CentOS 的用户态环境。CentOS 虚拟机使用自己的内核来处理系统调用、管理进程、分配内存等。这个内核与宿主机的内核完全独立,因此 CentOS 虚拟机可以运行与宿主机不同版本的内核。

对 Docker 项目来说,它最核心的原理实际上就是为待创建的用户进程:启用 Linux Namespace 配置;设置指定的 Cgroups 参数;切换进程的根目录(Change Root)。

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

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

相关文章

力扣1652.拆炸弹

你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。 为了获得正确的密码,你需要替换掉每一个数字。所有数字会 同时 被替换。 如果 k > 0 ,将第 i 个数字用 接下来 k 个数字之…

探索Spring Cloud Config:构建高可用的配置中心

目录 认识Spring Cloud ConfigConfig Server读取配置文件步骤1:(1)创建config-server项目(2)在config-server中开启Config Server功能(3)在config-server配置文件进行相关配置(4&…

Axure复选框全选反选取消高级交互

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:复选框全选反选取消制作 主要内容:点击复选框,实现列表数据项全选选中、反选和取消选中效果 应用场景:多项选定…

【MySQL 保姆级教学】表的增删改查(上)

表的增删改查 1. 创建一个表 CREATE2 插入数据 INSERT INTO2.1 语法2.2 插入单行数据全列插入2.3 插入多行数据指定列插入2.4 同步更新 ON DUPLICATE KEY UPDATE2.4.1 引入2.4.2 同步更新2.4.3 查看被影响的行 2.5. 替换 REPLACE INTO 3. Retrieve(查询SELECT&#…

有道在线翻译+4款新星,翻译从此无障碍,你get了吗?

现在全世界都连在一起了,说话不一样的问题再也不是啥大事。不管是搞研究、谈生意还是平时过日子,翻译软件都成了我们离不开的帮手。今儿,我们特激动地告诉大家,有道在线翻译和三个新伙伴一起,给Windows系统做了个超牛的…

9.校园二手网站系统( Springboot 和 thymeleaf(html)开源框架)

目录 1.系统的受众说明 2.系统需求分析 2.2.1用户功能模块 2.2.2二手交易功能需求 2.2.3需求发布功能需求 2.3.1操作流程 2.3.2添加信息流程 2.3.3删除信息流程 2.4 系统E-R图 3.系统概要设计 3.1系统的整体架构 3.2 数据库表 4.系统实现 4.1用户功能模块 4.2 二…

数据集成系统:赋能企业数字化转型的核心技术

在当今数字化时代下,企业面临数据量增长和多样化带来了巨大的挑战。如何整合利用这些数据是企业成功决策的基础。所以在这样的背景之下,数据集成系统成为了企业关注点。将不同来源的数据整合在一起,并且能够清晰的分析各类问题,已…

程序员们辛苦啦!1024程序员节,今天,我们不一样!

一、程序员节来历 程序员节(Programmers Day)是一年中专门为程序员和计算机科学工作者所设立的节日,通常是在每年的第256天庆祝。256这个数字在编程中具有特别的意义,因为它是2的8次方,代表着一个字节可以表示的所有可…

如何借助前端表格控件助力企业实现财务数字化转型

最新技术资源(建议收藏) https://www.grapecity.com.cn/resources/ 前言 在当今快速变化的经济环境中,记账软件对个人和企业的重要性愈发突出。对于个人而言,它可以帮助用户实时掌握财务状况,促进合理消费和有效储蓄&…

Java项目-基于Springboot的高校党务系统项目(源码+说明).zip

作者:计算机学长阿伟 开发技术:SpringBoot、SSM、Vue、MySQL、ElementUI等,“文末源码”。 开发运行环境 开发语言:Java数据库:MySQL技术:SpringBoot、Vue、Mybaits Plus、ELementUI工具:IDEA/…

【SoC_Design】USB基本知识

目录 USB物理接口 USB3.0物理层支持dp-alt的usb type-c接口 拓扑结构层次结构 USB物理接口 USB2.0 两线:D、D- USB3 六线:D、D-、SSTX、SSTX-、SSRX、SSRX- USB3 2lane 十线: D、D-、(SSTX、SSTX-、SSRX、SSRX-)x2USB2…

什么是KKT 条件(Karush-Kuhn-Tucker 条件)

KKT 条件(Karush-Kuhn-Tucker 条件)是优化理论中的一组必要条件,适用于求解带有等式和不等式约束的非线性规划问题。当目标函数和约束条件是凸的时,KKT 条件也是找到最优解的充分条件。在支持向量机(SVM)的…

CSS文本基础知识

1、文本缩进 属性名:text-indent 属性值:数值px; 数字em(推荐:1em当前标签的字号大小) 例:代码: 结果: 2、文本对齐方式 作用:控制内容水平方式 属性名&#xff1a…

【力扣 | SQL题 | 每日3题】力扣1990, 2020, 2051

1. 力扣1990:统计实验的数量 1.1 题目: 表: Experiments ----------------------- | Column Name | Type | ----------------------- | experiment_id | int | | platform | enum | | experiment_name | enum | ----------------------…

公众号变现及生财内参项目建议

一、核心内容 (一)公众号变现分享 从业者王薄荷介绍公众号常规盈利思路为推文广告和品牌广告,公众号能外链的地方有菜单栏和阅读原文,虽菜单栏点击率低但有商业价值。以小说为例,主要盈利方式是小黄文截止在高潮部分…

HTB:Knife[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many TCP ports are open on Knife? 2.What version of PHP is running on the webserver? 并没有我们需要的信息,接着使用浏览器访问靶机80端口 尝试使用ffuf对靶机Web进行一下目录FUZZ 使用curl访问该文件获取HTTP头…

VisionPro 手部骨骼跟踪 Skeletal Hand Tracking 虚拟首饰

骨骼手部跟踪由XR Hands Package中的Hand Subsystem提供。使用场景中的Hand Visualizer组件,用户可以显示玩家手部的蒙皮网格或每个关节的几何图形,以及用于基于手部物理交互的物理对象。用户可以直接针对Hand Subsystem编写 C# 脚本,以推断骨…

聚焦IOC容器刷新环节postProcessBeanFactory(BeanFactory后置处理)专项

目录 一、IOC容器的刷新环节快速回顾 二、postProcessBeanFactory源码展示分析 (一)模版方法postProcessBeanFactory (二)AnnotationConfigServletWebServerApplicationContext 调用父类的 postProcessBeanFactory 包扫描 …

React综合指南(二)

https://activity.csdn.net/creatActivity?id10787 #1024程序员节|征文# 21、 React中的状态是什么?它是如何使用的?? 状态是 React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现…

rk3568 android11 单独烧写内核。

问题: 我现在 遇到一个问题,如果我单独 烧写boot.img 的话,就会进入 recovery 的模式。 如下图: 问题说明: 如果我烧写的 Update.img 是可以启动的。那么我再烧写一个 编译 update.img 顺带编译出来的 boot.img 是可以正常启动的。 问题出在 , 如果我 重新编译一遍 ,使…