第5章 容器编排
5.1 容器编排简介
容器实现了单节点上的应用打包、发布、运行等功能,有了应用的容器镜像之后,用户更希望将应用运行在给定的集群(一组物理服务器)上。但随着应用规模的逐渐扩大,对散落在不同节点上的容器的管理成本逐渐上升,因此需要一个容器编排和调度工具来统一管理分布式的容器节点。容器编排是指自动化管理和协调容器的能力,它实现了容器的生命周期管理。容器编排器势必成为支撑分布式应用的必然趋势,其凭借强大的编排和调度能力,被认为是云平台上的分布式操作系统。
5.1.1 大事记
随着容器技术的发展,容器编排技术逐渐进入主流视野,以下是容器编排技术发展的大事记。
2015年,云原生计算基金会(Cloud Native Computing Foundation,CNCF)由Google、RedHat等公司牵头成立,开源了Kubernetes。CNCF致力于整合开源技术,使容器编排功能成为微服务架构的一部分。
2017年,在容器编排领域的竞争中,Docker公司的Swarm落败。因此,Docker公司在拒绝了微软早先的天价收购之后,在没有任何回旋余地的情况下,选择了逐步放弃开源社区,而专注于自己的商业化转型。Docker 公司将 Docker 项目的运行时部分containerd捐赠给CNCF,并宣布将Docker项目改名为Moby,交给CNCF自行维护。Docker公司基于Moby开源项目与CNCF共同构建了Docker社区版(CE),在社区版基础上构建了Docker企业版(EE),从此Docker成为商业产品的名字,而原Docker项目化身为Moby继续发展。
2017年9月,Apache公司宣布Mesos 1.10版本支持Kubernetes。
2017年10月,Docker公司宣布在自己的主打产品Docker企业版中内置了Kubernetes项目,宣告容器编排大战结束,以Kubernetes胜出告终。
2018年1月30日,RedHat宣布斥资2.5亿美元收购CoreOS。
2018年3月,在OSLS开源领袖峰会上,Google Cloud工程总监Chen Goldberg宣布Kubernetes成为第一个从CNCF毕业的项目。这也意味着该开源项目已经成熟,目前Kubernetes已经成为容器编排的事实标准。
5.1.2 Swarm与Kubernetes之争
Kubernetes、Mesos、Swarm是容器编排领域的“三驾马车”。由于Mesos始终只是借着容器技术的声势,并没有完全参与到容器领域中;同时,其所属的Apache社区有着固有的封闭性,导致它在容器编排领域鲜有创新。因此,容器编排领域的争端主要聚焦在Swarm和Kubernetes项目上。
虽然Docker是容器生态的事实标准,但是Docker公司在PaaS层上的能力与Google、RedHat等公司有着一定的差距。除了容器,用户还希望平台可以提供路由网关、水平扩展、监控、备份、灾难恢复等一系列运维能力。于是,Google 和 RedHat 等公司牵头发起了 CNCF,期望以Kubernetes 为基础,建立一个由开源基础设施领域的厂商主导、按照独立基金会运营的平台及社区,对抗以Docker为核心的容器商业生态。
Kubernetes的设计思想来源于Borg和Omega的内部特性,这些特性落到Kubernetes上,就是Pod、SideCar等功能和设计模式。而Google牵手RedHat成立联盟,将这些先进思想应用到 Kubernetes 项目中。Kubernetes 凭借其先进的设计理念和号召力,并没有被 Docker 公司的“Docker Native”的说辞击败,反而很快构建出一套与众不同的容器编排和管理的生态体系,并且在GitHub上各项指标“一骑绝尘”(如图5-1所示),远超Swarm项目。CNCF在成员项目中迅速添加了Prometheus(容器监控事实标准)项目后,又相继添加了Fluentd、OpenTracing、CNI 等一系列优秀的容器生态工具和项目,Kubernetes 社区被大量公司和创业团队所支持和推广。
Docker公司面对这样的态势,2016年宣布放弃现有的Swarm项目,将容器编排、集群管理和负载均衡功能全部内置到Docker项目当中。这也是Swarm项目的唯一优势——与Docker项目的无缝集成可以实现优势最大化。内置容器编排、集群管理和负载均衡能力,固然可以使Docker 项目的边界直接扩展成一个完整的 PaaS 项目的范畴,但是同时也增加了技术复杂度和维护难度,从长远来看这是不利的。
图 5-1
针对Docker公司打出的这张牌,Kubernetes反其道而行之,开始在整个社区推行“民主化”架构。因此,Kubernetes在2016年得到了空前发展。推行“民主化”架构,使得从API到容器运行的每一层,Kubernetes项目都为开发者暴露了可以扩展的插件机制,鼓励用户通过代码的方式接入Kubernete项目的每个阶段。这项变革立即在容器社区催生出大量基于Kubernetes API和扩展API的二次创新,其中包括:微服务治理项目Istio、有状态应用部署架构Operator,以及Rook通过Kubernetes的扩展接口,把Ceph这样的重量级产品封装成简单、易用的容器存储插件。
在Google的一篇关于内部Omega调度系统的论文中,将调度系统分为三类:单体、两层和共享状态,如图5-2所示。按照这种分类,通常Google的Borg被当作“单体”调度系统,Mesos被当作“两层”调度系统,而Google的Omega被当作“共享状态”调度系统。论文的作者实际上是Mesos的设计者之一,后来去了Google公司设计新的Omega系统,并发表了这篇论文。这篇论文的主要目的是提出一种全新的“Shared State”模式,来同时解决调度系统的性能和扩展性问题。但就目前阶段而言,Shared State 模式太过理想化,根据这个模式开发的Omega系统在Google内部似乎并没有被大规模使用,也没有任何一个被大规模使用的调度系统采用Shared State模型。
图 5-2
因为 Kubernetes 的大部分设计是延续Borg的,而且Kubernetes的核心组件(Controller Manager和Scheduler)默认都是绑定部署在一起的,状态也都被存储在etcd中,所以通常会把Kubernetes当作第一代“单体”调度系统。但其实Kubernetes的调度模型完全是两层调度的,与Mesos一样,任务调度和资源调度是完全分离的,Controller Manager承担任务编排的职责,而Scheduler则承担资源调度的职责。(注意:调度与编排的区别在于,调度是选择合适的节点部署应用;而编排则是根据事先准备好的配置模板创建、组合各种对象,从而构建应用。)
5.1.3 容器编排工具的核心功能
如果说容器镜像能够保证应用本身在开发与部署环境中的一致性,那么容器编排工具通过统一的配置文件,就可以保证应用的“部署参数”在开发与部署环境中的一致性。容器编排器的核心功能分为三个部分。
资源管理:将一组服务器视为由CPU、内存和存储卷构成的资源池,对其进行管理。
调度和编排:如 YARN、Mesos、Swarm 所擅长的是按照某种规则,把一个容器放置在某个最佳节点上运行,我们称之为“调度”。而Kubernetes所擅长的是按照用户的意愿和整个系统的规则,完全自动化地处理容器之间的各种关系,并且对其进行生命周期管理,这样的过程被称为“编排”。Kubernetes 的本质是为用户提供一个具有普遍意义的容器编排工具,更重要的是,Kubernetes 提供了一套基于容器构建分布式系统的基础依赖。
服务管理:为运行的应用提供额外的支撑性服务,如负载均衡、健康检查等。