摘要: Kubernetes 的生态地位已经确立, 可扩展性将是其发力的主战场异构计算作为非常重要的新战场, Kubernetes 非常重视而异构计算需要强大的计算力和高性能网络, 需要提供一种统一的方式与 GPUFPGANICInfiniBand 等高性能硬件集成
最近在调研 Kubernetes 的 GPU 调度和运行机制, 发现传统的
alpha.kubernetes.io/nvidia-gpu
即将在 1.11 版本中下线, 和 GPU 相关的调度和部署的代码将彻底从主干代码中移除
取而代之的是通过 Extended Resource+Device Plugin 两个 Kubernetes 的内置模块, 外加由设备提供商实现的相应 Device Plugin, 完成从设备的集群级别调度至工作节点, 到设备与容器的实际绑定
首先思考的第一个问题是为什么进入
alpha.kubernetes.io/nvidia-gpu
主干一年之久的 GPU 功能彻底移除?
1.OutOfTree 是 Kubernetes 一个很好的理念, 之前的 Cloud Provider 的重构也是类似的工作对于 Kubernetes 来说, 不做瑞士军刀, 专注于自身核心和通用能力, 而将像 GPU,InfiniBand,FPGA 和公共云能力的工作完全交给社区和领域专家这样一方面可以降低软件自身使用的复杂度, 减小稳定性风险, 另外 OutOfTree 分开迭代也能够更灵活实现的功能升级
2. 而开放的软件架构设计和标准也调动了社区参与的积极性, 而活跃的社区其实是 Kubernetes 打赢容器调度框架之战的核心法宝
先来简要介绍一下 kubernetes 这两个模块:
Extended Resource: 一种自定义资源扩展的方式, 将资源的名称和总数量上报给 API server, 而 Scheduler 则根据使用该资源 pod 的创建和删除, 做资源可用量的加减法, 进而在调度时刻判断是否有满足资源条件的节点目前这里的 Extended Resource 的增加和减少单元必须是整数, 比如你可以分配 1 个 GPU, 但是不能分配 0.5 个 GPU 该功能由于只是替代了 Opaque integer resources, 做了些更名的工作, 所以在 1.8 已经是稳定的状态了但是当 integer 这个关键词被移除, 也引发我们的想象, 未来会不会有 0.5 存在的可能性?
Device Plugin: 通过提供通用设备插件机制和标准的设备 API 接口这样设备厂商只需要实现相应的 API 接口, 无需修改 Kubelet 主干代码, 就可以实现支持 GPUFPGA 高性能 NICInfiniBand 等各种设备的扩展该能力在 Kubernetes 1.8 和 1.9 版本处于 Alpha 版本, 在 1.10 会进入 Beta 版本
应该说这个功能目前还比较新, 需要通过 feature gate 打开, 即配置 feature-gates=DevicePlugins=true
Device Plugin 的设计:
API 设计:
实际上 Device plugins 实际上是简单的 grpc server, 需要实现以下两个方法 ListAndWatch 和 Allocate, 并监听在 / var/lib/kubelet/device-plugins / 目录下的 Unix Socket, 比如 / var/lib/kubelet/device-plugins/nvidia.sock
- service DevicePlugin {// returns a stream of []Device
- rpc ListAndWatch(Empty) returns (stream ListAndWatchResponse) {}
- rpc Allocate(AllocateRequest) returns (AllocateResponse) {}
- }
其中:
ListAndWatch: Kubelet 会调用该 API 做设备发现和状态更新 (比如设备变得不健康)
Allocate: 当 Kubelet 创建要使用该设备的容器时, Kubelet 会调用该 API 执行设备相应的操作并且通知 Kubelet 初始化容器所需的 device,volume 和环境变量的配置
插件生命周期管理:
1. 插件启动时, 以 grpc 的形式通过 / var/lib/kubelet/device-plugins/kubelet.sock 向 Kubelet 注册, 同时提供插件的监听 Unix Socket,API 版本号和设备名称 (比如 nvidia.com/gpu)Kubelet 将会把这些设备暴露到 Node 状态中, 以 Extended Resource 的要求发送到 API server 中, 后续 Scheduler 会根据这些信息进行调度
2. 插件启动后, Kubelet 会建立一个到插件的 listAndWatch 长连接, 当插件检测到某个设备不健康的时候, 就会主动通知 Kubelet 此时如果这个设备处于空闲状态, Kubelet 就会将其挪出可分配列表; 如果该设备已经被某个 pod 使用, Kubelet 就会将该 Pod 杀掉
3. 插件启动后可以利用 Kubelet 的 socket 持续检查 Kubelet 的状态, 如果 Kubelet 重启, 插件也会相应的重启, 并且重新向 Kubelet 注册自己
部署方式
一般可以支持 daemonset 和非容器化的部署, 目前官方推荐使用 deamonset 部署
实现样例
Nvidia 的官方 GPU 插件
NVIDIA 提供了一个基于 Device Plugins 接口的 GPU 设备插件 NVIDIA/k8s-device-plugin, 从用户角度变得更加简单了比起传统的 alpha.kubernetes.io/nvidia-gpu, 不再需要使用 volumes 指定 CUDA 需要使用的库
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: tf-notebook
- labels:
- app: tf-notebook
- spec:
- template: # define the pods specifications
- metadata:
- labels:
- app: tf-notebook
- spec:
- containers:
- - name: tf-notebook
- image: tensorflow/tensorflow:1.4.1-gpu-py3
- resources:
- limits:
- nvidia.com/gpu: 1
Google GCP GPU 插件
GCP 也提供了一个 GPU 设备插件实现, 但是只支持运行在 Google Container Engine 的平台上, 可以通过 container-engine-accelerators 了解
Solarflare NIC 插件
网卡造商 Solarflare 也实现了自己的设备插件 sfc-device-plugin, 可以通过 demo 体验用户感受
总结
Kubernetes 的生态地位已经确立, 可扩展性将是其发力的主战场异构计算作为非常重要的新战场, Kubernetes 非常重视而异构计算需要强大的计算力和高性能网络, 需要提供一种统一的方式与 GPUFPGANICInfiniBand 等高性能硬件集成而 Device Plugin 是 Kubernetes 给出的答案, 还是非常简单优雅的, 虽然还在演进之中, 但是未来可期阿里云容器服务随后也会推出基于 device plugin 的 Kubernetes GPU 1.9.3 集群, 敬请期待
识别以下二维码, 阅读更多干货:
来源: http://geek.csdn.net/news/detail/256074