diff --git a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/gpu-partitioning.md b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/gpu-partitioning.md index 9a1dd2f3..87bdc606 100644 --- a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/gpu-partitioning.md +++ b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/gpu-partitioning.md @@ -137,7 +137,7 @@ kubectl exec gpumem-pod-a -- nvidia-smi +-----------------------------------------+------------------------+----------------------+ ``` -> **`0MiB / 4000MiB`**:容器看到的是一块 4000 MiB 的 GPU,而不是物理的 15360 MiB。这是 HAMi-core 的核心能力——一个通过 `LD_PRELOAD` 注入到容器中的库,它拦截 CUDA 和 NVML 调用并重写内存数值。另一个 Pod 在同一张物理卡上看到的是独立的 4000 MiB 上限。 +> **`0MiB / 4000MiB`**:容器看到的是一块 4000 MiB 的 GPU,而不是物理的 15360 MiB。这是 HAMi-core 的核心能力:一个通过 `LD_PRELOAD` 注入到容器中的库,它拦截 CUDA 和 NVML 调用并重写内存数值。另一个 Pod 在同一张物理卡上看到的是独立的 4000 MiB 上限。 ## 步骤 4: 通过 OOM 测试验证显存隔离 @@ -297,7 +297,7 @@ kubectl exec -n monitoring prometheus-prometheus-kube-prometheus-prometheus-0 -c > - **default**(默认):Pod 可以在 GPU 空闲时突破 `gpucores` 份额。有利于提高利用率,隔离较宽松。 > - **force**(`GPU_CORE_UTILIZATION_POLICY=force`):始终严格限制,如上测量所示。适合需要可预测性能隔离的场景。 > -> 如果不设置 `force` 环境变量,你会看到同样的工作负载在空闲卡上以 100% 利用率运行——这是设计如此:HAMi 会将空闲容量分配出去,而不是浪费它。 +> 如果不设置 `force` 环境变量,你会看到同样的工作负载在空闲卡上以 100% 利用率运行,这是设计如此:HAMi 会将空闲容量分配出去,而不是浪费它。 ## 步骤 6: 清理 diff --git a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/hami-dra.md b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/hami-dra.md index cf70c721..0bcf13bc 100644 --- a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/hami-dra.md +++ b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/hami-dra.md @@ -22,7 +22,7 @@ HAMi DRA 驱动尚处于快速发展阶段。本实验安装的是已在 Tesla T ::: -在 [实验 3](./gpu-partitioning.md) 中,你使用 HAMi 的扩展资源(`nvidia.com/gpumem`、`nvidia.com/gpucores`)对 GPU 进行了切片。本实验通过**动态资源分配(Dynamic Resource Allocation,DRA)**实现相同的效果——这是在 v1.34 中正式发布(GA)的 Kubernetes 原生设备 API。Pod 不再使用不透明的资源名称,而是通过 `ResourceClaim` 以结构化的、经过 Schema 验证的容量请求来申请设备。 +在 [实验 3](./gpu-partitioning.md) 中,你使用 HAMi 的扩展资源(`nvidia.com/gpumem`、`nvidia.com/gpucores`)对 GPU 进行了切片。本实验通过**动态资源分配(Dynamic Resource Allocation,DRA)**实现相同的效果,这是在 v1.34 中正式发布(GA)的 Kubernetes 原生设备 API。Pod 不再使用不透明的资源名称,而是通过 `ResourceClaim` 以结构化的、经过 Schema 验证的容量请求来申请设备。 ## 为什么 DRA 很重要 @@ -285,5 +285,5 @@ kubectl delete deviceclass hami-core-gpu.project-hami.io - 在同一集群上运行[实验 3](./gpu-partitioning.md),并排比较两种分配路径:扩展资源目前可在任何 Kubernetes 版本上使用,而 DRA 则提供了类型化设备选择、Schema 验证的容量请求以及原生调度器记账。 - 尝试修改 Claim:在 `setup.yaml` 中更改 `cores` 和 `memory`,请求超过设备剩余容量的值,观察 Claim 保持 `pending` 而非过度分配。 -- 在多 GPU 节点上,尝试 `double-gpu-0` Claim:它在单个 Claim 中请求两个具有不同容量的设备——这是扩展资源无法表达的。 +- 在多 GPU 节点上,尝试 `double-gpu-0` Claim:它在单个 Claim 中请求两个具有不同容量的设备,这是扩展资源无法表达的。 - 驱动仓库现已提供 Helm Chart(`chart/hami-dra-driver`);关注 [HAMi DRA 驱动发布](https://github.com/Project-HAMi/k8s-dra-driver/releases)了解本实验何时切换到 Chart,以及 [HAMi v2.10 路线图](https://github.com/Project-HAMi/HAMi/issues/1889)了解 DRA 支持的下一步计划。 diff --git a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/hami-isolation-k3s.md b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/hami-isolation-k3s.md index ef70a170..c362bfe6 100644 --- a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/hami-isolation-k3s.md +++ b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/hami-isolation-k3s.md @@ -18,11 +18,11 @@ toc_max_heading_level: 2 本实验在租用的 GPU 虚拟机上搭建单节点 k3s 集群,**不安装** NVIDIA GPU Operator 直接安装 HAMi,并证明 HAMi 的显存隔离是真实生效的:两个 Pod 共享一张物理显卡,每个 Pod 内的 `nvidia-smi` 只报告自己的切片大小,超出切片的 CUDA 分配会被 HAMi-core 拒绝(此时显卡上仍有几十 GB 空闲显存),而一个会导致超额分配的第三个 Pod 则保持 `Pending` 状态。 -本实验中的每条命令和输出均采集自 GCP `g4-standard-48` Spot 虚拟机上的真实运行(一张 96 GB NVIDIA RTX PRO 6000 Blackwell,单节点 k3s v1.36.2+k3s1、HAMi v2.9.0、NVIDIA 驱动 610.43.02、Ubuntu 22.04)。任何非 MIG 显卡的行为相同;只需调整切片大小(随显存容量缩放)。RTX PRO 6000 Blackwell 支持 MIG,但出厂默认禁用——本实验验证的正是 HAMi 的软件共享。 +本实验中的每条命令和输出均采集自 GCP `g4-standard-48` Spot 虚拟机上的真实运行(一张 96 GB NVIDIA RTX PRO 6000 Blackwell,单节点 k3s v1.36.2+k3s1、HAMi v2.9.0、NVIDIA 驱动 610.43.02、Ubuntu 22.04)。任何非 MIG 显卡的行为相同;只需调整切片大小(随显存容量缩放)。RTX PRO 6000 Blackwell 支持 MIG,但出厂默认禁用,本实验验证的正是 HAMi 的软件共享。 ## 与实验 3 的区别 -[实验 3](./gpu-partitioning.md) 在由 **GPU Operator** 提供驱动和容器工具包、HAMi 设备插件叠加其上的集群中证明了相同的隔离特性。本实验走另一条受支持的路径:**完全不使用 GPU Operator**。HAMi 自带设备插件,NVIDIA Container Toolkit 直接安装在主机上,并将 `nvidia` 设为 containerd 的**默认**运行时,使 HAMi-core 被注入到每个 GPU Pod 中。这是在边缘节点、裸金属机器或廉价租用 GPU 虚拟机上会采用的更精简的部署方式——并且它能直接展示 Operator 路径所隐藏的底层机制(步骤 7)。 +[实验 3](./gpu-partitioning.md) 在由 **GPU Operator** 提供驱动和容器工具包、HAMi 设备插件叠加其上的集群中证明了相同的隔离特性。本实验走另一条受支持的路径:**完全不使用 GPU Operator**。HAMi 自带设备插件,NVIDIA Container Toolkit 直接安装在主机上,并将 `nvidia` 设为 containerd 的**默认**运行时,使 HAMi-core 被注入到每个 GPU Pod 中。这是在边缘节点、裸金属机器或廉价租用 GPU 虚拟机上会采用的更精简的部署方式,并且它能直接展示 Operator 路径所隐藏的底层机制(步骤 7)。 ## 你将学到什么 @@ -51,18 +51,18 @@ flowchart LR - 一台全新的云虚拟机(Ubuntu 22.04 或更高版本),配备**一张 NVIDIA GPU** 并具有 root 权限。目标是任意未启用 MIG 的显卡:RTX PRO 6000、RTX A6000、L4、L40/L40S、RTX 4090/3090。对无法(或没有)通过 MIG 分区的显卡进行切分正是 HAMi 的核心使用场景。 - 主机上的 NVIDIA 驱动可正常工作(`nvidia-smi` 执行成功)。大多数 GPU 虚拟机镜像已内置驱动。 - 你能控制容器运行时:无法重新配置的受限市场容器不可用,因为 HAMi-core 是通过 NVIDIA 容器运行时注入的。 -- 所有操作**通过 SSH 在虚拟机上**执行——helm 和 kubectl 通过 localhost 与 k3s 通信,避免不稳定的远程链路。 +- 所有操作**通过 SSH 在虚拟机上**执行:helm 和 kubectl 通过 localhost 与 k3s 通信,避免不稳定的远程链路。 - 来自 [`tutorials/labs/examples/07-hami-isolation-k3s/`](https://github.com/Project-HAMi/website/tree/master/tutorials/labs/examples/07-hami-isolation-k3s) 的清单文件 :::note[费用] -一次完整的实验会话远低于一小时 GPU 时间。非 MIG 显卡的按需租用价格通常低于每小时 1 美元。GPU 资源紧张——你想要的那张卡经常缺货;选用任何可用的非 MIG 显卡并调整切片大小即可(清单文件中只需改一行)。 +一次完整的实验会话远低于一小时 GPU 时间。非 MIG 显卡的按需租用价格通常低于每小时 1 美元。GPU 资源紧张:你想要的那张卡经常缺货;选用任何可用的非 MIG 显卡并调整切片大小即可(清单文件中只需改一行)。 ::: :::warning[不要安装 GPU Operator] -HAMi 自带设备插件,[不能与 NVIDIA 官方设备插件共存](https://project-hami.io/docs/installation/prerequisites)。GPU Operator + HAMi 的集成没有官方文档支持([HAMi #1708](https://github.com/Project-HAMi/HAMi/issues/1708))。如果你的集群已经运行了 Operator,请改用实验 3 的路径——或为本实验使用一台全新的虚拟机。 +HAMi 自带设备插件,[不能与 NVIDIA 官方设备插件共存](https://project-hami.io/docs/installation/prerequisites)。GPU Operator + HAMi 的集成没有官方文档支持([HAMi #1708](https://github.com/Project-HAMi/HAMi/issues/1708))。如果你的集群已经运行了 Operator,请改用实验 3 的路径,或为本实验使用一台全新的虚拟机。 ::: @@ -78,7 +78,7 @@ nvidia-smi -L GPU 0: NVIDIA RTX PRO 6000 Blackwell Server Edition (UUID: GPU-3c4a3856-fbb4-1425-9679-aed25f4d2977) ``` -> 一张显卡,主机可见。如果 `nvidia-smi` 失败,请按照 [NVIDIA 驱动安装指南](https://docs.nvidia.com/datacenter/tesla/driver-installation-guide/)安装驱动后重试。在全新的 Ubuntu 虚拟机上,这意味着添加 NVIDIA CUDA apt 仓库并执行 `apt-get install nvidia-open`——Blackwell 一代显卡需要**开源**内核模块(驱动 ≥ 570);使用闭源模块时 `nvidia-smi` 会报 `No devices found`。 +> 一张显卡,主机可见。如果 `nvidia-smi` 失败,请按照 [NVIDIA 驱动安装指南](https://docs.nvidia.com/datacenter/tesla/driver-installation-guide/)安装驱动后重试。在全新的 Ubuntu 虚拟机上,这意味着添加 NVIDIA CUDA apt 仓库并执行 `apt-get install nvidia-open`:Blackwell 一代显卡需要**开源**内核模块(驱动 ≥ 570);使用闭源模块时 `nvidia-smi` 会报 `No devices found`。 ## 步骤 2: 先安装 Container Toolkit,再安装 k3s @@ -121,11 +121,11 @@ nvidia nvidia 55s node/hami-lab-rtx6000 labeled ``` -> 当工具包在 k3s 安装时已存在,k3s 会在其 containerd 配置中写入 `nvidia` RuntimeClass。如果缺失,重启 k3s(`systemctl restart k3s`)——参见 [k3s NVIDIA 运行时支持](https://docs.k3s.io/advanced#nvidia-container-runtime-support)。HAMi 的设备插件会调度到带有 `gpu=on` 标签的节点上。 +> 当工具包在 k3s 安装时已存在,k3s 会在其 containerd 配置中写入 `nvidia` RuntimeClass。如果缺失,重启 k3s(`systemctl restart k3s`),参见 [k3s NVIDIA 运行时支持](https://docs.k3s.io/advanced#nvidia-container-runtime-support)。HAMi 的设备插件会调度到带有 `gpu=on` 标签的节点上。 ## 步骤 3: 将 nvidia 设为 containerd 的默认运行时 -HAMi 的 Pod 不设置 `runtimeClassName`,因此只有当**默认**运行时是 `nvidia` 时,HAMi-core 才会被注入。使用 k3s 自带的 `default-runtime` 选项——这是与 containerd 配置模式无关的干净做法。**不要**手动编辑 `config.toml`:v2 和 v3 的模式不同,重复声明已有的表会直接破坏 k3s。 +HAMi 的 Pod 不设置 `runtimeClassName`,因此只有当**默认**运行时是 `nvidia` 时,HAMi-core 才会被注入。使用 k3s 自带的 `default-runtime` 选项,这是与 containerd 配置模式无关的干净做法。**不要**手动编辑 `config.toml`:v2 和 v3 的模式不同,重复声明已有的表会直接破坏 k3s。 ```bash echo 'default-runtime: nvidia' >> /etc/rancher/k3s/config.yaml @@ -146,7 +146,7 @@ default_runtime_name = "nvidia" ## 步骤 4: 安装 HAMi -HAMi 调度器运行一个 kube-scheduler sidecar,其镜像标签必须与集群 Kubernetes **服务端**版本匹配——版本不匹配是最常见的 HAMi 安装失败原因。先检测版本: +HAMi 调度器运行一个 kube-scheduler sidecar,其镜像标签必须与集群 Kubernetes **服务端**版本匹配,版本不匹配是最常见的 HAMi 安装失败原因。先检测版本: ```bash kubectl version | grep Server @@ -174,7 +174,7 @@ hami-device-plugin-62ck6 2/2 Running 0 38s hami-scheduler-5f5b5589c9-zhgsc 2/2 Running 0 38s ``` -> 与实验 2(禁用设备插件)不同,此处 **HAMi 设备插件正常运行**——它是集群上唯一的设备插件,独占这张 GPU。 +> 与实验 2(禁用设备插件)不同,此处 **HAMi 设备插件正常运行**,它是集群上唯一的设备插件,独占这张 GPU。 验证 HAMi 已注册显卡: @@ -190,12 +190,12 @@ kubectl get node hami-lab-rtx6000 -o jsonpath='{.metadata.annotations.hami\.io/n > 有两点值得牢记: > -> - `nvidia.com/gpu` 的 allocatable 值是 `10`——一张物理 GPU × `deviceSplitCount`(默认 10),即可以共享这张卡的 Pod 数量上限。 +> - `nvidia.com/gpu` 的 allocatable 值是 `10`:一张物理 GPU × `deviceSplitCount`(默认 10),即可以共享这张卡的 Pod 数量上限。 > - 可共享的显存(`devmem: 97887` MiB)记录在 `hami.io/node-nvidia-register` 注解中,**而非**节点 allocatable。`kubectl describe node` 中不会出现 `nvidia.com/gpumem`;HAMi 调度器和 webhook 依据该注解核算 `gpumem`/`gpucores`,由 HAMi-core 按 Pod 强制执行。 ## 步骤 5: 两个 Pod 共享一张物理 GPU -`share-two-pods.yaml` 运行两个 Pod,每个请求一张 GPU 和 8000 MiB 的切片——原生 Kubernetes 做不到这一点(它会把整张卡分配给一个 Pod): +`share-two-pods.yaml` 运行两个 Pod,每个请求一张 GPU 和 8000 MiB 的切片,原生 Kubernetes 做不到这一点(它会把整张卡分配给一个 Pod): ```yaml apiVersion: v1 @@ -266,7 +266,7 @@ Tue Jul 7 10:25:15 2026 +-----------------------------------------+------------------------+----------------------+ ``` -> Memory 列显示 **8000MiB**,而不是显卡真实的 97887MiB。HAMi-core 重写了容器看到的显卡容量。注意 `MIG M.: Disabled`——这里的共享是 HAMi 的软件切片,而非硬件分区。 +> Memory 列显示 **8000MiB**,而不是显卡真实的 97887MiB。HAMi-core 重写了容器看到的显卡容量。注意 `MIG M.: Disabled`,这里的共享是 HAMi 的软件切片,而非硬件分区。 其次,上限真的守得住吗?编译并运行一个每次 `cudaMalloc` 256 MiB、直到被拒绝为止的小型分配器: @@ -298,9 +298,9 @@ cudaMalloc refused after 7424 MiB allocated: out of memory [HAMI-core ERROR (pid:54 thread=133390658244608 allocator.c:52)]: Device 0 OOM 8629780480 / 8388608000 ``` -> 这就是证明,而且是一个矛盾:Pod 在约 7.4 GB 处触发 "out of memory",而物理显卡上还有约 82 GB 空闲。拒绝来自 **HAMI-core**(见错误行:它试图使用 8629780480 字节,超过了 8388608000 字节的限制——8388608000 字节恰好是 8000 MiB),而非硬件。只有拦截 CUDA 调用的软件上限才能做到这一点。表述时应说"超出切片的分配会被拒绝"——精确边界取决于分配器和 CUDA 上下文开销,不要断言确切的字节数。可以对 `hami-share-b` 重复此操作;行为完全一致。 +> 这就是证明,而且是一个矛盾:Pod 在约 7.4 GB 处触发 "out of memory",而物理显卡上还有约 82 GB 空闲。拒绝来自 **HAMI-core**(见错误行:它试图使用 8629780480 字节,超过了 8388608000 字节的限制,8388608000 字节恰好是 8000 MiB),而非硬件。只有拦截 CUDA 调用的软件上限才能做到这一点。表述时应说"超出切片的分配会被拒绝",精确边界取决于分配器和 CUDA 上下文开销,不要断言确切的字节数。可以对 `hami-share-b` 重复此操作;行为完全一致。 -现在证明显卡的显存是一个共享的、有限的预算。`oversubscribe-pending.yaml` 请求一个 90000 MiB 的切片——空的 96 GB 卡放得下,但在已有两个 8000 MiB 切片的情况下放不下(97887 − 16000 ≈ 82000 MiB 空闲): +现在证明显卡的显存是一个共享的、有限的预算。`oversubscribe-pending.yaml` 请求一个 90000 MiB 的切片,空的 96 GB 卡放得下,但在已有两个 8000 MiB 切片的情况下放不下(97887 − 16000 ≈ 82000 MiB 空闲): ```bash kubectl apply -f oversubscribe-pending.yaml @@ -319,7 +319,7 @@ Events: Warning FilteringFailed 16s (x2 over 16s) hami-scheduler 1 nodes CardInsufficientMemory(hami-lab-rtx6000) ``` -> `Pending` 且事件为 `CardInsufficientMemory`——与步骤 5 形成对比,同一个调度器在那里记录的是 `FilteringSucceed`。有两点必须正确,否则这个测试会"失败"(被调度而不是保持 Pending):请求大小必须适配**你的**显卡(大于切片旁的剩余空间、小于整张卡——见清单注释),并且两个共享 Pod 必须仍处于 `Running` 状态(它们持有切片;清单使用 `sleep infinity`,避免它们在实验中途悄然完成)。 +> `Pending` 且事件为 `CardInsufficientMemory`,与步骤 5 形成对比,同一个调度器在那里记录的是 `FilteringSucceed`。有两点必须正确,否则这个测试会"失败"(被调度而不是保持 Pending):请求大小必须适配**你的**显卡(大于切片旁的剩余空间、小于整张卡,见清单注释),并且两个共享 Pod 必须仍处于 `Running` 状态(它们持有切片;清单使用 `sleep infinity`,避免它们在实验中途悄然完成)。 ## 步骤 7: 揭示底层机制 @@ -340,11 +340,11 @@ total 684 -rwxr-xr-x 1 root root 684264 Jul 7 10:23 libvgpu.so ``` -> 整个机制就浓缩在这几行里:`libvgpu.so`(HAMi-core)被挂载进 Pod 并注册在 `/etc/ld.so.preload` 中,因此容器内的**每个**进程都会加载它;HAMi-core 从 `CUDA_DEVICE_MEMORY_LIMIT_0` 读取上限。应用发出的每个 CUDA 驱动调用都会经过这个库,步骤 6 中的拒绝正是来自这里。(`CUDA_DEVICE_SM_LIMIT=0` 表示未请求算力限制——这些 Pod 没有设置 `gpucores`;共享缓存文件是各 HAMi-core 实例跨进程核算用量的方式。)这与 NVIDIA 的 KAI Scheduler 于 [2026 年 6 月采用](https://github.com/NVIDIA/KAI-Scheduler/pull/60)的用于分数 GPU 显存隔离的 `CUDA_DEVICE_MEMORY_LIMIT` 机制完全相同。具体的变量名和路径随 HAMi 版本而异——请记录你实际看到的内容。 +> 整个机制就浓缩在这几行里:`libvgpu.so`(HAMi-core)被挂载进 Pod 并注册在 `/etc/ld.so.preload` 中,因此容器内的**每个**进程都会加载它;HAMi-core 从 `CUDA_DEVICE_MEMORY_LIMIT_0` 读取上限。应用发出的每个 CUDA 驱动调用都会经过这个库,步骤 6 中的拒绝正是来自这里。(`CUDA_DEVICE_SM_LIMIT=0` 表示未请求算力限制,这些 Pod 没有设置 `gpucores`;共享缓存文件是各 HAMi-core 实例跨进程核算用量的方式。)这与 NVIDIA 的 KAI Scheduler 于 [2026 年 6 月采用](https://github.com/NVIDIA/KAI-Scheduler/pull/60)的用于分数 GPU 显存隔离的 `CUDA_DEVICE_MEMORY_LIMIT` 机制完全相同。具体的变量名和路径随 HAMi 版本而异,请记录你实际看到的内容。 :::note[这是什么,不是什么] -这是**软件隔离**:用户态 CUDA 拦截。它不是 MIG 的硬件故障隔离——行为异常的 kernel 受到的是拦截约束,而非硬件分区。应将其视为带运行时强制执行的调度与核算保证,而不是等同于 MIG 的安全边界。本实验也不测量算力限制精度或持续负载下的邻居干扰;`gpucores` 的行为参见实验 3 的步骤 5。 +这是**软件隔离**:用户态 CUDA 拦截。它不是 MIG 的硬件故障隔离,行为异常的 kernel 受到的是拦截约束,而非硬件分区。应将其视为带运行时强制执行的调度与核算保证,而不是等同于 MIG 的安全边界。本实验也不测量算力限制精度或持续负载下的邻居干扰;`gpucores` 的行为参见实验 3 的步骤 5。 ::: @@ -355,7 +355,7 @@ kubectl delete pod hami-share-a hami-share-b hami-oversubscribe helm -n kube-system uninstall hami ``` -如果你为本实验租用了虚拟机,请保存输出后销毁实例——计费仍在进行。 +如果你为本实验租用了虚拟机,请保存输出后销毁实例,计费仍在进行。 ```bash /usr/local/bin/k3s-uninstall.sh # 可选:完全移除 k3s @@ -374,7 +374,7 @@ helm -n kube-system uninstall hami ## 下一步 -- 运行 [实验 2: 本地模拟 GPU](./local-fake-gpu.md),免费、无需 GPU 地学习这个故事的调度部分——模拟证明放置决策,本实验证明强制执行。 +- 运行 [实验 2: 本地模拟 GPU](./local-fake-gpu.md),免费、无需 GPU 地学习这个故事的调度部分,模拟证明放置决策,本实验证明强制执行。 - 与 [实验 3: GPU 分区](./gpu-partitioning.md) 对比,它通过 GPU Operator 路径得出相同的隔离证明,并额外覆盖 `gpucores` 算力限制。 - 阅读 [HAMi 集群架构](/zh/docs/core-concepts/hami-architecture),端到端梳理你刚刚验证过的 webhook → 调度器 → 设备插件 → HAMi-core 链路。 diff --git a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/local-fake-gpu.md b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/local-fake-gpu.md index deb311d2..3ce4aab0 100644 --- a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/local-fake-gpu.md +++ b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/local-fake-gpu.md @@ -19,7 +19,7 @@ toc_max_heading_level: 2 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -本实验将引导你搭建一个纯本地 Kubernetes 集群——使用 **OrbStack**(macOS)或 **kind**(Linux/Ubuntu)——配合 [run-ai/fake-gpu-operator](https://github.com/run-ai/fake-gpu-operator),然后在线安装 HAMi。 +本实验将引导你搭建一个纯本地 Kubernetes 集群,使用 **OrbStack**(macOS)或 **kind**(Linux/Ubuntu),配合 [run-ai/fake-gpu-operator](https://github.com/run-ai/fake-gpu-operator),然后在线安装 HAMi。 这个实验不需要真实 NVIDIA GPU,适合用于课堂预习、讲解 HAMi 组件组成、验证 GPU Pod 调度流程,以及在个人电脑上快速熟悉 HAMi 的基础使用方式。 diff --git a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/nvml-mock.md b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/nvml-mock.md index fe778c5d..341a4ed2 100644 --- a/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/nvml-mock.md +++ b/i18n/zh/docusaurus-plugin-content-docs-tutorials/current/labs/nvml-mock.md @@ -21,7 +21,7 @@ toc_max_heading_level: 2 import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -本实验使用 NVIDIA 的 **nvml-mock** 库在本地 **kind** 集群中模拟一个高端 GPU 节点——8 张虚拟 A100 GPU。你将直接基于 `main` 分支构建 HAMi,然后验证 GPU 调度功能:共享、显存/算力限制、百分比显存申请以及多 GPU 分配——全部无需物理硬件。 +本实验使用 NVIDIA 的 **nvml-mock** 库在本地 **kind** 集群中模拟一个高端 GPU 节点,8 张虚拟 A100 GPU。你将直接基于 `main` 分支构建 HAMi,然后验证 GPU 调度功能:共享、显存/算力限制、百分比显存申请以及多 GPU 分配,全部无需物理硬件。 ## 你将得到什么 @@ -146,7 +146,7 @@ Windows 用户请使用 [WSL2](https://learn.microsoft.com/zh-cn/windows/wsl/ins kind create cluster --name nvml-mock-test ``` -设置一次 `NODE_NAME` 变量——后续所有命令都会用到它: +设置一次 `NODE_NAME` 变量,后续所有命令都会用到它: ```bash NODE_NAME=$(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') @@ -306,7 +306,7 @@ kubectl -n kube-system rollout restart daemonset/hami-device-plugin kubectl -n kube-system rollout status daemonset/hami-device-plugin --timeout=120s ``` -检查是否有 MIG 相关错误——空响应即为预期输出: +检查是否有 MIG 相关错误,空响应即为预期输出: ```bash kubectl -n kube-system logs daemonset/hami-device-plugin -c device-plugin | grep -i mig @@ -328,7 +328,7 @@ hami-scheduler-7858c744cc-7pb79 2/2 Running 0 13m :::note -`vgpu-monitor` sidecar 会崩溃,因为它需要真实的 GPU 监控基础设施。`device-plugin` 容器运行正常——此处 `1/2` 是预期状态,不影响 GPU 调度。 +`vgpu-monitor` sidecar 会崩溃,因为它需要真实的 GPU 监控基础设施。`device-plugin` 容器运行正常,此处 `1/2` 是预期状态,不影响 GPU 调度。 ::: @@ -351,7 +351,7 @@ kubectl describe node ${NODE_NAME} | grep nvidia.com/gpu nvidia.com/gpu 0 0 ``` -`Capacity` 和 `Allocatable` 都显示 `80`,确认 device-plugin 已注册全部虚拟 GPU 槽位。最后一行是 `Allocated resources` 表——当前为 `0`,因为还没有 Pod 申请 GPU。 +`Capacity` 和 `Allocatable` 都显示 `80`,确认 device-plugin 已注册全部虚拟 GPU 槽位。最后一行是 `Allocated resources` 表,当前为 `0`,因为还没有 Pod 申请 GPU。 --- @@ -404,7 +404,7 @@ kubectl describe pod gpu-test-1 | grep vgpu-devices-allocated hami.io/vgpu-devices-allocated: GPU-12345678-1234-1234-1234-123456780006,NVIDIA,40960,100:; ``` -> 注解格式为 `,<厂商>,<显存MiB>,<算力>`。A100 GPU 有 40960 MiB 显存——看到这个注解即确认调度器分配并记录了一个虚拟 GPU。 +> 注解格式为 `,<厂商>,<显存MiB>,<算力>`。A100 GPU 有 40960 MiB 显存,看到这个注解即确认调度器分配并记录了一个虚拟 GPU。 --- @@ -485,7 +485,7 @@ EOF :::info -资源限制格式 `nvidia.com/gpumem` 接受**以 MiB 为单位的绝对值**——`"10"` 表示 10 MiB。`nvidia.com/gpucores: "30"` 表示在所选 GPU 上申请 30 个计算核心。 +资源限制格式 `nvidia.com/gpumem` 接受**以 MiB 为单位的绝对值**:`"10"` 表示 10 MiB。`nvidia.com/gpucores: "30"` 表示在所选 GPU 上申请 30 个计算核心。 ::: @@ -501,7 +501,7 @@ kubectl describe pod gpu-limits | grep vgpu-devices-allocated hami.io/vgpu-devices-allocated: GPU-12345678-1234-1234-1234-123456780002,NVIDIA,10,30:; ``` -注解记录了 `10` MiB 和 `30` 个核心——正是所申请的值。 +注解记录了 `10` MiB 和 `30` 个核心,正是所申请的值。 --- @@ -564,7 +564,7 @@ kubectl get pod gpu-mem-30pct \ GPU-12345678-1234-1234-1234-123456780003,NVIDIA,12288,100:; ``` -> 第三个字段显示 `12288` MiB——即 40960 MiB 的 30%——确认调度器正确地将百分比转换为本次分配的绝对显存预算。 +> 第三个字段显示 `12288` MiB(即 40960 MiB 的 30%),确认调度器正确地将百分比转换为本次分配的绝对显存预算。 --- @@ -624,7 +624,7 @@ Events: Normal Started 67s kubelet Container started ``` -`hami-scheduler` 事件——`FilteringSucceed`、`Scheduled` 和 `BindingSucceed`——确认 HAMi 的调度器处理了这个 Pod,并成功将其绑定到带 2 个 GPU 槽位的节点。 +`hami-scheduler` 事件:`FilteringSucceed`、`Scheduled` 和 `BindingSucceed`,确认 HAMi 的调度器处理了这个 Pod,并成功将其绑定到带 2 个 GPU 槽位的节点。 :::tip 查看完整的 vgpu-devices-allocated 注解