汇总各种公开/半公开的集群管理系统。
Google的第一代/第二代集群(资源)管理系统被称为Borg,Borg设计细节因零零星星出现在各种文章中而知名,但一直未公开(比如发一篇paper)。然而,我们可从腾讯公布的Torca(Torca是google华人老员工朱会灿加入搜搜后,仿照google borg开发的资源管理系统, 链接是:“Torca:Typhoon上的分布式集群调度系统”)设计文档中可猜测一二。
论文已经公开:borg paper
特点:
1. 隐藏资源和失败处理的细节,使用户专注于应用开发
2. 高可靠、高可用
3. 在上万台机器上高效运行
用户视角:
1. 用户向borg提交job
2. job由多个相同的task组成
3. 每个job在一个borg cell(borg中的一组机器)上运行
borg cell中任务类型:
1. 常驻任务,持续运行不退出
2. 批处理任务,运行结束后退出,对性能波动不敏感
3. borg cell中两种任务会有各种混合组合
使用情况:
1. MapReduce、FlumeJava、MillWhell、Pregel,实现了自己的controller,用于向borg提交任务,类似于yarn。
2. GFS、CFS、BigTable、Megastore都运行在borg上
部署拓扑:
1. 每个cell中的机器以fabric的方式互联,归属一个cluster
2. 一个cluster位于一个数据中心
3. 一个站点分布在多个数据中心中
4. 一个cluster通过有一个大的cell,和多个规模较小的test cell,以及有专门用途的cell
5. 一个中等的cell大约是1万台机器
6. 每台机器从多个维度评估: CPU、RAM、Disk、Network,External IP、Flash Storage
Job的属性:
1. Name、Owner、task's number
2. 硬约束和软约束,可以约束: CPU类型、OS version、External IP等
3. Job是有优先级的,优先级低的延迟启动
4. 每个job在一个cell中运行
5. 每个task在容器中运行
6. Borg中不使用VM,因为不想支付虚拟化的开销,以及当时已经在不支持虚拟化的硬件上做了相当多投入
7. Job的描述语言BCL是GCL(生成protobuf files)的变种,支持lambda函数,可以根据环境修改配置
8. 相当多的BCL文件超过了1000行,总计有数亿行
9. job的配置与Aurora类似
Task的属性:
1. 资源要求,CPU、RAM、Disk Space、Disk Access Rate、TCP port
2. 在Job中的编号
3. 程序都是静态连接的,以减少对运行环境对依赖
4. 软件包的安装由Borg负责
Job管理:
1. 可以修改运行中的job的配置
2. 更新是以滚动的方式进行的,每次可以中断的task数量是有限制的
3. Task被SIGKILL信号终止前,会被发送SIGTERM信号,可以有时间清理、保存状态
资源分配:
1. 一台机器机器上的资源是以alloc(allocation)为单位分配
2. 一个alloc中的资源即使没有被使用,也被认为是已经分配的
3. 在同一个alloc中运行的task共享alloc的资源
4. alloc set是分布在多个机器上的alloc,可以向其提交一个或多个job
资源竞争:
1. 每个job有优先级,高优先级的job可以抢占低优先级job的资源
2. 将优先级划分为几个范围(按由高到低排序): monitoring、production、batch、best effort(testing)
3. 高优先级的task被调度另一台机器上,可能抢占资源,导致低优先级的机器又被调度,引发抢占风暴
4. 为了防止抢占风暴,不允许production范围内的task抢占其它task的资源
5. 用quota来描述一个job在一段时间内需要的资源上限,admission control检查job的quota是否充足。
6. 高优先级的quota只有当cell中的资源确实满足的时候,对应的job才会被接受
7. 低优先级的quota即使cell中的资源不足,也会被接受,进行超卖
8. 管理员可以删除修改job,可以允许指定用户使用受限制的内核特性,以及关闭指定用户的job中的资源估计功能
命名:
1. 在BNS(Borg name service)中记录每个task,包括cell name、job name、task number
2. task的hostname和port被记录在chubby中,以task的BNS name为key
3. task的BNS name被用于task的dns name
4. job size和task的健康状态也被写入到chubby中,lb得以更新路由信息
5. 基本上每个task都会内置一个用于健康检查和提供性能指标的http server
6. Borg监控每个task的状态,自动重启异常的task
监控:
1. 用Sigma系统提供一个监控页面
2. Borg记录所有的job提交和task事件,以及每个task的资源使用情况,可用于计费、调试、资源规划等。
架构:
1. 一个逻辑上的中心控制器Borgmaster,每个机器上的agent: Borglet。
2. 全部用C++实现
3. Borgmaster由两个进程组成: main process、scheduler
4. main process处理client RPC、管理系统中所有资源的状态、与Borglet通信、像Sigma提供接口
5. Borgmater逻辑是上单进程的,实际是由5个副本组成,通过paxos协议选出leader
6. master的重新选举需要10秒,但在大集群中可能需要1分钟的时间重建内存中的记录
7. 重新上线的副本通过paxos协议更新数据
8. Borgmaster的状态会定期做checkpoint,即定期做snapshot,记录更改日志,记录在paxos记录中
9. 开发了一个Fauxmaster,它可以加载checkpoint,模拟borgmaster
调度:
1. job被提交后,borgmaster将其记录在paxos store中,并将job的task添加到pending队列中
2. scheduler异步地扫描pending队列,将任务分配到machine
3. scheduler按优先级调度任务,以round-robin的方式调度不同用户的同优先级任务
4. 调度过程分两步,选出可以承担任务的机器(feasibility checking),为选出机器打分(scoring)
5. 选机器的时候,会将优先级低的任务占用的资源认为是可以使用的。
6. 打分时会考虑用户指定的偏好,但主要还是依据内置的标准,例如,被抢占的任务数量最少,机器上
是否已经有任务的package文件,将任务跨供电区域、故障区域分配,在一个高优先级的任务和多个
低优先级的任务分配到同一个机器上(使高优先级任务可以从容扩容)
7. 最早使用E-PVM的变种进行计分,在安排新的任务时,将影响降到最低,实际结果是任务被分配到
所有机器上,预留了扩容空间,但是增加了资源碎片。(worst fit)
8. 另一种打分方案是,尽可能将已有任务的机器填满,这种方式可以是部分机器处于空置状态,可以
减少了资源碎片,但是不利于资源需求评估不当的job,不利于负载突增的任务,也不利于等待资源
空置时进行执行的批处理任务(机器上任务安排过于紧凑,得不到空置资源)。(best fit)
9. Borg采用的打分方案混合了worst fit和best fit。
10. 当被选中的机器上资源不足时,从优先级最低的任务开始抢占,直到资源满足。
11. 任务的启动延迟中位数是25s,80%的时间是加载任务的文件包,主要是因此磁盘写入速度的限制。
因此,scheduler优先考虑已经缓存了任务文件包的机器。
Borglet:
1. Borgmaster轮询Borglet来获取机器状态,以及发送请求,由borgmaster控制通信,去掉对流量控制
(flow conrol)的需要,并可以防止系统恢复时产生请求风暴。
2. 多个非Leader的Borgmaster副本都是无状态的,各自自动分管一批Broglet。
3. borglet回报的是全量状态,负责的borglet收到后,将计算出的增量提交给Borgmater Leader。
4. borglet与Borgmaster失联时,master将对应机器标记为宕机,并将任务迁移。borglet恢复后,
在Borgmaster的指示下删除对应的task。
5. 所有的Borgmaster宕机,不影响已经在运行的task
扩展性:
1. 单个Borgmaster可以管理几千台机器,每分钟处理上万个任务
2. 一个忙碌的Borgmaster,使用10-14个CPU,50G内存。
3. 早期的Borgmaster是同步串行运行的,后来将调度拆分到一个单独的进程中。
4. 调度进程自己缓存了一份cell的状态数据
5. 调度器采用乐观并发,即积极向master提交任务,master允许或者拒绝
6. 借鉴了Oemega,正在增加不同的调度器来处理不同的任务类型.
7. borglet通信、以及处理只读rpc的处理,在单独的线程中运行. 99%的UI查询响应在1s之内
95%的borglet轮询响应在10秒之内
8. 机器的打分过程是很消耗资源的,Borg缓存了机器的评分,直到属性发生变卦时,才更新评分
资源使用量的微小变动会被忽略,防止缓存频繁失效
9. job中的多个task都是等价的,因此调度时只需要做一次选机器和评分操作。
10. 选机器时,是随机的挑选一批机器进行核实,直到选出足够的机器
11. 实验结果,将一个cell中的所有任务调度一次需要的是几百秒。单个实时调度在半秒内完成。
高可用:
1. 自动重新调度被驱逐的任务
2. 将一个job的task跨宕机区域调度,例如跨机器、跨机架、跨供电域
3. 限制task的中断频率,限制一个job中可以关闭的task数量
4. 用户提交的最终期望的状态,发送的请求是幂等的
5. 限制重新调度task的速率,避免大规模宕机或者网络割裂导致大量调度
6. 避免将任务分配到曾经多次导致任务失败的机器上
7. 跟踪记录每个任务的日志,即使任务被重新分配到另一个机器上
8. Borgmaster的可用性是99.99%
调度策略的评估方法:
1. 用cell的压实度评估,即在指定的任务量下,一个cell最少需要的机器数量。
2. 不同优先级的任务(生产、测试)运行在同一个cell中,否则需要增加20~30%的机器。
3. 生产环境中任务通常都会多声明资源,这些多出的资源大部分时间是闲置的。
4. 所有用户共享cell,否则cell的数量需要增加2~16倍,机器需要增加20~150%。
5. 在一台机器上添加一个task,会使机器上其它task的每条CPU指令的执行周期(CPI)增加0.3%
6. CPU使用率增加10%,CPI增加不到2%
7. 多种类型的任务混合的cell的CPI比任务类型单一的cell的CPI要高出3%
8. 在专用的cell中,borglet的执行速度是共享cell的1.19倍
大规模的cell:
1. 建立大规模的cell,可以支持大规模的计算,并且减少碎片
2. 如果使用多个小规模的cell,要比一个大规模的cell耗费更多的机器
资源粒度:
1. CPU单位百万分之1核(milli-cores),这里的核是hyperthread
2. 内存和磁盘是字节
3. 设置固定的资源模版会增加30~50%的资源需求
资源回收:
1. Borgmaster会评估一个task真实需要的资源数量,并将其多申请的资源分配给对资源要求较低任务,例如批处理。
2. task的保留资源开始时等同于它所申请的资源,维持300秒,然后逐渐降低到它实际使用的资源数量。
3. 如果实际使用的资源开始上升,那么task保留资源数量也会快速上升。
4. 生产中的任务调度时计算的已有任务的申请资源,非生产环境中任务调度时,计算的是已有任务的保留资源。
一个任务的保留资源<=任务申请的资源,差额为被回收的资源
5. 当时机器上的资源需求过载时,杀死后限制非生产任务
6. 在一个中等规模的cell中,20%的任务使用的是被回收的资源
7. 实际使用的任务超出了limit的任务,在资源不足时,首先被抢占,无论它的优先级有多高。
隔离:
1. 50%的机器运行了超过9个任务
2. 运行了25一个任务的机器中,90%的机器上有45000个线程
3. 使用linux 的chroot进行任务隔离,通过borgssh登陆任务的运行环境
4. 在GAE和GCE中还使用了vm和沙盒技术,vm使用的是kvm。
5. 所有的任务运行在基于cgroup的container中,但还是有一些低层次资源的竞争,譬如内存带宽、L3缓存。
6. 任务的划分维度:低延迟的和其它、可压缩的资源(内存、磁盘带宽、CPU)和不可压缩的资源(内存和磁盘空间)
7. 如果任务使用不可压缩资源超过限制,立即被按照优先级由低到高的顺序终止。
8 .如果任务使用的可压缩资源超过限制,borglet压缩资源
9. borglet的通过预测为生产任务分配内存,依据内存使用情况,为非生产的任务分配内存,内存超过时OOM
10. 低延迟任务可以独占一个物理CPU
11. 动态调整低延迟任务的资源,防止其它任务得不到处理
12. 改进了Linux Kernel的CPU调度器
Torca是google的朱会灿加入搜搜后仿照google borg开发。
Cluster由Manager Server和Execute Server组成:
1. Cluster中的Central Manager负责调度
2. Cluster中的Execute Server承担任务
Central Manager负责调度:
1. Central Manager->Master Daemon: 管理进程
2. Central Manager->Scheduler: 裁断任务的调度策略
3. Central Manager->Collector: 收集Execute Server的机器和任务状态
4. Central Manager->Http Server: 提供浏览器查询
Execute Server承担任务:
1. Execute Server->Master Daemon: 管理进程
2. Execute Server->Start Deamon:
1. 接收Central Manager下发的任务
2. 创建执行任务的进程(注意: 任务进程是其子进程)
3. 根据Central Manager指令管理任务进程
4. 将任务进程状态上报Central Manager
5. 定期上报物理机状态
3. Execute Server->Http Server: 提供浏览器查询
Torca的容灾策略:
1. Central Master使用主备机制
2. Execute Server被监控
3. ZooKeeper提供强一致性
使用方法:
1. 用户通过Submitter(Torca客户端)从Central Manager获取任务状态、提交任务、管理任务等。
2. 任务的属性和资源需求通过任务描述文件说明。
3. 任务的依赖文件(程序体)存放在共享文件系统(XFS)中, Execute Server主动拉取。
4. 通过名字服务(Torca naming service)获得任务的服务地址(IP:Port)
任务的容灾策略:
1. 共享文件服务(XFS)中断导致任务的依赖文件无法获取, 正在转向Execute Server间的p2p减少XFS的依赖.
(评: 使用p2p没有必要, 存储的问题就应当有存储来解决)
2. Torca通过retry/migrate保证任务的执行。
3. Torca将任务的异常状态实时通知到指定人员(email、短信等)。
Torca的技术问题:
1. 任务的隔离: 在Execute Server上使用LXC技术进行隔离
2. 资源的分配算法: [Unkown: 详情未知]
3. 资源碎片: [Unkown: 详情未知]
4. 任务资源的出让和回收: [Unkown: 详情未知]
(任务空闲时出让计算资源, 负载上升时回收计算资源)
5. 任务峰值时所需资源的满足: 树状container [Unkown: 详情未知]
6. Torca的冷升级: 任务自动迁移
7. Torca的热升级: 记录进程的checkpoint, 升级后从checkpoint恢复
Torca是集中式的集群资源管理系统, 资源的控制粒度细致到CPU、内存(详细粒度取决于LXC), 从而使整个Cluster成为一个大的资源池。
整个Cluster资源池是由一个个包含了CPU、内存等资源的资源颗粒组成(也就是物理机), 因为资源颗粒内部资源不可互通,所以会存在资源碎片的问题
资源碎片类似于磁盘碎片。
Mesos最初是UC Berkeley的研究项目(mesos-paper)
Mesos要解决的问题:
各种分布式框架部署在独立的集群中, 集群的计算资源不能有效利用。
Mesos的解决方案:
将所有的分布式框架部署在同一个集群中, 动态调整各个框架对集群资源的占用, 实现集群的复用。
Mesos面临的问题:
分布式框架种类多, 原理与类型存在差异, 而且未来还会有新的框架不断出现。
Mesos的处理方式:
双层调度设计(two-level Scheduler)
Mesos负责将可用的计算资源交付给Framework, 由Framework自行调度它所接收的资源。
Framework使用完毕后将资源归还给Mesos, Mesos将其分配给其它的Framework, 从而提高资源的利用率。
Mesos的架构:
1 Master负责计算资源在Framework间的分配
2 Slave承担实际的计算任务
Mesos的任务隔离:
在Slave上使用容器技术进行隔离。
Mesos的容灾:
1. Master使用主备方式容灾
2. zookeeper
Job的容灾:
Job的容灾由Framework解决
Mesos的使用:
1. 注册Framework: 将实现了调度策略的Scheduler和承担task的Executer提交到Mesos.
2. 提交Job: 将Job提交到注册在Mesos中的Framework
在Mesos的论文中给出的实验数据显示, 相比将集群分割成多个小集群的方式, 采用Mesos的集群的CPU利用率提高10%,内存利用率提高18%。
Framework的工作的效率根据任务类型的不同各有升降, 最差的情况降低了20%, 最好情况提高了100%。
可以再Mesos上运行的Framework:
Mesos将资源分配给framwork后, framework自行管理, framework内部的状态对Mesos来讲是不可见的。Framework需要能够自觉的释放多余资源。
假设有这样一个framework, 这个framework中运行的100个web server, 每个web server都会占据一个计算单元。当web server的工作不饱和, 只需要10个web server就可以的时候, framework需要自觉的将其中的90个web server的资源归还。
web server与hadoop中的task是两类不同的task, 前者需要长期稳定的运行, 后者需要快速执行返回。Mesos的设计更有利于后者。
另一种解决思路是将framework部署在虚拟机中, 资源利用率的问题交给虚拟机管理平台解决。这种方式不需要对framework作改动。但是同样存在自觉释放资源的问题, 因为虚拟机管理平台也不知道应当何时对虚拟机进行增减。
如果采用部署在虚拟机中方式, 当虚拟机的负载较低时是否有将其释放的必要?如果不释放,会浪费哪些资源?
另外在Omega的论文中指出, Mesos对资源采用了悲观锁设计, 并发性不好。
YARN是Hadoop项目中的一个通用的调度系统, 是下一代Map-Reduce, 也称为MRv2。
Omega是google内部使用的集群管理调度系统, 在2013的一片论文中被披露。
Omega依然是two-level的设计, 资源的具体调度由各自的scheduler负责。与Mesos的不同是获取资源的方式:
Mesos: Master向Framework发送Resource Offer
Omega: scheduler可以看到全局状态, 直接抢占资源。
Omega中维护了一个集群的状态(cell state), 每个scheduler直接抢占资源,使用MVCC协议进行并发控制。
从Mesos到Omega, scheduler主动性进一步增加, 不仅仅自主管理已经获取的资源, 而且可以干涉整个集群的资源, 例如抢占优先级低scheduler的资源。
需要对scheduler严加控制,防止因为某个scheduler的故障,造成整个集群的不稳定。
与上面介绍的集群调度系统不同的是kubernetes侧重的是docker的调度管理。
kubernetes的组成部分:
kube::etcd::start --> etcd -name test --data-dir ?? -addr ??
apiserver -v=? --address=? --port=? --etcd_servers=? --portal_net=? --cors_allowed_origins
controller-manager -v=? --machines=? --master=?
kubelet -v=? --etcd_servers=? --hostname_override=? --address=? --port=?
proxy -v=? --master=?
scheduler -v=? --master=?