Hulu大规模容器调度系统Capos (2)

 

 

1.2 插件化的调度策略。capos scheduler会提供一系列的可插拔的过滤函数和优先级函数,这些优先级函数对offer进行打分,作用于调度策略。用户在提交作业的时候,可以组合过滤函数和优先级函数,来满足不同workload的调度需求。

 

1.3 延迟调度。当一个作业选定好一个offer后,这个offer不会马上被launch,scheduler会延迟调度,以期在一个offer中match更多作业后,再launch offer。获取更高的作业调度吞吐。

2 Metadata的raft-base key value store

 

2.1 多个scheduler之间需要有一个分布式的kv store,来存储作业的metadata以及同步作业的状态机。在scheduler downtime切换的时候,新的scheduler可以接管,做一些recovery工作后,继续工作。

 

 

2.2 基于raft实现的分布式一致性存储。Raft是目前业界最流行的分布式一致性算法之一,raft依靠leader和WAL(write ahead log)保证数据一致性,利用Snapshot防止日志无限的增长,目前raft各种语言均有开源实现,很多新兴的数据库都采用 Raft 作为其底层一致性算法。Capos利用了etcd提供的raft lib (https://github.com/coreos/etcd/tree/master/raft), 实现了分布式的一致性数据存储方案。etcd为了增强lib的通用性,仅实现了raft的核心算法,网络及磁盘io需要由使用者自行实现。Capos中利用etcd提供的rafthttp包来完成网络io,数据持久化方面利用channel并行化leader的本地数据写入以及follower log同步过程,提高了吞吐率。

 

2.3 Capos大部分的模块都是golang开发,所以目前的实现是基于etcd的raft lib,底层的kv存储可以用boltdb,badger和leveldb。有些经验可以分享下,在调度方面我们应该关注关键路径上的消耗,我们起初有引入stormdb来自动的做一些key-value的index,来加速某些带filter的查询。后来benchmark之后发现,index特别在大规模meta存储之后,性能下降明显,所以目前用的纯kv引擎。在追求高性能调度时候,写会比读更容器达到瓶颈,boltdb这种b+ tree的实现是对读友好的,所以调度系统中对于kv的选型应该着重考虑想leveldb这种lsm tree的实现。如果更近一步,在lsm tree基础上,考虑kv分离存储,达到更高的性能,可以考虑用badger。不过最终选型,需要综合考虑,所以我们底层存储目前实现了boltdb,badger和leveldb这三种引擎。

3 编程方式的appmaster

3.1 简单的作业可以直接把json描述通过restapi提交运行,我们这边讨论的是,比较复杂场景的SaaS,可能用户的workload是一种分布式小系统,需要多个container资源的运行和配合。这样需要capos提供一种编程方式,申请资源,按照用户需要先后在资源上运行子任务,最终完成复杂作业的运行。

3.2 我们提供的编程原语如下, Capbox.go capbox是capos中资源的描述

package client import ( "capos/types/server" ) type CapboxCallbackHandler interface { OnCapboxesRunning(*prototypes.Capbox) error OnCapboxesCompleted(*prototypes.Capbox) error } type RecoveryCapboxHandler interface { GetCallbackHandler(string) (CapboxCallbackHandler, error) } type AMSchedulerLifeCycle interface { Start(*prototypes.AMContext) (*prototypes.RegisterAMResponse, error) Stop() error } type AMSchedulerAction interface { // container resource api CreateCapbox(*prototypes.CapboxRequest, CapboxCallbackHandler) (*prototypes.Capbox, error) ReleaseCapbox(string) error PreviousStateRecovery(*prototypes.RegisterAMResponse, RecoveryCapboxHandler) error PreviousStateDrop(*prototypes.RegisterAMResponse) error GetCapAgentsSnapshot() ([]*prototypes.CapAgent, error) ListenCapboxStateChange() StopListenCapboxStateChange() }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjxdy.html