文言Docker中心原理

Docker是什么?

「Docker运用Google公司推出的Go语言进行开发完成,根据操作体系内核中Cgroup(资源控制)、Namespace(资源阻隔)与OverlayFS(数据存储)等技能,完成了根据操作体系层面的虚拟化技能。」

了解的早就了解了这句话中心本质,不了解的给他这么一解说仍是云里雾里。那咱们先不急于搞懂Docker是什么,提到Docker容器,就不得不说下虚拟机(Virtual Machine),Docker容器和虚拟机又有什么区别呢?

Docker vs 虚拟机

虚拟机关于咱们开发者是个再了解不过的概念,比方咱们经常运用VMware Workstation建立虚拟操作体系布置运用,运用JVM虚拟机运转Java运用等,如下图,「一般运用虚拟机管理器作为中心转化层,能够屏蔽底层操作体系或硬件设备差异」,比方上层虚拟机操作体系(Guest OS)履行程序或Java程序运转等,「这个中心件转化层就像翻译家一样,将上层履行的指令解说翻译成下层操作体系对应的指令进行履行」

【云原生 • Docker】用故事给老板讲Docker核心原理

正如Java世界中吹嘘的”一次编译,到处运转”,「虚拟机本质上经过中心件转化层屏蔽了底层差异,模拟出一个新环境,完成与平台无关,到达与外界阻隔的目的,这便是虚拟机完成虚拟化的中心思想」

从虚拟机架构完成上能够看出,其存在一个很大问题:一切的指令都必须经过虚拟机管理器这个中心转化层翻译解说才能在实在操作体系上运转,这就意味着虚拟机会存在功能损耗。别的,为了模拟一个Linux环境上运转的运用,需求运用VMware运转布置一个宿主机(Guest OS),再在宿主机上运转运用,宿主机自身占用好几个G的存储空间、400-500MB+内存空间,现在微服务架构动不动便是10+、100+个运用组件需求布置,那这些组件都需求做阻隔布置运用虚拟机方式无疑是致命的。

上述说的虚拟机存在功能问题和资源浪费形成了虚拟机对细粒度的环境阻隔有点力不从心,而这又与当时流行的微服务架构场景下,体系被拆分红几十、上百个微服务运用组件需求独立布置存在冲突。Docker推崇的是一种轻量级容器的结构,即一个运用一个容器。所以,Docker一出来就被面向巅峰,那它又是怎么搞定虚拟机阻隔存在的问题的呢?

Docker容器中心技能

Docker容器中进程是直接运转在底层操作体系上,没有中心转化层,所以也就不存在功能损耗的问题。要害那它是怎么做到阻隔的呢?

【云原生 • Docker】用故事给老板讲Docker核心原理

「这儿就引出了支撑Docker容器的两大内核技能:Namespace和Cgroups(Control Groups)」。Namespace首要是用来进行**「资源阻隔」,关于那些核算型资源,比方CPU、内存、磁盘IO等不能进行阻隔的资源,这时就需求选用Cgroups进行「资源约束」**,防止有些资源消耗较大的容器,将整个物理机器的硬件资源(CPU, Memory、磁盘IO等) 占满,从而影响其它进程功能。

NamespaceCgroups这两个技能都是Linux内核自身支持的功能,Docker假如只运用这两大技能也不可能造就出道即巅峰的火热程度,Docker立异点恰恰是引入镜像概念,并运用联合文件体系(UnionFS)技能很好的完成了镜像分层,这样就能够将运用布置介质、依靠环境配置文件以及操作体系二进制文件进行分层叠加构建出运用运转时文件体系环境。

【云原生 • Docker】用故事给老板讲Docker核心原理

镜像包括一个根底镜像(Base Image),这个一般包括操作体系介质,比方centosdebian,但是它只包括运用的操作体系二进制文件,并没有包括内核相关,所以,它的体积远远小于布置整个操作体系占用的空间,比方一个centos根底镜像大约只要70-80MB。别的,镜像分层设计进一步削减存储占用,比方现在100+运用组件都是根据centos根底镜像布置,实际布置时只需求拉取一份centos根底镜像,就像搭积木一样,将每一层运用的文件进行组合叠加,终究构建出程序运转时完好的目录结构。

文言中心技能联系

Docker容器技能火热的背后,其实是NamespaceCgroupsUnionFS三大技能立异的结合,造就出了Docker这种现象级产品」。下面用个比较形象的比方来协助你了解三大技能联系:

1、正常程序发动时直接运转在操作体系上,运用Docker发动程序时,也是直接运转在操作体系上,但是Docker引擎在发动程序时会给程序套一个立方体壳(见下图);

【云原生 • Docker】用故事给老板讲Docker核心原理

2、这个立方体壳前后左右四个面运用Namespace资源阻隔技能打造,这样就给Docker容器中进程和其它进程阻隔开来,给容器中进程形成一种运转在一个独立环境中的假象(见下图);

3、这个立方体壳的上面这个面运用Cgroups资源约束技能打造,防止程序强大成长出来抢占其它进程的资源,从而影响其它进程功能,这样就给盖盖上加上了一个紧箍咒,再牛逼的程序也会把你死死的约束住(见下图);

4、最终再来看下这个立方体壳剩余的最下面这个面,其选用UnionFS技能打造,构建出容器中进程运转时文件体系根基。将操作体系二进制指令、依靠配置文件、程序介质等经过镜像分层叠加构建出程序运转时看到的整个文件体系环境;比方宿主机是Debian体系,但是根底镜像是CentOS环境,容器中进程看到的是CentOS体系,而不是Debian体系,一起将yum install安装的依靠介质也经过镜像打包进来,容器中进程就不需求重视宿主机上究竟有没有安装该依靠介质等等,这样容器中进程看到是一个具有程序运转时完好介质,并与宿主机操作体系阻隔开的独立操作体系(见下图);

5、所以,程序运转在三大中心技能创造的立方体壳壳中,被遮盖双眼傻乎乎的认为运转在一个独立核算机环境中,看不到外界程序运转情况,也影响不到外界程序的运转。

【云原生 • Docker】用故事给老板讲Docker核心原理

怎么检查Docker进程在宿主机上的PID?

Docker容器中的进程是直接运转在宿主机上,能够经过docker inspect container检查到Docker容器中进程在宿主机上对应的PID信息(见下图):

【云原生 • Docker】用故事给老板讲Docker核心原理

宿主机上ps -ef检查下容器进程信息:

【云原生 • Docker】用故事给老板讲Docker核心原理

由于,这儿运转的是一个nginx容器,所以宿主机上看到对应的是nginx主进程,一起该进程创建了两个nginx worker子进程。

Docker容器缺点

「高功能、轻便是容器相较于虚拟机最大的优势,容器本质上是一种特别的进程。」

不过,有利就有弊,根据Namespace的资源阻隔和Cgroups的资源约束都不是那么完全,由于容器之间底层仍是共享运用宿主机的Linux内核,尽管你能够在容器里运用不同版别的操作体系文件,比方CentOS或者Ubuntu,但这并不能改变共享宿主机内核的事实。这意味着,假如你要在Windows宿主机上运转Linux容器,或者在低版别的Linux宿主机上运转高版别的Linux容器,都是行不通的。

其次,在Linux内核中,有许多资源和对象是不能被Namespace化的,最典型的比如便是:时刻。这就意味着,假如你的容器中的程序修正了时刻,整个宿主机的时刻都会被随之修正,这明显不符合用户的预期。

别的,跟Namespace的情况相似,Cgroups对资源的约束能力也有许多不完善的当地,这儿最常见的是/proc 文件体系的问题。Linux下的/proc目录存储的是记录当时内核运转状况的一系列特别文件,用户能够经过访问这些文件,检查体系以及当时正在运转的进程的信息,比方CPU运用情况、内存占用率等,这些文件也是top指令检查体系信息的首要数据来源。但是,你假如在容器里履行top指令,就会发现,它显示的信息居然是宿主机的CPU和内存数据,而不是当时容器的数据。形成这个问题的原因便是,Docker引擎在发动进程时直接将宿主机/proc下许多文件挂载到Docker容器上。