写点什么

揭秘爱奇艺深度学习平台云原生迁移实践

  • 2020-10-09
  • 本文字数:4498 字

    阅读完需:约 15 分钟

揭秘爱奇艺深度学习平台云原生迁移实践

Jarvis 深度学习平台介绍

1 平台整体架构

平台支持 GPU 和 CPU 的训练/推理,支持 S3、HDFS 和 NFS 作为训练数据的存储、模型的存储。平台支持 Tensorflow、Pytorch、Caffe、Caffe2、MxNet,但主要以 Tensorflow 和 Pytorch 为主,支持 tensorflow 从 1.X 到 2.X 的各个版本。


支撑公司的广告、搜索、推荐、NLP 等业务。我们基于 mesos + marathon 作为我们的弹性容器平台。这是因为我们容器弹性平台起步比较早,当时 k8s 还不是很成熟。因此在很长一段时间内,我们的容器并不是运行在 K8s 平台上,这点需要大家注意。


2 一站式平台服务

这里主要是通过 4 个小平台实现的, 第一个是数据预处理平台 :通过数据预处理平台可以对训练数据进行可视化分析,帮助用户合理的调参,并及时发现异常数据。



第二个是编写训练代码平台: 用户可以通过 runonce 训练或者 notebook 训练,得到一个和训练环境相同的环境编写训练代码,并上传 gitlab。


第三个是执行训练任务平台: 用户通过 Jarvis 训练平台执行训练任务,然后训练任务将执行用户的训练代码,输出算法模型。


最后用户通过 Jarvis 推理平台 创建推理服务,并对外提供服务。

3 平台发展


我们是从推理平台入手,首先解决让用户训练好的模型能对外提供服务的能力,而后再逐步的将平台功能扩展到支持训练、开发及数据预处理,目前我们正处在将容器弹性平台从 mesos + marathon 迁移至 k8s + volcano 的过程中。

4 使用 Volcano 之前训练平台架构

如图所示为我们在使用 Volcano 之前的训练平台架构:



其运行的流程为


(1)用户编写训练代码并提交到公司内部 gitlab。


(2)用户通过 web 页面、命令行工具去创建训练任务。创建训练任务需要用户填写的信息有:


  • 所需的资源

  • 使用的镜像,每一个框架的每一个版本都通过一个镜像来支持,选择镜像就等于选择了算法框架

  • 我们可能会有多个集群,需要用户指定在哪个集群上运行任务

  • 需要 Gitlab project 的 url,这个 project 中包含了用户编写的训练代码


(3)Jarvis cli/web 将请求转化为 grpc 发送给 Jarvis core。


(4)Core 中将请求转换,调用 marathon api 创建容器。


(5)容器在对应的集群中启动,执行训练任务

5 训练平台迁移到 K8s 的挑战

主要有 3 个方面的挑战


  • 原生 Pod/Deployment/Job 无法满足分布式训练的要求

  • 无队列管理、配额管理。

  • 调度能力缺失、如 Gang Scheduling

6 引入 Volcano

实际上,Volcano 对于我们来说最重要的是这么几个概念,一个是 vcjob,可以简单的理解成 vcjob 是对 K8s job 的一种扩展,或者是对 pob 的一种封装。


第二个对于我们比较重要的是 Queue ,也就是队列,因为在 Queue 上可以分配一些配额,可以做一些配额的管理、队列的管理;


第三个对我们比较重要的是 podgroup,可以把它看成是 pod 的一个集合,因为有了 pod 集合这个概念,所以它才能做一些更高级的上层调度。



按照我的理解


  • Volcano 是 K8S 原生的 batch System,高度符合 AI 训练场景。

  • 不侵入 k8s 源码,符合 k8s 的开发规范。(简单来说,方便我们二次开发)

  • 项目加入 CNCF,成熟度高

Power of Volcano

Volcano 要如何解决迁移到 K8s 上遇到的问题

1 Gang Scheduling 的问题

Gang Scheduling :可以简单的理解为要么同时被调度,要么同时不被调度,这对于 AI 训练场景来说是非常重要的,因为我们的大部分的训练都是基于分布式训练,分布式训练的特点是一次启动的 pod 非常多,可能最多的话是有四五十个 pod, 如果一个任务下有个别的 pod 被调度,部分 pod 没有被调度,那显然这个任务是不能正常运行的,那这些运行起来的 pod 是没有任何意义的,会造成资源的浪费,同时可能会引发死锁的问题。



比如,我们整个资源池只有 4 张 GPU 卡,有训练任务 A 和 B,A 任务有 4 个 pod,每个 pod 需要一张卡;另外 B 任务也是同样的情况,当 A 和 B 同时被创建,如果没有 gang scheduling,A 可能拿到了 2 张卡,而 B 拿到了 2 张卡,那这个时候无论哪个任务都不能顺利完成,这个时候系统就产生死锁了,除非你增加资源,否则就一直保持死锁的状态。


如果有了 Gang scheduling , 就能避免上述问题。Volcano 通过 podgroup 这个 CRD,能够以 podgroup 为单位对 job 进行整体调度,实现 Gang scheduling 的功能。

2 分布式任务原生支持

我们以 Tensorflow 分布式训练为例,它主要有这几个角色,PS、master、worker。Parameter Server(PS)是用来存储参数的,master、worker 简单理解为进行计算梯度的,在每个迭代过程,master、worker 从 parameter sever 中获得参数,然后将计算的梯度更新给 parameter server,parameter server 聚合从 master、worker 传回的梯度,然后更新参数,并将新的参数广播给 master、worker。



当然我们在这里不是分析 Tensorflow 分布式训练的细节。我们只讨论它的一个网络结构。比如 master、worker 它要和这个 Parameter Server 去做通信,那么要做通信的话就存在一个问题,如果我去创建一个 pod,在创建的时候我可能并不知道这个 pod 的 IP 是什么,如果我在一个 Deployment 创建多个 pod, pod 之间也互相不知道对方的 IP 地址或域名是什么,我们需要通过其他的办法来做这样一件事情,对于我们来说相当的复杂。


这里的每一个角色都要互相知道对方的 IP 地址或者域名,最终要组成 TF_CONFIG 这样一个配置文件,这个配置文件里面其实写的很清楚,至少包括 master、worker、ps 的 IP 地址或者域名,这些都要写在这个配置文件里面,每一个节点都需要知道这个东西,除此之外还需要知道自己所担任的是什么角色,Index 是多少,对于 K8s 的话是很难实现的,但有了 Volcano 后就变得非常简单了。



Volcano 会帮你在一个 vcjob 下多个 pod 去注入一个文件夹(etc/volcano),这个文件夹下面就会有所有的 master、volcano、ps 的域名,都会填在这里面,这样的话每个 pod 都知道整体集群里都有哪些 peer ,非常方便去组成 TF_CONFIG 这个文件,只要组成了这个 TF_CONFIG 文件,我们就能进行 Tensorflow 分布式训练。


现在的话 Tensorflow 提供一些高层的 API,比如说 TF estimator ,这个 estimator 里代码的单机和分布式代码是一模一样的,只不过这个 TF_CONFIG 的配置是不一样的,所有说只要有那样一个格式的环境变量或者配置文件传进去的话,就可以做分布式训练,对于我们平台方来说,帮助用户构建 TF_CONFIG,用户拿来直接运行就可以了。Volcano 通过注入文件,可以方便构建 TF_CONFIG,以支持 TF 分布式训练。

3 Horovod/mpi

Volcano 支持 Horovod 训练,Horovod 训练其实和 Tensorflow 分布式训练有点类似,因为大家都是分布式训练,区别是更新参数的方式不一样,大家可以注意一下 Horovod 训练简单来说它更新参数是环形的更新方式。



但这个并不重要,因为对我们平台侧的话,我们主要想要做的事情是我们要构建好基础环境,让上层应用来使用,这种 Horovod 网络架构,它对于我们基础环境有什么要求呢?


它的要求很简单,它除了要保证每一个节点都要知道对方的域名和之前的需求是一模一样的之外,它还额外的 ssh 互信,因为它经过 22 端口做 ssh 登录,去做一些工作,所有在这里面需要做好互性,互性的工作如果让我们来做,就很麻烦,我们要想一堆办法来做这个事情,Volcano 可以通过设置 ssh plugin 自动完成容器里的互性,就可以达到 Horovod 对于训练任务的网络要求。

4 配额系统、排队系统

Volcano 其实是通过 Queue 这么一个 CRD 来支持的,在图中这个是表示资源池里的一个资源,我们假设有两个 Queue,一个是 Queue1,一个是 Queue2,一个的配额有 20 个 GPU,一个有 10 个 GPU,当 Queue 已经使用的资源不太多时,新任务来了之后是可以被调度的,但是如果 Queue2 已经被使用了非常多,就已经使用完了,下面的新任务来了之后那就不可以被调度,只能继续排队,你 podgroup 的状态就处于 pending 的状态,就一直处于排队中。



Volcano 通过 Queue 支持排队及配额系统,正好与平台中的 team 对应,因为我们的结构也是一个组有一个独立的配额,这个配额与配额之间是相互独立的,你只能用这么多,使用量超过配额后,任务就将排队,当然排队的任务支持优先级策略,高优先级的任务将在有资源后首先被执行,正好和我们系统的设计是一致的,所以就非常的好对接。

5 与 volcano 集成

新增了 volcano_plugin,其封装了 vcjob、queue、podgroup 的 restful api,将 grpc 请求的内容转成 k8s api 规范的 yaml 配置,并调用 k8s api 创建容器。



Jarvis Core 根据传入的集群信息,决定使用哪个 backend。

实际使用中遇到问题

1 问题一

现象: 当升级 volcano 版本的时候,直接修改https://github.com/volcano_x0002_sh/volcano/blob/master/installer/volcano-development.yaml 中的 image,然后执行 kubectl apply -f <yaml file>,会导致已经存在的 queue/vcjob 等全部消失。


原因: yaml 中的 volcano-admission-init 会重复执行,导致 volcano 整体被 reset 现象


解决办法: 升级的时候想清楚升级对应的组件就可以了


2 问题二

现象: 通过 list_and_watch 监控 vcjob 状态变化的程序进行遇到 watch 连接无故断开的问题,即如果没有新的 events 产生,大约 80~90s 就会断开一次,每次时间还不固定,但是同样的代码 watch pod 就没有问题。


原因


通过阅读 k8s 源码,K8s 对于 CRD 资源,默认的 http timeout 的时间是 time.Duration(float64(minRequestTimeout) * (rand.Float64() + 1.0)),其 minRequestTimeout 为 1 分钟,因此会出现上述的问题。可以通过客户端指定 timeoutSecond 来避免该问题。


3 问题三

现象: Jarvis 训练平台中容器入口地址是一个 bash 脚本,在 k8s 下运行时,会出现 stop 命令下发后,等约 30s 才退出。


原因


bash 不会把 signal 传递给子进程中。当 graceful stop timeout 到了之后,守护进程发现容器还没有退出,会再发 SIGKILL,此时会将 bash 脚本杀掉,容器退出,但是容器中的其他进程将无法主动完成清理工作。


解决方案


使用 dumb-init,比如入口脚本:


#!/usr/bin/dumb-init /bin/bash


my-web-server & # launch a process in the background


my-other-server # launch another process in the foreground

4 对 Volcano 的修改

  • SVC plugin 支持传入参数,参数为 nodeport 的端口号,当创建 vcjob 并传入 SVC 参数时,将创建对应的 nodeport,这是因为我们的 tensorboard 及其他服务需要让外部访问。

  • ssh plugin 的名字超过 63 字节则会创建失败,我们自己修复了这个 bug。

  • Queue 的 capability 存在 bug,用户可以突破 capability 来使用资源,目前官方已经修复了这个问题。https://github.com/volcano-sh/volcano/issues/921

  • 给 vcjob annotation 后,某个 pod 失败时,无法触发删除 vcjob,https://github.com/volcano_x0002_sh/volcano/issues/805

总结

(1)Volcano 弥补了 kubernetes 深度学习场景下的基本能力的缺失


  • gang scheduler

  • 队列管理


(2)Volcano 代码遵循 kubernetes 的标准,采用非侵入式方案


  • 减少开发者的开发对接成本

  • 便于二次开发


(3) 基于 Volcano 的 Jarvis 训练平台目前已经上线并运行良好


作者介绍


本文转载自微信号容器魔方(ID:K8S-Huawei)。


原文链接


揭秘爱奇艺深度学习平台云原生迁移实践


2020-10-09 14:001887

评论

发布
暂无评论
发现更多内容

【CVPR2024】面向StableDiffusion的编辑算法FreePromptEditing,提升图像编辑效果

阿里云大数据AI技术

人工智能 深度学习 算法 CVPR 图像编辑

Navicat for PostgreSQL mac(PostgreSQL 数据库开发工具)v17.0.9版

Mac相关知识分享

Mac软件 数据库开发工具 软件下载

FxFactory 8 Pro for Mac(视觉特效处理包) v8.0.16版

Mac相关知识分享

Mac软件 fcpx插件 视觉特效插件

最高25k $MPC 资助,Partisia Blockchain 推出全新开发者计划

BlockChain先知

FinalReference 如何使 GC 过程变得拖拖拉拉

bin的技术小屋

JVM java

K歌技术大揭秘:从“清唱找调”到“智能修音”,如何让歌声自然飞扬、声动四方?

快手技术

回森 业务创新 智能修音

CompletableFuture 使用指南

FunTester

Partisia Blockchain 推出全新开发者计划,最高获 25k $MPC 资助

股市老人

2024年移动端技术探索

轻口味

android 移动端

攀登不止,华为数据库论文入选SIGMOD 2024,技术创新再谱新篇

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号2024年6月PK榜

生态共赢|心大陆携手搜狐视频,构建心理健康视听守护者!

心大陆多智能体

人工智能 AI 多模态 心理健康 数字心理

蓝易云 - springboot配置静态资源访问

百度搜索:蓝易云

CSS JavaScript Linux Spring Boot 云服务器

AI日报|英伟达Nemotron-4 340B模型助力各行业数据生成,扣子发起匿名AI模型擂台赛!

可信AI进展

#人工智能

中标新领域!亚信科技+用友网络,将助力广西某市城投集团玩转“人事”

亚信AntDB数据库

AntDB 用友 亚信科技 企业号 6 月 PK 榜

快手自研视频生成大模型「可灵」来啦!

快手技术

大模型 文生视频 可灵

最高25k $MPC 资助,Partisia Blockchain 推出全新开发者计划

股市老人

深度解析:基于Pixi渲染引擎打造沉浸式「滑雪竞技」小游戏!

快手技术

前端 H5 快手 pixi 渲染

Java 学习

玄兴梦影

学习 java

蓝易云 - centos服务器a.sh内如何 在指令中自动加入当前时间?

百度搜索:蓝易云

centos 服务器 云服务器 服务器租用 高防服务器

数据库管理和开发:Navicat 17 for MongoDB mac 激活版

你的猪会飞吗

Mac软件推荐 mac破解软件下载

在 Go 中如何让结构体不可比较?

江湖十年

Go golang golang 面试 编程技巧

金融机构如何打击帮信罪和掩饰罪?

芯盾时代

风险管理 反欺诈 账户安全 金融风控

OpenTiny CCF开源创新大赛赛事指南来啦,助力你赢取10W赛事奖金

OpenTiny社区

Vue 前端 低代码 组件库 OpenTiny

Vector | Graph:蚂蚁首个开源Graph RAG框架设计解读

TuGraphAnalytics

知识图谱 tugraph rag DB-GPT OpenSPG

Partisia Blockchain 推出全新开发者计划,最高获得 25k $MPC 资助

石头财经

蓝易云 - Nginx查找耗时的接口

百度搜索:蓝易云

nginx 云计算 运维 服务器 云服务器

揭秘爱奇艺深度学习平台云原生迁移实践_AI&大模型_李灏_InfoQ精选文章