实验 1: 在线安装 HAMi
本实验将在一台 Google Cloud GPU 虚拟机上,从零搭建 Kubernetes 集群并在线安装 HAMi,形成完整的 GPU 虚拟化运行环境。
你将得到什么
完成本实验后,你将拥有一台完整的 GPU 虚拟化 Kubernetes 集群。关于集群架构和各组件职责的详细解释,参见 HAMi 集群架构。
安装全景图
整个安装过程分 6 步,每一步都在解决一个具体问题:
%% title: HAMi 安装全景图
flowchart LR
Step1["步骤1<br/>创建 GCP VM"] --> Step2["步骤2<br/>安装 Helm"]
Step2 --> Step3["步骤3<br/>安装 Kubernetes"]
Step3 --> Step4["步骤4<br/>安装 Prometheus"]
Step4 --> Step5["步骤5<br/>安装 GPU Operator"]
Step5 --> Step6["步骤6<br/>安装 HAMi"]
| 步骤 | 目的 | 解决什么问题 |
|---|---|---|
| 创建 GCP VM | 准备一台带 GPU 的 Linux 服务器 | Kubernetes 需要 GPU 硬件才能调度 GPU 工作负载 |
| 安装 Helm | Kubernetes 的包管理器 | 后续所有组件都通过 Helm 安装,类似 apt/yum |
| 安装 Kubernetes | 容器编排平台 | HAMi 运行在 Kubernetes 之上,所有 GPU 资源由 K8s 管理 |
| 安装 Prometheus | 监控系统 | HAMi 和 GPU Operator 依赖 Prometheus 采集和存储指标 |
| 安装 GPU Operator | NVIDIA GPU 软件栈自动化管理 | 自动安装 GPU 驱动、容器工具包、指标采集器等组件 |
| 安装 HAMi | GPU 虚拟化与共享 | 让多个 Pod 共享同一张 GPU,实现显存切分和算力分配 |
前提条件
- Google Cloud 账号,已启用 Compute Engine API
- 已安装
gcloudCLI 并完成认证(gcloud auth login) - GCP 配额中有 NVIDIA T4 GPU 可用
步骤 1: 创建 GCP 虚拟机
目的
创建一台带 GPU 的虚拟机,作为整个实验的基础环境。HAMi 需要物理 GPU 硬件(或直通虚拟 GPU)才能工作,,它不是模拟 GPU,而是在真实 GPU 之上做切分和共享。
操作
设置环境变量:
export PROJECT_ID=$(gcloud config get-value project)
export ZONE=us-central1-a
export VM_NAME=hami-workshop
export MACHINE_TYPE=n1-standard-4
export GPU_TYPE=nvidia-tesla-t4
export IMAGE_FAMILY=ubuntu-2204-lts
export IMAGE_PROJECT=ubuntu-os-cloud
export DISK_SIZE=100
创建虚拟机:
gcloud compute instances create ${VM_NAME} \
--project=${PROJECT_ID} \
--zone=${ZONE} \
--machine-type=${MACHINE_TYPE} \
--accelerator=type=${GPU_TYPE},count=1 \
--maintenance-policy=TERMINATE \
--image-family=${IMAGE_FAMILY} \
--image-project=${IMAGE_PROJECT} \
--boot-disk-size=${DISK_SIZE}GB \
--boot-disk-type=pd-ssd
--maintenance-policy=TERMINATE是必须的,,GPU 不支持在线迁移,如果 GCP 要维护宿主机,VM 会被终止而不是迁移。
SSH 登录:
gcloud compute ssh ${VM_NAME} --zone=${ZONE}
登录后切换到 root:
sudo su -
步骤 2: 安装 Helm
目的
Helm 是 Kubernetes 的包管理器,后续安装 Prometheus、GPU Operator、HAMi 都通过 Helm 完成。你可以把它理解成 Kubernetes 世界里的 apt 或 yum。
操作
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
验证:
helm version
步骤 3: 安装 Kubernetes
目的
HAMi 是 Kubernetes 上的 GPU 调度增强层,它以 Pod 形式运行在 Kubernetes 中。没有 Kubernetes,HAMi 没有运行的基础。
本步骤使用 kubeadm 搭建一个单节点集群。在单节点上,这个节点既是 Master(控制平面)也是 Worker(运行工作负载)。
操作
3.1 关闭 swap
Kubernetes 要求关闭 swap,因为 Kubernetes 的资源调度假设内存是固定的,swap 会导致性能不可预测。
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
3.2 加载内核模块
容器网络需要 overlay 和 br_netfilter 内核模块。overlay 用于容器文件系统层叠,br_netfilter 用于让 iptables 正确处理桥接流量。
cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
3.3 配置内核网络参数
这些参数确保容器之间的网络流量能被正确路由和转发。
cat <<EOF | tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
3.4 安装 containerd
containerd 是 Kubernetes 默认的容器运行时,负责真正创建和运行容器。Docker 在 Kubernetes 1.24 后已不再是默认运行时。
apt-get update
apt-get install -y containerd
mkdir -p /etc/containerd
containerd config default | tee /etc/containerd/config.toml
# 启用 systemd cgroup 驱动,Kubernetes 要求运行时和 kubelet 使用相同的 cgroup 驱动
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
systemctl restart containerd
systemctl enable containerd
3.5 安装 kubeadm、kubelet、kubectl
这三个工具的关系:
%% title: kubeadm, kubelet, kubectl 关系
flowchart LR
kubeadm["kubeadm<br/>集群初始化工具"] --> cluster["Kubernetes 集群"]
kubelet["kubelet<br/>节点代理<br/>每个节点上运行"] --> pods["管理 Pod 生命周期"]
kubectl["kubectl<br/>命令行客户端"] --> api["与 API Server 交互"]
- kubeadm:一次性工具,用来初始化集群
- kubelet:常驻进程,负责本节点上 Pod 的创建和销毁
- kubectl:日常运维使用的命令行工具
apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | \
gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | \
tee /etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
apt-mark hold防止这些包被自动升级,Kubernetes 组件版本需要手动控制。
3.6 初始化集群
kubeadm init --pod-network-cidr=10.244.0.0/16
初始化完成后,配置 kubectl 访问权限:
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
3.7 安装网络插件(Calico)
Pod 之间需要网络通信。Calico 是一个 CNI(Container Network Interface)插件,负责为 Pod 分配 IP 地址并处理网络路由。没有 CNI 插件,Pod 无法相互通信。
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/custom-resources.yaml
3.8 允许 Master 节点调度 Pod
单节点集群中,这个节点既是控制平面又是工作节点。默认情况下 Kubernetes 不会在 Master 节点上调度工作负载,需要手动移除这个限制:
kubectl taint nodes --all node-role.kubernetes.io/control-plane-
3.9 验证集群状态
kubectl get nodes
预期输出(STATUS 为 Ready 表示集群就绪):
NAME STATUS ROLES AGE VERSION
hami-workshop Ready control-plane 2m v1.31.x
步骤 4: 安装 Prometheus
目的
Prometheus 是集群监控系统,负责采集和存储所有组件的指标数据。HAMi 和 GPU Operator 都依赖 Prometheus,,HAMi 的调度器指标、设备插件指标、GPU 利用率指标都需要 Prometheus 来采集。
为什么先装 Prometheus
因为后续安装的 GPU Operator 和 HAMi 都会创建 ServiceMonitor(告诉 Prometheus 采集哪些指标)。如果 Prometheus 没准备好,这些 ServiceMonitor 就没有消费者。
操作
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/kube-prometheus-stack \
-n monitoring --create-namespace \
--set grafana.enabled=false \
--version=75.15.1
--set grafana.enabled=false禁用了 Grafana,因为后续 HAMi WebUI 会提供 GPU 可视化界面。
验证 Prometheus 组件状态:
kubectl get po -n monitoring
预期所有 Pod 状态为 Running:
NAME READY STATUS RESTARTS AGE
prometheus-kube-prometheus-operator-xxxxxxxxxx-xxxxx 1/1 Running 0 2m
prometheus-kube-state-metrics-xxxxxxxxxx-xxxxx 1/1 Running 0 2m
prometheus-prometheus-kube-prometheus-prometheus-0 2/2 Running 0 2m
prometheus-prometheus-node-exporter-xxxxx 1/1 Running 0 2m
如果安装失败,需要先卸载再重装:
helm uninstall -n monitoring prometheus
步骤 5: 安装 GPU Operator
目的
NVIDIA GPU Operator 自动管理 GPU 软件栈(驱动、容器工具包、指标采集、特征发现)。GPU Operator 各组件的详细说明参见 HAMi 集群架构。
关键: 必须禁用 GPU Operator 自带的 device-plugin(
--set devicePlugin.enabled=false),因为 HAMi 会提供自己的增强版 device-plugin 来支持显存切分和 GPU 共享。两者不能共存。
操作
helm repo add nvidia https://helm.ngc.nvidia.com/nvidia
helm repo update
helm install --wait --generate-name \
-n gpu-operator --create-namespace \
nvidia/gpu-operator \
--set devicePlugin.enabled=false \
--set dcgmExporter.serviceMonitor.enabled=true \
--version=v25.3.0
--wait参数会等待所有 Pod 就绪后才返回。首次安装需要几分钟下载 NVIDIA 驱动镜像。
等待所有 Pod 就绪:
kubectl get pods -n gpu-operator
预期输出:
NAME READY STATUS RESTARTS AGE
gpu-operator-xxxxxxxxxx-xxxxx 1/1 Running 0 5m
nvidia-container-toolkit-daemonset-xxxxx 1/1 Running 0 4m
nvidia-cuda-validator-xxxxx 0/1 Completed 0 3m
nvidia-dcgm-exporter-xxxxx 1/1 Running 0 4m
nvidia-driver-daemonset-xxxxx 1/1 Running 0 5m
nvidia-gpu-feature-discovery-xxxxx 1/1 Running 0 4m
nvidia-operator-validator-xxxxx 1/1 Running 0 3m
nvidia-cuda-validator状态为Completed是正常的,,它是一个一次性 Job,验证 CUDA 可用后退出。
验证 GPU 驱动
进入 nvidia-driver-daemonset Pod 验证 GPU 驱动是否正常加载(关于 nvidia-smi 背后的调用链,参见 理解 GPU 驱动):
kubectl -n gpu-operator exec -it $(kubectl get pods -n gpu-operator -l app=nvidia-driver-daemonset -o name | head -1) -- nvidia-smi
预期输出包含 GPU 信息(驱动版本、CUDA 版本、GPU 型号):
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.144.03 Driver Version: 550.144.03 CUDA Version: 12.4 |
|-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
|=========================================+========================+======================|
| 0 Tesla T4 On | 00000000:00:04.0 Off | Off |
| N/A 35C P8 10W / 70W | 2MiB / 15360MiB | 0% Default |
+-----------------------------------------------------------------------------------------+
步骤 6: 安装 HAMi
目的
安装 HAMi GPU 虚拟化平台,让多个 Pod 可以共享同一张 GPU。HAMi 的架构和组件说明参见 HAMi 集群架构。
操作
通过 Helm 仓库在线安装 HAMi 开源版:
# 添加 HAMi Helm 仓库
helm repo add hami-charts https://project-hami.github.io/HAMi/
# 安装 HAMi
helm install hami hami-charts/hami -n kube-system
HAMi 开源版安装在
kube-system命名空间中。安装完成后,HAMi 会自动检测带有 GPU 的节点并启动 device-plugin。
验证:
kubectl get pods -n kube-system | grep hami
预期输出:
hami-device-plugin-xxxxx 2/2 Running 0 2m
hami-scheduler-xxxxxxxxxx-xxxxx 1/1 Running 0 2m
开启 GPU 节点
HAMi 不会自动接管所有 GPU 节点,,需要手动标记哪些节点由 HAMi 管理。这种设计是为了让 HAMi 和非 HAMi 节点可以在同一个集群中共存。
# 获取节点名称
NODE_NAME=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
# 标记节点由 HAMi 管理
kubectl label nodes ${NODE_NAME} gpu=on
验证 GPU 注册信息:
kubectl get node ${NODE_NAME} -o jsonpath='{.metadata.annotations.ham\.io/node-nvidia-register}'
预期输出类似:
GPU-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx,10,15360,100,NVIDIA-Tesla T4,0,true,0:
这个 annotation 的格式是:
{设备 UUID},{切分数量},{显存上限 MB},{算力上限%},{GPU 型号},{NUMA},{健康状态},{序号}
其中 切分数量=10 表示这张 GPU 被虚拟化为 10 个 vGPU,可以被最多 10 个 Pod 共享。
(可选)安装 HAMi WebUI
HAMi WebUI 提供 GPU 资源的可视化管理界面:
helm repo add hami-webui https://project-hami.github.io/HAMi-WebUI
helm install my-hami-webui hami-webui/hami-webui \
--set externalPrometheus.enabled=true \
--set externalPrometheus.address="http://prometheus-kube-prometheus-prometheus.monitoring.svc.cluster.local:9090" \
--set dcgm-exporter.enabled=false \
-n kube-system
--set dcgm-exporter.enabled=false因为 GPU Operator 已经安装了 dcgm-exporter,避免重复部署。
通过端口转发访问 WebUI:
kubectl port-forward service/my-hami-webui 3000:3000 --namespace=kube-system
访问 http://localhost:3000 即可打开 HAMi WebUI。