Docker:namespace环境隔离 CGroup资源控制

Docker:namespace环境隔离 & CGroup资源控制

    • Docker
      • 虚拟机
      • 容器
    • namespace
      • 相关命令
        • dd
        • mkfs
        • df
        • mount
        • unshare
      • 进程隔离
      • 文件隔离
    • CGroup
      • 相关命令
        • pidstat
        • stress
        • cgroup控制
      • 内存控制
      • CPU控制


Docker

在开发中,经常会遇到环境问题,比如程序依赖某个库,库又要具体的版本,以及某些函数必须在指定平台使用,这就会为开发带来很大的麻烦。

为此,有人提出采用虚拟化技术,为软件虚拟出一个环境。就像是在一个冰天雪地的地方建了一个花房养花,花房内温度湿度都刚刚好,将花房与外部的冰雪隔离开。

这种实现环境隔离的技术,主要有虚拟机和容器两种,Docker属于容器化的隔离技术。

虚拟机

所谓虚拟机,其实就是把一台物理主机虚拟为多台逻辑上的计算机。多台虚拟机共用物理上的同一台计算机,而每个逻辑上的计算机可以运行不同的操作系统,安装不同的库,从而提供不同的环境。

在这里插入图片描述

如图,上图红色部分与蓝色部分是两个不同的虚拟机,虚拟机技术在硬件层之上,在操作系统层就开始进行隔离。虚拟机通过伪造一个硬件的抽象接口,把操作系统嫁接到硬件上。

在这里插入图片描述

在硬件层与操作系统层之间,会存在一个虚拟化层,这其实就是一个软件,该层会负责分配硬件资源。

可以看出,如果想要创建多个虚拟机,就要在一台物理主机上跑多个操作系统,这其实要不小的开销,而容器是一种更加轻量的隔离技术。


容器

容器也是一种虚拟化的实现技术,它在操作系统之上进行环境隔离,每个容器可以有自己的一套工具和库,但是它们共享操作系统的内核

在这里插入图片描述

如图,红色和蓝色区域,是两个不同的容器,它们的网络,文件系统等等都是隔离的,互不影响。

因为使用同样的操作系统内核,所以它们的系统调用接口自然就相同,但是基于相同的系统调用接口,配置了不同的库,不同的文件系统,那么最后两个容器就不同。

在这里插入图片描述

比如说上图,可以通过容积隔离技术在一个centOS操作系统上,运行不同版本的Ubuntu容器。这听起来很异想天开,但其实不然。

每个容器有自己独立的用户空间,这包括文件系统、库和用户级工具。用户操作接口是用户在容器内操作系统时接触到的命令行工具、库和应用。因此可以在上层的容器中,执行Ubuntu的命令,虽然内核是CentOS的。

相比于虚拟机技术,容器化技术非常轻量,容器相当于一个跑在操作系统上的进程,启动一个进程的速度是非常快的,通过容器技术,只需几秒钟就在主机上打开一个新的操作系统。

而容器化技术,目前最流行的实现方案就是Docker

那么容器化技术是如何实现各种资源的隔离的?对Linux来说,它依赖于namespaceCGroup技术,这两个技术是由Linux内核提供的。

  • namespace:实现进程,文件系统,用户等资源隔离
  • CGroup:实现CPU,内存,网络等资源隔离

namespace

namespaceLinux 内核用来隔离内核资源的方式。通过 namespace 可以让进程只能看到与自己相关的一部分资源,不同namespace的进程感觉不到对方的存在。

具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。namespaces 是对全局系统资源的一种封装隔离,使得处于不同 namespace 的进程拥有独立的全局系统资源,改变一个namespace 中的系统资源只会影响当前namespace 里的进程,对其他namespace 中的进程没有影响。

常见namespace

namespace隔离资源
UTS主机名和域名
IPC进程间通信:信号量、消息队列、共享内存
PID进程
NetWork网络设备,端口等
Mount文件系统
User用户

解释:

  1. UTS:每个UTS namespace都可以有自己独立的主机和域名
  2. IPC:每个IPC namespace内部的进程可以进行进程间通信,但是不能跨越IPC namespace进行通信,在逻辑上这算跨主机通信
  3. PID:每个PID namespace都有自己独立的进程pid系统,不同的PID namespace可以出现相同的pid
  4. NetWork:每个NetWork namespace都有自己独立的网络设备,IP地址,路由表,端口号等
  5. Mount:每个Mount namespace有自己的文件系统,互相不能看到对方的文件
  6. User:每个User namespace都有自己独立的用户和用户组

相关命令

dd

dd可以从指定输入流读取数据,并输出到指定输出流。

参数:

  • if=文件名:从指定文件读取数据,如果不指定,则默认从标准输入读取
  • of=文件名:输出数据到指定文件,如果不指定,则默认输出到标准输出
  • bs=xxx:设定一个块block的大小
  • coun=blocks:仅仅从输入流拷贝blocks个块,结合上一个参数,可以指定要读取的数据个数

创建一个指定大小的空文件:

dd if=/dev/zero of=test.txt bs=1M count=80

以上指令,就是创建了一个80M的空文件,输入流是/dev/zero,这是一个会不断产生空白字符的文件,也就是ASCII中字符编码为0的字符。使用这个文件作为输入流,可以快速初始化一个空文件。

在这里插入图片描述

可以看到,最后创建了一个大小为83886080 byte的文件,其实就是80 M


mkfs

mkfs用于在设备上创建一个文件系统,俗称格式化。

mkfs [option] filesys [blocks]

选项:

  • -t:要创建的文件系统类型,比如ext3ext4

其中filesys是被格式化的文件,而block是文件系统的磁盘块数,可以省略。

把刚才创建的文件进行格式化:

mkfs -t ext4 test.txt

在这里插入图片描述

这样就把刚才的空文件进行了格式化,变成了一个文件系统。


df

df用于显示Linux中的文件系统磁盘使用情况。

选项:

  • -h:以更加可视化的形式输出,默认情况下数据以字节为单位,加上该选项后,会自动转化为GBMB等单位
  • -T:显示文件系统的类型

在这里插入图片描述

查看当前的文件系统,可以看到,其不包含刚才格式化的test.txt,因为他只是一个被格式化的文件,还没有被挂载。


mount

mount用于挂载文件系统,相当于给文件系统一个访问入口。

比如说你在电脑上插入一个U盘,它往往会显示为E盘或者其它盘符。这个盘符就是一个访问入口,因为U盘本身就是一个文件系统,如果想要访问这个文件系统的内容,Windows自然要提供一个入口,因此它自动分配一个E盘,让用户可以通过E盘访问U盘。

同样的,刚才格式化test.txt为一个文件系统,现在要将其挂载起来,才能访问这个文件系统。

mount [option] device dir
  • device:被挂载的文件
  • dir:挂载到的位置

选项:

  • -t:挂载文件的类型,比如ext3ext4,但是可以不填,mount会自动识别文件系统的类型

把刚才的test.txt挂载到当前/mymount目录下:

在这里插入图片描述

首先创建一个空目录/mymount,随后把test.txt挂载到这个目录下,随后可以看到,/mymount出现了新的内容。

随后通过df -t ext4查看系统的文件系统,可以看到/dev/loop0文件系统,被挂载到了/mymount下,说明成功挂载了一个文件系统。

如果想要删除这个文件系统,可以执行:

umount /mymount

以上所有命令,是在完成一个文件系统的创建,便于后续测试文件系统的隔离性。

接下来看看Linux提供的创建namespace的命令:

unshare

unshare用于执行一个进程,并且为这个进程提供一个独立的namespace

unshare [option] program 
  • program:要执行的程序

选项:

  • -i --ipc:不共享IPC空间
  • -m --mount:不共享Mount空间
  • -n --net:不共享Net空间
  • -p --pid:不共享PID空间
  • -u --uts:不共享UTS空间
  • -U --user:不共享用户空间
  • --fork:创建一个子进程执行program
  • --mount-proc:挂载一个新的/proc到命名空间内

此处这个--fork有一点点绕,因为ushare这个命令,本身也是一个进程,是在宿主机环境运行的。

如果直接执行unshare,流程如下:

  1. unshare 创建一个新的命名空间
  2. unshare 执行 program,但是没有创建新的进程,而是直接用 program 替换了 unshare 本身

在这里插入图片描述

以上unshare不带有--fork参数,执行了/bin/bash进程。进入namespace后,可以看到,/bin/bash的父进程是-bash。这个-bash就是宿主机的bash进程。因为unshare是在bash中执行的,所以unshare的父进程是-bash。最后将/bin/bash替换unshare/bin/bash的父进程就是原先的父进程-bash

这种情况下,看不到unshare进程,因为/bin/bash就是原先的unshare

如果加上--fork参数,流程如下:

  1. unshare 创建一个新的命名空间
  2. unshare 在新的命名空间中创建一个新的子进程来执行 program
  3. unshare本身不退出

在这里插入图片描述

加上--fork参数后,/bin/bash的父进程就变成了unshareunshare的父进程是-bash。也就是说unshare创建了一个子进程来执行program,而不是亲自执行program

如果你跟着操作了,此时还处于namespace中,要通过exit来退出,不然会影响后续操作。


进程隔离

现在尝试进行进程隔离,也就是隔离,通过--pid选项完成:

unshare --fork --pid --mount-proc /bin/bash

以上命令,用于创建一个新的PID命名空间,并执行bash进程,也就是执行一个新的命令行。

此处要加上--fork选项,因为要进行进程隔离,而unshare本身是宿主机的进程,如果直接让unshare本身去执行program,那么program就不在新的namespace中,导致错误。

在这里插入图片描述

以上示例中,因为没有加上--fork,报错了。

如果只加上--fork选项,此时还是不能观察到进程隔离。因为topps等进程监控的命令,是依赖于/proc/PID这个目录的。但是命令没有进行文件系统隔离,所以还是会使用宿主机的/proc/PID目录,导致namespace内部可以看到外部的进程。

为此,unshare命令专门提供了一个参数--mount-proc,在新的namespace挂载一个独立的/proc目录,方便进行进程的监控。

进程隔离结果:

在这里插入图片描述

可以看到,创建了新的namespace后,ps -aux只能查到两个进程,一个是bash,一个是grep。这就将namespace内部的进程与宿主机的进程隔离开了。


文件隔离

想要进行文件隔离,创建一个新的namespace,然后在里面创建一个文件系统并挂载。再在外部的宿主机查看是否可以看到这个文件系统。

  1. 创建一个新的文件隔离命名空间
unshare --mount --fork /bin/bash
  1. 创建一个指定大小的空文件
dd if=/dev/zero of=data.img bs=1M count=80
  1. 格式化文件为文件系统
mkfs -t ext4 data.img
  1. 挂载文件系统
mkdir /mymount
mount -t ext4 data.img /mymount

在这里插入图片描述

最后通过df -t ext4,可以看到文件系统已经挂载成功了。

打开一个新的终端,执行df -t ext4

在这里插入图片描述

此时左右终端看到的文件系统不同,左侧的namespace内挂载的新文件系统,右侧终端看不到了,这就是文件隔离。

此时在namespace中执行exit,就会退出这个bash,进而退出namespace,在其内部创建的文件,挂载的文件系统都会自动销毁。

在这里插入图片描述

exit退出后,再次查看文件系统,也找不到刚才挂载的文件系统了。这和刚才两个终端的情况不同,之前是不同namespace之间的文件隔离,而此处是退出namespace后,文件系统已经被销毁了。


CGroup

cgroup的可以把一系列任务,也就是进程划分到一个任务组,并且限制一个任务组的资源占用。比如可以限制一系列任务最多占用多少CPU,占用多少内存等等。

也就是说,namespace完成了不同容器之间环境的隔离,而cgroup完成了每个容器资源的访问限制。

相关命令

为了方便测试CPU与内存压力,此处使用两个工具分别完成产生压力以及压力检测。

pidstat

pidstat用于检测一个进程的CPU、内存、IO、线程等等资源的占用情况。

需要下载:

apt install sysstat

语法:

pidstat [option] [时间间隔] [次数]

选项:

  • -u:检测CPU使用情况,默认就是该选项
  • -r:检测内存使用情况
  • -d:检测IO使用情况
  • -p:指定进程pid,如果指定ALL则监视所有进程
  • -C:检测通过指定命令启动的进程

直接执行pidstat

在这里插入图片描述

此时会输出所有进程,默认输出CPU占用情况,也就是%CPU这一栏。

通过-p指定进程:

在这里插入图片描述

通过-C指定进程:

在这里插入图片描述

此处指定bash进程。

通过-r检测内存:

在这里插入图片描述

此处%MEM栏就是内存占用情况。

指定检测次数与频率:

在这里插入图片描述

此处的1 3表示:每隔一秒检测一次,一共检测三次。


stress

stress是一个压力测试工具,可以对CPU、内存IO等进行压力测试。

这个工具也要下载:

apt install stress

语法:

stress [option]

参数:

  • -c --cpu N:产生N个进程,每个进程都循环调用sqrt函数产生CPU压力
  • -m --vm N:产生N个进程,每个进程都循环调用malloc free函数,产生内存压力

示例:

在这里插入图片描述

左侧使用stress创建了一个进程进行CPU压力输出,右侧检测stress产生的压力,结果一个进程占满了100%的CPU资源。


cgroup控制

接下来看看如何操作cgroup,它并没有现成的指令来控制,而是需要操控配置文件来完成。

/proc/cgroups查看cgroup支持的资源控制:

在这里插入图片描述

/proc/cgroups文件中,包含了cgroup所支持的资源控制的类型,比如CPU、内存等。

查看cgroup挂载信息:

mount | grep cgroup

在这里插入图片描述

这里就是每一个资源的控制目录,比如在/sys/fs/cgroup/cpu目录下,就是控制CPU资源的配置文件。


内存控制

创建一个内存的控制组很简单,跳转到目录/sys/fs/cgroup/memory,然后创建一个目录:

在这里插入图片描述

此处创建了一个test_memory目录,这就算创建了一个test_memory内存控制组。进入目录后,可以看到这个目录被初始化了很多文件,其中memory.limit_in_bytes这个文件,就是这个cgroup可以使用的最大内存数目,以字节为单位。

想要限制这个cgroup的最大内存数量,直接往文件写入数据即可:

echo "20971520" > memory.limit_in_bytes

此处20971520其实就是20 mb,此后这个cgroup的最大内存占用就不会超过20 mb

那么要如何把一个进程加入控制组?这里有一个task文件,只需要把进程的PID写入到这个文件中,那么一个进程就算加入了这个cgroup

在这里插入图片描述

如图,创建一个进程,占用50m的内存:

stress -m 1 --vm-bytes 50m

随后在另一个端口通过pidstat查看stressPID,为1507015069,其中15069是控制进程,15070是真正在产生内存压力的进程。将15070写入tasks文件中,让其加入cgroup

结果左侧的stress退出了,无法产生50m的压力。这是因为一开始就限制了cgroup只能占用最多20 m的内存。一旦进程加入后,就会受到限制,从而崩溃。


CPU控制

创建一个CPU的控制组也一样,跳转到目录/sys/fs/cgroup/cpu,然后创建一个目录:

在这里插入图片描述

此处创建了一个test_cpu目录,也就死和创建了一个test_cpuCPU控制组。这个目录同样被初始化了很多文件。

其中控制CPU占用的是cpu.cfs_period_uscpu.cfs_quota_us,这两个文件共同完成CPU资源限制。其中cpu.cfs_period_us作为分母,cpu.cfs_quota_us作为分子,以百分比的形式限制CPU。

比如cpu.cfs_period_us内填入5000cpu.cfs_quota_us内填入2000。那么该cgroup最多可以占用2000/5000也就是40%的CPU资源。要注意的是,这两个文件的最小值都是1000,不允许使用比1000更小的数字进行配置。另外的cpu.cfs_quota_us的默认值为-1,表示可以占用100%的CPU。

另一个就是tasks文件,同样的只要把PID写入这个文件,就算加入了这个CPU控制组。

启动一个stress进程:

在这里插入图片描述

由于stress本身就会尽可能占满CPU,右侧输出窗口每隔一秒输出stress的状态,其一直保持100%的CPU资源占用。

左下角窗口先限制了test_cpu这个控制组的CPU最大占用率是2000/10000,也就是20%

随后把stress的PID20849写入tasks

在这里插入图片描述

写入后,从右边的窗口可以看出,stress的CPU占用率立马下降,100%37%最后稳定在20%

可以cgroup成功对进程的CPU进行了限制。


容器化技术在Linux中基于namespacecgroup实现,namespace完成不同容器之间的环境隔离,而cgroup完成多个容器对资源的占用限制,合理分配资源。这就是容器化技术,以及docker的最基本原理,也是底层依赖。


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

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

相关文章

RabbitMq-队列交换机绑定关系优化为枚举注册

📚目录 📚简介:🚀比较💨通常注册🌈优化后注册 ✍️代码💫自动注册的关键代码 📚简介: 该项目介绍,rabbitMq消息中间件,对队列的注册,交换机的注册&#xff0c…

D50【python 接口自动化学习】- python基础之类

day50 init方法 学习日期:20241027 学习目标:类 -- 64 init方法:如何为对象传递参数? 学习笔记: 魔术方法 init方法 class Klass(object):# 定义初始化方法,类实例化时自动进行初始化def __init__(self…

检索引擎Elasticsearch

一.为什么要用Elasticsearch 由于我们在运行我们的项目的时候通常都是将数据存到mysql或者sql serve等数据库中,在进行数据搜索时使用sql 语句 like进行模糊匹配查询,其一:虽然可以查到数据,但是它模糊匹配查询速度较慢&#xff0…

grep,wc和管道符,echo,tail和重定向符,vi编辑器

学习目标: 1.掌握使用grep命令过滤文件内容 2.掌握使用wc命令统计内容数量 3.掌握|管道符的概念和应用 4.掌握使用echo命令输出内容 5.掌握反引号的使用 6.掌握tail命令跟踪文件更改 7.掌握重定向符号使用 8.掌握使用VI \ VIM编辑器完成文件编辑工作 grep…

你知道吗?从 .NET9 开始删除内置的 Swagger 支持 (Swashbuckle)!

.NET 9 中使用 Scalar 替代内置的 Swagger 支持 (Swashbuckle) 为什么 Swagger (Swashbuckle) 被删除?Swagger 的替代方案:Scalar(Scalar.AspNetCore)如何在 Dotnet 9 中使用它?如何…

Python4

4. 更多控制流工具 除了刚介绍的 while 语句&#xff0c;Python 还用了一些别的。我们将在本章中遇到它们。 4.1. if 语句 if elif else if x<0: x 0 print(Negative changed to zero) elif x0: print( zero) else: print(More) 4.2. for 语句 Pyth…

【大模型理论篇】大模型压缩技术之注意力层剪枝以及与MLP层联合剪枝

1. 背景分析 本来打算写一篇关于大模型蒸馏的文章&#xff0c;但刚好看到近期发表的一篇讨论大模型压缩的文章【1】&#xff0c;是关于注意力机制冗余性的讨论&#xff0c;比较有意思&#xff0c;作者分析得出并不是所有的注意力都是必须的&#xff0c;可以通过对模型去除冗余的…

引爆品牌曝光:揭秘Facebook品牌知名度广告的成功秘诀

来源&#xff1a;CREATING SUCCESSFUL FACEBOOK BRAND AWARENESS 本文主要介绍如何创建成功的Facebook品牌知名度广告活动。 创建成功的Facebook品牌知名度广告活动 在当今以Facebook为驱动的社交媒体管理中&#xff0c;品牌需要通过以下共同因素来构建品牌知名度&#xff1a;…

【音视频 | ADPCM】音频编码ADPCM详细介绍及例子

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

【ArcGIS Pro实操第5期】全局及局部空间插值:GPI、LPI、IDW等

ArcGIS Pro实操第5期&#xff1a;全局及局部空间插值 ArcGIS Pro-用于空间插值的丰富工具箱实操&#xff1a;空间插值方法1&#xff1a;Trend Surface Model for Interpolation-以降水数据为例方法2&#xff1a;Kernel Density Estimation Method-以单位面积鹿的目击数为例方法…

spring-第十一章 注解开发

spring 文章目录 spring前言1.注解回顾1.1原理1.2springIOC注解扫描原理1.2.1解释1.2.2案例 2.声明bean的注解补充&#xff1a;Bean注解&#xff0c;管理三方包对象 3.spring注解的使用3.1加入aop依赖3.2配置文件中添加context命名空间3.3配置文件中指定要扫描的包3.4在Bean上使…

2024_SHCTF_week2_Crypto

pading 题目&#xff1a; from Crypto.Util.number import * import gmpy2 flag bSHCTF{********} assert len(flag) 39 p getPrime(512) q getPrime(512) n p * q e 0x3 pad ba_easy_problem c pow(bytes_to_long(flag pad),e,n) print(fn {n}) print(fc {c})思路…

视频编辑的创意工坊,使用视频剪辑软件将视频随机分割成两段并去声进行MP3音频和M3u8文件的生成,让视频制作更高效

面对海量的视频编辑任务&#xff0c;你是否曾感到手足无措&#xff0c;渴望一种既简单又高效的方式来处理它们&#xff1f;别担心&#xff0c;媒体梦工厂软件带着它的魔法棒来啦&#xff01;它就像一位技艺高超的视频巫师&#xff0c;能轻松帮你在线完成视频编辑任务&#xff0…

提示工程(Prompt Engineering)指南(入门篇)

一、什么是AIGC AIGC全称为 “Artificial Intelligence Generated Content”&#xff0c;即 “人工智能生成内容”。代表了一种由语言模型和聊天机器人等人工智能系统驱动的内容创作的突破性方法。与人类作者制作的传统内容不同&#xff0c;AIGC 是通过算法生成的&#xff0c;…

二十二、Python基础语法(模块)

模块(module)&#xff1a;在python中&#xff0c;每个代码文件就是一个模块&#xff0c;在模块中定义的变量、函数、类别人都可以直接使用&#xff0c;如果想要使用别人写好的模块&#xff0c;就必须先导入别人的模块&#xff0c;模块名须满足标识符规则&#xff08;由字母、数…

解密 Redis:如何通过 IO 多路复用征服高并发挑战!

文章目录 一、什么是 IO 多路复用&#xff1f;二、为什么 Redis 要使用 IO 多路复用&#xff1f;三、Redis 如何实现 IO 多路复用&#xff1f;四、IO 多路复用的核心机制&#xff1a;epoll五、IO 多路复用在 Redis 中的工作流程六、IO 多路复用的优点七、IO 多路复用使用中的注…

stm32 ISP 串口程序下载

硬件原理图&#xff1a; 下载是通过 uart1 。不同的芯片 &#xff0c; 下载的uart 是不一样的。 最终连接到了 PA9&#xff0c; PA10 驱动的安装&#xff1a; 这里的驱动我已经安装过了。 程序下载软件 flymcu 是免安装的。 需要注意的点就是这些。 下载实测&#xff1a;…

电脑连接海康相机并在PictureBox和HWindowControl中分别显示。

展示结果&#xff1a; 下面附上界面中所有控件的Name&#xff0c;只需照着红字设置对应的控件Name即可 下面附上小编主界面的全部代码&#xff1a; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; …

【算法练习】最小生成树

题意&#xff1a;【模板】最小生成树 方法1&#xff1a;Prim算法(稠密边用优&#xff09; #include <bits/stdc.h> using namespace std; int n,m,u,v,d,ans; bool f[5001]; vector<pair<int,int>> a[5001];//用结构体和重载比直接定义小根堆似乎还快一点点…

利用 Google AI 工具提升应用智能化:ML Kit、TensorFlowLite、Cloud Vision、AutoML、Gemini

在code应用开发中&#xff0c;机器学习和人工智能正逐渐成为提升用户体验和应用智能化的重要手段。Google 提供了多种强大的 AI 工具&#xff0c;可以帮助开发者快速集成各种机器学习功能。本文将详细介绍五个关键工具&#xff1a; Firebase ML Kit、TensorFlow Lite、Google …