2013 年的后端技术领域,已经太久没有出现过令人兴奋的东西了。曾经被人们寄予厚望的云计算技术,已经从当初虚无缥缈的概念蜕变成了实实在在的虚拟机和账单。而相比于如日中天的 AWS 和盛极一时的 OpenStack , 以 Cloud Foundry 为代表的开源 PaaS 项目,却成了当时云计算技术中的一股清流。

当时,Cloud Foundry 项目已经基本度过了最艰难的概念普及和用户教育阶段,吸引了百度、京东、华为、IBM 等一大批国内外技术厂商,开启了以开源 PaaS 为核心构建平台层服务能力的变革。如果你有机会问问当时的云计算从业者,他们十有八九会告诉你:PaaS 的时代就要来了!

这种说法其实一点儿也没错,如果不是后来一个叫 Docker 的开源项目突然冒出来的话。

事实上,当时还名叫 dotCloud 的 Docker 公司,也是这波 PaaS 热潮中的一份子。只不过相比于 Heroku、Pivotal、Red Hat 等 PaaS 弄潮儿,dotCloud 公司实在是太微不足道了,而它的主打产品由于跟主流的 Cloud Foundry 社区脱节,长期以来无人问津。眼看就要被如火如荼的 PaaS 风潮抛弃,这时 dotCloud 公司却做出了这样一个决定:将自己的容器项目 Docker 开源。

显然,这个决定在当时根本没人在乎。

“容器” 这个概念从来就不新鲜,也不是 Docker 公司发明的。即使在当时最热门的 Pass 项目 Cloud Foundry 中,容器也只是其最底层、最没人关注的那一部分。说到这里,我就以当时的事实标准 Cloud Foundry 为例来解说 PaaS 技术。

PaaS 项目被大家接纳的一个主要原因,就在于它提供了一种名为“应用托管”的能力。当时,虚拟机和云计算已经是比较普通的技术和服务了,主流用户的普通用法就是租一批 AWS 或者 OpenStack 的虚拟机,然后像以前管理物理服务器那样,用脚本或者手动的方式在这些机器上部署应用。

当然,在部署过程中难免会遇到云端虚拟机和本地环境不一致的问题,所以当时的云计算服务比的就是谁能更好地模拟本地服务器环境,提供更好的“上云”体验。而 PaaS 开源项目的出现就是当时这个问题的最佳解决方案。

举个例子,虚拟机创建好之后,运维人员只需在这些机器上部署一个 Cloud Foundry 项目,然后开发者只要执行一条命令就能把本地应用部署到云上,这条命令就是:

cf push _我的应用_

是不是很神奇?

事实上,像 Cloud Foundry 这样的 Pass 项目,最核心的组件就是一套应用的打包和分发机制。Cloud Foundry 为每种主流编程语言都定义了一种打包格式,而 cf push 的作用,基本上等同于用户把应用的可执行文件和启动脚本打进一个压缩包内,上传到云上 Cloud Foundry 的存储中。接着,Cloud Foundry 会通过调度器选择一个可以运行这个应用的虚拟机,然后通知这个机器上的 Agent 下载应压缩包并启动。

这时关键点来了,由于需要再一个虚拟机启动多个来自不同用户的应用,Cloud Foundry 会调用操作系统的 Cgroups 和 Namespace 机制为每一个应用单独创建一个称为“沙盒”的隔离环境,然后在“沙盒”中启动这些应用进程。这样就实现了把多个用户的应用互不干涉地在虚拟机里批量地、自动地运行起来的目的。

这正是 PaaS 项目最核心的能力。这些 Cloud Foundry 用来运行应用的隔离环境,或者说“沙盒”,就是所谓的“容器”。

Docker 项目实际上跟 Cloud Foundry 的容器并没有太大不同,所以它发布后不久,Cloud Foundry 的首席产品经理 James Bayer 就在社区里做了一次详细对比,告诉用户 Docker 实际上只是一个同样使用 Cgroups 和 Namespace 实现的“沙盒”而已,没有什么特别的“黑科技”,也不需要特别关注。

然而短短几个月,Docker 香满园就迅速崛起了。它的崛起速度如此之快,以至于 Cloud Foundry 以及所有的 PaaS 社区还没来得及成为它的竞争对手,就直接被宣告出局。

事实上,Docker 项目确实与 Cloud Foundry 的容器在大部分功能和实现原理上一样,可偏偏就是这剩下的一小部分不同的功能,成了 Docker 项目接下来“呼风唤雨”的不二法宝。

这个功能就是 Docker 镜像。

恐怕就连 Docker 项目的作者 Solomon Hykes 自己当时都没料到,这个小小的创新,在短短几年内就迅速改变了整个云计算领域的发展历程。

如前所述,PaaS 之所以能够帮助用户大规模地部署应用到集群里,是因为它提供了一套应用打包的功能。可偏偏就是这个打包功能,成了 PaaS 日后不断被用户诟病的一个“软肋”。

出现这个问题的根本原因是,一旦用上 PaaS ,用户就必须为每种语言、每种框架,甚至每个版本的应用维护一个打好的包。这个打包过程没有任何章法可循,更麻烦的是,明明在本地运行得好好的应用,却需要做很多修改和配置工作才能在 PaaS 里运行起来。而这些修改和配置并没有什么经验可以借鉴,基本上得靠不断试错,直到摸清了本地应用和远端 PaaS 匹配的“脾气”才能搞定。

结局就是,cf push 确实能一键部署了,但是为了实现这个一键部署,用户为每个应用打包的工作可谓一波三折,费尽心思。

而 Docker 镜像解决的恰恰就是打包这个根本性的问题。所谓 Docker 镜像,其实就是一个压缩包。但是这个压缩包里的内容,比 PaaS 的应用可执行文件+启动脚本的组合要丰富多了。实际上,大多数 Docker 镜像是直接由一个完整操作系统的所有文件和目录构成的,所以这个压缩包里的内容跟你本地开发和测试环境用的操作系统完全一样。

这就有意思了:假设你的应用在本地运行时,能看见的环境是 CentOs 7.2 操作系统的所有文件和目录,那么只要用 CentOS 7.2 的 ISO 做一个压缩包,再把你的应用可执行文件也压缩进去,那么无论在哪里解压这个压缩包,都可以得到与你本地测试时一样的环境。当然,你的应用也在里面!

这就是 Docker 镜像最厉害的地方:只要有这个压缩包在手,你就可以使用某种技术创建一个“沙盒”,在“沙盒”中解压这个压缩包,然后就可以运行你的程序了。

更重要的是,这个压缩包包含了完整的操作系统文件和目录,也就是包含了这个应用运行所需要的所有依赖,所以你可以先用这个压缩包在本地进行开发和测试,完成之后再上传到云端运行。

在此过程中,你完全不需要进行任何配置或者修改,因为这个压缩包赋予了你一种极其宝贵的能力:本地环境和云端环境高度一致!

这正是 Docker 镜像的精髓。

那么,有了 Docker 镜像这个利器,PaaS 里最核心的打包系统顿时就没了用武之地,最让用户头疼的打包过程中的麻烦也随之消失了。相比之下,在当今的互联网世界,Docker 镜像需要的操作系统文件和目录可谓唾手可得。

所以,你只需要提供下载好的操作系统文件和目录,然后使用它制作一个压缩包接口,这个命令就是:

docker build _我的镜像_

一旦镜像制作完成,用户就可以让 Docker 创建一个“沙盒”来解压这个镜像,然后在“沙盒”中运行自己的应用,这个命令就是:

docker run _我的镜像_

当然,docker run 创建的“沙盒”也是使用 Cgroups 和 Namespaces 机制创建出来的隔离环境。

所以,Docker 项目给 PaaS 世界带来的“降维打击”,其实是它提供了一种非常便利的打包机制。这种机制直接打包了应用程序运行所需要的整个操作系统,从而保证了本地环境和云端环境的高度一致,避免了用户通过“试错”来匹配不同运行环境之间差异的痛苦过程。

对于开发者来说,在终于体验到了生产力解放所带来的的痛快之后,他们自然选择了用“脚”投票,直接宣告了 PaaS 时代的结束。

不过,虽然 Docker 项目解决了应用打包的难题,但如前所述,它并不能代替 PaaS 完成大规模部署应用的职责。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐