24

微店算法平台在kubernetes上的实践探索

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzIzMDEyNzM4NQ%3D%3D&%3Bmid=2650956581&%3Bidx=1&%3Bsn=426e2707ec9289354174ae6d7c2efd0c
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、前言

目前在微店,搜索、推荐、广告、增长业务越来越多的开始使用机器学习和深度学习算法,而推进微店的算法工程师从传统统计方法过渡到机器学习、深度学习方法,需要建设机器学习、深度学习领域相关的基础设施。

如何支撑算法实现流程,提高算法工作效率,将算法转化成服务,成为我们在推荐广告业务支撑过程中遇到的一个挑战,下面对微店的算法平台遇到的问题和解决思路进行总结。

二、背景

MvQN7v3.png!mobile

算法平台主要以算法为中心,提供在线和离线的系统支撑,帮助算法开展工作,提高工作效率,最终对业务结果起到促进的作用。通过上面图来了解所有系统的关系,以及这些系统如何帮助算法去支持业务。

算法的开发工作可以分为实时流程、离线流程、在线流程三种模式。

  • 先看离线流程,从左往右算法同学先通过在线算法IDE完成代码的开发调试,当代码开发成熟以后,通过容器调度平台完成数据的周期更新;产出的特征数据通过回流导入到高性能的KV存储里,产出的模型数据通过容器调度回流到在线服务里。

  • 再看实时流程,算法同学通过实时计算平台计算实时特征和实时效果,将这些实时结果同步到在线KV存储。

  • 最后,算法同学在推荐容器来调用特征服务和预测服务,影响推荐结果的召回和排序,达到优化CTR和提高广告收入的目标。

从2019年开始逐渐引入新技术新系统,带来了基础设施的全面升级,这些新研发的核心系统主要包含:

  • 模型服务化框架:提供高性能的TensorFlow模型预测在线服务能力。

  • 算法在线IDE工具:提供开箱即用、用户隔离的开发环境,流畅一致的交互式体验。

  • 算法容器调度平台:提供可靠易用的任务调度机制,弹性的资源分配机制。

三、在线服务系统

这里的模型主要是TensorFlow模型,也有少量的xgboost模型。我们预判tf的技术可以覆盖95%的算法场景,并且支撑未来两到三年的发展。

所以我们把重心放在TensorFlow模型服务化项目。我们的目标是从开发到生产,简单快速部署一套高性能在线预测服务框架,横向扩展提高服务的吞吐量,纵向扩展支持更多的tensorflow模型。

模型服务化框架在k8s上的实践

我们调研了TensorFlow官网和业界经验,决定采用tf serving on docker by k8s的方案。

  1. tf serving是google开源的服务系统,适用于部署tf模型,具有延迟低、性能高、无状态支持横向扩展。

  2. docker是一种非常好的技术,可以让开发者打包他们的应用以及依赖到一个轻量级可移植的容器中,tf官网也推荐采用docker方案。

  3. 在生产环境中,我们希望能够随着应用程序负载的增加而扩展,在不停机的情况下实现扩容和升级,k8s刚好是这样一个容器集群管理系统,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。

quAJzqn.png!mobile

我们遇到的第一个挑战是API网关,我们需要为集群外部的流量访问提供了统一的入口。

为了快速上线,我们的架构从配置中心+LVS开始,转向更加优雅的LVS+ambassador,最后为了保证稳定而选择dubbo+zk。

  • 第一种模式,配置中心建立模型service和VIP映射;手动配置VIP规则,建立VIP和模型service关系,尤其是LVS的维护需要运维参与,不利于规模扩大。

  • 第二种模式,ambassador是一个k8s原生的开源微服务网关,它的控制平面负责监听k8中的service资源的变化,并将配置下发到网络代理来完成实际的流量转发。这个版本上线以后,发现service经常流量不均衡,路由信息经常不更新问题,从client到pod整个链路过长,导致RT不稳定,偶尔还需要重启。

  • 第三种模式,在我们继续调研业界的解决方案时,运维同学也抛出了一种新的网路模式,采用macvlan能够给POD分配了和宿主机相通的网段。基于这个前提,我们抛弃了service模型,pod的服务直接通过dubbo和zk来做服务注册和发现,通过zk和k8s探针保证健康检查,实现流量的负载均衡。

通过这个项目,我们搭建和线上实践了微店首个k8s生产集群,将来会有更多的轻量级应用跑在k8s集群。有了系统支撑,算法开始大规模地拥抱和使用深度学习模型优化业务效果,上线后新的模型预测服务给推荐广告业务直接带来GMV的提升。

四、离线调度系统

上面提到的模型是一般都是算法通过Python训练任务跑出来的,但是我们缺少一个操作平台可以开发调试python代码,也没有一个调度平台可以支持python任务执行。

原有的方式是给所有算法分配物理机权限,只能通过公用账号登陆机器开发调试代码,通过配置crontab来保证定时任务的数据产出。这种方式的弊端是:

  • 机器报警的时候,进程、任务、代码都找不到人,大量过期的文件没有人敢动;

  • 有人修改软件污染环境,直接影响到生产任务执行,生产任务失败也没有监控报警;

  • GPU机器交给人来维护,没有调度机制算法任务经常因为资源冲突导致失败;

可视化建模实践

在这个背景下,我们萌生了提供一个能够触发算法任务执行的调度平台的想法。 分析了当时比较流行的算法平台,做了2点行业预判:

  • 可视化建模可以降低用户开发的门槛

  • 算法包装成组件可以提高开发效率

eaiQrmy.png!mobile

基于这些我们设计的算法调度平台架构图是这样的,这个系统主要划分为

  • 视图层:提供拖拽组件的交互方式,快速生成一个任务执行的拓扑图。

  • 任务生成层:将前端不同的组件生成不同的任务,交给任务提交层去执行。

  • 任务提交层:将任务交给执行引擎执行,并接收反馈结果。

  • 管理中心:存储任务的属性、代码、状态、日志,提供定时调度和监控报警。

这个系统的后期遇到很多困境,我们开始质疑可视化可能是个伪需求,至少现阶段不适合业务的发展,可视化画布开发过于复杂,严重影响前端迭代的效率;可视化组件既依赖算法实现,又束缚了算法的使用场景;

第二个困境来自资源调度层面,资源分配没有实现自动化,效率低;资源分配没有做到环境隔离,风险高;无法管控存储的申请和释放,浪费严重;

第三个困境主要是来自用户层面,任务的运行环境高度定制化无法统一;任务的开发调试和生产调度对系统要求完全不一样;算法工程师的水平风格因人而异,形成用户习惯是一个长期的过程。

这些困境催促我们做了一些断臂求生的想法:

  • 放弃复杂的画布控件,摆脱前端资源困境;

  • 交互方式从组件回到编辑器,算法专注业务实现;

  • 把docker+k8s技术沿用起来,彻底解决租户环境隔离;

  • 提供基础镜像,多样化的需求交给用户自己定制镜像;

  • 寻找合适的存储插件,用多少占多少,用完即清;

  • 考虑未来的发展,最好能支持腾讯云GPU机器能够灵活的插拔。

我们沿用k8s做资源调度,思路越走越宽:

  • 算法的生产任务,代码稳定,需要准确的调度保证;

  • 算法的代码开发,频繁修改代码,及时查看结果;

  • 既然不能统一,我们就拆开,既保证可靠性,又要有灵活性;

  • 开发用jupyter生态,交互式调试,所见即所得;

  • 生产调度对接调度平台,触发更准确,监控更稳定;

  • 把单机训练支持的更好,任务增长快速形成规模。

算法在线IDE在k8s上的实践

通过前面的反思衍生的第一个项目算法在线IDE,算法在线IDE主要是从算法同学常用的notebook出发,旨在解决算法在代码开发和调试阶段的问题和需求,提供弹性有限的gpu/cpu资源调度,提供多种环境镜像能力,支持用户自定义环境能力,提供统一的终端管理平台。

E7Vv6bQ.png!mobile

我们调研了notebook的周边生态,基于jupyter notebook原有组件做了扩展和升级,引入k8s资源调度,代替单机的notebook。

  • 首先我们集成了jupyterhub,支持多用户的登陆和认证,角色管理。

  • 其次我们升级了jupyterlab,支持多窗口,可以调用控制台,支持多种编程语言,拥有很多插件。 我们保留了notebook所有功能,你可以编写代码、运行代码、查看输出、可视化数据并查看结果。

  • 最后我们把这些控制实例和用户实例都部署在docker上,通过k8s管理,避免单点和机器异常导致的不可用。

我们重点扩展以下几个能力:

1. 为了适配tf、cuda、Cudnn版本兼容,我们扩展了默认镜像,提供多种镜像能力

6VbYbae.png!mobile

2. 通过k8s的动态存储自动为多个用户创建独立的代码数据空间

bmA3E3u.png!mobile

3. 通过容器内的conda工具解决小众软件版本的多样性需求

eY3ae2b.png!mobile

机器学习平台在k8s上的实践

接着衍生的第二个项目算法调度平台,有了算法IDE的成功经验,把调度平台做成容器分配,任务执行,监控任务状态就水到渠成了。

  • 通过docker和镜像技术,定制用户代码的依赖软件,隔离用户任务的执行环境。

  • 依赖调度的消息触发,包含了定时调度还是依赖调度,我们没有重复造轮子,而是主动选择和mars(传统离线调度平台)团队合作。

  • 为了减少对mars侵入性,我们自己做了任务状态的维护,代码持续集成,监控报警等。

qimIzu6.png!mobile

图灵系统上线一个月,算法任务规模增长非常快,弥补了传统离线任务调度平台在机器学习领域的空白。 未来还有很多事情需要完成,我们计划提供一个支持自动化镜像打包平台,在任务管理上对输入输出做资源细粒度的管控,代码和参数分离方便用户做效果的调优,算法规模膨胀之前更好地支持分布式。

五、踩坑

在开发过程中几乎是摸着石头过河,踩了很多坑,这里挑两个和大家分享以供参考。

1、page allocation failure

容器创建一直卡在containerCreating,查看宿主机/var/log/messages

amaq6nU.png!mobile

大量低阶内存,说明内存碎片很严重

INBfAzI.png!mobile

释放缓存

eMzMjaM.png!mobile

内存压缩

RbaIjyi.png!mobile

优化后,系统高阶内存页变多了。

2、 limit导致 Kernel panic

通过k8s跑任务时服务器会时不时挂掉,重启后日志里面没有任何可疑信息。开启kdump服务再跑任务重启后在/var/crash下发现有crash日志。查看vmcore-dmesg.txt日志发现有hard lockup报错,hard lockup是指cpu无法执行进程也无法响应中断,在配置内核参数/proc/sys/kernel/nmi_watchdog为1的时候当内核检测到cpu发生了hard lockup会panic。

u26ZRrM.png!mobile

确定了内核panic,但是无法判断是什么原因导致的,开发反馈在跑任务时加上cpu限制就会出问题。通过google查看有一个相似的案例,尝试升级内核看是否能解决,将内核升级到4.9.4-1.el7.elrepo.x86_64,再跑任务未发生宕机。

结语

在此非常感谢微店运维团队的技术支持,围绕算法支撑的工具平台建设是一个长期的过程,有时候短期很难看到一个确定的未来。在这个过程中,我们需要渐渐消除算法和工程的技术隔阂,我们需要推动算法能力在更多业务领域的落地发力。在过去的十年,数据已经成为生产力,互联网的很多从业人员已经掌握这门技术;未来的十年,把AI转换成生产力,需要通过工具来降低门槛,也需要更多的工程师提高算法知识。

IBj6beM.jpg!mobile

I n


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK