♦️HAMI 与Device Plugin
type
status
date
slug
summary
tags
category
icon
password
Blocked by
Blocking
AI summary
Architecture

23年是AI元年,异构芯片增长迅猛,除了NV,市面上还有寒武纪、海光、天数、华为的ascend等AI设备,异构算力对企业的调度造成了困扰,而HAMI在调度层面,实现GPU的调度和管理,实现异构算力的融合。
Features
- 在K8s上共享GPU
- 容器内资源的隔离
- 高级的调度能力,设备类型UUID
- 共享任务设置优先级
- 灵活的调度策略, binpack & spread
- 动态注册节点上的卡

binpack & spread 调度策略
binpack调度策略
优先调度到一张GPU卡,避免共享业务造成的GPU资源碎片
spread调度策略
共享业务员分散到节点的不同GPU卡,降低故障影响,实现负载均衡,避免某些卡空间空闲的情况
算力是可以压缩的;显存不能压缩,这时用内存替代
Device Plugin
CPU 和内存等常规资源是由 Kubernetes 的节点组件 Kubelet 直接上报的。而被标准资源,如GPU、FGGA这些资源,是由device plugin 来实现资源的上报。
常规资源的数据采集具体流程
- Kubelet 会从节点本地的操作系统中收集资源使用情况:
- CPU:读取
/proc/stat
文件,或者通过系统调用获取 CPU 核心数量、使用率等信息。 - 内存:读取
/proc/meminfo
文件,获取内存的总量和可用量。 - 存储:通过文件系统 API 获取磁盘容量和使用情况。
- 网络:读取网络接口统计信息。
- 容器层的资源监控:
- 对于运行中的 Pod,Kubelet 会通过容器运行时接口(CRI)和 cgroup(控制组)收集容器的 CPU 和内存资源使用情况。
- 它会将这些资源限制、使用信息与 Pod/容器绑定,定期上报给 API Server。
- 上报到 API Server:
- Kubelet 将节点的资源总量(如 CPU 总核数、内存总大小)和使用情况通过心跳(
NodeStatus
)上报给 Kubernetes 的 API Server。 - API Server 将这些信息存储在
Node
对象的status.capacity
和status.allocatable
字段中。
Device Plugin 的作用范围
Device Plugin 仅负责非标准资源的上报,例如:
- GPU(
nvidia.com/gpu
)
- FPGA(
xilinx.com/fpga
)
- TPU(
google.com/tpu
)
- 自定义设备(
example.com/custom-device
)
GPU 上报的核心接口
ListAndWatch
:向 Kubelet 上报 GPU 列表和状态,是 GPU 发现的核心接口。
Allocate
:在容器创建时分配 GPU,是 GPU 使用的核心接口
DevicePluginServer
的grpc接口设备分配等整体流程
- 注册:Device Plugin 启动后,通过grpc注册到kubelet中
- 设备发现:通过
ListenAndWatch
,持续上报GPU状态
- 设备分配:当pod请求GPU资源时,kubelet调用
Allocate
分配设备
- 优化分配:通过
GetPreferredAllocation
提供分配建议
- 与启动:在容器启动前
PreStartContainer
完成设别初始化
HAMI 调度器和Device Plugin 协作流程
设如备注册
- device plugin 开启grpc server
- 将 resourceNmae 注册到 kubelet中
device plugin 实现
DevicePluginServer
的grpc接口设备插件在注册设备时,会实现
ListAndWatch
方法。这个方法是设备插件与 kubelet
之间的通信机制之一,用于向 Kubernetes 报告节点上可用的设备资源。在 ListAndWatch
方法中,设备插件会列出节点上所有可用设备的数量和相关资源名称这时,node状态可能为这样
- 注册
MutatingWebhookConfiguration
创建一个 需要gpu的pod
- 当pod创建后,如果MutatingWebhookConfiguration有配置xxx资源有被limit的资源包含,那么就运行 yyy mutating webhhok,这个webhoook把pod的
schedulerName
修改为hami-scheduler
- 此时调度器变成了 HAMI,经过
HAMI
决策后(具体的部署策略 binpack+spread)+filter+score,得到一个最优解,比如选择了 node1,将nodeName
设置为node1
- kubelet准备向准备创建容器,申请资源,调用设备插件的
Allocate
方法,设备插件根据 Pod 请求的资源(例如 GPU)分配设备,并返回设备信息
Kubelet 会使用设备插件返回的这些信息,在容器启动时为容器挂载设备,并设置环境变量。具体步骤如下:
- 环境变量设置:Kubelet 会将设备插件返回的环境变量传递给容器,容器内的应用程序可以读取这些环境变量来识别可用的设备资源。
- 设备挂载:Kubelet 根据
AllocateResponse
中提供的挂载信息,将设备路径(如/dev/nvidia0
)挂载到容器内的相应位置(例如/dev/nvidia0
),确保容器可以访问物理设备。
- 启动容器:在容器启动时,设备插件已分配的设备资源将准备就绪,容器的应用程序可以通过这些挂载点和环境变量来访问硬件设备
总结
- pod使用哪一个节点的GPU,这是由HAMI调度器决策的
- device plugin 通过
ListAndWatch
完成资源的上报和状态的同步
- kubelet 通过Allocate grpc方法,尝试给pod分配gpu资源,返回一些包含设备挂载点的env环境变量
- 完成pod与node绑定,后续的容器启动,这是kubelet干的活了,后续pod就能安心使用GPU资源了
具体的一个pod是如何用到gpu卡的?
NVIDIA Container Toolkit 的主要作用是将 NVIDIA GPU 设备挂载到容器中

- pod指定资源的gpu卡
- scheduler进行调度,选择一个最优的节点,调用devide_plugin 的allocate方法,分配一个卡给pod,将卡的信息写入pod的环境变量中
- containerd启动容器,由于配置了 nvidia-container-runtime,所以会调用nvidia-container-shim来为这个pod增加一个hook
- runc执行时,首先执行prestart-hook,其中就会包含nvidia-container-hook
- 从容器 Spec 的 mounts 或者 env 中解析 GPU 信息
- 调用
nvidia-container-cli
命令,将 NVIDIA 的 GPU Driver、CUDA Driver 等库文件挂载进容器,保证容器内可以使用被指定的 GPU以及对应能力
ref
- HAMI GitHub repo
- k8s device plugin doc
- kubecon HAMI
- kubevirt-gpu-plugin
- matrixdc-device-HAMI
- Pod 是如何使用到 GPU 的
Prev
CKA ✅
Next
从0到1,利用kubevirt构建ubuntu虚拟机
Loading...