场景

最近在工作中经常使用到gpu资源,传统环境下我们一般在宿主机上部署算法程序,但是这样无法形成快速交付,并且维护成本会非常高。所以nvidia其实也考虑到这一点 通过docker调用宿主机的gpu资源。一般情况下我们需要部署gpu-container-runtime或者nvidia-docker去调用宿主机的gpu资源。那么既然docker可以使用gpu资源,我们是不是可以在kubernetes环境去使用gpu资源呢?答案是肯定的,接下来我这边会分享在kubernetes如何使用device plugin实现调度gpu资源。

设计

其实在kubernetes1.11版本之前社区给出的解决方案是加入了alpha.kubernetes.io/nvidia-gpu去使用gpu资源但是这个特性在1.11版本之后就已经下线了。取而代之的是通过Extended Resource+ Device Plugin两个Kubernetes的内置模块,外加由设备提供商实现的相应Device Plugin, 完成从设备的集群级别调度至工作节点,到设备与容器的实际绑定。

首先思考的第一个问题是为什么进入alpha.kubernetes.io/nvidia-gpu主干一年之久的GPU功能彻底移除?

  1. Kubernetes有一个核心理念:OutOfTree是一个很好的理念,简单来讲就是专注于自身核心和通用能力 将像GPU,InfiniBand,FPGA和公共云能力的工作完全交给社区和领域专家。这样一方面可以降低软件自身使用的复杂度,减小稳定性风险,另外OutOfTree分开迭代也能够更灵活实现的功能升级。

Device Plugin的设计:

实际上Device plugins实际上是简单的grpc server,需要实现以下两个方法 ListAndWatchAllocate,并监听在/var/lib/kubelet/device-plugins/目录下的Unix Socket,比如/var/lib/kubelet/device-plugins/nvidia.sock。

type DevicePluginServer interface {// GetDevicePluginOptions returns options to be communicated with Device// ManagerGetDevicePluginOptions(context.Context, *Empty) (*DevicePluginOptions, error)// ListAndWatch returns a stream of List of Devices// Whenever a Device state change or a Device disapears, ListAndWatch// returns the new listListAndWatch(*Empty, DevicePlugin_ListAndWatchServer) error// 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 containerAllocate(context.Context, *AllocateRequest) (*AllocateResponse, error)// PreStartContainer is called, if indicated by Device Plugin during // registeration phase,// before each container start. Device plugin can run device specific // operations// such as reseting the device before making devices available to the containerPreStartContainer(context.Context, *PreStartContainerRequest) (*PreStartContainerResponse, error)
}

其中:

  • ListAndWatch: Kubelet会调用该API做设备发现和状态更新(比如设备变得不健康)
  • Allocate: 当Kubelet创建要使用该设备的容器时, Kubelet会调用该API执行设备相应的操作并且通知Kubelet初始化容器所需的device,volume和环境变量的配置。

ListAndWatch函数(register 时候会调用一次,而且仅仅就这一次,因为 ListAndWatch 是个 GRPC 长连接,DP 可以通过这个长连接不停的反馈。):

func (m *NvidiaDevicePlugin) ListAndWatch(e *pluginapi.Empty, s pluginapi.DevicePlugin_ListAndWatchServer) error {s.Send(&pluginapi.ListAndWatchResponse{Devices: m.devs})for {select {case <-m.stop:return nilcase d := <-m.health:// FIXME: there is no way to recover from the Unhealthy state.d.Health = pluginapi.Unhealthys.Send(&pluginapi.ListAndWatchResponse{Devices: m.devs})}}
}

简阅Allocate函数主要的作用是分配相应的device资源:

// Allocate which return list of devices.
func (m *NvidiaDevicePlugin) Allocate(ctx context.Context,reqs *pluginapi.AllocateRequest) (*pluginapi.AllocateResponse, error) {responses := pluginapi.AllocateResponse{}log.Infoln("----Allocating GPU for gpu mem is started----")var (podReqGPU uintfound     boolassumePod *v1.Pod)// podReqGPU = uint(0)for _, req := range reqs.ContainerRequests {podReqGPU += uint(len(req.DevicesIDs))}log.Infof("RequestPodGPUs: %d", podReqGPU)
........

类似阿里云的gpu share基本在这里加入了很多自定义逻辑实现了多卡gpu调度

大致的逻辑就是通过Annotations 标签选择合适的gpu device。这里就不详细说明了 感兴趣的同学可以去看下源码。

之后我们来看下device plugin 工作流程

shareGPUManager ---run()---> NvidiaDevicePlugin ----Serve()----> Start GRPC server and Register

那么整个Kubernetes调度GPU的过程如下:

1. GPU Device plugin 部署到GPU节点上,通过 ListAndWatch 接口,上报注册节点的GPU信息和对应的DeviceID。

2. 当有声明 nvidia.com/gpu 的GPU Pod创建出现,调度器会综合考虑GPU设备的空闲情况,将Pod调度到有充足GPU设备的节点上。

3.  节点上的kubelet 启动Pod时,根据request中的声明调用各个Device plugin 的 allocate接口, 由于容器声明了GPU。 kubelet 根据之前 ListAndWatch 接口收到的Device信息,选取合适的设备,DeviceID 作为参数,调用GPU DevicePlugin的 Allocate 接口,GPU DevicePlugin ,接收到调用,将DeviceID 转换为 NVIDIA_VISIBLE_DEVICES 环境变量,返回kubelet

4. kubelet将环境变量注入到Pod, 启动容器容器启动时, gpu-container-runtime 调用 gpu-containers-runtime-hookgpu-containers-runtime-hook 根据容器的 NVIDIA_VISIBLE_DEVICES 环境变量,转换为 --devices 参数,调用 nvidia-container-cli prestart,nvidia-container-cli 根据 --devices ,将GPU设备映射到容器中。 并且将宿主机的Nvidia Driver Lib 的so文件也映射到容器中。 此时容器可以通过这些so文件,调用宿主机的Nvidia Driver。

整体架构图:

总结

Kubernetes的生态地位已经确立,可扩展性将是其发力的主战场。异构计算作为非常重要的新战场,Kubernetes非常重视。而异构计算需要强大的计算力和高性能网络,需要提供一种统一的方式与GPU、FPGA、NIC、InfiniBand等高性能硬件集成。这也就是为什么淘汰了alpha.kubernetes.io/nvidia-gpu改用了Extended Resource+ Device Plugin的原因。

当然在我司也修改了部分逻辑,我们没有沿用gpu plugin默认device规则,我们在device的基础上新增了逻辑device的概念在逻辑层限制了每个应用可以申请的gpu显存。当然没办法硬性隔离,这部分目前需要依赖device底层实现。

kubernetes-nvidia-plugin设计解读相关推荐

  1. Kubernetes的Device Plugin设计解读

    摘要: Kubernetes的生态地位已经确立,可扩展性将是其发力的主战场.异构计算作为非常重要的新战场,Kubernetes非常重视.而异构计算需要强大的计算力和高性能网络,需要提供一种统一的方式与 ...

  2. 谈 Kubernetes 的架构设计与实现原理

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 本文转载于公众号:真没什么逻辑 Kubernetes 基本上是这两年最热门.最被人熟知的技术了,它 ...

  3. rs结果集可以传递给另一个jsp吗_从未如此高调 宝骏RS-5独家设计解读

    [汽车之家 设计解码] 尽管宝骏多款"神车"已经用非常漂亮的销量数据打消了大家的疑虑,可事实上,它的车型就用途而言大多还是偏商用的,厂商也低调表示自己在乘用车方面还只是小学生.如今 ...

  4. Volcano 监控设计解读,一看就懂

    摘要:Volcano 方便AI,大数据,基因,渲染等诸多行业通用计算框架介入,提供高性能任务调度引擎,高性能异构芯片管理,高性能任务运行管理等能力. Volcano 是一个 Kubernetes 云原 ...

  5. Kubernetes 架构与设计

    什么是kubernetes? 官方说明: Kubernetes is an open-source system for automating deployment, scaling, and man ...

  6. Kubernetes v1.17 版本解读 | 云原生生态周报 Vol. 31

    作者 | 徐迪.李传云.黄珂.汪萌海.张晓宇.何淋波 .陈有坤.李鹏 审核 | 陈俊 上游重要进展 1. Kubernetes v1.17 版本发布 功能稳定性是第一要务.v1.17 包含 22 个增 ...

  7. Kubernetes滚动更新速率控制解读

    女主宣言 利用kubernetes的滚动更新时,可能经常遇到发布"太快不稳定"或"太慢体验差"的情况.本文将介绍kubernetes滚动更新控制速率的特性. P ...

  8. 干货|以产品要素设计解读线上小微信贷

    小微信贷市场中经常收到客户的一些反馈,如:没有房子抵押.额度不够.利率太高.期限短等等,这些反馈的声音主要集中在产品要素上,客户拿到的贷款就是这些产品要素的组合,换句话讲,这些要素也正是一款产品的卖点 ...

  9. Kubernetes 一指禅,文章集锦(实时更新)

    Kubernetes不简单,阿里云容器服务团队希望能通过这篇集锦助你一臂之力~ 你还有哪些学习和使用的困惑?请留言给我们哦~ Kubernetes 的ABC与解读 Kubernetes与Docker基 ...

最新文章

  1. 20155308郝文菲--第三次作业
  2. 如何在JavaScript中比较数组?
  3. 世界上最完美的公式 ----欧拉公式
  4. 下一个排列—leetcode31
  5. 代码练习中的bug及修改方法
  6. oracle中enqueue,ORACLE: Enqueue 烂笔头
  7. Apache JK Tomcat 集群问题
  8. linux多线程学习(三)——线程属性设置
  9. php设计要求,《PHP设计模式介绍》第十章 规范模式
  10. win10中VM15内centos7的安装
  11. BP神经网络预测(人口)程序(matlab)
  12. 搭建新环境的准备工作
  13. CAD卸载/完美解决安装失败/如何彻底卸载清除干净cad各种残留注册表和文件的方法
  14. CSS的特殊性 (specificity)
  15. java里面有radix树吗_基数树(radix tree)
  16. Vue实现 侧边固定定位图标 滑动隐藏
  17. python要学什么英文歌_Python分析网易云音乐近5年热门歌单
  18. vscode及typro快捷键
  19. Linux红帽RHEL 7/8 系统重置root用户密码
  20. JSONObject.toBean() 把jsonobject转换成实体类

热门文章

  1. 山外山科创板上市破发:首日下挫19% 公司市值38亿
  2. Cfree之万能头函数bits\stdc++.h的添加和注意事项
  3. 极限中0除以常数_用计算器按出来的常数费根鲍姆常数
  4. 小黑升级记----记ThinkPad470p加装固态盘
  5. Webix JavaScript UI 9.1.6
  6. openssl ca(签署和自建CA)
  7. (附源码)ssm基于微信小程序的恋上诗词设计与实现 毕业设计 011431
  8. 引水工程 最小生成树
  9. 操作系统:线程死锁、饥饿、活锁
  10. CVPR 2022 | “直面真实的世界”