乐趣区

关于腾讯云:云原生的弹性-AI-训练系列之三借助弹性伸缩的-Jupyter-Notebook大幅提高-GPU-利用率

Jupyter Notebooks 在 Kubernetes 上部署往往须要绑定一张 GPU,而大多数时候 GPU 并没有被应用,因而利用率低下。为了解决这一问题,咱们开源了 elastic-jupyter-operator,将占用 GPU 的 Kernel 组件独自部署,在长期闲暇的状况下主动回收,开释占用的 GPU。这篇文章次要介绍了这一开源我的项目的应用形式以及工作原理。

Jupyter Notebooks 是目前利用最为宽泛的交互式开发环境,它很好地满足了数据迷信、深度学习模型构建等场景的代码开发需要。不过 Jupyter Notebooks 在不便了算法工程师和数据科学家们日常开发工作的同时,也对基础架构提出了更多的挑战。

资源利用率的问题

最大的挑战来自于 GPU 资源利用率。在运行的过程中即便没有代码在运行,Notebook 也会长期占用着 GPU,造成 GPU 的空置等问题。在大规模部署 Jupyter 实例的场景下,个别会通过 Kubernetes 创立多个 Notebook 实例,调配给不同的算法工程师应用。而在这样的状况下,咱们须要在对应的 Deployment 中当时申请 GPU,这样 GPU 会与对应的 Notebook 实例绑定,每个 Notebook 实例都会占用一张 GPU 显卡。

然而同一时间,并不是所有的算法工程师都在应用 GPU。在 Jupyter 中,编辑代码的过程是不须要应用计算资源的,只有在执行 Cell 中的代码片段时,才会应用 CPU 或 GPU 等硬件资源,执行并返回后果。由此能够预感,如果通过这样的部署形式会造成相当程度的资源节约。

造成这一问题的起因次要是原生的 Jupyter Notebooks 没有很好地适配 Kubernetes。在介绍问题起因之前,先简略概述一下 Jupyter Notebook 的技术架构。如下图所示,Jupyter Notebook 次要由三局部组成,别离是用户和浏览器端,Notebook Server 和 Kernel。

其中用户和浏览器端是 Jupyter 的前端,次要负责展现代码和执行后果等。Notebook Server 是它的后端服务器,来自浏览器的代码执行申请会被 Notebook Server 解决,分派给 Kernel 执行。Kernel 是真正负责执行代码,返回后果。

在传统的应用形式中,用户会通过 jupyter notebook $CODE_PATH 等命令,在本地运行 Jupyter Notebook Server,随后拜访浏览器中的 Jupyter 交互式开发界面。当代码须要执行时,Notebook Server 会创立一个独立的 Kernel 过程,这一过程会应用 GPU 等运行。在 Kernel 长期闲暇,没有代码须要执行时,这一过程会被终止,GPU 也就不再会被占用。

而当部署在 Kuberenetes 之上后,问题就产生了。Notebook Server 和 Kernel 运行在同一个 Pod 的同一个容器下,只管只有执行代码时才须要运行的 Kernel 组件是须要 GPU 的,而长期运行的 Notebook Server 是不须要的,然而受限于 Kubernetes 的资源管理机制,还是须要给其提前申请 GPU 资源。

在 Notebook Server 的整个生命周期中,这一块 GPU 始终与 Pod 绑定。在 Kernel 过程闲暇时尽管会被回收,然而曾经调配给 Pod 的 GPU 卡却不能再交还给 Kubernetes 进行调度了。

解决方案

为了解决这一问题,咱们开源了我的项目 elastic-jupyter-operator。思路十分奢侈:问题源于 Notebook Server 和 Kernel 在同一个 Pod 中,导致咱们无奈别离为这两个组件申请计算资源。那只有将他们离开部署,让 Notebook Server 在独自的 Pod 中,Kernel 也在独自的 Pod 中,相互之间通过 ZeroMQ 通信即可。

通过这样的形式,Kernel 会在闲暇时被开释。在须要时会再次被临时性地申请 GPU,运行起来。为了实现这一目标,咱们在 Kubernetes 中实现了 5 个 CRD,同时为 Jupyter 引入了一个新的 KernelLauncher 实现。通过它们,用户能够在 GPU 闲暇时将 Kernel 回收开释,在须要执行代码时再动静地申请 GPU 资源,创立 Kernel Pod 进行代码执行。

简略的例子

上面咱们将通过一个例子介绍应用形式。首先咱们须要创立 JupyterNotebook CR(CustomResource),这一个 CR 会创立出对应的 Notebook Server:

apiVersion: kubeflow.tkestack.io/v1alpha1
kind: JupyterNotebook
metadata:
  name: jupyternotebook-elastic
spec:
  gateway:
    name: jupytergateway-elastic
    namespace: default
  auth:
    mode: disable

其中指定了 gateway,这是另外一个 CR JupyterGateway。为了可能让 Jupyter 反对近程的 Kernel,须要这样一个网关进行申请的转发。咱们同样须要创立这样一个 CR:

apiVersion: kubeflow.tkestack.io/v1alpha1
kind: JupyterGateway
metadata:
  name: jupytergateway-elastic
spec:
  cullIdleTimeout: 3600
  image: ccr.ccs.tencentyun.com/kubeflow-oteam/enterprise-gateway:2.5.0

JupyterGateway CR 中的配置 cullIdleTimeout 指定了通过多久的闲暇工夫后,其治理的 Kernel Pod 会被零碎回收开释。在例子中是 1 个小时。创立完这两个资源后,就能够体验到弹性伸缩的 Jupyter Notebook 了。如果在一个小时内始终没有应用的话,Kernel 会被回收。

$ kubectl apply -f ./examples/elastic/kubeflow.tkestack.io_v1alpha1_jupyternotebook.yaml
$ kubectl apply -f ./examples/elastic/kubeflow.tkestack.io_v1alpha1_jupytergateway.yaml
$ kubectl port-forward deploy/jupyternotebook-elastic 8888:8888
$ kubectl get pods 
NAME                                          READY   STATUS    RESTARTS   AGE
jovyan-219cfd49-89ad-428c-8e0d-3e61e15d79a7   1/1     Running   0          170m
jupytergateway-elastic-868d8f465c-8mg44       1/1     Running   0          3h
jupyternotebook-elastic-787d94bb4b-xdwnc      1/1     Running   0          3h10m

除此之外,因为 Notebook 和 Kernel 解耦的设计,使得用户能够不便地批改 Kernel 的镜像与资源配额、向曾经在运行的 Notebook 中增加新的 Kernel 等。

设计与实现

在介绍完应用形式后,咱们简略介绍其设计与实现。

当用户在浏览器中抉择执行代码时,首先申请会发送给在 Kubernetes 上运行的 Notebook Server。因为目前集群上没有正在运行的 Kernel,代码执行工作无奈调配上来,所以 Notebook Server 会向 Gateway 发送一个创立 Kernel 的申请。Gateway 负责管理远端的 Kernel 的生命周期,它会在 Kubernetes 集群中创立对应的 JupyterKernel CR。随后会与集群中曾经创立好的 Kernel 通过 ZeroMQ 进行交互,而后将代码执行的申请发送给 Kernel 进行执行,随后将后果发送给 Notebook Server 再将其返回给前端进行渲染和展现。

而 Gateway 会依据在 JupyterGateway CR 中定义的无关资源回收的参数,定时查看目前治理的 Kernel 中有没有满足要求,须要被回收的实例。当 Kernel 闲暇工夫达到了定义的阈值时,Gateway 会删除对应的 JupyterKernel CR,将其回收,开释 GPU。

总结

目前深度学习在开发与落地生产的过程中依然存在着诸多的挑战。elastic-jupyter-operator 瞄准了在开发过程中的 GPU 利用率与开发效率的问题,提出了一种可行的计划,将占用 GPU 的 Kernel 组件独自部署,在长期闲暇的状况下主动回收,开释占用的 GPU,通过这样的形式进步资源的利用率的同时,也给予了算法工程师用户更多的灵便度。

从算法工程师的角度来说,elastic-jupyter-operator 反对自定义的 Kernel,能够自行抉择在 Kernel 的容器镜像中装置 Python 包或者零碎依赖,不须要放心与团队外部的 Notebook 对立镜像的版本一致性问题,进步研发效率。

而从运维与资源管理的角度来说,elastic-jupyter-operator 遵循了云原生的设计理念,以 5 个 CRD 的形式对外提供服务,对于曾经落地 Kuerbenetes 的团队来说具备较低的运维老本。

License

  • This article is licensed under CC BY-NC-SA 3.0.
  • Please contact me for commercial use.

    【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!

退出移动版