黄文才:云智天枢AI中台架构及AI在K8S中的实践

2019年9月7日,腾讯云开发者社区(腾讯云官方开发者社区)主办的技术沙龙——AI技术原理与实践,在上海成功举行。现场的5位腾讯云技术专家,在现场与开发者们面对面交流,并深度讲解了腾讯云云智天枢人工智能服务平台、OCR、NLP、机器学习、智能对话平台等多个技术领域背后架构设计理念与实践方法。

以下内容整理自腾讯云资深技术专家黄文才,从云智天枢平台的整体架构出发,揭秘AI在K8S中的实践经验,为大家带来“云智天枢AI中台架构及AI在K8S中的实践”。

黄文才:大家下午好!

很荣幸能够来到现场,今天我的分享主题是云智天枢中台架构及AI在K8S里的实践经验。首先自我介绍,我叫黄文才, 2010年加入腾讯,先后参与了QQ群、群空间、webQQ、Q+、腾讯游戏、QQ全民闯关等项目的架构设计与开发,在海量服务、分布式系统方面有一定的经验,目前担任云智天枢平台的技术架构师,负责平台架构设计。

今天主要分三大块来讲:

第一,云智天枢平台架构。

第二,各核心窗口的架构设计。

第三,AI在K8S中的实践经验。

云智天枢平台是支持快速接入各种算法、数据和智能设备,并提供可视化的编排工具进行服务和资源的管理和调度。进一步通过AI服务组件持续集成和标准化接口开放,帮助开发者快速构建AI应用。

总的来说,平台的定位是全栈式人工智能服务平台,实现与应用、算法、设备等合作伙伴共赢,合作伙伴只需要实现应用层逻辑。

以人脸结构化场景的例子,讲述一下云智天枢平台的大概功能。应用会通过API网关调用任务管理,任务管理服务创建和启动任务。任务管理器根据负载均衡等策略,根据人脸结构化引擎,去实例化一个人脸结构化任务。人脸结构化任务首先会通过设备中心的人脸抓拍机服务获取图片,然后调用人脸属性服务提属性,同时会把结构化数据通过数据中心落地,并把结构化数据推送到消息组件。应用可以通过消息网关去订阅这些任务跑起来后源源不断的结构化数据。

我们平台其实是典型的三层架构。

从下往上看,基础设施是基于docker、 k8s、 蓝盾CICD。

最下层是存储层,用到了一些组件mysql、kafka、influxdb、cos/ceph、es等。因为目前主要是做私有化,公司组件或者云上组件都没法用,所以会用开源的组件搭建起来。

中间层是微服务,分为6大块:

(1)算法仓库:主要提供自助接入、自助打镜像的能力,可快速把可执行程序的安装包、模型文件等容器化为算法服务。目前接入算法种类50+,涵盖人脸,车辆,语音,文字,语义等。

(2)设备中心:做了设备自助接入平台,主要对接各个厂商的各个型号的设备,比如普通摄像机、抓拍机、AI相机等等。设备是平台比较重要的数据来源。

(3)数据中心:主要负责平台数据接入、推送、转换、存储等,同时负责屏蔽私有化项目的结构化与非结构化数据存储介质的差异。

(4)AI工作室:主要实现了任务调度,流程与服务的编排能力。已经沉淀行业应用12+,通用组件30+;

(5)应用中心:主要是创建应用、密钥、订阅管理,视图库等能力;

(6)管理中心:主要是账号系统、角色权限、镜像仓库、操作日志等能力。各个窗口之间是有联动的,通过消息队列kafka来解耦。

最上层是网关,网关分两块:

(1)API网关,采用的是腾讯云API3.0的标准。网关主要做鉴权、限频、转发等功能。

(2)消息网关,支持GRPC和http推送能力。监控系统用了Telegraf、influxdb和grafana,日记系统用了ELK。

AI工作室主要由三大块组成:1.平台对接系统;2.流程引擎系统;3.函数服务系统。

这里实现了流程与服务的编排能力。平台系统主要是打通和平台的各个窗口能力,比如说数据中心、设备中心等窗口的联动。函数服务用python写了函数服务,负责执行python代码段。 因为流程服务编排的过程中A服务的输出不一定满足下一个节点B服务的输入,所以要做数据转换,这一块儿交给了函数服务来做。

平常我们在开发业务功能过程中会经常写一些相似的代码逻辑,比如调用A服务,A服务回来之后会做数据处理,处理完以后会并发掉BC服务,之后等BC服务回包后再做数据处理,这一块儿有很多相似的业务逻辑,我们进行了抽象并实现了流程和服务的编排能力。

流程编排能力实现了并发分支、条件分支、合并分支等功能。服务编排方面支持直接调用服务,可以不用关心网络层的调用,只需要写A服务和B服务之间数据转换python几行代码转换就好。

函数服务是为了解决A服务的输出和下游B服务的输入不太满足,所以可能会做一些数据转换,也是抽象出来让用户合作伙伴可以写几行python代码,就可以把流程打通。函数也做了安全措施,比如说python的 sys、commands等package会不让用,我们可以静态动态扫描。

算法接入过程中通常会遇到一些问题,算法种类可能比较多,对接厂商比较多、协议比较多,对接成本高。制作镜像对于算法开发者来说会有一些门槛,比如说熟悉docker命令等,所以有比较高的接入成本,我们做了接入平台统一镜像接入,通过页面操作可以让不懂docker的人也能轻松地制作算法的微服务。

目前已经支持了安装包的方式、镜像仓库、镜像文件、模型文件的接入能力。右边有个模型镜像,会把基础镜像里安装的常用组件打出来成立成模型镜像,这样以后安装类似组件场景的话可以快速复用,缩短制作镜像的时间。

镜像仓库有两个难点:缩小镜像制作过程中的耗时,比如说gcc编译或者Cuda以及Boost库编译都比较耗时。其次是镜像大,怎么降低镜像大小?

会把常用的gcc版本、Cuda与操作系统版本做成基础镜像直接提供用。常用的组件会预先编译好做成模板镜像。会动态分析镜像制作任务,把组件使用的频率、耗时大的通过空间换时间的思想提前沉淀下来。优化镜像大小用了Alpine操作系统,这样只有几兆。通过一般的操作系统镜像会很大,可能会有1到2G。dockerfile里把RUN命令写成一行,会减少镜像的层数,也分离了构建镜像和运行镜像。

设备中心的功能主要是设备自助接入能力,各个厂商以及厂商里各个型号的协议都会有差异,很难统一。比如业界有ONVIF、ISAPI、GB28181、私有化SDK等,没有统一,其实私有化SDK基本上每个厂商都有自己的一套。

对于私有化SDK,我们会分成三层微服务:(1)上层服务逻辑(做成基础镜像);(2)适配逻辑SDK(so插件);(3)私有化SDK(so插件)。各个类型设备会通过设备层适配层so插件把私有化协议转化成内部统一协议。我们会把上层做成基础镜像,设备厂商自主接入的时候只要实现适配插件,就能快速把设备接入进来。

对于http接口,可能每一个厂商的地址不太一样,还有一种是接口能力也不一样,输出输入也不一样,这里复用了在AI工作室里沉淀的函数服务能力,来支持动态指定http接口名和输入输出参数的转换。

也实现了云边端混合部署的能力,主要解决边端的算力不足、带宽、延时等问题。如把算法解码或者优选算法服务部署在边端进行处理,处理之后会把图片、结构化数据通过加密数据通道到云端做后续处理。同时也实现了从云端的K8S延伸到边端的部署更新微服务的能力。

数据中心窗口,负责实现平台数据的接入、外部推送、转换、存储、屏蔽读写存储介质等能力。包括本地的上传、分片断点续传等能力。通过消息队列kafka来解耦窗口间的耦合,比如要给AI工作室任务的话,会把元数据写到消息队列里,任务调度器会消费元数据通道,调度拉起任务,执行编排好的流程引擎来做对应任务。

数据中心会拉取一些文件,通过把地址写到数据通道里,任务执行器会不断地从数据通道里消费数据做逻辑。我们在部署过程中也会遇到比较大的挑战,比如私有化落地时存储介质不一样,有些用ceph,cos、NAS等,我们把数据中心抽象了FileAgent容器提供给每个窗口用,屏蔽所有底层的存储介质,部署的时候以sidecar模式跟业务容器同时部署在一起pod上跑。

监控系统通过开源组件:telegraf + influxdb + grafana 搭建起来的。每个node节点会部署一个daemonset的容器monitor_agent。业务容器通过unix socket与monitor_agent通讯。monitor_agent每分钟汇总上报数据到influxdb存储,grafana通过读取influxdb进行视图展示和告警设置等。

当然业界也有其他的解决方案,比如说Prometheus(普罗米修斯),我们做了选型的对比:

1. 它的采集器是以exporter的方式去运行的,每一个要监控的组件都有要装一个exporter,promethus再从多个exporter里面拉数据。

2.promethus自带的展示界面比较挫,即使采用promethus,也要配合grafana才能用

3.promethus是拉模式来搜集数据的,业务要上报数据的话要安装它的一个代理pushgateway,数据先push到代理,然后再等promethus去拉,实时性和性能都比推模式略差一点

我们采用的类似侵入式的方式,更适合我们这个平台。另外telegraf有很多扩展插件,用起来会很方便。

传统上,GPU只负责图形渲染,而大部分的处理都交给了CPU。自二十世纪九十年代开始,GPU的发展迅速。由于GPU具有强大的并行计算能力,加之其可编程能力的不断提高,GPU也用于通用计算,为科学计算的应用提供了新的选择。

2007年6月,NVIDIA公司推出了CUDA (Compute Unified Device Architecture),CUDA 不需要借助图形学API,而是采用了类C语言进行开发。

从左边图来看,CUDA软件体系分为三层:(1)CUDA函数库;(2)CUDA 运行时API;(3)CUDA驱动API。

所以应用程序和CUDA Libraries以及CUDA Runtime间不会有什么问题?

主要问题在CUDA Runtime和CUDA Driver之间。CUDA Driver库是在创建容器时从宿主机挂载到容器中,很容易出现版本问题,需要保证CUDA Driver的版本不低于CUDA Runtime版本。

容器内使用GPU:

1、GPU设备挂载到容器里

--device挂载设备到容器

特权模式privileged

2、CUDA Driver API挂载到容器

3、CUDA Runtime API和CUDA Libraries

通常跟应用程序一起打包到镜像里

4、K8S通过nvidia-container-runtime实现挂载gpu设备和cuda驱动进容器

5、K8S通过nvidia-device-plugin实现分卡。扩展资源 ,使gpu能像cpu那样分配。

GPU虚拟化是为了解决GPU资源合理分配问题,业界提出GPU虚拟化技术 。

nvidia有两种GPU虚拟化的解决方案:(1)GRID;(2)MPS。第一种模式更多用于虚拟机场景,基于驱动,隔离型会做的比较强,但不开源,性能比较好。MPS是应用到容器场景的,基于软件的方式,隔离性比较弱,但也不开源。

MPS服务时间分片没有权重,所以分卡能力做不到0.1卡或者0.01卡的粒度,只能做到二分之一、四分之一,八分之一等。

gpu的调度是时间分片的,gpu的利用率是按照sm(Streaming Multiprocessors)的占用率来展示的。

我们公司有另外一个团队实现了GPU半虚拟化的能力,基于驱动函数实现,也是改变了函数显存申请、释放和线程的发起函数。

从左边下图来看分为0.3和0.7,从执行时间来看缩短很多,比如说0.7GPU的话nvidia是87秒,用了GPU虚拟化方案66秒就把网络模型给训练好。目前来说能做到0.01的粒度,有100%的方式,更多是最小配到0.1的粒度,因为配到很小0.01的话, 这种对自身程序影响很大,经常容易被挂起空转。太小了用处不大,因为你显存本身不会占用1%这么小。

在K8S使用过程中组件像MySQL、kafka最近也在做容器化,之前没有做容器化。在物理机部署的时候会遇到问题,容器内访问非容器化部署的组件是怎么做的?

比如如果每个环境通过IP部署起来的话成本太高,加上MySQL集群发生主从切换引起ip变化,这里我们引入了consul的 dns能力,在容器里解析的时候会通过kube-dns发现是consul.service结尾域名,可以通过转发到consul dns解析。

调用链是基于Jaeger,Jaeger是基于Google的Dapper论文实现的,我们把traceid、spanid传递能力集成到框架里(python、go),包括grpc、http调用下层服务,使写业务逻辑的时候就不用关心这一块儿。

下一代调用链是基于istio OpenTracing标准业务无侵入。

在K8S里可能还会遇到些挑战,比如说弹性收缩: GGPU资源自动扩缩容、基于qps自动伸缩;

负载均衡:有状态路由,K8S DNS是用轮询的方式负载均衡,但在实践过程中可能会有场景,比如说用到一致性哈希的路由场景。

存储容器化:组件容器化(如mysql、es、kafka等)

容器安全因为没有像虚拟机一样隔开,是共享内核的,所以docker还是存在共享内核导致的安全,以及镜像安全和函数服务安全。

ok,今天的分享就到这里。谢谢大家!

本站文章资源均来源自网络,除非特别声明,否则均不代表站方观点,并仅供查阅,不作为任何参考依据!
如有侵权请及时跟我们联系,本站将及时删除!
如遇版权问题,请查看 本站版权声明
THE END
分享
二维码
海报
黄文才:云智天枢AI中台架构及AI在K8S中的实践
2019年9月7日,云+社区(腾讯云官方开发者社区)主办的技术沙龙——AI技术原理与实践,在上海成功举行。现场的5位腾讯云技术专家,在现场与开发者们面对面交流,...
<<上一篇
下一篇>>