云原生 • Docker用故事给老板讲Docker核心原理
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了云原生 • Docker用故事给老板讲Docker核心原理相关的知识,希望对你有一定的参考价值。
白话Docker核心原理
Docker是什么?
Docker使用Google公司推出的Go语言进行开发实现,基于操作系统内核中Cgroup(资源控制)、Namespace(资源隔离)与OverlayFS(数据存储)等技术,实现了基于操作系统层面的虚拟化技术。
理解的早就理解了这句话核心本质,不理解的给他这么一解释还是云里雾里。那我们先不急于搞懂Docker
是什么,说到Docker
容器,就不得不说下虚拟机(Virtual Machine
),Docker
容器和虚拟机又有什么区别呢?
Docker vs 虚拟机
虚拟机对于我们开发者是个再熟悉不过的概念,比如我们经常使用VMware Workstation
搭建虚拟操作系统部署应用,使用JVM
虚拟机运行Java
应用等,如下图,通常使用虚拟机管理器作为中间转换层,可以屏蔽底层操作系统或硬件设备差异,比如上层虚拟机操作系统(Guest OS
)执行程序或Java
程序运行等,这个中间件转换层就像翻译家一样,将上层执行的指令解释翻译成下层操作系统对应的指令进行执行。
正如Java世界中吹嘘的"一次编译,到处运行",虚拟机本质上通过中间件转换层屏蔽了底层差异,模拟出一个新环境,实现与平台无关,达到与外界隔离的目的,这就是虚拟机实现虚拟化的核心思想。
从虚拟机架构实现上可以看出,其存在一个很大问题:所有的指令都必须经过虚拟机管理器这个中间转换层翻译解释才能在真实操作系统上运行,这就意味着虚拟机会存在性能损耗。另外,为了模拟一个Linux
环境上运行的应用,需要使用VMware运行部署一个宿主机(Guest OS
),再在宿主机上运行应用,宿主机本身占用好几个G的存储空间、400-500MB+内存空间,现在微服务架构动不动就是10+、100+个应用组件需要部署,那这些组件都需要做隔离部署使用虚拟机方式无疑是致命的。
上述说的虚拟机存在性能问题和资源浪费造成了虚拟机对细粒度的环境隔离有点力不从心,而这又与当前流行的微服务架构场景下,系统被拆分成几十、上百个微服务应用组件需要独立部署存在冲突。Docker
推崇的是一种轻量级容器的结构,即一个应用一个容器。所以,Docker一出来就被推向巅峰,那它又是如何搞定虚拟机隔离存在的问题的呢?
Docker容器核心技术
Docker
容器中进程是直接运行在底层操作系统上,没有中间转换层,所以也就不存在性能损耗的问题。关键那它是如何做到隔离的呢?
这里就引出了支撑Docker
容器的两大内核技术:Namespace和Cgroups(Control Groups)。Namespace主要是用来进行资源隔离,对于那些计算型资源,比如CPU
、内存、磁盘IO等不能进行隔离的资源,这时就需要采用Cgroups
进行资源限制,防止有些资源消耗较大的容器,将整个物理机器的硬件资源(CPU
, Memory
、磁盘IO等) 占满,进而影响其它进程性能。
Namespace
和Cgroups
这两个技术都是Linux
内核本身支持的功能,Docker
如果只使用这两大技术也不可能造就出道即巅峰的火热程度,Docker
创新点恰恰是引入镜像概念,并使用联合文件系统(UnionFS
)技术很好的实现了镜像分层,这样就可以将应用部署介质、依赖环境配置文件以及操作系统二进制文件进行分层叠加构建出应用运行时文件系统环境。
镜像包含一个基础镜像(Base Image
),这个一般包含操作系统介质,比如centos
、debian
,但是它只包括使用的操作系统二进制文件,并没有包括内核相关,所以,它的体积远远小于部署整个操作系统占用的空间,比如一个centos
基础镜像大概只有70-80MB
。另外,镜像分层设计进一步减少存储占用,比如现在100+应用组件都是基于centos
基础镜像部署,实际部署时只需要拉取一份centos基础镜像,就像搭积木一样,将每一层使用的文件进行组合叠加,最终构建出程序运行时完整的目录结构。
白话核心技术关系
Docker
容器技术火热的背后,其实是Namespace
、Cgroups
和UnionFS
三大技术创新的结合,造就出了Docker
这种现象级产品。下面用个比较形象的比喻来帮助你理解三大技术关系:
1、正常程序启动时直接运行在操作系统上,使用Docker
启动程序时,也是直接运行在操作系统上,但是Docker
引擎在启动程序时会给程序套一个立方体壳(见下图);
2、这个立方体壳前后左右四个面使用Namespace
资源隔离技术打造,这样就给Docker
容器中进程和其它进程隔离开来,给容器中进程造成一种运行在一个独立环境中的假象(见下图);
3、这个立方体壳的上面这个面使用Cgroups
资源限制技术打造,避免程序壮大生长出来抢占其它进程的资源,进而影响其它进程性能,这样就给盖盖上加上了一个紧箍咒,再牛逼的程序也会把你死死的限制住(见下图);
4、最后再来看下这个立方体壳剩下的最下面这个面,其采用UnionFS
技术打造,构建出容器中进程运行时文件系统根基。将操作系统二进制指令、依赖配置文件、程序介质等通过镜像分层叠加构建出程序运行时看到的整个文件系统环境;比如宿主机是Debian系统
,但是基础镜像是CentOS环境
,容器中进程看到的是CentOS系统
,而不是Debian系统
,同时将yum install
安装的依赖介质也通过镜像打包进来,容器中进程就不需要关注宿主机上到底有没有安装该依赖介质等等,这样容器中进程看到是一个拥有程序运行时完整介质,并与宿主机操作系统隔离开的独立操作系统(见下图);
5、所以,程序运行在三大核心技术创造的立方体壳壳中,被蒙蔽双眼傻乎乎的以为运行在一个独立计算机环境中,看不到外界程序运行情况,也影响不到外界程序的运行。
如何查看Docker进程在宿主机上的PID?
Docker
容器中的进程是直接运行在宿主机上,可以通过docker inspect container
查看到Docker
容器中进程在宿主机上对应的PID信息(见下图):
宿主机上ps -ef
查看下容器进程信息:
因为,这里运行的是一个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
容器上。
云原生技术分享 | Docker入门系列:初识容器技术
云原生技术部落已经成立啦!后续将在部落专栏以系列短文的形式,向大家分享微服务、容器方面的技术与实战经验。
”Docker入门系列“系列将为大家带来容器与Docker相关的基础知识和使用技巧,涉及容器技术的基础知识、Docker常用操作、Docker的存储与网络、容器运行时与管理工具的探索等内容。由浅入深,带您轻松掌握容器技术,弄潮云原生。
赶紧来看看第一篇吧!
应用平台部 孙佳明/文
在讲技术之前,我们先来直观了解下容器这个词。容器是英文单词Container的直译,Container这个单词有集装箱、容器的意思。要形象的理解什么是容器技术,可以从集装箱上寻找答案。
早期航运是没有集装箱概念的,那时候货物的堆放杂乱无章,很影响出货和运输效率。集装箱的出现,因其标准化,并可以层层重叠,既能通过卡车货运,也可以直接通过吊车装卸并大量放置在特别设计的远洋轮船中,极大地提升了运输效率。
容器技术完美地吸收了集装箱概念的应用优点。一方面通过操作系统内核的资源隔离技术,实现了一种轻量级的虚拟化;另一方面将集装箱思想运用到了软件交付上,为应用程序提供了一个标准化运输系统。这套运输系统包括“集装箱”(容器镜像)、承载集装箱的“运载工具”(容器运行环境)、“运输系统调度人员”(容器管理工具)等。应用程序本身及其依赖可以打包成一个轻量级、可移植、自包含的容器镜像,容器镜像可移植到不同的容器运行环境上运行成容器实例。
容器技术的底层实现
容器技术主要是通过Linux内核中的Cgroup和Namespace两项技术实现轻量级虚拟化。
Cgroup全称Control Group。容器本质上是宿主机上的一个进程,Linux操作系统通过Cgroup可以设置进程使用CPU、内存和IO资源的限额。
Namespace则实现了进程之间资源的隔离,这项技术使得每个容器(进程)内看起来都有自己的文件系统、用户、进程等。拿网卡来说,即使宿主机上只有一块物理网卡,但每个容器都会认为自己有一块独立的网卡。
图:Linux使用的六种Namespace
容器正是对Cgroup和Namespace两项技术的封装,以实现的轻量级虚拟化。
容器技术的核心优势
轻量级虚拟化,小、快、强!
传统的虚拟化技术(如 VMWare, KVM, Xen),服务器上不仅需要安装Hypervisor环境,每个虚拟机还需要运行一个完整的操作系统,通常一个虚拟机镜像达到几个G,资源损耗较大。容器是一种轻量级虚拟化技术,容器是宿主机上的相互隔离的进程,每个容器共享宿主机的操作系统内核,一般容器镜像只有几百M。
图:虚拟化技术与容器技术对比
启动容器即相当于在操作系统上启动一个进程,不必再启动整个操作系统,所以容器的部署和启动速度比虚拟机快,资源利用率也大幅高于虚拟机。
环境一致,软件交付简单、高效
如今系统架构越来越复杂,由传统的单体应用,部署到有限的几台物理服务器上(Web Server/App Server/Database Server),到使用微服务架构,系统由成百上千个服务组成。一方面系统包含多种服务,这些服务有自己所依赖的库和软件包;另一方面又存在多种部署环境(研发、测试、生产),服务在交付过程中需要在不同的环境中迁移。开发人员在编写代码时需要考虑环境差异,运维人员则需要为不同的服务配置相应的环境。对双方来说,这都是一项复杂且繁琐的任务。
容器技术的使用,很好地解决上述问题:
对于开发人员 - Build Once, Run Anywhere:容器技术意味着环境隔离和可重复性。开发人员只需为应用创建一次运行环境,然后打包成容器镜像便可在其他环境上运行。
对于运维人员 - Configure Once, Run Anything:只需要配置好标准的容器运行环境,服务器就可以直接使用容器镜像运行应用实例。这使得运维人员的工作变得更高效,一致和可重复。
总结
● 容器是一种轻量级的虚拟化隔离技术,资源利用率高,具备轻、快、保证软件环境一致的特点。
● 容器镜像是开发与运维团队都认可且易于部署的交付件,降低了双方的协助成本,可大幅提升软件交付效率。
今日话题
大家对容器技术有什么自己的理解呢?欢迎留言。祝大家假期愉快~
以上是关于云原生 • Docker用故事给老板讲Docker核心原理的主要内容,如果未能解决你的问题,请参考以下文章
故事,从 Docker 讲起 | 深度揭秘阿里云 Serverless Kubernetes
用138个案例讲明白了Spring全家桶+Docker+MQ