导读
一般来讲,在云端构建大规模计算集群是难以实现完整的资源自治的。那么在计算任务运行容器化之后,应当如何进行云上构建计算集群并对大规模容器进行管理呢看这篇文章。
演讲嘉宾: 林帅康 | 晶泰科技云计算平台技术总监,2015年加入晶泰科技,主要负责晶泰科技高性能计算平台(majorana)的研发工作,专注于在公有云上通过mesos/k8s构建大规模的容器化高性能科学计算平台,以实现高效,低成本,灵活的云上超算系统。
以下内容整理自分享:
我是来自晶泰科技的林帅康,今天我想和大家分享的主题是《云上构建容器化的科学计算平台》。
晶泰主要致力于通过分子模拟平台以及药物动力学、剂型预测技术,减少在药物前期的研发周期,从6-8年可以减少到4-5年时间。它所依赖的技术,最右边会有量子算法,这主要是和科学计算相关,它可能会包括大家听说过的蚁群算法以及退火算法等东西。再结合AI的融合,最终这两部分会跑在超算的平台上面,例如我们熟知的天河2 或者新出的中国最大的超算中心。但是因为超算上面使用的资源可能会有申请的过程,而且使用量会有一定的限制,比如说一个小企业申请,有可能会限制只可用几十台或者上千台,比较困难。
我们就会想到,现在云计算发展得非常快,很多企业已经从传统企业转换成云上企业,已经成功落地。能否把传统的科学计算移到云上面然,现在很多公有云平台已经在做,比较典型的产品可能是批量计算、高性能计算。我们把这两部分技术结合之后,借助腾讯云和AWS去构建一个大规模的HPC集群,可能会达到百万核实量级。核实在科学计算里面是一个通用的概念,主要衡量计算池的标准,和超算用浮点的计算能力是一样的,100万核实怎么换算如说每一台机器会有24核或者32核,1万个核需要300台机器,100万可能会到几千上万级的机器集群。
计算平台演变
刚才的介绍是想说明未来支撑比较特别的场景,可能需要一个大规模的资源池的支撑。在构建这个资源池的时候,有一个计算平台演变的过程,这个演变过程就不放太多的架构图,稍微解析一下。我们公司从2015年成立的时候,也是从超算这边开始脱离出来使用的。当然了,我们第一代平台有一个PBS调度系统,一般跑在超算上面都会有一个任务调度系统。相对于K8s这种复杂的容器编排来说是比较轻量级的。
但是随着业务的递增,我们需要计算量越来越大,这两个也有它们的局限性,例如有些资源利用率的不足以及LPS的性能不足,LPS压测可能会焊住以及假死等等状况。这样我们就会有第二代平台的迭代更新在里面,蓝色这边是我们开使用Mesos。我们2016年也有关注K8s,有一个简单的转型,但是当时K8s还处于比较早期的状态,而且也没有太支持批量计算服务在里面,我们就选用了mesos。当时mesos比较火,在国内有很多公有云都会根据它做一些第三方的插件调度软件之类,我们也会拿mesos来管理我们的集群。
它的架构是这样的。左边是业务前端,我们使用的Jupiter的Web服务,Jupiter大量用于科学家在线编程以及机器学习。下来是我们对输入的文件进行一键化清洗和初步的分析,最终会到以对象存储以及其他存储空间组成一个数据壶,中间融合了一定的workflow操作在里面,业务人员随着提交任务计算,会不停的在每个阶段对计算出来的结果进行分析,再去重新生成新的任务。
最右边是计算平台的架构图,有任务的管理、任务队列、中间件,例如使用一个MQ对接了不同云的集群,下面是某一个公有云集群,例如是腾讯云TKE容器集成在里面。当然,我们还是会有兼任mesos集群在里面管理。
我们使用CI也比较简单,触发一个drone的CI,然后输入的SDK库,SDK库是我们一些科学家和量化工程师开发的专有算法,去打包或者其他软件,通过这个私有库下载到Docker镜像,根据Dockerfile去构建。拉取一些基础的镜像。然后把镜像同步了AWS或者腾讯云上面来,最终有一个发布通知的过程。
右边有一个镜像分层的结构在里面,基础镜像比较熟悉了,第二块比较特别一些,有HPC Images在里面。我们会使用一些现有比较有名的二进制软件在里面,这些软件都是在固定的平台去编译的,有的有源代码,有的没有源代码,他们在固定平台编译的时候,因为云服务发展得比较快,例如腾讯云可能又推出一些新的机器类型,它的CPU指定级以及其他一些架构有变化,老的NEG系统跑起来,可能跑着跑着就会死掉,还有一个性能的问题,它可能没有用到一些优化的CPU指令集,比如说ABS的一些指令集,然后会导致效率上下降20-30%。
如果大批量使用,这是很大的成本量。我们会针对不同的平台有智能化的构建,去适配不同的当前在腾讯云上面用的机型,以便它能对应在某一台机器跑的时候,不至于是跑了一个错误的镜像在里面。下面有一个工程的镜像在里面,就是刚才说的算法开发组上传的一些SDK,最终是Docker跑起来运行池状态。
讲完镜像,开始真正讲K8s集群的构建。我们当然是基于腾讯云服务器的TKE来构建,之前是叫CCS,现在叫TKE了。它现在的构建方式相对于之前我们自己手动构建的方式更加方便,基本一键就可以构建出一个带有Master的K8s小集群在里面,有点像集群即服务,我这个集群可以通过一种服务的方式提供出来,你可以随时删掉或者创建。
腾讯云这边也打通了和其他每个一些云服务的服务,例如监控、hap、安全的以后一些服务在里面,用起来还是比较方便的。TKE会提供一个API出来,但是它提供的API主要还是针对一些服务编排,真正去做高性能计算的任务提交,我们现在还是用原生的client-go来做的。右边是一个K8s高可用的集群架构。
下面有一个红色标,这个pod数就会超出了它的限制,可能是1000-70000个pod。容器和上面相同,稍后我会解释为什么相同。pod单个结点一般会有1-24,我们目前是用24的机器。下面产生这个数据的原因有这么几点,我们的SBC单机的配置要求比较高,可能是24核或者32核的大机器类型,现在一个pod对应一个tast,就是一个pod会跑一个任务。
我们最小的一个pod是多少要的CPU是一个核,24核在最极端的情况下会跑24个任务,就会有24个pod在跑,这样算起来就超过它的限制。我们还会有单次提交任务量比较大的情况,例如我们单次会提交10万个任务,如果你不控制任务提交速度,把10万个任务都提交到K8s里面去,即使资源都起来100台,但是已经有9万多个任务在等待了,这对它的其他组件是有一个冲击性的,特别是一些周期性查询的组件在里面。
我之前使用腾讯云,坦白讲还是遇到了一些问题,毕竟现在国内公有云上的K8s集群还相对来说不是完全的特别成熟,特别是面对我们这种使用情况比较特殊的,构建集群也比较大,任务队列也比较长,这需要有个定制化开发,或者慢慢去调试的过程。左边是我们遇到的一些问题,比如说Kubectl请求超时,推荐一个命令,加-V可以打印每请求一步请求到哪里,以及到哪里去超时,可以定位到相应的问题是请求到一个API还是别的地方。K8s调度严重延时,这也是因为任务队列过长的一个主结点集群性能下降,可能会有调度的退避算法在里面,即使Node上面有资源,但是这里卡住了,不会把相应的pod调进去。
还有K8s-dns负载过高,如果每个pod里面都会有一个dns请求,就可能单次有上万个pod去跑,对K8s-dns去请求。因为K8s-dns还是比较轻量级的,它虽然有一个负载过程在里面,但是还有可能会拉垮它,API不可能开始出来,以及ETCD读取延时变大,因为提交任务比较大,每个任务通过job去创建,那么在ETCD上面就会有对相应的数据存储,以及ETCD可能还会有一个事件对象存储在里面。K8s容器 络不可用也是和其他相关的。
K8s官方也提供了一些构建大集群的辅助文档在里面,但实际上你在构建的时候还是会有形形色色的问题在上面是没有提及到的。
K8s主结点集成已经由腾讯云给我们构建出来了,接下来肯定是要添加计算结点在里面,通常情况下都会提供弹性伸缩组融合在里面。目前大多数都会实现了K8s官方的 区版实现。我们的要求主要出于节约成本的目的,一定要高度弹性的以及快速扩缩容,因为它会涉及到我们案例 告产出,我们有一个案例有一个周期,需要在特定的时间内输出这个 告。
但是我一次性提交10万个任务,可能会要求几天之内要把这个任务算完,所以单次的弹性资源有可能是0-1000/2000个结点一起跑,然后跑完之后又从2000个结点缩放到0的结点,会有这种场景在里面。大概是这样子,也就是说我8点的时候就开始提交任务资源,从8:20提交得队列比较长在这里了,我们就会限制一个流控。稍微了解一下K8s弹性伸缩的原理,是根据pending pod的数目进行触发的。
我们可能要求20分钟之内扩到4万个资源在里面,也就是2000台机子在里面。这个任务量比较大,算的时间比较久,可能从今天8点算到明天9点大概会算完,因为任务的输出很多时候都会有相似性,所以计算的周期相似,那么就会有一大批任务会释放出来。到这里就会有一个比较长的曲线在里面,这也会影响我们的成本,我们称之为长尾的任务,也是一个遗留的装箱问题,我们还没有实现K8s的重调度以及任务可重调度断点去算的功能在里面。
稍微提及一下,因为了解K8s的可能都会知道。刚才我们提到了扩容机制,可能调度失败的pending pod数量同我们配置伸缩组里面的配置,例如有一个1万个是调度失败的,那么我们现在配置的伸缩组可能就是每个机器类型是24核,它就会计算出相应的机器类型,会有分批的添加计算资源,达到调度的效果。
缩容方面,目前官方文档也有一个触发条件,是当前Node一个(英文)的CPU可能会少于50%,K8s这边伸缩容不会考虑实际上的机器负载,主要是针对pod来调度,如果pod没有可调度的资源,它就会进行扩容,如果Node结点有一些CPU的(英文)值,例如24核当前只跑了8核任务,它也可能会触发调度,最终从三个结点把pod漂移到两个结点上面去,这种情况对于我们做HPC jop会有影响,我们HPC jop是一次性的,并不像服务可以随时漂移,它需要一次性算完就算完,中间如果打断,有可能浪费前面10个小时计算的机时。
基于这种情况,我们会想怎么阻止pod被重调度漂移,官方提供了一些参数,例如在cistern上面的空间,这些pod不会漂移,还有一些外部存储的pod也不会漂移。但是我们不让它漂移,刚才有一个长尾的情况在里面,最终到9点的时候,因为这一千台机器的任务都是分散调度的,在调度时并不知道这个任务是多长多久的,最终会导致有一些长任务分布到每一台机器上面去,所以大部分任务跑完之后会发现有很多机器上面单独跑了一两个任务,每个任务可能就占8核,那可能每台机器有16核的浪费,有几百台机子都是16核,其余去等待几小时让它算完,就有资源浪费的情况。
当时我们考虑支持断点续算的功能,断点续算在我们这边的实现原理也比较简单,可能说当HPC job周期性算的时候,我们有(英文)的动作在里面,把中间的结果保存下来,就像进程调度一样,有上下文压占和出占一样,就是说开个(英文)上传到对象存储,过了几个小时,发现有大批量的释放之后,整个集群的资源利用率会下降,这时候就可以触发这个重调度,把这些占用了结点资源,但是只是占用了小部分可以做一个漂移,它漂移到另外新的结点,就可以从对象存储里面把之前的上下文下载下来,重新开始它上一步计算。当然,这个重调度计算还是会有一定的机时在浪费,因为(英文)这边有一个周期,可能会浪费一个小时,我们通过这个情况缩短了它浪费的力度。这里主要是资源利用率的问题。
这边是一个单结点的任务定义,下面说我们现在支持的HPC多结点并行的任务。了解过高性能计算的人,都会通常意识到现在一些公有云的普通 络没有办法满足MPI数据并行任务。MPI需要一个高性能的 络,可能是几倍、几十倍的万兆 卡,需要一些专有的 卡去支持远程的直接内存访问。
通用的概念是,有两台机子,这台可以通过 络去访问那一台的内存,就像我在本机访问的速度一样,延时是非常低的。当然,这需要一些专有的 卡。运行任务的运行周期会相对长一些,右边是我们在K8s实现的MPI任务。刚才提及现有的TKE提供的 络没有达到通用的MPI的 络要求,但是我们会其中筛选出一些可以在云上面跑的MPI任务。它们结点之间的数据交互通常是比较少的,这样它们走的 络数据传输也比较少,这样就可以避免高性能 络的限制,但是还是会有很大的局限性,在 络发展里面肯定会接触很多流体力学计算在里面,现在这种情况是没有办法满足的。
但是刚才看老师的解析,我们也关注到现在公有云陆陆续续会上一些裸金属的机器在里面,机器上面会配备一些高性能的 卡。并且K8s这边有一个叫做(英文)插件支持的机制在里面,可以直接把RDMA 卡或者其他高性能的 卡插到上面去,跨过了OS以及TCBIB 络层,可以实现低延时的数据分发在里面。右边这个图是InfiniBand性能和百兆 卡性能(英文)区别,可以看到它的测序是OpenMPI以及MPICH两个开源的MIP库,右边时间明显比左边时间长很多,因此它是依赖于高性能 络提高计算效率的。可能大家还是接触比较少,我稍微提及一下。
任务的性能监控刚才已经提及到了,容器云这边已经提供了比较健全的服务监控。当然,我们可能会出于一些其他的需求,需要实时监控pod CPU以及内存。目前不会去监控 络吞吐,所以我们也会搭一个heapster+influxdb+grafana开源架构在里面,去收集我们想要的信息,去对比算法版本更新的时候会否导致CPU的运行效率下降和内存变多,但是因为任务量比较多,所以存储的数据会比较大。
下面有个kubelet10250端口的参数,我们之前碰到一次,刚刚创建集群的时候,在安全组上面太粗心大意了,没有把计算结点10250端口封掉,导致会被人家入侵,因为它开启了enable-debugging-handlers=true 的情况下,外部可以直接通过这个端口,到pod里面进行集群调试,我们发现有人通过扫描机器,在上面跑了一些外挂程序。大家使用的时候稍微注意一下,官方已经有一个PR在里面。
日管理依赖腾讯云,对接了Kafka和ELK,不详细说了。前面是腾讯云的容器服务实践,遇到了一些痛点。腾讯云容器发展得还是比较快的,但是它也不可能覆盖所有的应用场景,通过我们和它的合作,一是满足业务的需求,一是可以推进它更好的做一些比较少见的服务,例如高性能计算,在这方面可以完善得更好。
未来规划
下面是我们对未来的一些规划。我们也比较关注云容器实例服务,这已经在K8s TKE层面上再推进了一步,集群的主结点创建和弹性伸缩都不需要管理了直接通过腾讯云这个接口提交相应的任务,上面就可以跑起来了。所以这方面落地更加方便一些,serverless lambda大家也比较了解,在高性能应用中也会使用到,一些比较小的排位任务,可能是一分钟的任务,但是它有几百万量级的东西,就可以通过serverless lambda来实现。完善的作业工作流管理刚才在架构图中也提到过,对于一些复杂的预测流程,任务之间有严重的依赖关系。例如这个图中,job2、job3、job4是依赖job1的输出文件作为输入文件,后面的job5、job6也是依赖前面文件的。如果中间有一个任务出错了,在开发的过程中可以重走这个工作流去,节省到前面几个任务的计算流程直接到job6,继续往上面走,继续修复以及类似的循环这样去做。
↓↓↓点击阅读原文,你也可以成为技术大牛!
文章知识点与官方知识档案匹配,可进一步学习相关知识云原生入门技能树容器编排(生产环境 k8s)kubelet,kubectl,kubeadm三件套8589 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!