容器,到底是什么东西?

通俗的来说容器其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用“装”起来的技术。这样,应用与应用之间,就因为有了边界而不至于相互干扰;而被装进集装箱的应用,也可以被方便地搬来搬去。不过,这两个能力说起来简单,但要用技术手段去实现它们,确并不是很容易。所以,本篇文章就来剖析一下容器的实现方式

我们知道一个程序被执行起来之后,它就会从磁盘上的二进制文件,变成了计算机内存中的数据、寄存器里的值、堆栈中的指令、被打开的文件,以及各种设备的状态信息的一个集合也就是一个进程

所以,对于进程来说,它的静态表现就是程序,平常都安安静静地待在磁盘上;而一旦运行起来,它就变成了计算机里的数据和状态的总和,这就是它的动态表现。

而容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”。正是因为这个边界才会让容器里面的程序看不到宿主机上其他的程序从而给程序一种它就是在一个独立的操作系统上的假象

对于 Docker 等大多数 Linux 容器来说,Cgroups和Namespace 技术就是它们实现的关键

接下来的内容是以你已经初步了解docker的使用为基础的

Namespace
1
docker run -it holloword /bin/sh

我们知道使用如上命令就可以直接启动一个holloword容器

如果这个时候我们在容器里执行一下 ps 指令,就会发现一些比较有趣的事情:

123
PID  USER   TIME COMMANDine  1 root   0:00 /bin/sh 10 root   0:00 ps

可以看到,我们在 Docker 里最开始执行的 /bin/sh,就是这个容器内部的第 1 号进程(PID=1),而这个容器里一共只有两个进程在运行。这就意味着,

前面执行的 /bin/sh,以及我们刚刚执行的 ps,已经被 Docker 隔离在了一个跟宿主机完全不同的世界当中

本来,每当我们在宿主机上运行了一个 /bin/sh 程序,操作系统都会给它分配一个进程编号,比如 PID=100。这个编号是进程的唯一标识,就像员工的工牌一样。所以 PID=100,可以粗略地理解为这个 /bin/sh 是我们公司里的第 100 号员工,而第 1 号员工就自然是比尔 · 盖茨这样统领全局的人物

而现在,我们要通过 Docker 把这个 /bin/sh 程序运行在一个容器当中。这时候,Docker 就会在这个第 100 号员工入职时给他施一个“障眼法”,让他永远看不到前面的其他 99 个员工,更看不到比尔 · 盖茨。这样,他就会错误地以为自己就是公司里的第 1 号员工

这种机制,其实就是对被隔离应用的进程空间做了手脚,使得这些进程只能看到重新计算过的进程编号,比如 PID=1。可实际上,他们在宿主机的操作系统里,还是原来的第 100 号进程

这种技术,就是 Linux 里面的 Namespace 机制。而 Namespace 的使用方式也非常有意思:它其实只是 Linux 创建新进程的一个可选参数。我们知道,

在 Linux 系统中创建线程的系统调用是 clone(),比如:

1
int pid = clone(main_function, stack_size, SIGCHLD, NULL);

这个系统调用就会为我们创建一个新的进程,并且返回它的进程号 pid。

而当我们用 clone() 系统调用创建一个新进程时,就可以在参数中指定 CLONE_NEWPID 参数,比如:

1
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);

这时,新创建的这个进程将会“看到”一个全新的进程空间,在这个进程空间里,它的 PID 是 1。之所以说“看到”,是因为这只是一个“障眼法”,

在宿主机真实的进程空间里,这个进程的 PID 还是真实的数值,比如 100。

当然,我们还可以多次执行上面的 clone() 调用,这样就会创建多个 PID Namespace,而每个 Namespace 里的应用进程,都会认为自己是当前容器里的

第 1 号进程,它们既看不到宿主机里真正的进程空间,也看不到其他 PID Namespace 里的具体情况

而除了我们刚刚用到的 PID Namespace,

Linux 操作系统还提供了 Mount、UTS、IPC、Network 和 User 这些 Namespace,用来对各种不同的进程上下文进行“障眼法”操作

比如:

  • Mount Namespace,用于让被隔离进程只看到当前 Namespace 里的挂载点信息;
  • Network Namespace,用于让被隔离进程看到当前 Namespace 里的网络设备和配置。

    这,就是 Linux 容器实现的第一个机制了

所以,Docker 容器这个听起来玄而又玄的概念,实际上是在创建容器进程时,指定了这个进程所需要启用的一组 Namespace 参数。这样,容器就只能“看”到当前 Namespace 所限定的资源、文件、设备、状态,或者配置。而对于宿主机以及其他不相关的程序,它就完全看不到了

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

这时,这些进程就会觉得自己是各自 PID Namespace 里的第 1 号进程,只能看到各自 Mount Namespace 里挂载的目录和文件,只能访问到各自 Network Namespace 里的网络设备,就仿佛运行在一个个“容器”里面,与世隔绝

Cgroups

实际上只是使用Namespace隔离了进程还不能称之为容器,例如:

虽然容器内的第 1 号进程在“障眼法”的干扰下只能看到容器里的情况,但是宿主机上,它作为第 100 号进程与其他所有进程之间依然是平等的竞争关系。

这就意味着,虽然第 100 号进程表面上被隔离了起来,

但是它所能够使用到的资源(比如 CPU、内存),却是可以随时被宿主机上的其他进程(或者其他容器)占用的。

当然,这个 100 号进程自己也可能把所有资源吃光。这些情况,显然都不是一个“沙盒”应该表现出来的合理行为。

而Linux Cgroups 就是 Linux 内核中用来为进程设置资源限制的一个重要功能它最主要的作用是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽以及对进程进行优先级设置、审计,以及将进程挂起和恢复等操作

除 CPU 子系统外,Cgroups 的每一项子系统都有其独有的资源限制能力,比如:

  • blkio,为块设备设定I/O 限制,一般用于磁盘等设备
  • cpuset,为进程分配单独的 CPU 核和对应的内存节点
  • memory,为进程设定内存使用的限制

Linux Cgroups 的设计还是比较易用的,简单粗暴地理解呢,它就是一个子系统目录加上一组资源限制文件的组合。

而对于 Docker 等 Linux 容器项目来说,它们只需要在每个子系统下面,为每个容器创建一个控制组(即创建一个新目录),然后在启动容器进程之后,把这个进程的 PID 填写到对应控制组的 tasks 文件中就可以了。

而至于在这些控制组下面的资源文件里填上什么值,就靠用户执行 docker run 时的参数指定了,比如这样一条命令:

1
docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/sh

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

1234
$ 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 带宽。

一个正在运行的 Docker 容器,其实就是一个启用了多个 Linux Namespace 的应用进程,而这个进程能够使用的资源量,则受 Cgroups 配置的限制。

这也是容器技术中一个非常重要的概念,即:容器是一个“单进程”模型

原文地址:https://www.cnblogs.com/zhixiang-org-cn/p/11287003.html

时间: 2024-10-20 11:23:01

容器,到底是什么东西?的相关文章

Mysql数据库的mysql Schema 到底有哪些东西& 手工注入的基础要领

#查看数据库版本 mysql> select @@version; +------------+ | @@version  | +------------+ | 5.5.16-log | +------------+ 1 row in set (0.00 sec) mysql> select * from information_schema.schemata; # 保存了系统的所有的数据库名 ,关键的字段是schema_name # 2 rows in set (0.04 sec)表示只有2

学习PHP到底要学习哪些东西?

很多学PHP的人一直也搞不清楚,一个PHP程序员和Java程序员或者是.net程序员有什么不同,告诉你,其实都一样,没有什么不同.下面的内容,就是针对一个Java程序员掌握的技能对比PHP来说的!告诉你,它们其实是一样的,不过是工具而已,没有高低贵贱之分.只不过你不熟练,不知道而已. 语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样的语法错误,并且知道如何修正. 命令:必须熟悉PHP带的一些常用命令及其常用选项,熟悉那些命令,自己运行php.exe -

对刷对打到底是什么东西呢?是否靠谱?

对刷对打到底是什么东西呢?是否靠谱? 如何解答标题,请看个人介绍 为什么你不敢说累,因为你还没有成就!为什么你不敢说苦,因为你身后还有一大家子人!为什么你不敢休息,因为你还没有存款!为什么你不敢偷懒,因为你还要生活!为什么你敢努力奋斗,因为你没得选择!总之一句话,你不能选择放弃!坚持到底,相信你自己,加油!加油!你今天的努力,终有一天会有美好的回报!快乐总是低于我们的期望,而痛苦则永远超出我们对它的想象.人的特性是每个人都不一样,有不一样的肉体,不一样的想法,不一样的欲望,不一样的想法.一个人的

经常听说人说汽车的ECU 这个到底是什么东西

别人老说刷ECU,喜欢研究车,总会对专业术语要研究一下, ECU是汽车电脑,刷汽车电脑可以提高动力,也可以减低动力,看需求.    简单原理如下.    1.汽车发动机运转由汽车电脑(即ECU)控制.    2.ECU控制发动机的进气量,喷油量,点火时间等,从而决定引擎运转效率和功率.扭力等.    3.发动机工作在各种转速.档位.负荷.温度等条件时'所对应'的进气量,喷油量,点火时间等信息,以数据库方式记录在ECU中,这个数据库称为"M.A.P.".    4.刷ECU的实质就是修改

JS事件处理函数中return false到底是什么东西

在<JS DOM编程艺术>一书中,用return false来阻止事件默认行为,可是js高程3里没有这种用法,那这到底是什么呢. 先看一下知乎的一个解释 就此问题,首先要纠正两个观点: 1. 事件处理方法中 的 return false 并不是终止事件,而是阻止事件宿主的默认行为: 2. 不是在所有的事件处理方法中 return fasle 都能阻止事件宿主的默认行为: 事实上,仅仅是在HTML事件属性 和 DOM0级事件处理方法中 才能通过返回 return false 的形式组织事件宿主的

scipy csc csr到底是什么东西

哎,真尼玛,网上关于scipy 和 theano的 sparse matrix中的 csc matrix 和 csr matrix太少了,有,也只是使用,并没有说明,那个矩阵是怎么生成的.参考例子: >>> data = np.asarray([7, 8, 9]) >>> indices = np.asarray([0, 1, 2]) >>> indptr = np.asarray([0, 2, 3, 3]) >>> m = sp.c

php单元测试到底是什么东西呢?

前言: 真正写php代码也有3年时间了,勉强算是一个php程序员, 但是,心底却一直没有底气. 都说测试驱动开发,可我连程序开发中什么是单元测试?这种基本的程序员的素养都 还不是很清楚,痛定思痛,决定这些基本的知识技能还是要有所了解和掌握.要不然,一直用着别人现成的框架,写着一些简单的业务逻辑代码,宝宝心里其实是慌的 :). 这篇文章不错:https://www.sitepoint.com/tutorial-introduction-to-unit-testing-in-php-with-php

Spring容器初始化

问:Spring容器.SpringIOC是什么? 那么Spring容器到底是什么东西呢,长什么样子呢?为什么感觉像是哆啦A梦的百宝箱,什么东西都能拿出来? 所以本文针对以上问题对一个简单的说明, 1.首先我们整个过程中要保持一个概念,容器中的Bean要经历以下步骤带着这个思想去看就会好理解一些: 2.来个简单的例子 ??:XML方式定义Bean <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=

关于容器、虚拟机以及 Docker 的一个入门教程

Yves yao · 2017-09-05翻译 · 1315阅读 原文链接 huangxiaolu审校 源地址:http://zcfy.cc/article/a-beginner-friendly-introduction-to-containers-vms-and-docker-4139.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io Source: https://flipboard.com/topic/