在开始文章之前,我们先来问一个问题,为什么是国际上是亚马逊,国内是阿里这两家公司云计算搞得最好呢?这两家公司之间有一个巨大的共同点,就是它们都是电商公司。电商公司的特点很明显,就是流量不是固定的,往往会受到大促、节日的影响。像是国内的双十一和美国的黑色星期五就是典型的大促。在大促的时候的流量会是平常的十倍甚至更多,这么大的流量必须要有更多的机器去应对。但问题是如果去买这么多机器,但是大促过了,流量下降,那么这些机器就又用不到了,显然就会造成浪费。
那怎么样才能避免浪费呢?就是搞一个大集群,把所有机器和计算资源管理起来,大促的时候就用来应对大促的流量,平时呢可以用来搞搞大数据运算或者是租给其他公司或个人,形成一定的经济收益,总是就是不让这些机器闲着,以免浪费。
本质上来说,亚马逊和阿里搞云计算、云服务器背后的核心驱动因素之一原因都是为了解决这个问题。
集群资源管理
集群资源管理是分布式非常普遍的应用场景,可以说是无论公司大小都必然有所接触。像是阿里云、亚马逊云说起来很高大上,但是底层也离不开这个。
这个问题的背景非常简单,无论大小公司往往都不止一套系统。但是公司的资源是有限的也是固定的,但是我们需要应用机器的场景却是灵活的。比如今天新上线了一个系统,需要占用几台服务器,明天这个系统效果不好,撤了,再把这几台服务器清出来。一开始的时候没有动态管理的集群系统,都是靠运维手动操作,所以那年代的运维都练就了一手拔插网线的好本事和健硕的手部肌肉。
在大数据时代到来之前,基本上机器变更基本上都是系统上线下线的情况,这还好说。毕竟一般的公司系统变化不会特别频繁,但是大数据时代来临之后,临时任务的数量大增,今天需要跑下用户的这份数据,明天需要统计一份报表,来来回回的临时需求,而且这些需求往往需要用到大量机器(大数据嘛,机器少算不完),总不能都靠运维人肉处理吧?也不能指望每个开发都练就运维的本事,很浪费时间也不现实。所以很自然地人们想到了开发一套系统来做这件事情。
于是集群资源管理系统应运而生,像是我们常常听说的Yarn,Mesos,Corona等,都是做这个的。
系统架构
我们了解了资源管理系统是做什么的了之后,就可以来看看它的架构了。
它的架构本身并不复杂,本质上这个系统只做了两件事情,一件事情是分配,另一件事情是回收。从功能上很好理解,我们需要把任务下发到机器,当任务执行了之后,我们需要把资源回收回来从而以后分配其他的任务。但从逻辑上,要实现这两点并不容易。
首先,我们需要知道当前所有任务的情况,比如需要多少机器,以及执行的状态,是还没开始,还是已经开始了,或者是已经结束了。如果是结束了,那么需要收回机器,如果还没开始,则需要分配机器资源。除此之外还需要知道资源的情况,哪些资源被哪些任务占据了,哪些是空闲的,这样才好进行分配。要做到这一点,必须要保证系统和所有机器的通信,还需要一个程序来执行分配策略给还没有执行的任务分配资源。我们把这些内容整理一下,就可以画出系统架构图了。
简单解释一下上图,上面的部分就是我们的资源管理系统,下面的部分自然就是机器了。由于一台物理机的功能非常强大,所以一般我们不会直接接入系统,而是会在上面部署多个容器,相当于多个虚拟机,也就是把一台机器变成多台加入集群。所以这个过程称为虚拟化。以前很多C 工程师是就是专门做这个的,现在docker兴起,据说很多已经逐渐换成docker了。好处是如果单个或若干个容器挂了,整个物理机还活着,可以随时重启。还有一个原因是一般没有那么大的任务可以吃掉一整个物理机的资源,也是节约资源。除了容器之外,还需要一个节点管理器,负责和整个管理系统通信。
资源收集器负责搜集这些容器当前的状态,如果有已经执行结束的,则把它们添加进资源池当中,也就是当前可用的意思。调度策略执行器发现有新的机器可用之后会去查看任务队列,将其中一些任务分配到这些可用的容器当中。工作队列当中的任务可以是多种多样的,比如spark,MapReduce等等。
不难看出这当中调度策略执行器是整个管理系统的核心,其他所有的模块都是为它服务的。详细的分配策略涉及的细节和逻辑非常多,所以我们把具体的策略内容放到下一篇文章当中。我们只需要有个大概的认识,知道它是负责调度任务和分配执行的即可。
集群管理的优缺点
虽然我们已经有了管理系统,看起来好像牛哄哄的。但是这方面目前仍然处于摸索状态,还远远没有成熟。这些系统之间多有不同,但是原理都是类似的,本质上都是在我们的硬件资源之上抽象出一个管理系统,就好像雇佣了一个工作飞快永远不会累的管家。我们只需要告诉他,我们当前需要做什么,需要多少资源。至于怎么分配,怎么完成,统统交给他,我们再也不用操心。
这么做和之前人肉分配相比,进步了非常多,有非常明显的优点。我们随便就可以列举出好几条。
优点
比如我们的机器利用率变高了,因为之前人工分配了资源之后资源就固定了。比如分配给A任务一台机器,但问题是A任务并不是一直满负荷的。可能白天流量大,消耗高,但是到了晚上流量就小了,占用的资源就少了。而B任务可能相反,白天不需要运作,到了晚上开始发力,需要大量计算(比如现在很多机器学习的大型job都是凌晨跑的)。如果是人工分配的话,我们可能需要两台机器分别执行A和B,但显然这是不合理的,因为我们完全可以把它们合并,让它们互相互补。但是每天都依靠人力来做这件事情是不现实的,万一运维哪天忘了不是完蛋了。而有了管理系统,会有个系统替我们做这件事,它会把所有资源都安排妥当,自然利用率就高了。
其次,某种程度上来说也减少了数据存储的消耗。比如之前的用户数据在许多系统当中用到,不同的系统需要单独存储一份。不然不同的team用同一份数据很容易出现责任划分不清楚扯皮的问题,有了分布式管理系统之后,我们只需要在分布式系统当中存储一份数据找专人维护即可,避免了重复劳动。
最后,支持多种计算框架。比如像是Yarn,mesos等集群支持众多计算框架,无论是MapReduce也好,还是spark也罢,或者是hive等等都可以用一套系统来管理,非常灵活方便。甚至还可以支持多版本,也不会影响。
不足
凡事有好有坏,没有事情的完美的。既然有优点必然有不足,关于调度策略产生的问题,我们今天先不谈,今天主要讲讲调度系统本身的问题。
第一点也是最重要的一条就是风险,表面上看我们使用集群调度系统降低了集群的风险,因为单个的节点挂了并不会影响整个集群的运行。我们只需要找到单个节点挂掉的原因进行修复,或者等待系统自动重启就好了。系统宕机的风险被均摊了,但问题是均摊风险其实本身就是很危险的事情,它也意味着风险的聚集。
比如说有没有想过如果集群管理系统本身宕机了呢?
如果连负责任务调度的系统都挂了,显然整个集群也就完蛋了。这种事情看似发生的概率非常小,但是一旦发生,对于企业带来的影响和损失是巨大的。据说之前阿里云宕机了一个下午,中国大半个互联网的网站受此影响无法访问。这也是阿里这几年一直在搞异地多活,各种容灾备案的原因。
第二个不足是系统目前还不够智能,比如说如果集群规定了每个任务最多占用的资源总量,突然我们扩容了机器,或者是临时有一个大任务需要超额。这些情况都需要人工干预,再比如对于系统开发的时候能够预料的一些问题有很好的解决措施,比如节点挂了,资源吃满了等等。但是对于没有预料到的问题则完全解决不了,比如某个节点卡死了,没有挂一直占着资源。
再比如一些集群里被人为安置了一些非法的脚本,比如黑客的入侵脚本,或者是挖矿脚本等等。前阵子比较火的某度员工在公司机器上挖矿了好几个月才被抓,为什么没能及时发现?因为资源都是系统调度的,人工很少干预,也没人会去整天看系统里到底都在跑些什么任务。
当然,有问题就有前进的方向,这些问题其实也反应了我们目前这一块还有很长的路要走,目前的方案还比较原始。以后应该会有更好用的集群管理的设计理念也会有更好的系统,当然万丈高楼平地起,未来的方案也是基于当下一点一点改进得到的。我们学习的目的和意义也正在于此。