容器平台选型的十大模式:Docker、DC/OS、K8S 谁与当先?(下)

社区编辑2018-05-18 16:21

本文连接上文:容器平台选型的十大模式:Docker、DC/OS、K8S 谁与当先?(上)


模式七:深入掌握使用 Kubernetes

 
使用场景:万节点集群,IT 能力强
 
随着 Kubernetes 使用规模的越来越大,大型的公司可以对 Kubernetes 进行一定的定制化,从而可以实现万节点甚至更大规模的支撑,当然需要 IT 能力比较强,网易在这方面有很多的实践。
 

从 APIServer 看集群的规模问题

 
随着集群规模的扩大,apiserver 的压力越来越大。
 

 
因为所有的其他组件,例如 Controller、Scheduler、客户端、Kubelet 等都需要监听apiserver,来查看 etcd 里面的变化,从而执行一定的操作。
 
很多人都将容器和微服务联系起来,从 Kubernetes 的设计可以看出,Kubernetes 的模块设计时非常的微服务化,每个进程都仅仅干自己的事情,而通过 apiserver 的松耦合关联起来。
 
而 apiserver 则很像微服务中的 api 网关,是一个无状态的服务,可以很好地弹性伸缩。
 
为了应对 listwatch,apiserver 用了 watchcache 来缓解压力,然而最终的瓶颈还是在 etcd 上。
 
最初用的是 etcd2,这时候 listwatch 每次只能接受一个事件,所以压力很大。为了继续使用 etcd2,则需要使用多个 etcd2 的集群来解决这个问题,通过不同的租户分配到不同的 etcd2 集群来分担压力。
 
将来会迁移到 etcd3 有了事件的批量推送,但是从 etcd2 到 etcd3 需要一定的迁移工作。
 

通过优化 Scheduler 解决并行调度的问题

 
大的资源池的调度也是一个很大的问题,因为同样一个资源只能被一个任务使用,如果并行调度,则存在两个并行的调度器同时认为某个资源空闲,于是同时将两个任务调度到同一台机器,结果出现竞争的情况。
 
为了租户隔离,不同的租户是不共享虚拟机的,这样不同的租户是可以参考 Mesos 机制进行并行调度的。因为不同的租户即便进行并行调度,也不会出现冲突的现象,每个租户不是在几万个节点中进行调度,而仅仅在属于这个租户的有限的节点中进行调度,大大提高了调度策略。
 

 
并且通过预过滤无空闲资源的 Node,调整 predicate 算法进行预过滤,进一步减少调度规模。
 

通过优化 Controller 加快新任务的调度速度
 

 
Kubernetes 采用的是微服务常使用的基于事件的编程模型。
 
当有增量事件产生时,则 controller 根据事件进行添加、删除、更新等操作。
 
但基于事件模型的一个缺点是,总是通过 delta 进行事件触发,过了一段时间,就不知道是否同步了,因而需要周期性地 Resync 一下,保证全量的同步之后,然后再进行增量的事件处理。
 
然而问题来了,当 Resync 时,正好遇到一个新容器的创建,则所有的事件在一个队列里面,拖慢了新创建容器的速度。
 
通过保持多个队列,并且队列的优先级 ADD 优于 Update 优于 Delete 优于 Sync,保证相应的实时性。
 

模式八:深入掌握使用 DC/OS

 
使用场景:万节点集群,IT 能力强
 
前面说过 Mesos 由于本身独特的调度机制,从而支撑的集群规模比较大,但是大多数使用 Mesos 的公司都没有使用 DC/OS,而是裸使用 Marathon 和 Mesos 外加自己定制开发的一些组件。
 
Mesos 可以支持当集群规模非常大,单个 Marathon 的性能不足以支撑时,可以使用自己的 Framework 机制,使得不同的租户使用单独的 Marathon 来解决问题。
 

 
后来 DC/OS 在最基础的 Marathon 和 Mesos 之上添加了很多的组件,如图所示,现在已经非常丰富,例如 DCOS 的客户端 (kubectl)、API 网关 admin router (类似 apiserver)、服务发现 minuteman(类似 kube-proxy)、Pod 的支持、CNI 插件的支持、存储插件的支持等,和 Kubernetes 已经非常像了。
 
很多公司裸用 Marathon 和 Mesos 而没有进一步使用 DC/OS,可能是因为和核心组件 Mesos 已经经过大规模生产性支撑不同,这些外围的组件也是新的,对其稳定性也是有一定的顾虑,所以需要比较长的学习曲线,并且对于这些新的组件有非常好的把控,才敢上生产。
 
所以从这个角度来讲,虽然 Mesos 的稳定性和大规模无容置疑,但就整个 DC/OS 来讲,和 Kubernetes 从功能和稳定性来讲,在伯仲之间,都需要使用者有强大的 IT 能力,对于开源软件的各个模块非常熟悉,甚至能够做一定的代码修改和 Bug fix,才敢在大规模集群中使用。

 

模式九:部署大数据,Kubernetes vs. Mesos

 
Mesos 还有一个优势,就是 Mesos 可以通过开发 Framework,构建大数据平台,例如 Spark 就有基于 Mesos 的部署方式。
 

 
基于 Mesos 的 Spark 有两种方式,粗粒度和细粒度。
 
粗粒度模式(Coarse-grained Mode):应用程序的各个任务正式运行之前,需要将运行环境中的资源全部申请好,且运行过程中要一直占用这些资源,即使不用,最后程序运行结束后,回收这些资源。组粒度的方式浪费资源。
 
细粒度模式(Fine-grained Mode):按需分配,应用程序启动时,先会启动 executor,但每个 executor 占用资源仅仅是自己运行所需的资源,不需要考虑将来要运行的任务,之后,mesos 会为每个 executor 动态分配资源,每分配一些,便可以运行一个新任务,单个 Task 运行完之后可以马上释放对应的资源。细粒度的缺点是性能有问题。
 
其实细粒度模式才是真正能够发挥 Mesos 动态资源调度最有效的方式,但是考虑到有大幅度的性能降低,https://issues.apache.org/jira/browse/SPARK-11857,很可惜这种方式在 Spark 2.0.0 被 deprecated 掉了。
 
如果使用 kubernetes 部署大数据,其实和部署一个普通的应用思路差不多,和 Mesos 不同,kubernetes 不会干预到大数据运行的上下文中,Kubernetes 启动的容器仅仅作为资源预留方式存在,容器内的资源分配则大数据平台自己解决。这样的利用率就降低了,相当于粗粒度模式。
 
基于容器部署大数据平台,也是建议部署计算部分,例如 Map-Reduce,或者 Spark,对于数据部分 HDFS,应当另行部署。
 

模式十:容器和虚拟化混合部署

 
使用场景:大型公司,逐步容器化
 
对于很多大公司但是非互联网公司,使用容器还是需要小心对待的,因而需要逐步容器化,所以存在有 IaaS 平台,并且虚拟机和容器混合使用的状态,这种状态可能会持续相当长的时间。
 
在这种情况下,建议容器套在虚拟机里面使用。
 
使用 Flannel 和 Calico 都仅仅适用于裸机容器,而且仅仅用于容器之间的互通。
 

 
一旦有 IaaS 层,就会存在网络二次虚拟化的问题。
 
虚拟机之间的互联是需要通过一个虚拟网络的,例如 vxlan 的实现,而使用 Flannel 或者 Calico 相当于在虚拟机网络虚拟化的上面再做一次虚拟化,使得网络性能大幅度降低。
 
而且如果使用 Flannel 或者 Calico,那容器内的应用和虚拟机上的应用相互通信时,则需要出容器平台,多使用 node port,通过 NAT 的方式访问,或者通过外部负载均衡器的方式进行访问。在现实应用中,不可能一下子将所有的应用全部容器化,只是部分应用容器化,部分应用部署在虚拟机里面是常有的现象。然而通过 NAT 或者外部负载均衡器的方式,对应用的相互调用有侵入,使得应用不能像原来一样相互调用,尤其是当应用之间使用 Dubbo 或者 SpringCloud 这种服务发现机制时,尤其如此。
 

 
网易云开发了自己的 NeteaseController,在监听到有新的 Pod 创建时,调用 IaaS 的 API 创建 IaaS 层的虚拟网卡,然后在虚拟机内部,通过调用 Netease CNI 插件将虚拟网卡添加到容器里面。添加技术用的就是上一节提到的 setns 命令。
 

 
通过这个图我们可以看出,容器的网卡是直接连接到虚拟私有网络的 OVS 上的,和虚拟机是一个平的二层网络,在 OVS 来看,容器和虚拟机是在同一个网络里面的。
 
这样一方面没有了二次虚拟化,只有 OVS 一层虚拟化。另外容器和虚拟机网络打平的好处是,当部分应用部署容器、虚拟机时,对应用没有侵入,应用原来如何相互访问,现在还是如何访问,有利于应用逐步容器化。
 

 
OpenStack 里面有一个项目 Kuryr 可以很好地去做这件事情,完全使用开源的 OpenStack 和 Kubernetes 可以尝试集成一下。