传统的高性能计算集群一般都习惯性地使用 Slurm + Lustre 的方案作为任务调度和存储, 然而,随着容器的发展,互联网业务的部署已经越来越多地开始了容器化, 而 Kubernetes 也成为了容器编排的事实标准。

而且,对比容器化的简洁, SlurmLustre 复杂的配置,让人头疼的运維压力, 也让作为互联网的最前沿之一的机器学习,也开始了容器化探索。

简介

本系列文章主要记录了在 Kubernetes 内使用 Pytorch 运行 ImageNet 的淌坑经验, 同时也使用 CephFS 作为网络存储,解决数据存放问题。

计划:

  • 简介和容器内使用显卡(本文)
  • Kuberentes 和 Device Plugin
  • Kubeflow 和 Pytorch-Operator
  • CSI(Cofntainer Storage Interface) 和 CephFS 网络存储
  • mnist Demo 和分布式训练(MPI)
  • 分布式 ImageNet

Slurm

Slurm(Simple Linux Utility for Resource Management) 是一个用于Linux 和 Unix 内核系统的免费、开源的任务调度工具, 被世界范围内的(包括天河等)超级计算机和计算机群广泛采用。

Slurm 的成熟度毋庸置疑,但是有两个问题:

  1. 在互联网公司不一定能有专人维护 Slurm 集群
  2. 交付环境没有 Slurm

Lustre

Lustre(得名于:Linux + Cluster) 一种平行分布式文件系统,通常用于大型计算机集群和超级计算机。 很多时候都是和 Slurm 配套使用的,所以也会有类似 Slurm 的两个问题。

Kubernetes + Ceph

互联网时代,容器化并使用 Kubernetes 同时使用 Ceph 作为网络存储肯定是毫无疑问的方案和方向。 如果 Kubernetes + Ceph 能够解决机器学习中高性能集群资源分配和利用的问题, 那对于互联网公司,肯定会是更好的选择。

容器内使用显卡

GPU

现在机器学习的主流是深度学习,自然 GPU 是少不了的。本文中使用了 Nvidia 的 GTX 1080Ti。

驱动

首先确认机器上是否有 GPU 卡:

lspci -vnn | grep NVIDIA

# Nvidia 显卡可以用自家工具看到详情
nvidia-smi

确认安装了 Nvidia 驱动 (cuda-driver),一般直接从源里安装即可。

https://github.com/NVIDIA/nvidia-docker/wiki/Frequently-Asked-Questions#how-do-i-install-the-nvidia-driver

如果官方源里没有,那就在 Nvidia 提供的这里下载安装文件,安装也可。

这里需要注意的是高版本的 CUDA 同样需要高版本的驱动,对应关系如下:

!CUDA Driver

Nvidia docker 2.0

https://github.com/NVIDIA/nvidia-docker

默认的 Docker 是不支持 GPU 的,所以我们需要 nvidia-docker ,这是 Nvidia 为了支持 Docker 生态出的一个包, 而 nvidia docker 2.0 是第二版,主要是为 Docker 新增了一个 nvidia 的运行时,

所以在安装完 nvidia docker 2.0 后,需要把 Docker 的默认运行时个性为 nvidia 。 可以通过修改 docker 配置文件 /etc/docker/daemon.json 让 docker 能够使用 Nvidia Container Runtime

Nvidia Container Runtime 作为核心部分,在原有的容器运行时 runc 的基础上增加一个 prestart hook , 用于调用 libnvidia-container 库。

libnvidia-container 提供一个库和一个简单的 Cli 工具,这个库让容器能够使用 Nvidia 的 GPU。

runc 是docker默认的容器运行时,根据 Open Containers Initiative (OCI) 创建容器。

总而言之,就是当我们要在 Docker 里使用 Nvidia GPU 时,就必须要安装 Nvidia Docker

安装完之后,基本的用法如下,可以测试一下:

docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi

如果出现 brand = tesla: unknown 的错误,就是 cuda 的版本和我们使用的驱动不匹配, 可以看一下宿主显卡驱动的版本和使用的 CUDA 版本,然后对照上文的图片看是否匹配。

可以使用对应版本的 CUDA 镜像,如:

docker run --runtime=nvidia --rm nvidia/cuda:8.0-runtime nvidia-smi

也可以更新宿主机驱动。

至此,我们就可以在容器内使用 GPU 了,但是我们想在 Kubernetes 内使用,还需要使用 Device Plugin ,这个会在后文说到。