[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  COMMAND
    1 root      0:00 /bin/sh
    6 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)。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【思维导图】C语言—常见概念

hello,友友们,今天我们进入一个新的专栏——思维导图! 思维导图帮助我们复习知识的同时建构出一个清晰的框架,我往后会不断更新各个专栏的思维导图,关注我,一起加油! 今天我们回顾C语言中的常见…

技术分享:A-23OH型树脂在汽车涂装废溶剂回收中的应用

在当今汽车制造业竞争激烈的环境下,提高生产效率、降低成本的同时,满足环保要求已成为各制造商追求的核心目标。水性涂料因其环保、节能等多重优势,在汽车涂装领域的应用日益广泛。然而,随之而来的喷涂废溶剂处理问题也日益凸显。…

Java 项目如何连接并使用 SFTP 服务的示例详解

文章目录 1、SFTP介绍2、pom依赖3、SFTPUtil4、测试5、测试结果 1、SFTP介绍 SFTP(Secure File Transfer Protocol)是一种安全的文件传输协议,是SSH(Secure Shell)协议的一个子协议,设计用于加密和保护文件…

测试代理IP的有效性和可用性:全面方法与技巧

使用代理IP的有效性和可用性直接关系到用户的工作效率,尤其是在进行数据抓取、网络爬虫和保护个人隐私等场景中。然而,如果代理IP的质量不佳,或者无法正常工作,就可能导致操作中断、数据丢失,甚至影响整个项目的进度。…

《OpenCV计算机视觉》——人脸检测__Haar特征、级联分类器

文章目录 Haar特征一、定义与原理二、分类三、计算方法四、应用五、优缺点 级联分类器一、定义与原理二、结构与组成三、举例说明 Haar特征 Haar特征是一种在计算机视觉和图像处理中常用的特征描述方法,特别适用于物体识别,尤其是人脸检测。以下是对Haa…

一次性入门三款分布式定时任务调度框架:Quartz、ElasticJob3.0、xxl-job

分布式定时任务调度框架(文末有源码) 前言1、Quartz1.1 数据库1.2 maven依赖1.3 代码实现1.3.1 创建一个job1.3.1 为job设置trigger 1.4 配置文件1.5 启动、测试1.1 单机1.2 集群 2、ElasticJob2.1 下载zk2.2 新建三个类型的作业2.3 配置文件2.4 启动项目…

基于Java微信小程序的水果销售系统详细设计和实现(源码+lw+部署文档+讲解等)

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不…

创客项目秀 | 基于使用 XIAO BLE Sense 和 Edge Impulse 的宠物活动跟踪器

今天为大家带来的是来自美国的创作者米顿-达斯的作品:宠物活动跟踪器.这个装置主要是为宠物主人提供关于宠物日常活动量的详尽数据,还能够根据宠物的独特需求,提供个性化的健康建议和活动指导。 项目背景 为了全面促进宠物的健康与活力,采用…

Python 数值计算与数值分析基础

Python 数值计算与数值分析基础 示例演示 当涉及到Python数值计算和数值分析时,下面是20个示例,涵盖了一些常见的用法: 1.数值积分: 在 Python 中,你可以使用 scipy.integrate 模块中的 quad 函数来进行数值积分 …

【Linux驱动开发】通过ioremap虚拟内存映射的寄存器操作驱动、C应用函数库开发 devmem命令测试(正点原子STM32MP135文档BUG)

【Linux驱动开发】通过ioremap虚拟内存映射的寄存器操作驱动、C应用函数库开发 devmem命令测试(正点原子STM32MP135文档BUG) 【Linux驱动开发】通过ioremap虚拟内存映射的寄存器操作驱动 devmem命令测试 gitee库: https://gitee.com/Mike_Zho…

记一次Netty模拟压测应用开发

背景 最近需要开发一个上游端模拟数据推送,测试高流量下下游的业务功能处理速度,大致架构如下 准备工作 构造消息体,由于是模拟大量数据推送并没有业务逻辑,所以我们使用池化的directBuffer增加推送消息以及减少创建和消费buf…

13.1 Linux_网络编程_TCP/UDP

字节序 1、概述 什么是字节序: 字节序就是字节的存储顺序,分为大端字节序和小端字节序。 大端字节序:低地址存高位(网络)小端字节序:低地址存低位(主机) 检验主机字节序模式&…

Java @RequestPart注解:同时实现文件上传与JSON对象传参

RequestPart注解:用于处理multipart/form-data请求的一部分,通常用于文件上传或者处理表单中的字段。 java后端举例: PostMapping("/fileTest")public AjaxResult fileTest(RequestPart("file") MultipartFile file,Req…

【时间之外】IT人求职和创业应知【10】

认知决定你的赚钱能力。以下是今天可能影响你求职和创业的热点新闻: 今日关键字:SFISF【互换便利】 1. 央行推出股票回购增持再贷款,科技股全线爆发 新闻概要: 2024年10月18日,央行等三部门联合发布《关于设立股票回购增持再贷款有关事宜的通知》,同时表示年底有进一步…

基于GeoScene Pro的开源数据治理与二维制图规范化处理智能工具箱

内容导读 本文描述的是一个基于GeoScene Pro4.0/ArcGIS3.1 Pro平台的开源数据治理与二维制图规范化处理智能工具箱(免费试用,文末有获取方式),旨在解决GIS应用中数据转换、检查、治理和制图数据规范化处理方面的问题。 工具箱结合了Geoscene/ArcGIS Pr…

Asp.net Core SignalR 跨域设置(Furion)

前端VUE2.0/3.0 后端NET8.0/NET6.0 框架Furion 前端安装SignalR通信库&#xff0c;下面任意一条安装指令都可以&#xff0c;根据项目自行选择 npm install microsoft/signalr yarn add microsoft/signalr前端使用 <script> import { HubConnectionBuilder } from micr…

[Halcon矩阵] 通过手眼标定矩阵计算相机旋转角度

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…

SpringBoot教程(三十二) | SpringBoot集成Skywalking链路跟踪

SpringBoot教程&#xff08;三十二&#xff09; | SpringBoot集成Skywalking链路跟踪 一、Skywalking是什么&#xff1f;二、Skywalking与JDK版本的对应关系三、Skywalking下载四、Skywalking 数据存储五、Skywalking 的启动六、部署探针前提&#xff1a; Agents 8.9.0 放入 项…

C#从零开始学习(用unity探索C#)(unity Lab1)

初次使用Unity 本章所有的代码都放在 https://github.com/hikinazimi/head-first-Csharp Unity的下载与安装 从 unity官网下载Unity Hub Unity的使用 安装后,注册账号,下载unity版本,然后创建3d项目 设置窗口界面布局 3D对象的创建 点击对象,然后点击Move Guzmo,就可以拖动…

云服务解决方案,针对小程序、网页、HTML5等轻量化视频解决方案

无论是社交媒体上的短视频分享&#xff0c;还是企业官网中的产品展示&#xff0c;亦或是教育平台上的互动课程&#xff0c;高质量、易制作的视频内容正以前所未有的速度改变着我们的生活方式和工作模式。然而&#xff0c;面对多样化的发布平台和日益增长的个性化需求&#xff0…