互联网技术

Kubernetes上机器学习平台的应用

2023年11月6日 · admin
openmagic ad

Kubernetes上机器学习平台的应用

本文将回顾网易云音乐的机器学习平台GoblinLab在容器化实践中所做的一些探索和尝试。

过去,音乐算法的模型训练任务主要依赖物理机进行开发、调试和定时调度。每个算法团队都有自己专属的物理机,这种分散的管理模式带来了许多问题。首先,物理机分布不均,缺乏统一管理,团队主要依靠文档记录机器的使用情况;其次,各业务之间的资源调配常常需要跨机房迁移物理机,十分耗时;此外,由于多人共享同一开发环境,开发与调度任务混用,导致环境相互影响和资源争夺。针对这些问题,可以总结如下:

  • 资源利用率低:部分机器资源的利用率较低,无法根据不同业务阶段快速实现扩缩容,导致资源配置不合理。
  • 环境相互影响:多人共享同一开发机,缺乏隔离,可能造成环境和资源的争夺。
  • 监控报警缺失:物理机模式下缺乏任务监控和报警功能,影响运维效率。

在资源未能得到合理调配的情况下,负载不均衡,资源利用率无法最大化。在快速扩缩容、环境隔离和资源监控等方面,Kubernetes及其相关扩展能够有效解决这些问题。GoblinLab将物理机集中管理,构建成一个Kubernetes集群。通过分析算法团队的工作方式,GoblinLab决定基于Kubernetes提供在线开发调试容器环境和任务容器化调度两种方案,分别针对任务开发和调度场景。

在任务开发阶段,GoblinLab旨在降低算法团队从物理机迁移到容器化环境的学习成本。系统中将Kubernetes容器视为云主机使用,容器镜像基于各版本的TensorFlow(底层为Ubuntu),集成了大数据开发环境(如Hadoop、Hive、Spark等),并安装了常用软件。同时,容器环境提供了三种使用方式:Jupyter Lab、SSH登录和Code Server(VS Code)。

在GoblinLab中,新建容器化开发环境十分简单,只需选择镜像,填写所需资源以及挂载的外部存储(在任务开发环境中简称为开发实例)。算法开发者可以选择任意一种方式进行任务开发或调试,使用Code Server(VS Code)可获得更好的体验。

任务开发所用的容器化环境在Kubernetes上通过StatefulSet类型实现,相关资源编排文件如下(已精简细节):

目前,GoblinLab已提供11个基于TensorFlow各版本的CPU和GPU通用镜像,以及多个定制化镜像。

任务调度

在容器化环境使用之前,算法团队的任务开发调度都是在GPU物理机器上完成,调度主要通过定时器或cron命令执行,缺乏失败、超时等报警机制,也没有重试等功能,运维工具几乎不存在。

在介绍容器中开发的任务如何上线调度之前,先简要概述GoblinLab的系统架构。GoblinLab的简化系统架构分为四层,从上到下依次为:

  • 应用层:提供直接面向用户的机器学习开发平台(GoblinLab)
  • 中间层:接入统一的调度、报警及配置服务
  • 执行服务:提供统一的执行服务,包括Kubernetes、Spark、Jar等任务的提交和执行,支持快速扩展
  • 基础设施:底层基础设施,包括Kubernetes集群、Spark集群及普通服务器等

为了保障调度任务的稳定性,GoblinLab将任务的开发与调度拆分。开发完成后,任务调度通过任务流中的容器化调度组件实现,用户需填写组件相关参数(代码所在PVC及路径、配置镜像等),再通过任务流的调度功能实现任务调度。与任务开发不同,每个调度任务在独立容器中执行,确保任务间相互隔离,并通过后续介绍的资源隔离方案优先保障线上调度任务所需资源。

任务调度执行时在Kubernetes上资源编排文件(已精简细节):

权限控制

容器化开发环境启动后,用户可以通过SSH登录、Code Server或Jupyter Lab等方式访问。为了避免容器化开发环境被他人使用,GoblinLab为每种方式设置了统一密钥,每次启动时密钥随机生成。

数据持久化

在Kubernetes容器中,若无特殊配置,容器中的数据不会持久化,随着容器删除或重启,数据将丢失。相应的解决方案是将需持久化的目录挂载外部存储。在GoblinLab中,会为每个用户自动创建一个默认的外部存储PVC,并挂载到容器的/Root目录。同时,用户也可以自定义外部存储的挂载。

除了自动创建的PVC外,用户还可以自己创建PVC,支持将创建的PVC设置为只读或读写共享给他人。此外,GoblinLab也支持对PVC内数据进行管理。

服务暴露

Kubernetes集群中创建的服务无法直接在集群外访问,GoblinLab使用Nginx Ingress + Gateway进行访问,将集群内的服务暴露到外部。

容器化开发环境的Service资源编排文件如下(已精简细节):

每当用户启动一个容器化开发环境,GoblinLab将通过接口自动修改Nginx Ingress配置,将服务暴露出来,供用户使用,Ingress转发配置如下:

资源管控

为提高资源利用率,GoblinLab的Kubernetes底层资源基本以共享方式使用,并进行一定比例的超售。然而,当多个团队共享资源总量固定的集群时,为确保每个团队公平共享资源,需要对资源进行管理和控制。在Kubernetes中,资源配额是解决此问题的工具。目前,GoblinLab主要管控的资源包括CPU、内存、GPU及存储等。平台根据各团队的实际需求,将资源划分为多个队列(Kubernetes中的概念为namespace),供各团队使用。

在集群中,最常见的资源为CPU与内存,由于可超售(overcommit),因此存在limits与requests两个配额限制。其他资源为扩展类型,不允许超售,因此只有requests配额限制。

资源隔离

GoblinLab的资源隔离指的是在同一Kubernetes集群中,调度层面的相对隔离,包括GPU机器资源的隔离、线上与测试任务的隔离。

在Kubernetes集群中,GPU机器资源相较于CPU资源更为珍贵,因此为了提高GPU利用率,禁止CPU任务调度到GPU节点。

GPU节点设置污点(taint):禁止一般任务调度到GPU节点

注意:以上内容中所有 [[[IMG_n]]] 占位符均保留。