实验 1A: mac 本地 Fake GPU 安装 HAMi
本实验将在 macOS 上使用 OrbStack 自带 Kubernetes 和 run-ai/fake-gpu-operator 搭建一个纯本地 Kubernetes 集群,然后在线安装 HAMi。
这个实验不需要真实 NVIDIA GPU,适合用于课堂预习、讲解 HAMi 组件组成、验证 GPU Pod 调度流程,以及在个人电脑上快速熟悉 HAMi 的基础使用方式。
你将得到什么
完成本实验后,你会得到一个本地 Kubernetes 集群:
- fake-gpu-operator 在 CPU 节点上模拟
nvidia.com/gpu资源 - HAMi scheduler、admission webhook 等控制面组件正常运行
- 普通 Pod 可以通过
nvidia.com/gpu申请模拟 GPU - 可以观察 fake GPU 资源从节点发现、Pod 申请、调度到运行的完整链路
注意:fake GPU 不能代表真实 GPU 的显存隔离、算 力隔离、CUDA 运行时和驱动能力。本实验用于理解 HAMi 组成和基础调度链路;涉及真实显存切分、
nvidia.com/gpumem、nvidia.com/gpucores、CUDA 程序运行和性能隔离时,仍需要真实 NVIDIA GPU 环境。
安装全景图
整个本地安装过程分 7 步:
| 步骤 | 目的 | 解决什么问题 |
|---|---|---|
| 确认本地环境 | 检查 OrbStack、kubectl、Helm | 确保 Kubernetes 集群可用 |
| 安装 fake-gpu-operator | 模拟 NVIDIA GPU 资源 | 让无 GPU 节点也能上报 nvidia.com/gpu |
| 安装 HAMi | 部署 HAMi 控制面 | 观察 HAMi scheduler、webhook 等组件 |
| 安装 Prometheus | 部署监控栈 | 采集 GPU 指标,给 HAMi WebUI 提供数据源 |
| 运行模拟 GPU 工作负载 | 验证调度链路 | 体验 Pod 申请 GPU 后被调度运行 |
| 安装 HAMi WebUI | 部署可视化管理界面 | 图形化查看 GPU 节点、资源分配和使用趋势 |
| 观察 HAMi 和 fake GPU | 理解组件职责边界 | 明确哪些能力需要真实 GPU |
前提条件
- macOS,Intel 或 Apple Silicon 均可
- 已安装 OrbStack 并启用内置 Kubernetes
- 能访问 GitHub、GHCR 和 HAMi Helm 仓库
- 本机至少 4 CPU、8 GB 内存可用于实验
为什么用 OrbStack? OrbStack 自带 Kubernetes(基于 k3s),无需额外安装 kind 或 Docker Desktop。资源占用更少,启动更快,macOS 上做本地实验首选。
步骤 1: 确认本地环境
先检查 Kubernetes 集群是否正常运行。
检查集群版本:
kubectl version
输出示例:
Client Version: v1.33.9
Kustomize Version: v5.6.0
Server Version: v1.33.9+orb1
Server Version中带有orb1后缀,说明这是 OrbStack 内置的 Kubernetes。Client 和 Server 版本一致即可。
查看集群节点:
kubectl get nodes -o wide
输出示例:
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
orbstack Ready control-plane,master 148d v1.33.9+orb1 192.168.139.2 <none> OrbStack 7.0.5-orbstack-00330-ge3df4e19b0a0-dirty docker://29.4.0
节点名称
orbstack,角色control-plane,master,这是单节点集群,同时充当控制面和工作节点。STATUS为Ready说明集群正常。
检查 Helm(后面安装 fake-gpu-operator 和 HAMi 都需要):
helm version
输出示例:
version.BuildInfo{Version:"v4.2.0", ...}
Helm 3.x 即可。如果 Helm 未安装,执行
brew install helm。
步骤 2: 安装 fake-gpu-operator
fake-gpu-operator 会在没有 NVIDIA GPU 的节点上模拟 GPU 资源,并把节点容量写成 nvidia.com/gpu。这一步替代了真实 GPU 环境中的 NVIDIA GPU Operator、驱动、device-plugin 和 DCGM 指标采集链路。
2.1 创建命名空间并设置安全策略
kubectl create namespace gpu-operator
kubectl label namespace gpu-operator pod-security.kubernetes.io/enforce=privileged
namespace/gpu-operator created
namespace/gpu-operator labeled
gpu-operator命名空间专门放 fake-gpu-operator 相关组件。privileged标签允许 Pod 以特权模式运行,fake-gpu-operator 的 device-plugin 需要访问宿主机设备文件。
2.2 给节点打标签
fake-gpu-operator 通过节点标签来决定在哪些节点上模拟 GPU:
NODE_NAME=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
kubectl label node ${NODE_NAME} run.ai/simulated-gpu-node-pool=default
node/orbstack labeled
标签
run.ai/simulated-gpu-node-pool=default告诉 fake-gpu-operator:"在这个节点上模拟 GPU"。这是 fake-gpu-operator 的节点选择器机制。
2.3 安装 fake-gpu-operator
export FAKE_GPU_OPERATOR_VERSION=0.0.80
helm upgrade -i gpu-operator \
oci://ghcr.io/run-ai/fake-gpu-operator/fake-gpu-operator \
--namespace gpu-operator \
--create-namespace \
--version ${FAKE_GPU_OPERATOR_VERSION}
Release "gpu-operator" does not exist. Installing it now.
Pulled: ghcr.io/run-ai/fake-gpu-operator/fake-gpu-operator:0.0.80
Digest: sha256:...
NAME: gpu-operator
LAST DEPLOYED: ...
NAMESPACE: gpu-operator
STATUS: deployed
REVISION: 1
TEST SUITE: None
helm upgrade -i= 如果 release 不存在则安装,存在则升 级。oci://前缀表示从 GitHub Container Registry 拉取 Helm Chart。0.0.80是 2026-04 发布的稳定版本。
2.4 等待组件运行
kubectl get pods -n gpu-operator
输出示例:
NAME READY STATUS RESTARTS AGE
device-plugin-l8m6j 1/1 Running 0 31m
kwok-gpu-device-plugin-5996cdf4f9-mfvpm 1/1 Running 0 31m
nvidia-dcgm-exporter-knfsn 1/1 Running 0 31m
nvidia-dcgm-exporter-kwok-b8fd4976-blb8c 1/1 Running 0 31m
status-updater-59965d7bc6-fbkmk 1/1 Running 0 31m
topology-server-9d57b6c79-7dv6h 1/1 Running 0 31m
各组件说明:
device-plugin:DaemonSet,在每个 GPU 节点上运行,向 Kubernetes 上报 GPU 资源kwok-gpu-device-plugin:用 KWOK(Kubernetes WithOut Kubelet)模拟 GPU 设备nvidia-dcgm-exporter:模拟 DCGM 指标导出(GPU 温度、利用率等)status-updater:更新节点 GPU 状态topology-server:管理 GPU 拓扑信息
如果所有 Pod 都 Running 且 READY 为 1/1,说明安装成功。
2.5 验证模拟 GPU 资源
检查节点是否上报了 GPU 容量:
kubectl get node ${NODE_NAME} \
-o custom-columns=NAME:.metadata.name,GPU:.status.capacity.nvidia\\.com/gpu
NAME GPU
orbstack 2
GPU列显示2,说明 fake-gpu-operator 已经在节点上模拟了 2 块 GPU。这个数字可以在 fake-gpu-operator 配置中调整。
进一步查看节点的 GPU 详细标签:
kubectl get node ${NODE_NAME} --show-labels | tr ',' '\n' | grep -E 'nvidia.com/gpu|run.ai'
nvidia.com/gpu.count=2
nvidia.com/gpu.deploy.dcgm-exporter=true
nvidia.com/gpu.deploy.device-plugin=true
nvidia.com/gpu.memory=11441
nvidia.com/gpu.present=true
nvidia.com/gpu.product=Tesla-K80
run.ai/fake.gpu=true
run.ai/simulated-gpu-node-pool=default
这些标签模拟了一台真实 GPU 节点的信息:
nvidia.com/gpu.count=2:模拟 2 块 GPUnvidia.com/gpu.product=Tesla-K80:模拟 GPU 型号为 Tesla K80nvidia.com/gpu.memory=11441:模拟每块 GPU 有 11441 MiB 显存run.ai/fake.gpu=true:标记这是模拟 GPU
如果 GPU 列为空,检查节点标签:
kubectl get node ${NODE_NAME} --show-labels | grep run.ai/simulated-gpu-node-pool
步骤 3: 安装 HAMi
本步骤安装 HAMi 的控制面组件:
hami-scheduler:调度增强组件,参与 GPU Pod 的调度决策- admission webhook:自动改写 GPU Pod 的调度器配置
- Helm release:统一管理 HAMi 相关 Kubernetes 资源
在 fake GPU 环境中,GPU 资源由 fake-gpu-operator 提供。为了避免两个 device-plugin 同时注册 nvidia.com/gpu,本实验不让 HAMi device-plugin 接管 fake 节点。
3.1 添加 HAMi Helm 仓库
helm repo add hami-charts https://project-hami.github.io/HAMi/
helm repo update
"hami-charts" has been added to your repositories
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "hami-charts" chart repository
Update Complete. ⎈Happy Helming!⎈
3.2 安装 HAMi
helm install hami hami-charts/hami \
-n kube-system \
--set devicePlugin.enabled=false
NAME: hami
LAST DEPLOYED: ...
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
--set devicePlugin.enabled=false是关键参数。因为 fake-gpu-operator 已经在管理 GPU 设备,如果 HAMi 的 device-plugin 也启动,两个组件会冲突。所以这里只安装 HAMi 的调度增强组件。
3.3 验证 HAMi 组件
kubectl get pods -n kube-system | grep hami
hami-scheduler-5d9678f989-dnf65 2/2 Running 0 28m
2/2表示这个 Pod 里有 2 个容器(scheduler 容器 + webhook 容器),都运行正常。
查看 HAMi 安装的控制面资源:
kubectl get deploy,svc,cm,sa -n kube-system | grep hami
deployment.apps/hami-scheduler 1/1 1 1 28m
service/hami-scheduler NodePort 192.168.194.156 <none> 443:31998/TCP,31993:31993/TCP 28m
configmap/hami-scheduler 1 28m
configmap/hami-scheduler-device 1 28m
serviceaccount/hami-scheduler 0 28m
各资源说明:
deployment.apps/hami-scheduler:HAMi 调度器 Deploymentservice/hami-scheduler:调度器 Service,NodePort类型,端口31998(webhook)和31993(调度)configmap/hami-scheduler:调度器配置configmap/hami-scheduler-device:设备配置serviceaccount/hami-scheduler:调度器使用的服务账号
3.4 确认所有 Helm Release
helm list -A
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
gpu-operator gpu-operator 1 2026-05-21 16:12:01.872099 +0800 CST deployed fake-gpu-operator-0.0.80 0.0.80
hami kube-system 1 2026-05-21 16:15:24.295479 +0800 CST deployed hami-2.9.0 2.9.0
两个 Helm Release 都
deployed。gpu-operator在gpu-operator命名空间,hami在kube-system命名空间。
步骤 4: 安装 Prometheus
HAMi WebUI 需要从 Prometheus 读取 GPU 指标数据。本步骤使用 kube-prometheus-stack 部署完整的监控栈。
为什么要装 Prometheus? HAMi WebUI 的集群概览、GPU 利用率、显存使用率等图表数据全部来自 Prometheus。没有 Prometheus,WebUI 只能显示空白页面。
4.1 添加 Helm 仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
4.2 安装 kube-prometheus-stack
helm install prometheus prometheus-community/kube-prometheus-stack \
-n monitoring --create-namespace \
--set grafana.enabled=false \
--version=75.15.1
NAME: prometheus
LAST DEPLOYED: ...
NAMESPACE: monitoring
STATUS: deployed
REVISION: 1
--set grafana.enabled=false:不安装 Grafana,本实验只用 Prometheus 作为 HAMi WebUI 的数据源。如果你需要 Grafana 做更丰富的可视化,可以去掉这个参数。
4.3 等待 Prometheus 就绪
kubectl get pods -n monitoring
输出示例:
NAME READY STATUS RESTARTS AGE
alertmanager-prometheus-kube-prometheus-alertmanager-0 2/2 Running 0 2m
prometheus-kube-prometheus-operator-d89fb8945-htjjd 1/1 Running 0 2m
prometheus-kube-state-metrics-7f5f75c85d-mbsbh 1/1 Running 0 2m
prometheus-prometheus-kube-prometheus-prometheus-0 2/2 Running 0 2m
prometheus-prometheus-node-exporter-77pxd 1/1 Running 0 2m
所有 Pod
Running即可。其中prometheus-prometheus-kube-prometheus-prometheus-0是核心 Prometheus 实例。
4.4 创建 ServiceMonitor 采集 GPU 指标
kube-prometheus-stack 自带的 ServiceMonitor 不包含 fake-gpu-operator 的 GPU 指标。需要手动创建:
kubectl apply -f - <<'EOF'
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: nvidia-dcgm-exporter
namespace: gpu-operator
labels:
release: prometheus
spec:
selector:
matchLabels:
app: nvidia-dcgm-exporter
namespaceSelector:
matchNames:
- gpu-operator
endpoints:
- port: gpu-metrics
path: /metrics
interval: 15s
EOF
servicemonitor.monitoring.coreos.com/nvidia-dcgm-exporter created
ServiceMonitor 告诉 Prometheus:"去
gpu-operator命名空间找 label 为app: nvidia-dcgm-exporter的 Service,从它的gpu-metrics端口每 15 秒采集一次/metrics"。release: prometheuslabel 是 kube-prometheus-stack 的 ServiceMonitor 选择器要求的。
等待约 30 秒后验证 GPU 指标已采集:
kubectl exec -n monitoring prometheus-prometheus-kube-prometheus-prometheus-0 -- \
promtool query instant http://localhost:9090 'DCGM_FI_DEV_GPU_UTIL'
DCGM_FI_DEV_GPU_UTIL{..., device="nvidia1", ..., modelName="Tesla-K80", ...} => 0
DCGM_FI_DEV_GPU_UTIL{..., device="nvidia0", ..., modelName="Tesla-K80", ...} => 0
看到
DCGM_FI_DEV_GPU_UTIL数据说明 Prometheus 已经在采集 fake GPU 指标了。利用率为 0 是正常的,当前没有真实 GPU 计算任务在运行。
步骤 5: 运行模拟 GPU 工作负载
验证 Kubernetes 可以把申请 nvidia.com/gpu 的 Pod 调度到 fake GPU 节点。fake-gpu-operator 会为 GPU Pod 注入模拟 nvidia-smi 工具,便于观察 GPU 可见性。
由于本实验没有启 用 HAMi device-plugin,HAMi 不会写入真实环境中的 hami.io/node-nvidia-register 节点注册信息。因此测试 Pod 会显式绕过 HAMi webhook,使用 Kubernetes 默认调度器和 fake-gpu-operator 提供的模拟 GPU 资源。
5.1 创建测试 Pod
先看一下 Pod YAML:
apiVersion: v1
kind: Pod
metadata:
name: fake-gpu-pod
labels:
hami.io/webhook: ignore
annotations:
run.ai/simulated-gpu-utilization: "10-30"
spec:
restartPolicy: Never
containers:
- name: app
image: ubuntu:22.04
command: [ "bash", "-lc", "sleep 3600" ]
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
nvidia.com/gpu: 1
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
YAML 要点:
hami.io/webhook: ignore标签:告诉 HAMi webhook 不要拦截这个 Pod,使用默认调度器run.ai/simulated-gpu-utilization: "10-30"注解:fake-gpu-operator 会让nvidia-smi报告 10%-30% 的 GPU 利用率resources.limits.nvidia.com/gpu: 1:申请 1 块 GPUsleep 3600:让容器保持运行 1 小时,方便我们进入容器观察
创建 Pod:
kubectl apply -f fake-gpu-pod.yaml
pod/fake-gpu-pod created
5.2 等待 Pod 运行
kubectl get pod fake-gpu-pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
fake-gpu-pod 1/1 Running 0 7m 192.168.194.22 orbstack <none> <none>
STATUS为Running,NODE为orbstack,说明 Pod 成功调度到本地节点。如果第一次拉取ubuntu:22.04镜像,可能需要几十秒。
5.3 查看 Pod 的 GPU 资源申请
kubectl describe pod fake-gpu-pod | grep -A6 "Limits"
Limits:
nvidia.com/gpu: 1
Requests:
nvidia.com/gpu: 1
Environment:
NODE_NAME: (v1:spec.nodeName)
Limits和Requests都是nvidia.com/gpu: 1,说明这个 Pod 申请了 1 块 GPU。Kubernetes 只在 requests 和 limits 都设置了nvidia.com/gpu时才会把 Pod 调度到有 GPU 的节点。
5.4 查看节点的 GPU 资源分配情况
kubectl describe node ${NODE_NAME} | grep -A10 "Allocated resources"
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 750m (7%) 1700m (17%)
memory 870Mi (10%) 1996Mi (24%)
ephemeral-storage 0 (0%) 0 (0%)
nvidia.com/gpu 1 1
nvidia.com/gpu列显示 Requests 和 Limits 都是1