本文投稿给《高可用架构》首发。

2015年自己还只是一个容器的使用者,2016年作为容器和云相关的开发者,对容器生态圈也比较关注,本文整体从生态圈角度分析了一下当前的各容器相关产品,作为个人年度总结(本来是打算年前发的,可惜一直拖到年后了)。

  1. 本文只代表个人观点,难免有遗漏的地方,还请指正。
  2. 本文的视角是技术生态圈角度,而不是使用和市场占有角度,也就是说该产品是以填补了技术生态圈的某个空隙而生存下来,而不是通过市场或者其他方式。

Docker

提到容器就不能不说 Docker。容器技术虽然存在了很长时间,却因 Docker 而火。很长时间里,很多人的概念里基本 Docker 就代表容器。一次一产品经理朋友问我做什么,我说做容器相关,她表示很不懂,但说是 Docker ,她就明白了,可见 Docker 之火。这一年里,Docker 发布了几个重要版本。我们先回顾下 Docker 本来是什么,再说它的变化。

  1. Docker 的镜像机制提供了一种更高级的通用的应用制品(artifact)包,也就是大家说的集装箱能力。原来各种操作系统或编程语言都有各自己的制品机制,ubuntu 的 deb,redhat 的 rpm,java 的 jar、war,各自的依赖管理,制品库都不相同。应用从源码打包,分发到制品库,再部署到服务器,很难抽象出一种通用的流程和机制。而有了 Docker 的镜像以及镜像仓库标准之后,这个流程终于可以标准化了。于是雨后春笋般冒出很多镜像管理仓库,这在以前的制品管理领域是很难想象的,以前貌似也就 java 领域的 nexus 和 artifactory 略完备些。
  2. Docker 镜像机制以及制作工具,取代了一部分 ansible/puppet 的职能,至少主机上的各种软件栈以及依赖关系的定义和维护被容器替代,运维人员的不可变基础设施的梦想被 Docker 实现。
  3. Docker 对 cgroups/namespace 机制以及网络的封装,使其很容易在本地模拟出多节点运行环境,方便开发人员开发调试复杂的,分布式的软件系统。
  4. Docker 的 daemon 进程,取代了一部分 systemd/supervisor 这样的系统初始化进程管理器的作用,通过 Docker 运行的服务,可以不受 systemd 管理,由 docker daemon 维护其生命周期。

前三点基本上都是容器相关或者延伸的,唯独第四点,深受其他容器编排调度厂商的诟病。任何分布式的管理系统,都会在每个主机上安装一个自己的 agent,由这个 agent 管理该节点上的应用进程。从这点功能上来说,和 Docker daemon 是冲突的,操作系统的 systemd,可以忽略不用就行,但要用 Docker 容器的话,离不开 Docker daemon 。设想一下,如果你老板让你管理一个团队,但任何管理指令都只能通过另外一个人来发出,你也会感觉不爽吧?所以 Docker 和其他容器编排调度系统的冲突从开始就种下了。感觉开始 Docker 团队也没思考这个问题,自己的 Swarm 也是用独立的 agent,但后来发现有点多余,把 Swarm 的 agent 以及调度器内置到 Docker daemon 不就行?何况 Docker daemon 本身已经支持了 remote API,并且这样设计还是一个无中心的对等节点集群模式,部署运维更方便。于是 Docker 的 1.12 内置了 Swarm(准确的说是SwarmKit),几个命令就将多个单机版本的 Docker daemon 变成一个 cluster,还支持了 service 概念(多个容器实例副本的抽象),1.13 支持了 stack 的概念(多个 service 的组合) 和 Compose(编排定义文件),基本上一个略完备的编排调度系统已经成型。

而这个变化,也表明了和其他容器编排调度系统的决裂。本来 Docker 作为容器的一种,大家都在上面基于容器搭建编排调度系统,还能和平共处。容器相当于轮子,编排调度系统是车,结果有一天造轮子的厂商说自己的几个轮子直接拼接起来就称为一辆车了,造车的厂商不急才怪,这相当于发起了『降维』攻击。

有了编排调度系统,Docker 进而推出 Store 也是顺理成章。服务器端的应用大多不是单个节点或进程的应用,需要将多个服务组装,一直以来大家都在寻找一种方式实现服务器端应用的一键安装和部署。Docker 的应用打包了编排文件以及镜像定义,配合编排调度系统提供的标准环境,再用 Store 作为应用分发,意图已经非常明确。但感觉 Docker 这步走的略匆忙,当前编排调度系统尚未成熟,就着急推出更上一层的应用,可能会拖累后面的演进,不过这也应该是受商业化的压力所致吧。

当然 Docker 出此决策,面临的挑战也是巨大的。容器生态圈的割裂,导致 Docker 得以一己之力重塑自己的生态圈。Docker 推出的容器网络标准(libnetwork)不被其他厂商接受,其他厂商也在降低对 Docker 的依赖程度(整个后面具体分析时会提到)。Swarm 成熟度还不够用在生产环境,它的网络当前只支持 overlay,尚不能支持自己的网络插件标准,编排文件的完备程度也不够。存储方面,去年 Docker 收购了 Infinit (很早就关注 Infinit,它一直宣称要开源,但迟迟没等到源码,就听到了它被 Docker 收购的消息)这家做分布式存储的公司。如果 Docker 在2017年解决网络和存储两个分布式系统的痛点,Swarm 的前景还是可期。

作为一个开发者,我自己其实挺喜欢 Docker 的这种设计的,虽然它推出的有点晚。这种模式符合开发团队对容器的渐进式接纳。比如开始可以先将 Docker 当做一种制品包管理工具,网络用 host 模式,这种方式和在主机上维护部署多个应用的进程没有区别,只是接管了依赖以及安装包的维护。然后当开发流程的打包机制改造完毕,开发人员的习惯逐渐改变,这时候就可以引入 Docker 的网络解决方案,先改造应用直接通过容器的网络进行通信,但部署和调度都沿用原来的模式。等这些都改造完,运维也成熟了,然后开启 Swarm 模式,将应用的部署和调度交给 Swarm,基本上完成了应用的容器化改造。这就像谈恋爱一样,先约约会,牵牵小手,然后(此处省略若干字),然后才是谈婚论嫁,考虑要不要做一辈子的承诺。而其他编排系统呢,一上来就要用户回答:你准备把你的一切以及后半生交付给我了么?很多人就得犹豫了吧。

总结一下,这一年,Docker 已经不是原来的 Docker,它代表一种容器方案,一个系统软件,也代表一个商标,一个公司,还代表一种容器编排调度系统。容器之战刚刚开始,三足鼎立,胜负未知。但无论最后结果如何,Docker 一初创公司,从开发者工具切入,仅仅三年,火遍全球技术圈,搅动整个服务器端技术栈,进而涉足企业应用市场,携用户以抗巨头,前所未有。传统的企业市场,决策权多在不懂技术的领导,所以解决方案中对开发者是否友好,不是一个关键点,但从 Docker 以及国外最近的一些公司的案例(比如 slack,twilio 等)来看,这一现象正在改变,这表明了开发者群体的成熟和话语权的增加,企业应用对开发者的友好程度将成为一个竞争的关键点。

Kubernetes

我在15年底分析 Kubernetes 架构的时候,当时1.2版本尚未发布。到现在已经发布了1.6 beta 版本了。去年是 Kubernetes 爆发的一年,从社区文章以及 meetup 就可以看出来。有很多文章已经等不及开始宣布 Kubernetes 赢得了容器之战了。

Kubernetes 的优势是很多概念抽象非常符合理想的分布式调度系统,即便是你自己重新设计这样一个系统,经过不断优化和抽象,最后也会发现,不可避免的慢慢向 Kubernetes 靠近。 比如 Pod,Service,Cluster IP,ReplicationController(新的叫 ReplicaSets ),Label,以及通过 Label 自由选择的 selector 机制,以及去年引入的 DaemonSets 和 StatefulSets。

DaemonSets 用于定义需要每个主机都部署一个,并且不需要动态迁移的服务,比如监控的服务。Swarm 中尚未引入这种概念,不过这种也可能会用另外的实现方式,比如插件机制。通过 DaemonSet 定义的服务可以理解成分调度系统的 agent 扩展插件。

StatefulSets(1.5 版本之前叫 PetSets)主要是为了解决有状态服务部署的问题,它保证 pod 的唯一的网络标志(主要是 pod 的 hostname,ip 是否能保持不变取决于网络实现)的稳定性,不随 pod 迁移重建而变化,另外支持了 PersistentVolume 规范,封装了已有的分布式存储以及 IaaS 云的存储接口。

网络方面,Kubernetes 推出 CNI(Container Network Interface) 网络标准。这个标准比较简单,只是约定了调用命令的参数,如果想扩展自己的实现,只需要写个命令行工具放到系统 path 下,然后根据 CNI 调用的参数来给容器分配网络即可,可以用任何语言实现。它和 Kubernetes 基本没有任何耦合,所以也可以很容易被其他调度系统采用(比如 Mesos)。

从 Kubernetes 的演进可以看出,谷歌对 Kubernetes 的期望在标准制定,最核心的点是描述能力。官方文档 What is Kubernetes? 中有这样一段描述:

Kubernetes is not a mere “orchestration system”; it eliminates the need for orchestration. The technical definition of “orchestration” is execution of a defined workflow: do A, then B, then C. In contrast, Kubernetes is comprised of a set of independent, composable control processes that continuously drive current state towards the provided desired state. It shouldn’t matter how you get from A to C: make it so. 

它的目标不仅仅是一个编排系统,而是提供一个规范,可以让你来描述集群的架构,定义服务的最终状态,它来帮助你的系统达到和维持在这个状态。这个其实和 Puppet/Ansible 等配置管理工具的目的是一致的,只是配置管理工具只能做达到某个状态,没法实现维持到这个状态(没有动态的伸缩以及故障迁移等调度能力),同时配置管理工具的抽象层次也比较低。它之所以选择容器只是因为容器比较容易降低主机和应用的耦合,如果有其他技术能达到这个目的,支持下也不影响它的定位。所以 Kubernetes 去年推出 CRI (Container Runtime Interface) 容器标准,将 Kubernetes 和具体的容器实现进一步解耦,一方面是对 Docker 内嵌 Swarm 的一种反制,另外一方面也是它的目标的必然演进结果。

正因为这样,它让渡出了很大一部分功能给 IaaS 云(比如网络,存储),也不着急推出具体的解决方案,也不着急兼容已有的各种分布式应用,发布两年多还在专心在规范定义以及系统优化上。Kubernetes 系出名门,不担心商业化的问题,大家闺秀不愁嫁,无需迎合别人,自然有人来适应自己。

当然理想是美好的,现实是当前已经有大量的分布式系统,重复实现了许多 Kubernetes 已经实现的功能,或者集群机制是当前的 Kubernetes 的抽象概念没有覆盖到的,当前将这些系统运行到 Kubernetes 还是一件很难的事情(比如 redis cluster,hadoop,etcd,zookeeper,支持主从自动切换的mysql集群等),因为任何抽象都是以损失个性化和特殊化为代价的。这里特别说下,以前分析 Kubernetes 的时候有人反驳我这个说法,我这里不是说 Kubernetes 上不能运行 zookeeper 这样的服务,而是很难实现一键部署并且自动伸缩以及配置自动变更,很多情况下还是需要手动操作接入,比如官方的这个 zookeeper 例子

CoreOS 为了解决这个问题,推出了 operator 的概念,给不容易通过 Kubernetes 当前的抽象描述的服务(有状态服务或者特殊的集群服务),专门提供一个 operator,operator 通过调用 Kubernetes 的 API 来实现伸缩,恢复,升级备份等功能。这样虽然和 Kubernetes 的声明式理念相冲突,也无法通过 kubectl 直接操作(kubectl 有支持插件机制的提案,未来这种需求可能通过插件实现),也但当前也是一个可行的办法。(注:本文发布后 CoreOS 的李响对这段关于 operator 的描述进行了纠正,operator 是基于 Kubernetes 的 Third Party Resources 方式扩展的,可以通过 kubectl 操作,特此纠正

另外,Kubernetes 在大数据方面支和 Mesos 还有差距。去年 Kubernetes 支持了 job 概念,job 生成的 pod 执行完成后立刻退出,原来的 service 可以理解成一个死循环的 job。这样,Kubernetes 就具有了分发批量任务的能力,但还缺乏上层的应用接口。理论上,将 Hadoop 的 MapReduce 移植到 Kubernetes,用 Kubernetes 替代底层的 Yarn 的资源调度功能,也是可行的(只是开脑洞,没有具体分析)。有个打算整合 Yarn 和 Kubernetes 的项目已经很久没更新了,这两者的整合我不太看好,两个系统冲突严重,是互相替代的关系,不像 Mesos 和 Kubernetes 的整合(这个后面 Mesos 的段落会分析)。

部署复杂是 Kubernetes 一直被大家诟病一点。15年我做测试的时候,部署一套 Kubernetes 是一项很复杂的工作。去年 Kubernetes 推出了 kubeadm,很大程度的降低了部署的复杂度。当前 Kubernetes 除了 kubelet 需要直接在主机上启动,其他的组件都可以通过 Kubernetes 自己托管,一定程度上实现了『自举』,但易用度上和 Swarm 还是有差距。

随着 Kubernetes 的成熟,其他厂商开始制作自己的发行版,比如 CoreOS。CoreOS 原来的容器思路应该是通过自己定制的容器操作系统,以及 etcd ,将多个 CoreOS 主机合并成一个集群,然后通过改造过的 systemd 充当 agent,上面再增加一个调度器,就可以实现容器编排调度,也是一种可行的思路,既然单机的服务进程管理可以通过 systemd,将多个机器的 systemd 连接起来不就是一个分布式的服务进程管理?但后来改变了策略,估计是这种方案采纳成本太高(用户需要同时改变自己主机的操作系统以及应用的部署习惯),所以当前的容器策略变为了定制 Kubernetes,推出 tectonic,CoreOS 改名为 Container Linux(应该是为了避免产品和公司的名称重叠,另外也透露出的一个信息是产品重心的变更),专注于主机操作系统(这个后面的操作系统部分会分析到)。

总结一下,Kubernetes 经过一年快速发展,基本已经非常完备。原来的 kube-proxy 的性能问题(1.2 版本之前),也已经解决。建议原来处于观望状态的用户可以入坑了。不过在应用的最终 package 定义上,Kubernetes 尚未推出自己的解决方案,不确定这个是打算官方来搞,还是让度给发行版厂商,不过可以预计2017年肯定会有相关方案推出。

Mesos

如果说 Kubernetes 是为了标准而生,那 Mesos 则是为了资源而生。它的理念是:

define a minimal interface that enables efficient resource sharing across frameworks, and otherwise push control of task scheduling and execution to the frameworks

定义一个最小化的接口来支持跨框架的资源共享,其他的调度以及执行工作都委托给框架自己来控制。

也就是说它的视角是资源视角,目标是资源共享。这个和 Kubernetes 的目标其实是一体两面,一个从定义描述角度一个从资源角度。Mesos 其实是最早切入容器领域的,但它的容器封装的比较简单,只是用来做简单的资源隔离,用户一般没什么感知。有了 Docker 以后,也引入了 Docker,但正如前面我分析的原因,Mesos 上的 Docker 一直有点别扭,于是 Mesos(准确的说应该是 mesosphere DC/OS) 搞了一个 Universal container,改进了 Mesos 原来的容器,支持了 Docker 的镜像格式,这样用户可以在自己的开发环境中使用 Docker,但生产环境中就可以直接切换到 Mesos 自己的容器上,虽然可能有一些兼容性问题,但镜像格式这种变化不会太快,问题在可控范围内。

这也从另外一方面表明了 Docker 的镜像格式基本上已经成了一个事实标准,一个容器解决方案能否切入整个生态圈的关键是是否支持 Docker 镜像格式。当然 Mesos 成员对这点其实也有点抵触,在一些分享里强调 Mesos 也支持部署其他类型的软件包格式,比如gzip等,尤其大规模服务器的场景,从 Docker 仓库拉取镜像有瓶颈。这点个人不太同意,大规模服务器场景,从任何中心节点拉取任何格式的安装包都会有问题,所以 twitter 才搞 p2p 安装包分发,但 Docker 镜像也可以搞成 p2p 分发的,只要有需求,肯定有人能搞出来。

容器网络方面,原来 Mesos 的网络解决方案就是端口映射,应用需要适应 Mesos 做修改,对应用倾入性比较强,通用性较差,所以 Mesos 支持了 Kubernetes 发起的 CNI 网络标准,解决了这个问题。

Mesos 通过 framework 的机制,接管了当前已经存在的分布式系统的一部分职能,让多个分布式系统共享同一个资源池变为可能,容器编排也只是 Mesos 之上的一种应用(Marathon)。这种方式的好处是让整合复杂的分布式系统变为可能,因为 framework 是编程接口,灵活度也比较高,很多不容易跑在 Kubernetes 上的复杂应用,都可以在 Mesos 之上,比如 Hadoop 等大数据相关的系列应用。

正因为 Mesos 和 Kubernetes 的目标正好是一体两面,然后能力也可以互补,所以很早就有人想整合 Kubernetes 和 Mesos,将 Kubernetes 跑在 Mesos 之上,这样 Kubernetes 接管容器编排调度,替代 Marathon,Mesos 解决其他复杂的分布式应用,实现多种应用的资源共享。但 kubernetes-mesos 这个项目后来就不活跃了,一方面是 Kubernetes 变化太快,另外一方面估计是 mesosphere 发现和 Kubernetes 的竞争大于合作吧。后来 IBM 搞了个 kube-mesos-framework 放在 Kubernetes 孵化器里孵化,不过当前尚不能正式使用。个人感觉如果要真的很好整合,对 Kubernetes 和 Mesos 两方都需要做很大改造,但这个项目对生态圈来说是一个大变数,有可能打破三足鼎立的局势。

Mesosphere 的 DC/OS 在 Mesos 基础上搞了一个分布式应用的 package 规范。以前的应用发布都只能发布面向单机操作系统的 package,Mesosphere 通过 Marthon,镜像以及配置文件,定义了一套分布式的 package 规范,用户可以通过一个命令从仓库(repo)上部署复杂的分布式应用到 Mesos。这个和 Docker 的 Store 思路类似。

总结一下,Mesos 的优势是可定制性强,它诞生于 twitter 这样的互联网公司,也比较受互联网公司欢迎。互联网公司的基础设施以及系统大多是自己研发,可以通过规范来要求自己的应用适应调度系统,所以对标准化和抽象能力的的需求不如资源共享强烈。它的缺点是周边生态比较庞杂,接口以及规范设计上,没有 Kubernetes 那么『优雅』。

Rancher

既然容器之上的编排系统已经三足鼎立了,各有所长了,还有其他机会么?Rancher 尝试了另外一个途径。它自己的定义是一种 IaaS,一种基于容器的 IaaS。首先,它通过容器降低了部署成本,每个只需节点运行一个命令就能部署一套 Rancher 系统,相对于 OpenStack 这种复杂的 IaaS 来说就太容易了。其次,它自己的定位是专门运行容器编排系统的 IaaS,可以在上面一键部署 Kubernetes,Docker Swarm,Mesos。容器编排系统,直接运行到物理机上还是需要一些改造,并且有升级和运维困难的问题,于是 Rancher 出来了,希望抽象出一层非常薄的 IaaS 来解决这个问题。

它的思路是既然现在三家纷争,选哪一方都是一个艰难的决定,那不如选 Rancher 好了。Rancher 一方面可以让几种编排系统共存,另外一方面降低了以后的切换成本,这个艰难的决定可以以后再做。

另外它也推出了自己的应用规范和应用仓库(App Catalogs),它的应用规范也兼容其他的容器编排系统的定义文件,相当于一个容器编排系统应用的一个超集。这样和基础设施相关的应用可以用 Rancher 自己的规范,和业务相关的,变化快需要动态伸缩的应用可以放到容器编排系统中,以后切换也不麻烦。

不过 Rancher 的这个产品假设的问题是,假如以后容器编排调度系统是一家独大,那它的存在空间就会越来越小了。

容器平台去向何方?CaaS,IaaS,PaaS,SaaS?

有人把容器服务叫做 CaaS(Container as a Service),类似于当前 IaaS 平台上的数据库服务(RDB as a Service)等,是 IaaS 之上的一种新的应用服务。但个人认为 CaaS 其实是一个伪需求,用户需要的并不是容器,从来也没有人把 IaaS 叫做 VaaS(VM as a Service),容器服务提供的是一种运行环境,并不是具体的服务。

容器编排调度平台首先是一个面向开发者的的工具平台,它上面调度的是应用,这是和当前 IaaS 最大的区别。当前的 IaaS 主要面向的是管理者,调度的是资源,所以 IaaS 的使用入口主要是控制台,虽然有 API,但指令式的 API 使用复杂度要远大于声明式的 API,并且 API 的使用者也多是运维工具,很少有融入业务系统的使用场景。这是由当前 IaaS 云的历史使命决定的。云的第一步是让用户把应用从自己的机房迁移到云上,只有提供可以完全模拟用户物理机房的环境(虚拟机模拟硬件支持全功能的OS,SDN网络,云硬盘存储),对应用无侵入,用户的迁移成本才更低。

但当这一步完成时,用户就会发现,这样虽然省去了硬件的维护成本,但应用的开发维护成本并没有降低,认识到自己本质的需求并不是资源,而是应用的运行环境。这个需求有点像 PaaS,但原来的 PaaS 的问题是对应用的侵入性太强,并且和开发语言绑定,能直接部署的应用有限,用户需要的是一种更通用的 PaaS,可以叫(Generic Platform as a Service),这个词是我生造的,就是一种基本可以部署任何复杂应用的平台服务,正好容器平台可以承担起这样一种职责。

容器平台虽然都有各自的历史背景和侧重点,解决方案也不一样,但最终指向的目标却是一致的,就是屏蔽分布式系统的资源管理细节,提供分布式应用的标准运行环境,同时定义一种分布式应用的 package,对开发者来说降低分布式系统的开发成本,对用户来说降低分布式应用的维护成本,对厂商来说降低分布式应用的分发成本。总结一下,其实就是 DataCenter OS 或 Distributed OS。DC/OS 这个词虽然已经被 Mesosphere 用在自己的产品上了,但个人认为它是所有容器平台的最终目标。当然,这次容器浪潮是否能真的实现这个目标还不好说,但至少现在看来是有希望的。

于是, PaaS 会变成了 DCOS 之上的 devops 工具栈,当前很多 PaaS 平台正向这个方向演进。而 IaaS 就变成了给 DCOS 提供运行环境的服务,DCOS 接管了上层的应用以及基础服务。当然 IaaS 之上还有其他的 SaaS 模式的服务(由于 SaaS,PaaS 的外延并没有精确定义,很多场景下,把面向开发者的 SaaS 模式的中间件叫做 PaaS 组件,我的理解是通过软件实现多租户,完全按量计费的服务都应该属于 SaaS,比如对象存储。这个要细说,估计需要另外一篇文章,这里就不详细分析了),SaaS 模式资源利用率最高,对用户的成本最低,用户一般不会用独立部署的服务去替换。这样一来,格局就变成了用户在 IaaS 之上部署一套 DCOS,需要独立部署的服务以及自己开发的服务都运行在 DCOS 之中,其他的能抽象成标准 SaaS 服务的中间件则优先用 IaaS 提供的。相当于 IaaS 将独立部署的基础设施服务,以及用户自己的服务的部署和调度让渡给了 DCOS。当然,最后 IaaS 本身是否会直接变成一种多租户的 DCOS,由调度资源变成直接调度应用,也不是没可能,但这样调度层会面临非常大的压力,数据中心支撑的节点会受限,暂时看来两层调度的可行性更大些。

这对整个 IaaS 影响很大,所以有人说对 AWS 造成威胁的可能不是 Google Cloud,而是 Kubernets(DCOS)。但即便是 DCOS 成熟,最后如何商业化还是有很大的变数。大家理想中的那个像 Apple 的 AppStore 的服务器端应用市场,最终会是由 DCOS,SaaS,还是 IaaS 服务商提供?DCOS 的优势是掌握了标准可以定义应用规范,SaaS 服务商的优势是直接面向最终用户,可能占据企业应用入口,IaaS 服务商的优势是它掌控了应用的运行环境,无论在计费模式还是反盗版上都有很大优势。但在私有云领域,IaaS 产品会面临 DCOS 更大的冲击。私有云领域如果多租户隔离的需求没那么强烈的情况下,部署一套 DCOS 是一种更简单高效的选择。

容器与虚拟机之争

从 Docker 技术成为热门开始,容器与虚拟机的争论就从来没有停止过。但去年一年,大家的注意力逐渐转移到上层,容器和虚拟机的争论算告一段落。这个主要是因为容器本身的外延在变化。

容器,首先它不是一个技术词汇,它是一个抽象概念。顾名思义,就是装东西的器皿,装什么东西呢?应用。

其实 J2EE 领域很早就使用了容器(Container)概念,J2EE 的服务器也叫做 web container 或者 application container,它的目标就是给 java web 应用提供一种标准化的运行环境,方便开发,部署,分发,只不过这种容器是平台绑定的。

而 linux 容器自诞生之初,就是一组进程隔离的技术的统称。随着容器领域的竞争与演进,Kubernetes 的 OCI (Open Container Initiative)标准推出,Docker,Unikernels, CoreOS 的 Rocket,Mesos 的 Universal container,Hyper 的 HyperContainer(基于 VM 的容器解决方案) 等百花齐放,容器的概念逐渐清晰,我们这里可以下个定义:

容器就是对应用进程的一种标准化封装,无论是采用 linux 的 cgroup namespace 技术,还是使用虚拟化 hypervisor 技术来做这种封装,都不是关键,关键是是目标,容器是为应用标准化而生。

也就是说,最早,大家认为容器是和虚拟机一样的一种隔离技术,所以会拿容器和虚拟机做比较,比较二者的隔离成本,隔离安全性,但现在容器的外延变了,和传统虚拟机的本质差异不在于封装技术,而在于封装的目标,传统虚拟机封装的目标是操作系统,为操作系统提供虚拟化硬件环境,而容器封装的目标是应用进程,其中内嵌的操作系统只是应用的依赖而已。

另外一方面,基于虚拟机的调度系统,比如 OpenStack,也可以将容器作为自己的调度系统的 compute_driver,也就是将容器当虚拟机使用,用来降低虚拟机的隔离成本。所以容器与虚拟机之争本质上是调度理念之争,而不是隔离技术之争

容器对操作系统的影响

Docker 没出现之前,服务器端的操作系统基本是传统 linux 大厂商的天下,ubuntu 好不容易通过自己的桌面版的优势赢得一席之地,一个创业公司试图进入这个领域基本是没有机会的,但 Docker 的出现带来了一个契机。这个契机就是一个操作系统需要考虑自己的目标是管理硬件还是管理应用。如果是管理硬件,也就是运行在物理机上的操作系统,目标就是提供内核,管理好硬件(磁盘,网络等),而应用层的事情交给容器,这样硬件层的操作系统不需要考虑各种应用软件栈的兼容问题,降低了操作系统的维护成本。如果是管理应用,那就可以放弃对硬件层的管理,专心维护软件栈。所以这个领域能冒出几家创业公司的产品试水:

  1. CoreOS 的 Container Linux 以及 Rancher 的 RancherOS 这两个 OS 的主要目标都是接管硬件,将主机操作系统从复杂的软件栈中解放出来,专心管理硬件和支持容器。传统的 Linux 操作系统为维护上层软件栈的兼容性付出了巨大的成本,发行版的一个优势在于提供全面软件栈的兼容性测试。而当二者解耦后,这个优势不再,竞争的核心在于能否提供更好的支持容器以及系统和内核的升级。
  2. Alpine Linux 这个精简后的 Linux 发行版则是专注于维护软件栈,给容器内的应用提供运行环境。所以它可以做到非常小,默认只有几M大小,即便是包含 bash 进去,也只十多M。所以 Docker 官方默认以它作为镜像的基础系统。

操作系统的演进和更替是一个长期的工程,基本上得伴随着硬件的淘汰,所以至少五到十年的演进,着急不得,但可以期待。

关于技术类创业的思考

技术类创业,要思考清楚自己的机会是在市场还是在技术生态圈里占领一席之地。当然前者要比后者容易,后者最终也得变为市场的应用才能盈利,而即便是在技术生态圈中取得地位也不一定能找到商业模式,不过后者的潜力要大于前者。国内的创业一般倾向与前者,而国外则多倾向与后者,所以国内同质化的竞争比较激烈,而在差异化的生态构建方面则缺少建树。主要是因为国内的技术积累以及普及度和国外还有差距,还属于追随者,只有追随并赶超之后才会有创新,这个和 2C 领域的类似,2C 领域最近越来越少 C2C(Copy To China) 模式成功的案例了,2B 领域肯定还需要些年,不过感觉应该也不远。

个人认为,2017年容器编排调度领域的竞争会上升到应用层面,DCOS 之上的多语言应用框架(比如 微服务框架,Actor模型框架),各种已有应用和基础设施的容器化,标准化,让已有应用变为云原生(Cloud Native)应用,等等。

当然,理想和现实之间是有鸿沟的。一波一波的技术变革,本质上其实都是在试图将开发和运维人员从琐碎的,重复的,无聊的任务中解放出来,专注于有创意的领域。但变革最难变革的是人的思维方式和做事习惯,以及应对来自组织的阻碍。你说云应该就是按需的,动态的,自服务的,但用户的运维部门就喜欢审批开发人员资源申请,于是云变成了一个虚拟机分配系统。你说资源应该动态调度,应用混部有利于提高资源利用率,但用户的安全部门要求应用的业务必须分层,每层必须需要部署到独立的服务器上,跨层调用的端口还需要申请。所以技术变革最后要落地成商业模式,首先要通过技术理念的传播去改变用户的思维方式以及组织体系,当然这肯定不可能是一蹴而就的,是一个长期的,反复过程,其次要等待业务需求的驱动,当业务增长导致软件复杂度到一定规模的时候,自然会寻求新技术来解决复杂性。

结语

写了这么多,有人会问,我还是没能确定到底选择哪一家合适啊?未来是不可预测的,但是可以创造的。当你做出选择的那一刻,你希望的未来就向你靠近了一步

相关链接


  1. Kubernetes 架构浅析 我15年底写的关于 Kubernetes 架构解析的文章

  2. Mesos 架构以及源码浅析 我16年中写的关于 Mesos 架构解析的文章

  3. What is Kubernetes? Kubernetes 官方介绍

  4. Kubernetes 官方的部署 Zookeeper 例子

  5. CoreOS operator 的官方介绍

  6. kubernetes-mesos 项目地址

  7. kube-mesos-framework 项目地址

  8. HyperContainer 官网地址