k8s 组件通讯整个基于 List-Watch 的异步消息机制,这个机制主要得益于 etcd 和 http 长连接。保证了数据的一致性,实时性,和稳定性。我比较欣赏的地方就是,k8s 不引入哪些什么消息中间件,就可以实现一套比较稳定的异步消息系统,完全自己撸代码的特点,当然这也得益于 etcd 这个重要组件。这样,你的系统才更加干净,如果是 openstack 就非常复杂,光上手都没法上手起来,OpenStack或许在公有云还有它的一席之地,但我觉得未来属于 k8s。
下图可以看到,唯一和 etcd 打交道的组件就是 apiserver,其他都是通过 list-watch 机制和 apiserver 交互,controllermanager/scheduler 都会及时收到watch资源的变化,从而及时响应,比如控制和调度。
这个设计和 yarn 完全不同,yarn 的组件通讯非常原始,采用的是 心跳包, 数据的变化(删除、更新、添加)全部和心跳数据耦合在一起传递的。比如调度器调度一个 task,其实不是调度器主动监听到的变化,而是 NodeManager 发来心跳包给 ResourceManager,而后通知调度器,心跳决定了这个消息的延迟。这主要是两者面向的场景不同,yarn 采用这种机制并不会影响调度器的性能,因为在大数据场景下,运行的都是离线任务,重点关注的是尽快执行完,而不是尽快调度完,他不需要很快及时的调度完成。更详细的原因,见我在另一篇mapred-v1-scheduler上的记录.
是节点向
JobTracker
申请Task
,而不是任务被提交后就可以立即由调度器进行调度分配,Hadoop 采用这种模式,我认为主要是因为第一,离线任务都属于耗时任务,任务提交后排队延迟和调度时间相对于任务本身执行时间忽略不计, 不关注调度时间,关注的是任务本身执行时间和任务之间的协同。而像公有云虚拟机调度,是希望调度能够立即响应出分配策略的,因此采用了主控制器主动分配给某个Host节点,而不是由Host节点主动通过心跳包拉取可分配的任务(创建虚拟机,相对来说创建虚拟机是比较快的,基本在几分钟左右,容器则更快,几十秒即可); 第二,JobTracker
和TaskTracker
之间是通过 RPC 协议通讯的,这里JobTracker
对于TaskTracker
来说,扮演的其实是服务器的角色。JobTracker
不会去主动调用TaskTracker
。
对于 k8s,调度的是容器pod,目前应用场景大部分都是需要快速扩缩容的,必须调度快。目前 k8s 的批调度器比如 kube-batch
以及 机器学习控制 kube-flow
, 大数据 spark on kubernetes
都在开发中,我认为将来肯定是统一的平台来运行不同类型的工作负载。
两者都是基于事件驱动的设计,但是 yarn 耦合了状态机的设计模式,yarn的代码还是比较复杂的,尤其是里面复杂的状态机代码,看懂了它里面状态机的设计,你才有可能去看它里面其他的代码逻辑,k8s社区并不对资源对象做状态机设计。