美团⼤数据及机器学习集群云原⽣改造实践 美团数据平台资源与系统负责⼈/吴通 ⽬录 •早期架构及升级背景 •云原⽣改造过程 •关键问题和思考 •未来规划 改造前架构 场景特点 •⼤数据和机器学习两个⼤场景,先有⼤数据,后有机器学习 •⼤数据场景供需共构,对扩展性、可观测性等诉求不⾼,机器故障率低 •机器学习场景供需异构,对调度语义、扩展性、可观测性、运维友好均有⾼诉求,机器故障率⾼ 改造前痛点 •扩展App类型复杂度⾼ •依赖AM,⽽⽤户⽆感知,影响资源统计 •⽀持GPU、RDMA、NPU等设备复杂度⾼ •调度策略定制成本⾼ •故障感知、监控、可观测⽔平低 更深层次的原因 •离线场景的路径依赖 •架构变更带来的不确定性 K8SVSYARN •YARN:分布式集群资源调度系统 •K8S:分布式集群操作系统,管理集群资源的⽅⽅⾯⾯,不仅仅是调度 改造后架构 ⽬录 •早期架构及升级背景 •云原⽣改造过程 •关键问题和思考 •未来规划 组件 改造内容简介 etcd 服务器和客户端均升级⾄3.5.5,提升性能并修复单节点revision落后较多的问题 kube-apiserver 1.解决负载不均衡问题2.httplog获取userAgent可能触发map并发读写问题3.修复get&watch在apiserver_request_duration_seconds_bucket错误展示的问题 controller-manager 1.改造EndpointController,以解决underlayCNI不⽀持ClusterIPservice问题 2.增强NodeLifecycleController处理NotReadyNode的能⼒,降低节点不可⽤对已有负载的影响 Operator 1.SparkOperator:解决sparkonk8s,⽀持spark2.2和RSS2.TrainingOperator:解决TF、MPI、PyTorchonK8S,⽀持容错3.AFOServingOperator:以PaaS⽅式解决TF、PyTorch、Triton推理onK8S4.OrdinaryServingOperator:以类IaaS⽅式管理在线服务5.CodelabOperator:以容器⽅式给⼯程师提供开发实验环境6.PrestoOperator:PrestoclusteronK8S,⽀持弹性容错 调度器 ⾃研调度器,⽀持各种⾼级特性,吞吐⽔平较⾼ 控制⾯改造内容概览 组件 改造内容简介 物理机 调整挂盘⽅式,借助硬/软Raid解决kubelet不能管理多磁盘的问题 1.⽹卡、GPU亲和性⽀持到PCIE级别2.⽀持多⽹卡Pod分配多IP kubelet3.不同作业采⽤不同的oom处理策略 4.改造staticcpumanager,适配⽆预留cpu核⼼的绑核⽤法5.修复⼀系列导致kubelet不稳定的问题,如device权限、terminatingpod、IP回收等问题 1.gpu-device-plugin⽀持按卡类型汇报资源名 device2.gpu-device-plugin、rdma-device-plugin⽀持更丰富的设备健康检查和异常处理机制plugin3.gpu-device-plugin、rdma-device-plugin⽀持PCIE级亲和策略 4.npu-device-plugin⽀持ring内 npd 1.增强节点异常检查功能,保证节点在运⾏期环境是符合预期的2.包括CPU、GPU、⽹卡等硬件环境,也包括存储系统、IP管理等软件环境 ⽹络 1.采⽤underlayCNI,实现pod和集群外部⽹络资源互联2.改造clusterIPservice实现⽅式,实现在underlayCNI的负载均衡⽅案 存储 1.⽀持访问HDFS,主要解决从NameNode获取token和renewtoken,并存储到Pod内的问题2.⽀持访问DolphinFS,实现了⼀套CSIDriver,采⽤静态提供PV的⽅式,并⽀持⽂件系统故障后可⾃动恢复,不影响已有负载3.⽀持访问EBS,实现了⼀套CSIDriver,采⽤动态提供PV的⽅式。⽤来剥离解决实验开发场景的状态保存,以实现挂起恢复功能 节点端改造内容概览 组件改造内容简介 1.3分⽚2副本Prometheus,3thanos,3thanos-ruler 监控告警2.建设k8s_alert对接公司内部的告警系统 3.建设raptor-adaptor,对接在线服务指标到公司内部中间件1.主流⽇志⽅案⼀般采⽤消息队列实时收集⽇志,但解决不了时延、时序和丢失问题,对⽤户troubleshooting影响很⼤ 2.⾃研了⼀套⽇志⽅案,基本思路是在每个节点部署简单的⽂件服务器⽤来读取running状态可观测pod⽇志,pod结束后持久化到s3 3.构建了⼀套数据收集⽅案,实时收集etcd和Prometheus等数据源的数据,并通过消息队列存 储到持久化存储 4.构建了数百张dashboard,描述系统的运⾏状况和不同组件的内部细节,并借此指导各类优化 ⼯作 改造内容概览 ⾃研调度器 简介 •⽀持多租户配额管理,⽀持排队 •集群唯⼀调度器,⽀持GangScheduling,租户间、租户内公平调度 •⽀持抢占式调度,配额之上增加弹性量,提升资源利⽤率 •⽀持划分逻辑资源池,Pod⾃适应优选策略,减少GPU碎⽚ •⽀持RDMA亲和性调度,更好地⽀撑⾼性能计算需求 •完善的退避机制,⽀持租户->Job->Pod多层级退避 •调度吞吐300+pods/s 租户-配额管理 两级队列: ⽗队列:租户,⼦队列:租户内细分,min:配额,max-min:弹性量 Pod划分: SystemPod,UserPod(指定PodGroup),单调度器统⼀调度 GangJob: PodGroup唯⼀映射⼀个GangJob,指定作业提交队列 主流程 •OpenSession:从cache中复制Node、Queue、Job和Pod等对象,使调度流程⽆锁化 •AllcoateSystem:调度SystemPod,⽆优选过程,快速调度 •PreAllocate:为上⼀轮抢占成功的UserPod分配节点,GangJob遵循事务提交 •Allocate:调度UserPod,搜索最优Node,GangJob遵循事务提交,核⼼流程 •Preempt:为调度失败的UserPod抢占资源,GangJob遵循事务提交,核⼼流程 •CloseSession:更新Job和Pod状态,记录event事件和监控指标数据 调度概述 •队列公平调度:配额满⾜率低的队列优先 •GangScheduling优先调度:未满⾜Gang的Job优先 •Job公平调度:Pod调度率低的Job优先,防⽌⼀个⼤Job『饿死』其他Job •优先级调度:⽀持队列内指定Job优先级、Job内指定Pod优先级 •异构调度:⽀持10+种GPU卡型,⽀持5+种⽣命周期、特点不⼀的任务 •调度语义丰富:⽀持k8s原⽣调度语义,扩展了如⾃适应聚集/均衡调度、RDMA⽹络亲和调度等 抢占概述 •队列max>min即表示开启弹性调度,max-min部分的资源占⽤在集群资源紧张时会被抢占 •队列只在配额未满⾜的情况下才能抢占,弹性量部分不通过抢占来满⾜ •公平性:和调度过程类似,优先为配额满⾜率低的队列和Pod调度率低的Job发起抢占 •优先级抢占:⽀持队列内指定Job优先级、Job内指定Pod优先级,抢低优保⾼优 •GangScheduling保护:优先抢占每个Job超出minMember的Pod,如果GangScheduling被破坏,则抢占整个Job 抢占关键实现-GangScheduling •GangScheduling:为Job分配⼤于等于minMember数量的Pod •调度事务化,连续为Job调度⾜够数量的Pod后提交调度结果,否则回滚 •抢占分成两步,先尝试仅抢占超出minMember部分的Pod,再执⾏Gang抢占 抢占关键实现-两级事务控制 为GangJob发起抢占会有多个Preemptor,多个Preemptor抢占结果提交需要保证原⼦性;每个Preemptor可能抢占Node上的多个Preemptee,多个Preemptee的抢占结果也需要保证原⼦性。 逻辑资源池划分 核⼼思想:刻画任务类型特征,在资源碎⽚、可⽤性、性能和可维护性之间找到平衡点 •有状态的⻓作业。执⾏迁移和运维动作困难,尽量聚集在⼀⼩批机器上 •⼤规模训练作业。单worker占据整机资源,集群需要预留⼀些空载机器 •多实例在线服务。将不同实例打散到不同机器,当节点故障时降低对服务的影响 在逻辑上分成均衡池和聚集池。均衡池负责多实例应⽤的容错和提升集群整体IO及⽹络带宽,聚集池降低⼤尺⼨Pod的等待时间,并将有状态⻓作业束缚在少量机器上。 逻辑资源池只是⼀种优选机制,当聚集池满了之后,聚集型的Pod也可以被调度到均衡池中,反之亦然。 退避机制 前提假设: ⼀轮调度失败的任务,在之后⼏轮中⼤概率还是失败 四级退避设计: 指数退避算法,防”坏分⼦”,减少调度器做⽆谓调度,充分保证正常队列、任务的调度需求,在 ⾼调度负载场景下可以显著提升调度吞吐 CodelabOperator 什么是Codelab •Codelab是基于容器实现的实验开发环境,定位于⽤户进⾏⼩规模开发实验,提供隔离独⽴的开发环境,持久化存储实验环境和数据,能快速启动和恢复 •Codelab核⼼功能:1)状态持久化,⽀持挂起和恢复;2)资源监控;3)集成实验环境及WebIDE,如JupyterNotebook、PyCharm等 Codelab系统架构 1.Application应⽤层:通过APIService暴露API给⽤户,渲染Codelabyaml 2.Controller控制层:调谐PC的⼀切⾏为 3.Storage存储层:Codelab通过PVC挂载或客户端访问所需共享 CodelabOperator架构 •准备:前置准备⼯作,如添加Finalizer,申请HDFS访问token等; •创建Pod:根据podTemplate创建Pod及其相关资源 •挂起和恢复:通过spec.pause标记挂起和恢复期望,挂起时删除Pod,恢复时重新创建Pod; •同步集群外资源:对接公司内服务树系统,将Codelab注册到某个AppKey; •删除和清理:清理⽆效Codelab,从Appkey注销,并释放HDFSToken; •更新状态:计算Codelab状态,并更新.status Codelab启动过程 •通过容器共享挂载实现初始化容器⽂件共享 •使⽤EBS存储持久化⽤户开发环境,主要包括yum和pip包 •使⽤DolphinFS储存组内共享的数据和代码 •pc-start.sh作为systemd服务初始化Codelab 挂起与恢复 1.闲时⾃动挂起Codelab,删除Pod,释放所占计算资源,保留PV 2.恢复时将重建Pod,重新挂载PV,恢复数据和环境 DolphinFS接⼊ 简介 •HostPath->CSI •租户⽬录唯⼀映射PV,静态绑定加速调度 •多DolphinFS集群⾃动识别,业务⽆感知 •Pod粒度fuse,提升读写并发 •Fuse进程位于物理机,升级CSIplugin不中断挂载 •⽀持挂载点异常检测和热恢复 改造前痛点: •机器上所有Pod共享同⼀个挂载点,挂载进程异常影响所有Pod •客户端发⽣重启,容器内的挂载点丢失,⽆法热恢复,只能重启容器 •客户端升级等运维操作会导致挂载中断,⽇常运维“战战兢兢” •针对多集群挂载需求,每⼀种上层作业引擎需要重复适配 租户-PV映射机制 •租户挂载固定⽬录,设计⼀个租户唯⼀映射⼀个PV •预分发租户PVC和PV,并完成静态绑定,加速调度过程 多集群⾃动识别 •多集群的配置信息存到ConfigMap,并挂载到CSIPod,⽀持热更新