董晓聪,作业帮基础架构负责人,主要负责架构研发、运维、DBA、安全等工作。基于开源的力量,和云厂商一起完成作业帮技术体系的云原生重塑。
项目背景
作业帮教育科技(北京)有限公司成立于2015年,一直致力于用科技手段助力教育普惠,运用人工智能、大数据等前沿技术,为学生提供更高效的学习解决方案。随着业务需求的发展,作业帮的 IT 系统面临巨大挑战,现有基础平台架构已经无法满足快速增长的业务需求。业务对快速迭代、急速弹性、调用链追踪、统一的监控日志平台、提升计算资源利用率等需求迫在眉睫。2019年下半年,作业帮开始规划并调研容器化解决方案。在此期间,腾讯云团队和作业帮进行了多次深入的技术交流,同时作业帮也和腾讯云的其他容器客户进行了充分交流沟通,多方面了解腾讯云原生技术和腾讯云的服务质量,最终决定将其部分重要业务迁移到腾讯云容器服务TKE。
企业成本管控的常规做法是将各项计算、存储、网络资源归口到具体业务单元,然后由系统运维、SRE、业务线研发以业务单元为视角综合评估成本的合理性。常见的成本优化点按照架构层次从上往下,依次是以下几个方面。应用性能有待提升
对于企业主流使用的语言,如PHP、Golang从框架入手。应用框架的理论性能和实际业务的性能往往有很大gap,多为业务架构缺陷或者数据存储设计的不合理导致。同时应用框架随着功能的不断迭代和更高的要求,自身性能上也需要优化。
对于一些占用资源比例较重,如超过10%的应用服务也是值得深入投入,其性能的提升能带来更明显的回报。应用部署模式差,带来计算资源的浪费
单应用服务机器负载率低
对于高并发业务,虚机下机器峰值负载常规在10%-20%,极限可提升到30%-40%。高流量业务一般代表着公司核心业务,一方面为了稳定性的考虑,整体水位不能控制的过低。另一方面,为了应对一些突增流量,要预留一定buffer。低负载业务一般碎片化比较严重,而这些服务比较长尾,进而拉低了整体负载。
时间不均
互联网业务普通有明显的波峰波谷,波峰和波谷的实际资源使用量至少有一个数量级差距,且真正的最高峰只有不到一个小时。企业不得不为这一个小时的用量而付出一天的成本。空间不均衡
一方面是在线集群波谷空闲了大量计算资源,另一方面是大数据离线计算需要大量计算资源。从整个公司视角来看,资源使用极不均衡。资源性能有待提升
英特尔、英伟达每年都会有更强性能、更好性价比的硬件推出,云厂商也会有对应产品的发布。但是企业中业务线众多,一个个去适配、验证新机型,导致更换的周期往往要1-2年起。无法充分享受硬件带来的成本优化红利。
解决方案
云原生给企业带来一次技术重塑的机会。容器技术实现了资源和应用的解耦。业务研发和 SRE 关注 Pod 即可。底层计算资源由系统运维统一管理,对上层透明。Kubernetes 研发优化应用调度策略,实现计算利用率的最大化。大幅提升应用性能
对公司主流的技术栈,深度优化所对应的框架。通过使用更高内核的运行态、使用 Kubernetes 原生的注册发现机制、保持各类网络连接等等,实现 PHP 应用43%的性能提升。通过使用 fluid,完成检索服务计算和存储的分离,极大提升了运维效率。过程中对内存基带的使用进行了优化,带来30%性能提升,节省万核级别计算资源。调度优化,整体提升计算利用率
容器服务使用统一的集群,常态在40%左右,在保障业务稳定的情况下极限可达60%。机器利用率大幅度提升。碎片化问题也得到彻底解决。但中间过程是曲折的,和腾讯云一起攻克了一系列业界难题。在2020年上半年我们完成了一块核心业务的容器化之后,突然发现我们的运维成本居然增加了。原来在虚机模式下,运维在晚高峰的时候,只需要去做一些稳定性的巡检,其实并不需要有过多的一些运维动作。但容器化后,我们在晚高峰下需要不断地对一些资源负载比较高的的去进行封锁,然后把上面的一些比较重的 Pod 进行驱逐,为什么会这样呢?就是我们分析了一下 Kubernetes 的原生调度器,还是以 request 进行调度。互联网业务都会一个明显的波峰波谷,在线教育的波峰波谷会更加剧烈,波峰波谷可能会有两个数量级的一个差异。当研发在波谷的时候进行一次发布,这时候就会触发容器的一次重新调度,比如像我这个服务有几十个 Pod 的,可能会有十多个 pod 调度到一台机器,因为这时候的机器的使用率很低,就是服务怎么调度其实都可以,但是到了晚高峰的时候,我的每一个 pod 资源的使用率就上来的,CPU 使用高了,它的吞吐也高了,然后我这十个都在同一个机器上,我这台机器就会出现一些资源的瓶颈。可以看出原生的调度器只考虑了一些简单的指标,同时也没有考虑未来的一个变化。所以我们做了一个定义的调度器,将就是晚高峰的一些提前的情况进行了一些预测,以及融合了 CPU 、内存、各种 io 的这些复杂指标都考虑进来做因子,同时就是我们也会定期的把历史的数据进行大数据回归更新策略。GPU 这块它是一个比较相对贵的资源,我们调研了一些方案,主要推荐的方案是 GPU 虚拟化,但至少带来15%的性能损耗,这个是我们没法接受的。我们大多数的 GPU 服务是使用的各种资源是相对比较固定,所以我们基于算力和显存去进行了一些策略的调度,其实也就是比较经典的背包问题,同时夜间的话我们也会进行一下预测再重新调度,如果中间出现一些卡的一些故障,我们也会执行转移相关的策略。当 web 业务的完成容器化改造之后,我们也把一些定时任务迁移到容器的平台。这时候新的问题又来了,很多任务会涉及到密集的计算,容器本身其实并不是一个隔离的机制,还是在做 CPU 时间片的一个分配。这些计算密集的任务多多少少还是会对 web 的任务造成一定的影响。同时它也会占用主机的 IP 资源,node 上的 IP 资源是有限的,定时任务调度上来之后就会分配 IP,任务销毁时 IP 资源也不会立刻销毁,如果频繁的把定时任务的 pod 的调度到主机群的节点上,就会导致主机群的 web 服务没有足够的 IP 资源。同时大规模的创建跟回收定时任务,也会触发一些内核的问题,就比如有些定时任务的内存使用比较大,大规模回收会导致陷入内核态,hang 住的时间比较长。这块我们做的一些改造是这样的,我们建立了三个池子,serverless、任务集群、主机群,我们优先会把定时任务去调度到 serverless 上,如果调入失败的话,再依次到任务集群、主集群,serverless 并不是一种完全可靠的计算模式,对于他的使用我们这里引入了一种资源预占的方式,比较类似于金融领域为保证事务的两阶段提交,我们预先去申请相关的资源,当完成预占之后,我们再把真正的把任务调度过去。在离线混部是工程界的就是一个比较经典的课题。在线资源是有明显的波峰波谷,波谷有大量的剩余计算资源。大数据离线使用了大量的一些资源,但多数的任务对计算的实时性并没有那么强的要求,说必须在几分钟内得到结果,几个小时跑出来也可以。如果我在在线集群波谷时来跑大数据离线计算,大数据离线的资源就可以节省出来,这样就可以达到一个双赢的效果。但是它会面临很多挑战,就是其实很难做到资源的完整隔离,在线资源的稳定性、延时都会受到影响。负责在线业务的同学也会有顾虑,就是我没有得到很大的一个收益,然后还影响了我的业务。在内核增加了新的一个调度器,在 cfs 和 idle 之间,把大数据的任务放到这种放到这类调度器上,然后就实现了 CPU 的避让。在放量的过程中,我们也整体控制节奏,我们先在夜间在线服务没什么量的时候来跑离线计算,然后跑相对比较稳定之后,我们再在白天的波谷时间来跑大数据离线。又经过一段时间稳定之后,我们现在其实在晚高峰的时候,也在跑离线任务,只不过是控制在10%的 CPU 使用以内。使用新硬件,大幅提升单位计算的性价比
容器环境下集群底层计算资源使用有限数量的机型,做一些机型更换时减少了业务研发适配的成本,更换效率大幅度提升。实践价值
在多重举措的合力推动下,作业帮容器化的收益显著,同样业务迁移前后,使用了 HPA 和在离线混合部署后,成本下降43%,稳定性提升到99.995%,接口响应提升10%。由此,有效支持了作业帮业务的快速迭代,秒级急速扩缩容,服务运行态规范落地和统一的运维环境,多云的环境统一,提升服务可用性。这也便于云间相互自由迁徙,实现单云故障的应急预案,通过优化资源碎片,在离线混合部署,自动扩缩容,整体成本进一步下降。