什么是容器?
首先来看下什么是容器技术,容器是由英文 “Container” 翻译过来的,这个单词即有容器也有集装箱的意思,在这里其实更偏向于集装箱,这点也可以从Docker的Logo里看出来,不能说是毫无关系,可以说是一摸一样!我们可能是因为好读所以才译为容器。
从集装箱的用途我们可以形象的理解容器技术的场景。
集装箱的出现大大降低了航运的运输成本,因为集装箱是固定规格,整齐摆放,提升了空间利用率。当你的货物有大有小,且随意摆放,这时候会有大量的空间会被浪费,装卸货也很麻烦,就像下图这样:
有了集装箱之后,我们可以把不同大小的货物都装进不同规格的集装箱,这些集装箱都是方的,可以拼接摆放,虽然单个集装箱内部空间利用率可能不高,但是整个船的空间利用率会提升。
细一点的朋友可能会问,可不可以找几个比较大的集装箱,然后大货物小货物一起放,大货物的间隙还可以放点小货物,极致利用资源这样不是更加节省了空间?
这就说到了集装箱的另一个作用:隔离
当我们需要不同货物分开放置,避免货物之间交叉污染,这样使用集装箱可以有效的隔离不同类型的货物,这一点在IT领域更加实用,除了公司揭不开锅的情况下,生产环境我们通常不会在同一台服务器部署多个服务,虽然混部可以更有效的利用服务器资源,但是给业务带来了风险。一个是隔离级别不够,避免服务之间互相影响,导致出现对外不可用的情况,还有一个是资源不好评估,因为按照固定规格来评估服务部署数量是比较准确的,虽然服务器大部分时间在空跑,会造成比较大的浪费。但如果混部的话,同一台机器上服务和服务之间的峰值以及不同服务的业务高峰期均无法准确评估,也就无法评估出需要多少台机器,更别说后续的扩缩容了,如果你需要同时部署很多个服务,那么多个服务所在的机器管理也是一件相当麻烦的事情。
有了上面集装箱的例子,让再来看下IT领域的容器技术是什么?
容器就好比集装箱,操作系统就好比轮船,而我们的服务就是货物,我们需要使用容器来规格化服务的资源使用,如限制只使用固定大小的CPU、内存等,同时容器要能把服务隔离起来,不被外界任何进程所干扰。当然容器的创新并不仅仅是在实现一个集装箱上,还包括如何自动管理和呈现上万个这样的箱子,这才是问题的关键。
容器的核心技术就两点:
- 通过隔离保证各个服务之间不互相影响,这是通过内核提供的Namespace技术实现的一个障眼法,不同容器之间、容器和宿主机之间不可见。
- 通过限制不同容器的资源(CPU、内存等)使用,来提高硬件的使用率,这是使用内核Cgroup技术来做资源限制,保证单个容器使用资源不会占有其他容器资源,也不会占用宿主机上其他进程资源。
所以说容器其实就是Linux几个内核技术的组合,后面会单独讲这几个技术原理。
什么是Docker?
那什么是Docker呢?首先Docker不等同于容器,容器的历史要比Docker长得多,以下是容器的历史发展图:
可以看到,Docker只是容器技术的一个集大成者!它也是通过内核的Namespace和Cgroup来实现的资源隔离,但是完全可以说是Docker一己之力推动了容器的大规模推广和使用,那么Docker为什么能火爆呢?
1. 解决了应用移植过程中环境一致性问题,提供标准化的软件打包、分发的能力
就像Docker的Slogan说的: Build, Ship, and Run Any App, Anywhere ! Docker解决了如何让应用从一个软件环境转移到另一个软件环境时可靠运行的问题。可能是从开发者的笔记本到测试环境,从预发布环境到生产环境,也可能是从IDC的物理机到云上的虚拟机。
当应用支持的软件环境不相同时,就可能会出现问题。比如使用 Python 3 进行开发,而生产环境中只有Python 2.7 ,众所周知py2和py3是两种语言,大概率是跑不了了。又或者是应用依赖于第三方库,而不同环境的第三方库版本不一致,不兼容的话就很容易导致出现Crash。除了开发因素外,基础的运行环境和组件,比如网络拓扑、存储、安全策略都有可能随时发生变化,集群迁移是一件很正常的事情。
而Docker创新性的解决了这个问题,它通过定义一个容器镜像,本质上是一个容器的快照,来记录启动一个容器所需要的基本信息:程序、库、资源、配置等。同时开发人员还可以使用容器镜像公共存储仓库比如Docker Hub 、或者自建镜像存储仓库来存储你的镜像,当你的应用开发完成了,可以将应用打包进一个容器镜像,上传到镜像仓库,然后不论在任何环境都可以通过拉取镜像,执行镜像跑起来你的服务。
2. 独特的设计和封装,带来了体验上的变革。
有小伙伴可能会说,既然内核的Namespace/Cgroup都已经可以实现容器的基本功能了,那还要Docker干什么?
咱自己创建一个Cgroup,然后把进程pid放进去,用Namespace搞个障眼法,分分钟跑起来,不也能达到容器的效果吗?这样有个问题是:容器对于用户来说是个黑盒,看不见摸不着,你甚至不知道服务在容器里的运行状态,体验很不好。但是Docker带来的用户体验,是完全可以媲美虚拟机的,大家可以像登陆虚拟机一样登陆容器,执行shell命令,查看服务运行状态。这对于容器的体验来说是质的变革,传统开发者基本上不用适应容器的特性可以轻松上手了,这使得容器迅速火爆和大规模使用了起来,要感谢Docker。
现在很多公司还做了所谓的 “富容器”,通过给容器运行公共的init进程,使得容器不跟业务服务的生命周期绑定,然后可以添加系统Service进程、自定义运维组件等,进一步达到跟虚拟机一样的体验,使得容器更受欢迎。目前我司也使用了富容器技术,把员工的开发机全面换成了Docker,不再使用虚拟机了,整体体验差不多,但更灵活、轻量,成本有了进一步的提升。
虚拟机和容器的区别?
虚拟机和容器经常被放在一起讨论,但其实它们是殊途同归的,只是实现方案不一样。
不管是虚拟机还是容器都有一个共同的目标,也可以说是最主要的目标:降低成本,毕竟老板比较看重自己的钱袋子。
而数据表明,我们的服务器成本确实存在着较大的优化空间。
美国环境保护署(EPA)报告的一组有趣的统计数据:EPA 研究服务器和数据中心的能源效率时发现,实际上服务器只有 5% 的时间是在工作的。在其他时间,服务器都处于 “休眠” 状态。
虚拟机和容器则是属于实现该目标的两种不同的方案,接下来通过几个网图来形象描述下两种技术的比对:
首先来看下我们最开始的物理机时代,前面提到过,我们每个服务器通常只会部署一个服务,就像小别墅一样,独立地基,且只住一家人,避免合住带来不必要的冲突。这个时候我们是用物理机来实现了业务之间的隔离,但是服务器资源不像房子一样,越大越好,采用物理机隔离导致物理机大部分时间在空跑,带来了成本的开销,现实生活中也只有大户人家才住的起小别野,咱老百姓还是成本太高滴!
想要降低成本,最核心的还是要共享,实现对主机资源的共享,在共享的前提下要先保证隔离,因为隔离是必要的,没有隔离我们的业务就没法保证健康的运行。
接下来看下虚拟机和容器这两兄弟是如何解决这个问题的?
虚拟机技术比较像我们现在的楼房,在一块地基上盖一栋楼,把一栋楼分成很多层,每一层属于不同的人家,这样相比于独栋别墅来说,可以同一块地基容纳更多户的人家,这块地基不属于某一户人家,而是大家共享,随之带来的问题是住户和住户之间的距离感变小,隔离程度没有独栋别墅高,比如大家共享电梯,大门等。
虚拟机则是共享物理机资源,在同一个物理机上划分多个虚拟机,每个虚拟机都独立运行自己的操作系统 (类比每一层属于一户人家)。
宿主机通过 Hypervisor 在计算机硬件上创建抽象层,将单个宿主机的硬件元素(包括处理器、内存、存储器等)分成多个虚拟计算机,称为虚拟机。每个虚拟机都运行自己的操作系统 ,其行为类似于独立的计算机,实际上它仅在实际底层计算机硬件的一部分上运行。
而容器就像是胶囊式公寓一样,本质上不是一个房子 (不像虚拟机一样独立运行操作系统),只是把不同用户放在不同的箱子里分隔开来。
这里核心的一个区别是:虚拟机使用的资源(CPU/内存等) 都是宿主机实际分出去的,比如分给VM 2核4G,那这个资源就是该VM的了,其他VM或者宿主机是无法使用的,就像楼房一样你买了一层别人就住不了。而容器其实是宿主机上的一个进程而已,只不过这个进程用了一些内核技术来限制容器的资源使用上限,当容器实际用不了那么多资源时,资源会被宿主机分配给其他进程。
此外容器启动不需要先运行操作系统,启动时长比较快
因为虚拟机要先运行Guest OS,因此启动会比较慢,通常是分钟级,而容器不依赖 Guest OS,因此启动也更快,通常是秒级,这也是Docker官方经常吹嘘的优势!
容器具体实现是通过在宿主机运行一个 Docker 引擎,把应用程序放进一个独立的运行环境,称为容器,并对容器的资源进行隔离。宿主机不虚拟出底层硬件,也不预分配资源,所以资源利用率更高。
虚拟机所用硬件资源是宿主机预分配的,无论应用程序是否需要这些资源,这些资源都会被占用,而容器只是做了资源限制,并不会预占用资源,如果某个容器的实际使用资源并没有达到设定的资源限制,那空出来的资源比如CPU/内存是会给宿主机上其他进程使用的。
容器会代替虚拟机吗?
自Docker火爆起来,很多人都觉得容器要代替虚拟机,因为容器带来的用户体验已经不亚于虚拟机。
但其实容器有一个一直被大家所诟病的点,那就是他的隔离级别不高,经常会引发一些安全问题。所以目前来说,虚拟机和容器还是各有各的应用场景。
虚拟机通常用来贯穿一个操作系统的生命周期,常用于云上多租户共享物理资源,比如多个用户在同一个物理机运行自己的VM,独立操作系统,因为VM的隔离级别高,这样多个用户即使在同一台物理机上也几乎不会互相影响。
容器通常用来贯穿一个服务的生命周期,常用于单个租户集群内调度,比如一个用户买了多台物理机或者虚拟机,然后以这些机器作为母机来运行多个容器,这样保证容器的调度始终使用的是同一个用户的硬件资源,避免互相影响。如果是同一台物理机上运行着多个用户的容器,当某个用户修改了一些容器不做隔离的内容,比如Core文件路径这种不做namespace隔离的,结果影响了所有用户的容器,会带来很大的风险。
Docker带来的技术变革?
除了上述提到的容器可以有效的降低我们的服务器成本外,容器技术在一定程度上推动了很多技术架构的变革,尤其是云原生的发展,使软件开发更现代化。
1. DevOps
得益于Docker的标准化交付,开发和运维大大减少了扯皮时间。传统的应用各式各样,无统一部署方式,依赖多,运维同学通常需要编写很长的启动部署脚本才可以完整的部署一个服务,更重要的是打包发布流程无法自动化,要根据每个服务特性做专属的自动化,每个服务都做一套自动化流程加大了后期的运维成本。有了Docker之后任何应用开发完成后都输出一个Docker镜像,运维部署时只需要运行镜像就行,这种标准化的开发部署方式使持续集成和持续部署 (CI/CD)变得很好做,一整套流程可以轻松的实现自动化打包、自动化部署,提高交付速度和交付质量。
2. 微服务
目前主流的软件架构倾向于将大仓转变为一个个独立开发和部署的微服务。成千上万个这样的微服务组合起来实现产品功能。微服务可以快速迭代、降低单模块分险,随之带来的问题是服务越分越细,本来一个产品只有几个服务,现在变成了成千上万个小的微服务,那如何管理这些微服务就变得很dan疼,有了容器之后,每个服务的运行标准统一了,也因此涌现了许多“分布式操作系统”,如k8s,将服务调度、部署、动态扩缩容等一体化、平台化,分布式应用的管理问题得到了更优的解决方案。
3. 云计算
不管是虚拟机还是容器,如果仅限于在单个物理机上进行资源划分,对业务来说是没有意义的,我们所管理的物理机是成千上万的,这个时候有了“云”,很多云厂商比如阿里云、腾讯云都在做这件事情,云是有决策能力的,通过把物理资源池化,然后给不同用户/软件分配合适的资源,提高整体的资源利用率,这不论是对于大企业、小企业、还是能源效率都是一件很有意义的事情!
关于我们
欢迎关注公众号《奇迹狗狗》,很开心在这里能和你相遇~
我们会分享一些技术文章,包括但不限于游戏技术、云原生、ACM题解、基础编程知识等,如果能授人以渔,荣幸之至!
我们也会做一些有温度的产品、游戏,会陆续分享给大家,如果能博君一笑,再好不过!
产品列表: ★ WorkerHub小程序,信息均来自各个大厂员工爆料,可以查询各个公司/部门/岗位的工作做细、工作体验、工作评价等,供打工er找工作的时候参考,避雷卷王团队/天坑团队!