HAMi 源码导读

跟着一个 Pod,走完它从 kubectl apply 到在 GPU 上跑起来的全过程。

版本 v2.10.0 commit 347502f Go 代码 28,000 行 代码块 214

为什么需要一条主线

HAMi 的代码量不大,核心逻辑只有几千行。难的是它由三个独立进程组成: 调度器扩展器、设备插件、容器里的 CUDA 劫持库。 主链路主要靠 Kubernetes 注解里的字符串传话;NUMA refit 是一个例外, 设备插件会直接请求调度器的 /refit 接口。

单独读任何一个组件,都会卡在「这个值是谁写进来的」。 所以这里的顺序不按目录结构走,而是按一个 Pod 实际经过的路径走。

用户提交一个要 GPU 的 Pod
limits: nvidia.com/gpu: 1, nvidia.com/gpumem: 3000
↓apiserver 准入
MutatingWebhook第 03 章
把 schedulerName 改成 hami-scheduler,补默认值,拦非法请求
↓kube-scheduler 调扩展器 HTTP
Filter:同时选节点和选卡第 04、05 章
重建各节点用量,并发打分,逐卡过 14 道筛选,最后把「用哪几张卡、各扣多少」写进 Pod 注解
↓POST /bind
Bind:抢节点锁再绑定第 06、07 章
锁一直持有到设备插件分配完,防止并发超卖
↓kubelet 调设备插件 gRPC
Allocate:注解翻译成环境变量第 08 章
注入 CUDA_DEVICE_MEMORY_LIMIT_0=3000m,挂载 libvgpu.so,释放节点锁
↓容器启动,ld.so.preload 生效
HAMi-core 在容器内拦 CUDA第 09 章
应用调 cuMemAlloc,超过 3000MB 返回 OOM;算力用令牌桶限速

目录

怎么读

每章的结构固定:先给一张源码地图,然后按执行顺序拆关键函数, 中间穿插可以直接操作的模拟器。 学习目标是可勾选的,勾完自动记进度,存在浏览器本地。

核心逻辑大多是纯内存函数,不需要 GPU,也不需要 Kubernetes 集群。 在 Linux 或 WSL2 下,打分、Fit 筛选、注解编解码都能用 go test 直接跑。 项目自带的表驱动用例(score_test.go 有 4600 行)比任何文档都完整, 改一个输入跑一次,比读十遍代码快。

建议按顺序读。第 01、02、05 章是主干,后面反复要用; 第 09、10 章第一遍看懂原理就行,等真要改那块时再回来。

源码链接的处理

所有 GitHub 链接和 文件:行号 引用都指向 commit 347502f(2026-09-03), 上游后续改动不会让链接跳错行。本地对照时先 git checkout 347502f。 换版本只需改 assets/js/site.js 顶部的 SOURCE, 换版本后行号会漂移,需要重新校对。

从 第 00 章 开始, 15 分钟把仓库跑起来,之后每一章的猜想都能当场验证。