一、背景
在一些企业业务场景中,需要使用离线集群提供的虚拟机保证策略人员的研究和开发,以及AI训练和非AI训练都会在集群上进行处理。而数据源一方面是线上每天产生大量的数据,另一方面是从第三方数据商获取的大量数据,这些所有的数据都通过一个稳定的ETL流程汇总到分布式存储上。然而,通常情况下数据形式和内容参差不齐,此时就需要进行大规模计算实行数据清洗和数据预处理操作。其中,分布式批处理任务也需要运行在集群上。
下文以锐天投资基于Volcano的大规模分布式离线计算平台的应用实践为例,描述Volcano的相关功能及解决方案。
二、技术选型
(1)Kubernetes作为容器集群管理工具
通过Container 隔离用户环境。不同的用户、开发环境和策略各不相同,python/java,环境直接封装在Container 中,方便快捷。
- 通过Device Plugin 支持GPU 等异构设备,无论对于调度,还是对于资源管理,都是有很大的好处。
- ETCD 的中心式数据存储机制。整体管理非常好用,随心所欲地重启,如果备份整个集群,只需要对ETCD中数据进行备份。
- 活跃健全的技术生态和社区内容,新特性频繁发布
- Go 语言符合公司技术栈
(2)文件系统使用Ceph提供的分布式文件存储CephFS
- Posix Filesystem 权限与接口。对于普通用户,最佳的文件获取接口就是一个文件管理系统。Posix Filesystem 权限管理让用户将自己的权限无缝迁移到Ceph上面。
- 强一致性。在A节点写入一个文件,B节点可以直接读取,好处:通过数据交互的形式达到信息交互。
- 同时支持大规模小文件存取与大带宽IO。CephFS元数据服务器,可以对多个子目录深度进行负载均衡,满足大规模小文件存取。
- 层级化硬件支持,机械硬盘,SSD,能够在提供稳定性能的同时让容量达到一定量级的唯一方案,让硬件资源得到很好的利用,节省成本。
- Kubernetes ReadWriteMany PV,所有节点读取同一个原始数据,生成模型数据,必须是ReadWriteMany形式才可以。
三、选择Volcano
容器管理和存储已经选择完毕,剩下的关键就是资源调度的选择。
(1)Why not default-scheduler
default-scheduler无法满足需求,最重要的是无法满足公平调度,通常多个团队同时使用集群,任务过多时,下一个任务资源应该给谁,这意味着基于队列的公平调度和基于用户的公平调度都是必不可少的。
- 缺少队列调度
- 缺少公平调度
- 缺少多租户支持
- 缺少高级调度策略,如Gang-Scheduling,浪费资源,浪费是最大的敌人
(2)Why not kube-batch
下图为kube-batch在Github页面介绍,图中依旧很详细的写出了kube-batch只是一个调度器,不提供调度以外的任何解决方案。我们需要做一个批处理解决方案,而不只是需要一个调度器,那么显然kube-batch是不满足的。
(3)Why is Volcano
Volcano是CNCF 下首个也是唯一的基于Kubernetes的容器批量计算平台,主要用于高性能计算场景。它提供了Kubernetes目前缺少的一套机制,这些机制通常是机器学习大数据应用、科学计算、特效渲染等多种高性能工作负载所需的。
- 支持公平调度
- 支持丰富的高级调度策略,如Gang-Scheduling、Binpack等
- 支持通过SSH plugin 方式实现Pod 互访
- 支持通过ENV plugin 方式向Pod 注入任务依赖,天然支持Tensorflow Worker Sharding
- 支持SVC plugin 方式对外提供服务
基于上述各种架构平台,整个系统服务架构如下图
基础设施层是Ceph和Kubernetes,基于 Ceph 提供高性能存储。
基于 Kubernetes 管理多种异构硬件,通过Volcano调度整个系统。
Loki 和Grafana 用于收集日志,以及同时作为用户面板与监控面板。
应用层为Batch Job、Machine Learning、ETL,基于 Batch Job 形式,扩展多种业务场景。
中间件可选,Redis提供存储,Kafka提供message信息处理,ClickHouse提供DB相关处理形式。同时中间件还有诸多好处:提供用户更多的接口,实现更多的形式来让用户使用,中间件与应用层混部,充分使用集群资源。
(4)多租户问题
采用的是社区中比较经常使用的方案。Kubernetes namespace做用户所有资源隔离 ,每个namespace对应一个用户,LDAP+OIDC与开发对接,给用户一个认证。RBAC用户资源的授权,授权用户使用Pod Security Policy,限制用户提交时必须采用Security Context写上自己的UID,用户运行时的环境以此为准。
(5)工作流
解决完上述问题以后,一个基础的工作流出现。本地渲染 Job Yaml进行提交,用户所有依赖数据全部同步在CephFS,并通过PVC挂载Pod。每个用户Nmaespace下,拥有自己目录的PVC权限。
四、Volcano的深度定制
上述功能和设计依然无法满足部分需求,在系统运行过程中,遇到了各种各样的问题,必须对Volcano进行改造。
(1)自研提交工具——Jobctl
定制任何东西,都需要一个基础的提交框架平台,Jobctl同时支持命令行提交和 Python Lib 集成。两种提交形式:异步:不停的提交任务,提交完就退出,可以提交各种参数组合提交一大堆任务到集群。同步:提交完一个任务以后,当任务完成后再返回给用户。以及可以自动生成复杂 Job 配置,对用户隔离 Kubernetes 复杂性。提供最基础的按replicas并行与按天并行。
(2)OOM Auto Scale Up
问题:用户不是技术人员,不能很好预估内存,OOM 后需要重复提交验证,可能需要重复多次,影响用户体验。
解决:将OOMKill所申请的资源按比例放大,放大以后通过OOMKill Auto Scale Up 自动重复提交,得到合理内存申请值。能够在用户不参与的情况下重复提交,最终得到合理内存申请值
(3)MinSuccess
问题:minAvailable个Pod 结束,则任务结束,非Gang 的任务难以灵活调度。
解决:添加minSuccess参数,minSuccess个Pod 结束,则任务结束,以及解耦Gang 所需Task 数量和完成Job 所需任务数量,以此来完成整个任务的生命周期。
(4)NodeZone
问题:一个Volcano 实例管理所有节点, 无法解决Noisy Neighbor,以及无法做到紧急资源预留。
解决:隔离多个Volcano 实例,分别管理多个Zone,对某些任务做物理隔离。
(5)Volcano Namespace Quota
问题:触发原生Namespace Quota 时,Pod 直接Fail,然而对于某些 Fail的Pod,会导致其他Pod无法运行,造成很大影响。
解决:触发Volcano Namespace Quota 时,Pod 排队延迟创建。
(6)Volcano 监控与报警
希望可以直接依赖时序存储,在Grafana直接展示监控面板。监控任务失败报警,减少浪费资源。
Volcano Exporter
- 输出Task 的队列标签
- 输出队列Capability
- 输出Job 的开始完成时间
WatchDog组件
- 注册Informer,并收集Metrics
- 负责任务失败与使用率报警
- 自动更新队列的Capability
五、高并发场景下的挑战与解决方案
随着平台的发展和用户的需求增加,依旧会出现很多问题。主要是集群规模过大:
单集群计算节点数量200,存储总量1.5PB,读写带宽15GB/s。同时承载长时间任务(1week)与短时间任务(1min),长时间任务不能停止,非常耗费时间,短时间任务,如遗传算法不停的迭代,造成 pod增长很快,进一步的导致Pod 每日增长量10W ~ 30W
(1)单个Job对象过大
问题:在有大量Pod 时超过ETCD Max Request Size (1.5MB)。直接调整Max Request Size,大量的Object对ETCD 造成冲击。
解决:通过单个Task 多Replica 的形式提交任务。Pod 内部通过ENVplugin 插件提供的信息,以Sharding的形式读取参数。
(2)Out Of CPU/Memory
问题:节点数少,并且大量短时任务不停调度,KubeletPLEG 压力大,Pod Binding 时间过长。Volcano 默认session 间隔时间为1s,造成Cache Snapshot不一致,导致Out of CPU 以及 Out of Memory。
解决:增加Node Binding Task Number,在Session 开始创建Snapshot 时,跳过Binding Task Number > 0 的Node。
六、总结
- 通过Kubernetes 统一管理计算资源,CephFS统一管理存储资源
- 通过用户认证与用户Uid限制,保证权限统一
- 通过Volcano Job 的Replica 来Shading 每个Pod 读取的参数
- 通过MinSuccess和MinAvaliable控制Job 的调度和完成行为
- 通过NodeZone和Queue 控制计算资源隔离共享分配
- 已在每日30W Pod 的大规模集群上稳定运行
通过分析锐天投资的基于Volcano的应用实践,对多个相似工具进行比较中,Volcano是功能较为完善和高效的,Volcano继承了Kubernetes接口的设计风格和核心概念。可以在充分享受Volcano的高效性和便利性的同时不用改变任何以前使用Kubernetes的习惯,并且对于某些场景,原始Volcano即使不能很好满足,用户也可以自由定制,为己所用。
附:本文整理自锐天投资:基于Volcano的大规模分布式离线计算平台的应用实践,点此回看
查看活动:https://bbs.huaweicloud.com/blogs/266530