腾讯业务及组织架构现状
先简略和大家介绍一下腾讯外部的业务及相干组织架构的现状,有助于帮忙大家了解为什么咱们会基于前面的架构来设计整套计划。
下图的利用大多数人常常会用到,比方微信、腾讯视频、游戏等等APP,其背地承载的技术也不尽相同,波及了NLP、计算机视觉、强化学习、语音等不同的AI技术。
比方咱们玩的《王者光荣》或者下围棋,背地所对应的就是用强化学习训练进去的一个机器人,玩游戏没有队友陪同时,机器人能够满足咱们对战单干等游戏需要。
不同的业务部门,APP对外需要也不同,均会针对本人的业务场景做一些AI平台的定制。咱们做的是底层算力,给业务部门提供服务时,在思考整体资源利用率的状况下,也要为各业务便捷地去做些定制服务,这就是腾讯外部的一个多租户的现状。
业务特点与规模
接下来,介绍一下腾讯外部业务的一些特点以及大略规模。
目前的环境是基于开源我的项目TKEStack,TKEStack是腾讯私有云TKE的开源版本,是一个开源的容器云平台解决方案,用的KubernetesV1.14版本,操作系统是腾讯自研的Linux操作系统,曾经为GPU或者腾讯外部业务做了一层性能的调优和bugfix。
GPU节点是NVIDIA的V100、P100,个别会有一些M40的机器。网络联通应用100G的RoCE,既可能提供以太网的反对,又可能提供RDMA的网络协议反对,对于用户去做一些多机通信的优化有事倍功半的成果,也从硬件层面保障了整体的应用效率。
残缺流程设计思路
接下来介绍一下咱们是怎么欠缺、开发以及设计这一整套流程的。
Kubeflow 是什么
这里先介绍一下对于Kubeflow以及Kubeflow外面一些次要的组件,帮忙大家了解其中的一些具体业务,或者设计。
Kubeflow是什么呢?
Kubeflow自从2017年底公布,目前逐步成为支流的在Kubernetes下面跑机器学习、深度学习等训练或者推理工作的次要工具。
Kubeflow蕴含十分多的组件,比拟多的像Operator ,或者像主动调参的工具。
Operator
先介绍一下Operator,它是Kubernetes中的一种概念,次要是用来打包、部署以及治理用户的工作。但在Kubeflow外面,Operator次要用来治理机器学习或者深度学习外面的工作。
那么它能帮用户做什么呢?
比方在多机的工作上面,如何去治理和保护一个工作的多个节点,以及之前通信是怎么做的,怎么可能帮忙用户治理整个Pod以及工作的生命周期,比方某一个Pod失败了,整个工作是终止还是有一些其余的容错方法,这个都是由Operator来实现。
目前支流的Operator有几种,会对应每一种框架。比方用的最多的TF-Operator,次要对应的是tensorflow,MPI-Operator次要对应Horovod,Pytorch和Caffe2的Operator,它们针对各自的框架都有一些定制的场景。
这里着重介绍两种Operator以及咱们对它做的一些重点优化,也是咱们用的比拟多的两个Operator以及框架工作。
MPI-Operator
MPI-Operator是为了MPI的工作或者Horovod的工作提供一个多机的管理工作。它有V1 1、V1 2以及V1的版本,V1正在大规模开发中,所以咱们举荐用V1 2 。将来V1 release之后,能够举荐应用。
在这种版本上面,它有两个概念:一个Launcher,另一个是Worker。Launcher相当于一个启动器的角色,它会等Worker都就位之后,去启动MPI的工作。然而在这里,Launcher自身就会占用一些CPU的资源,其实咱们是能够将它合并到一起的,也的确做了一些改良并提交到社区,去掉一些无用的CPU的Pod,让某一个GPU节点起到这种角色。
此外,为了晋升Pod的创立速度,以及晋升Job的启动速度,咱们也做了一些优化。
比方Launcher在期待其余Worker就位的时候,是从其余Shell脚本的版本变成了多线程的工具,能够极大晋升整体的等待时间。
除此之外,比方再减少一个额定的init container去下载用户的docker镜像,这样来做docker镜像相似于并行加载这种形式。
咱们举荐是间接参照Kubeflow的MPI Operator的GitHub去查看更多的详情,大体的流程也在上图右侧展现进去,次要是将MPI Job换成对应的Kubernetes能够辨认的一些资源,比方应用CRD、应用Configmap以及RBAC管制权限等等。
TF-Operator
除了MPI-Operator,还有另外一个用得更多的是TF-Operator,TF-Operator次要就是帮忙用户启动多机的一个PS-Worker这种架构的状况下的一个多机的工作,因为这个集群全副是GPU相干的集群,所以咱们举荐用户是将PS和Worker放在一个Pod外面启动,缩小一些通信的老本。
除此之外,咱们还做了一些额定的优化。比方像就近部署的计划以及脱库调度的计划。为了放慢image加载的工夫,也是用IfNotPresent这种形式去放慢整个的速度。
目前TF-Operator还是比较完善的,其余各家公司也都会有比拟多的投入。
多租户场景下应用Kubeflow构建训练平台
介绍完Kubeflow目前的一些Operator,言归正传,明天的主题也是多租户的场景上面应用Kubeflow构建一个训练平台。
惯例构建计划
先来看一下目前Kubeflow的多租户平台是如何构建的。
目前,在这个平台有两种形式,一种是用原生的Kubernetes RBAC,就是Role based access control去做权限的管控。另外一种是应用Istio,Istio这种形式更偏差于推理场景。通过这种形式对用户的拜访进行一个管制。
能够简略来看这张图,当咱们为用户提供一个集群,个别有两种形式。一种是通过命令行的形式应用,另外一种就是提供Web端,Web端通过Istio的gateway接入整个集群,而后Istio的RBAC去做权限管控、去做流量的散发、去保护整个集群的权限。
另外一点,如果是客户端,除了集成的客户端,另外还引入Kubernetes的RBAC去做容许或禁止,帮忙用户解决权限管控的问题。
但它有一个小的问题,就是所有的用户都会共用所有这些资源,像Operator、Controller,用户只能应用定义好的资源,比方咱们设计好一种Job的类型或者Operator的类型,那么用户就必须这么应用。
然而对于多个事业群,大家会有一些自定义的需要或者定制的Operator,在这种场景下,就会有些顾此失彼。为此,咱们也引入了一些其余的形式改善这种需要。
优化构建计划
用户分层
当初咱们做的多租户的Kubeflow训练平台,首先在资源层将GPU资源汇集到一个或多个集群,在此GPU集群之上提供多个用户的集群,也是K8s的集群。用户能够通过Virtual Kubelet,而后接入到底层的算力集群,分成两层:
- 在用户的集群,这些租户的管理员去治理或者去创立,去本人定义一些Operator或者Controller,用户接入的是这些租户的K8s原生的KPI;
- 在底层算力集群 ,咱们对立集中调度,晋升资源利用率。
当有工作下发的时候,通过Virtual Kubelet,或者用Kubernetes实现的Virtual Node转发到算力集群,在底层算力层面而言,能够通过Namespace隔离不同的租户以及不同租户的工作,将一些特定需要的节点划分造成一些小的资源池,更多就是通过Namespace进行隔离。
然而对于下层用户而言,他们有一些自定义的权限,也能够本人开发一些本人的组件,相当于将权限分来到。
咱们这里实现的Virtual node,相当于用Virtual Kubelet实现的,Virtual Kubelet相当于Kubernetes下面一个开源的Kubernetes kubelet实现,最开始是由微软的一个团队开发并保护,后募捐给了CNCF成为sandbox的我的项目。Virtual Kubelet前面是能够接入像ACI、AWS forgate、IOT等等可扩大的组件或者服务。比方OpenStack也是能够接入的。
而咱们这里其实相当于接入了一个新的性能,它是一个比较简单的,次要定义为用户有一个Pod下发申请或者有一个其余资源下发申请,咱们间接转发到底层的一个K8s,同时Virtual Kubelet也会监控底层它关注的资源状态,并将状态汇报给下层,它相当于一个桥梁的作用,承前启后去同步整体的状态。
这张图就是一个比较完善的用户的集群或者用户的一个架构图。在左侧有用户的集群,对应的是通过Virtual Kubelet连贯到底层不同的算力集群,这些算力集群都是有GPU资源的算力集群,也是K8s的集群。
如果用户比较简单,能够间接接入咱们举荐的组件,造成一个整体的简略管控策略。比方用户想跑一些工作,以及有本人的controller去定义整个的规定,其实能够接入像MPI-Operator、TF-Operator等operator资源。
这里也多提一句,当用户下发一个MPI的Job,MPI-Operator就会转换成像Configmap、Secret,像RollBinding ,以及像多个Pod这种资源。
当这些转换产生实现之后,Pod通过调度器到具体的某一个Virtual Kubelet,Virtual Kubelet发现资源到本人的节点后,会将其转发到具体的某一个Kubernetes集群,并关注这些Pod或者其余资源的状态,造成整个的一个转发和传递的成果。
对于下层集群的管理员,不再须要关注底层集群的状况以及权限管控等,只有关注上一层即可。底层的管理员须要关注更多整体资源的应用状况,造成上上层的拆散。
晋升资源利用率
介绍完上上层拆散以及怎么做多租户这种场景,转到咱们之前提到的集群全副资源归集到一起,次要指标是为了晋升资源的利用率。当整个资源买通当前,怎么晋升资源利用率?而且通过后面介绍的多租户的机制,让用户也不必感知到。
在深度学习或者机器学习场景下,大部分工作都须要批量调度性能,也就是须要保障多个Pod同时地调度。它次要算法就是all or nothing的算法,保障整个资源要么能够调度,要么就不要调度,如果无奈调度那么就排队,保障整个资源不会被饿死。这是一个比拟常见的需要。
这外面次要是用volcano去做gang-scheduling。
引入工作优先级
除此之外,咱们也引入了一个优先级的工作。顾名思义,就是咱们给每个用户或者每个租户都凋谢高优先级的工作,他们能够在一个固定工夫之内被调度。当整个集群的利用率不太高的时候或者调配还有一些空间的时候,就能够开发一些低优的工作给用户,用户能够提交整个的弹性工作或者叫低优的工作。
这种工作下发下来之后,就能够以低优的工作占据这些闲暇资源,当高优工作下发的时候,就能够抢占这些低优资源,保障整个资源池是最满的状态。
策略优化
最初一点是一些优化的策略,如基于网络拓扑架构或者GPU的拓扑架构的拓扑调度或者应用binpack,缩小底层集群的碎片,保障更多的资源是能够尽快被调度的。
其余的优化,如晋升MPIJob的一个启动速度,可能尽快地将工作下发上来,将底层闲暇的算力资源变得越来越少。
除此之外,家喻户晓,咱们跑GPU工作个别都会用nvidia—docker2版本,咱们剖析了一下,其实nvidia—docker2对应的版本,它的Pod启动速度相比于个别的runC的这种启动速度还是慢不少,剖析起因,次要集中在每次启动的Pod或者container,它都会去查问CUDA或者Nvidia驱动的版本对应的信息,而后供Nvidia Container的CLI Prehook去操作。
然而在咱们场景外面,其实不太能用得上,因为咱们是一个公有云的平台,公有云的平台外面不波及特地多的常常更换硬件或者驱动版本常常变动的场景。所以咱们能够简化。
怎么简化呢?最简略一种方法,就相当于将CUDA、INVIDA这种驱动信息全副缓存下来,而后保留到某一个固定的文件,当机器重启或者将驱动变动,CUDA的版本发生变化的时候,才会从新触发这个动作,获取更新的信息缓存下来,这样能够大大减少每一次Pod创立的时候都会获取这些信息的次数。
这个信息的工夫,如图中所示大概在几百毫秒。
通过这样一个优化,咱们是能够将整个Pod的启动工夫晋升大略30%到40%的工夫。对于用户体验还是十分敌对的。
当然这个只能说做几百毫秒的优化,像深度学习的场景,CUDA的版本、Nvidia的版本,Nvidia驱动自身就比拟大,所以如何可能优化这个docker image的加载,或者可能缩小它的镜像拉取,做一些预散发、预部署,这个也是咱们十分关注的一点。除了一些调度层面能够做的事件,其实业界也有一个比拟风行的形式就是做一种提早加载。
docker image是分多层的,以及它分metadata。考察发现,基本上大多数的镜像外面的内容个别不会被用上,能用上的也就10到20%。
咱们做一些提早加载,当它在用的时候才去加载,当然这个也是一个比拟前沿或者工夫性质的性能,咱们也在重度参加。前面有一些停顿,大家能够继续关注咱们,会一直和大家来分享。
总结
基于kubeflow目前的架构或者一些现有的组件反对多租户以及一些前面优化的策略,为了晋升整个用户体验,咱们其实还是有很多工作去要去做。比方当初比拟风行的弹性训练任务,像基于kubeflow、基于horovod自身的能够动静伸缩,去占用更多的资源,可能缩小用户的训练工夫,都是十分要害的。
另外一点,MPI-Operator自身V1.0的版本咱们也在重点参加,心愿它能尽快被release。
参考
- Virtual-Kubelet: https://github.com/virtual-ku...
- MPI-Operator: https://github.com/kubeflow/m...
- TF-Operator: https://github.com/kubeflow/t...
- Nvidia-docker2: https://github.com/nvidia/nvi...
- Tensile-kube: https://github.com/virtual-ku...
- Learn more about TKE: https://cloud.tencent.com/pro...
- Jobs: https://careers.tencent.com/h...
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!