写点什么

GPU 在 Kubernetes 中的使用与管理 | 社区征文

作者:大菠萝
  • 2022 年 2 月 15 日
  • 本文字数:2245 字

    阅读完需:约 7 分钟

GPU在Kubernetes中的使用与管理 | 社区征文

前言

随着人工智能与机器学习技术的快速发展,在 Kubernetes 上运行模型训练、图像处理类程序的需求日益增加,而实现这类需求的基础,就是 Kubernetes 对 GPU 等硬件加速设备的支持与管理。在本文中我们就说一下在 Kubernetes 中启动并运行 GPU 程序的注意事项。

Kubernetes 对 GPU 支持的不足之处

我们知道 Kubernetes 可以实现对宿主机的 CPU、内存、网络实现精细化的控制,但是到本文书写为止,Kubernetes 尚未实现像管理 CPU 那样来管理 GPU,比如有如下限制:


  • 对于 GPU 资源只能设置limit,这意味着requests不可以单独使用,要么只设置limit、要么同时设置二者,但二者值必须相等,不可以只设置request而不设置limit

  • pod 及容器之间,不可以共享 GPU,且 GPU 也不可以过量分配(所以我们线上的程序采用daemonSet方式运行)。

  • 不允许以小数请求 GPU 资源分配。

Kubernetes 如何管理 GPU 资源

扩展资源(Extended Resources)

和 CPU 资源不同的是,硬件加速设备类型有多种,比如说 GPUs、NICs、FPGAs,而且它们的厂商也不止一家,Kubernetes 要想挨个支持是不现实的,所以 Kubernetes 就把这些硬件加速设备统一当做扩展资源来处理。


Kubernetes 在 Pod 的 API 对象里并没有提供像 CPU 那样的资源类型,它使用我们刚说到的扩展资源资源字段来传递 GPU 信息,下面是官方给出的声明使用 nvidia 硬件的示例:


apiVersion: v1kind: Podmetadata:  name: cuda-vector-addspec:  restartPolicy: OnFailure  containers:    - name: cuda-vector-add      # https://github.com/kubernetes/kubernetes/blob/v1.7.11/test/images/nvidia-cuda/Dockerfile      image: "k8s.gcr.io/cuda-vector-add:v0.1"      resources:        limits:          nvidia.com/gpu: 1 # requesting 1 GPU
复制代码


要想使用上面 yaml 文件声明使用 GPU 设备,那么需要先在 Node 节点上安装设备插件Device Plugin

设备插件(Device Plugin)

设备插件与设备厂商绑定,这里使用 nvidia 提供的 Device Plugin。


官方的 NVIDIA GPU 设备插件 有以下要求:


  • Kubernetes 的节点必须预先安装了 NVIDIA 驱动

  • Kubernetes 的节点必须预先安装 nvidia-docker 2.0

  • Docker 的默认运行时必须设置为 nvidia-container-runtime,而不是 runc

  • NVIDIA 驱动版本 ~= 384.81


安装过程可以参考上面链接,这里就不在赘述,这里讨论 Device Plugin 做了哪些事及其实现方法。


  • 暴露每个 Node 上的 GPU 个数

  • 在 Kubernetes 上运行可以支持 GPU 的容器


Device Plugin 工作流程图:



第一步:向 kubelet 的 Device plugin Manager 发起注册请求。

第二步:启动 gRPC 服务用于和 kubelet 进行通信。

第三步:kubelet 通过 ListAndWatch 这个 API 定期获取设备信息列表。

第四步:kubelet 将获取到的设备信息发送给 API server。


不管是 nvidia 还是其它类型的硬件,如果要实现用于 Kubernetes 的自己的设备插件,都需要遵守 Device Plugin 的规范来实现如下代码中所示的 ListAndWatchAllocate API。


// DevicePlugin is the service advertised by Device Pluginsservice DevicePlugin {  // GetDevicePluginOptions returns options to be communicated with Device  // Manager  rpc GetDevicePluginOptions(Empty) returns (DevicePluginOptions) {}
// ListAndWatch returns a stream of List of Devices // Whenever a Device state change or a Device disappears, ListAndWatch // returns the new list rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}
// GetPreferredAllocation returns a preferred set of devices to allocate // from a list of available ones. The resulting preferred allocation is not // guaranteed to be the allocation ultimately performed by the // devicemanager. It is only designed to help the devicemanager make a more // informed allocation decision when possible. rpc GetPreferredAllocation(PreferredAllocationRequest) returns (PreferredAllocationResponse) {}
// Allocate is called during container creation so that the Device // Plugin can run device specific operations and instruct Kubelet // of the steps to make the Device available in the container rpc Allocate(AllocateRequest) returns (AllocateResponse) {}
// PreStartContainer is called, if indicated by Device Plugin during registeration phase, // before each container start. Device plugin can run device specific operations // such as resetting the device before making devices available to the container rpc PreStartContainer(PreStartContainerRequest) returns (PreStartContainerResponse) {}}
复制代码

总结

总的来讲,以 Device Plugin 方式来管理 GPU 等硬件设备,目前的控制还不够精细,粒度较大。所以很多情况下要把 GPU 用起来好像也不是非 Device Plugin 不可。我发现很多公司在使用时,并没有在 YAML 文件中指定 GPU 的个数,也没有在 Kubernetes 集群中安装 Device Plugin 插件,因为他们的程序以 DaemonSet 的方式运行,且每台机器上只有一块 GPU,这样相当于一个程序独占一个 GPU,至于把 GPU 设备及驱动加载到 Docker 容器内,可以通过在 YAML 文件中指定NVIDIA_DRIVER_CAPABILITIES环境变量来实现:


# 参考:https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/user-guide.htmlcontainers:- env:  - name: NVIDIA_DRIVER_CAPABILITIES    value: compute,utility,video
复制代码


发布于: 刚刚阅读数: 2
用户头像

大菠萝

关注

Keep running! 2019.01.07 加入

保持专注,努力工作,人工智能公司SRE。

评论

发布
暂无评论
GPU在Kubernetes中的使用与管理 | 社区征文