← 文章 / 云原生与基础设施
NVIDIA 开发者博客 2小时前 · 2026-09-23 02:05:06 · 1 阅读

基于 NVIDIA Topograph 的拓扑感知工作负载调度

AI 工厂是受电力限制的系统,只有在充分优化时才能发挥最大价值。GPU 工作负载的放置是实现优化的关键。不佳的放置策略会拓扑域碎片化,迫使流量穿越共享链路,从而降低吞吐量、推高任务成本,并导致 GPU 在等待数据而非推进计算时,白白消耗已预留的电力。

GPU 在训练和推理期间持续交换数据,因此分布式工作负载受益于通信局部性。NVIDIA NVLink 和 NVLink Switch 在机架级 GPU 域内提供高带宽、全对全的纵向扩展连接,而 NVIDIA Spectrum-X Ethernet 则在各系统和机架之间提供可预测、低延迟的横向扩展网络。

调度器只有掌握这些 GPU 和 fabric 关系的实时、准确视图,才能高效地放置工作负载;然而,随着集群变化而保持该视图的实时性,正是实际部署中放置环节常失效的症结所在。

NVIDIA Topograph 解决了这一难题。它从云 API 或本地 fabric 系统中发现集群拓扑,将其归一化为通用模型,并以各工作负载管理器所需的格式发布:Kubernetes 节点标签、Slurm 拓扑配置或 Slinky ConfigMaps。在 NVIDIA DSX OS 集群编排层内,Topograph 与 动态资源分配(DRA) 和 KAI Scheduler 协同工作,以在 AI 工厂基础设施上实现拓扑感知的 gang 调度。

本文将逐步介绍如何部署 Topograph,并利用它在 Kubernetes、Slurm 和 Slinky 上调度拓扑感知的工作负载

核心拓扑问题

Topograph 映射集群硬件的连接方式,使调度器能够优先使用邻近资源。可以将网络视为道路系统:同一局部性域内的 GPU 拥有短且高带宽的路径,而域间流量则需穿越更多共享链路和交换机。将紧密耦合的工作负载分散到相距较远的域中,可能加剧争用并增加延迟,因此 Topograph 有助于将工作负载放置在最高效的位置,从而规避这些瓶颈。

现代 NVIDIA Quantum InfiniBand 端口速率可达 800 Gb/s;而 NVIDIA NVLink 的第五代(如 NVIDIA Blackwell,即 GB200/GB300)在专用 NVLink Switch 架构下提供每 GPU 1.8 TB/s 的双向带宽,第六代(Vera Rubin)则提升至每 GPU 3.6 TB/s。这种无阻塞的全互联设计让每块 GPU 独享链路,无需在负载下共享带宽。具备实时拓扑视图的调度器可以优先选择拓扑距离更近的 GPU。

Slurm 和 Kubernetes 均支持拓扑感知分配,但调度器只能基于其观察到的拓扑进行决策。Topograph 会按需或在监控的集群发生变化时重新生成该视图,使调度器基于最新数据而非人工维护的快照运行。

跨环境的统一模型

Topograph 是一个开源工具包,用于识别集群网络拓扑,使工作负载管理器能够做出拓扑感知的调度决策。它包含两个核心概念:provider 和 engine。Provider 负责从云 API 或本地系统中发现拓扑,并将其归一化为标准模型;Engine 则将该模型转换为 Slurm 配置、Kubernetes 标签、Slinky ConfigMaps、Node Feature Discovery(NFD)资源或面向实例的拓扑 JSON。

已与 Topograph 完成集成的云服务商包括 Google CloudLambdaNebiusNscaleOCI,更多云及托管服务商的集成正在开发中。

本地部署时,可配合 ibnetdiscover 使用 InfiniBand provider,或者对于 Spectrum-XMulti-Node NVLink (MNNVL) 域,使用 NetQ

provider 接口是开放的,运维人员可以为自己的环境新增 provider,并向上游贡献。

环境与引擎支持

环境或 providerKubernetesSlurmGraph
Node labels
(k8s)
NFD resources
(nfd)
Slinky ConfigMap
(slinky)
云及托管服务提供商
Crusoe
Google Cloud
Lambda
Nebius
Nscale
Oracle Cloud Infrastructure (OCI)
本地部署模式
Kubernetes 中的 InfiniBand 支持支持
裸金属或虚拟机上的 InfiniBand支持支持
本地部署的网络与拓扑
Spectrum-X 或 NetQ 管理的网络支持支持支持支持支持
MNNVL NVLink 分区(仅限 DRA 块拓扑)支持
表 1. 各引擎支持的拓扑提供器

范围与解读。此矩阵反映的是 2026 年 9 月 16 日时点的当前上游主干代码版本。它展示了支持的提供器与引擎输出组合;具体需求可能因 Topograph 版本、环境和提供器配置而异。

  • Crusoe 提供器从 Crusoe Managed Kubernetes 节点读取网络和加速器域标签;因此,该提供器要求 Topograph 运行在 Kubernetes 环境中。
  • Slurm 引擎可以运行在 Kubernetes 中,但要求其配置的 topology.conf 输出路径所指向的卷必须可写。
  • NFD 引擎需要启用 alpha 版本的 NodeFeatureGroupAPI 功能门控。Kubernetes 引擎则通过发布节点标签来实现。

保持集群视图同步更新

五个组件共同确保该视图保持最新状态:

  • API Server:校验请求、去重并分发发现任务。
  • Node Observer:监控已配置的 Kubernetes 节点或 Pod 变更及 API 就绪状态,随后触发带有重试机制的重新生成请求。
  • Node Data Broker:收集每个节点的属性并将其存储为节点注解。
  • Provider:将云端或网络数据转换为规范表示。
  • Engine:以调度器可理解的格式写入该表示。
三段式 Topograph 架构。生成请求可选择云拓扑 API 或网络 fabric 提供方路径,并可输入加速器域信息。API Server 负责校验和分发请求;Provider 发现并规范化拓扑为规范图;Engine 则发布 Slurm 配置、Kubernetes 资源或面向实例的拓扑 JSON。Kubernetes 部署还可以使用 Node Observer 和 Node Data Broker 这些运行时助手。
图 1。Topograph 接收生成请求,从所选云或网络 fabric 提供方发现并规范化拓扑,进而发布 Slurm 和 Kubernetes 可用的调度器就绪输出,或面向实例的拓扑 JSON。Kubernetes 部署还可借助运行时助手响应集群变更并收集每个节点的数据

客户端如何查询拓扑

API server 提供五个服务接口:

  • POST /v1/generate – 提交异步请求并返回其 ID,HTTP 状态码 202。
  • GET /v1/topology?uid=<request-id> – 处理中返回 HTTP 202,完成后返回 HTTP 200 及结果。
  • POST /v1/lookup – 不重复提交,直接返回相同请求体的缓存状态或结果。
  • GET /healthz – 存活端点。
  • GET /metrics – 暴露 Prometheus 指标。

聚合延迟是必需的,通常为 15 秒。完全相同的重复请求会重置尾部计时器并只处理一次,从而减少集群事件突发时的冗余工作。

在没有生产硬件的情况下进行测试,仿真模型描述了节点和交换机层次。使用 kwok-nodes 工具和 Kind/KWOK 助手,可以将这些模型转换为虚拟 Kubernetes 节点。

在 Kubernetes 上解决(引擎:k8s)

Kubernetes 默认调度器不感知物理互连层次。Topograph 通过发布提供方报告的拓扑作为节点标签来弥补这一不足,原生亲和性和拓扑感知调度器可以消费这些标签。

前置要求:Kubernetes 1.27 或更高版本、Helm 3.10+ 或 4.x、kubectl 权限,以及受支持的 provider。如需拓扑感知的 gang 调度,可选装 KAI SchedulerKueue TAS

使用 Helm 部署 Topograph

Topograph 以 Helm chart 形式发布:

helm repo add topograph https://dsx-ai-factory.github.io/topograph
helm repo update
helm install topograph topograph/topograph \
--namespace topograph \
--create-namespace \
--set engine.name=k8s \
--set provider.name=<provider>

请将 <provider> 替换为与你环境对应的值。

仓库的 charts/topograph 目录中提供了示例 Helm values 文件,命名以 values.k8s 为前缀并附有简短的场景说明,每个文件都带有内联配置注释。

安装完成后,验证部署是否成功:

helm test topograph --namespace topograph

内置的测试钩子会在集群内请求 /healthz/metrics,并确认响应中包含 topograph_version 指标。

确认 Pod 正在运行:

kubectl get pods -n topograph

验证节点上的拓扑标签

Topograph 用一组可变深度的标签表示网络拓扑位置,用两级层次结构表示加速器拓扑位置:

fabric.topograph.run/tier-0          # 离节点最近的交换机
fabric.topograph.run/tier-1          # 下一层网络层级
fabric.topograph.run/tier-<N>        # 更多发现的层级
accelerator.topograph.run/domain     # 加速器域
accelerator.topograph.run/sub-domain # 可选的嵌套子域

网络层级 0 是离计算节点最近的叶子交换机,层级编号向外递增。Topograph 只写入实际发现的层级标签,没有固定的最大深度。运维人员可以通过 Kubernetes engine 的 fabricLabels 数组和 acceleratorLabel 参数使用自定义键名,超出该数组的层级不会被标注。sub-domain 键名是固定的。

要验证标签是否已应用,执行以下命令:

kubectl get nodes --show-labels | grep -E 'fabric\.topograph\.run|accelerator\.topograph\.run'

如果标签缺失,请检查 Topograph 日志:

kubectl logs -n topograph -l app.kubernetes.io/name=topograph

注意: Topograph 反映的是实际报告的网络拓扑,而非预期拓扑。标签会在生成过程运行时刷新,例如在监控的节点或 Pod 发生变化后。网络变更的可见性取决于提供商及其触发事件。

暴露 API

API 默认是一个 ClusterIP 服务。基于上述的发行版本和命名空间,其地址为:topograph.topograph.svc.cluster.local:49021

本地调试方法:

kubectl -n topograph port-forward svc/topograph 49021:49021
curl http://localhost:49021/healthz

使用标准 Kubernetes 调度

拓扑标签可作为 Pod 亲和性中 topologyKey 的值用于首选调度策略:

affinity:
  podAffinity:
    preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 90
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: myapp
          topologyKey: fabric.topograph.run/tier-0
      - weight: 70
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: myapp
          topologyKey: fabric.topograph.run/tier-1

每个匹配项都会为候选节点评分,强烈倾向于现有 app=myapp Pod 所在的 tier-0 域,同时也奖励 tier-1 的局部性。由于默认调度器是逐个放置 Pod 的,这属于偏好设置,而非全局最优的 gang 调度。

KAI Scheduler 和 Kueue 可以利用相同的节点标签实现拓扑感知的 gang 调度。Kubernetes 1.36 还通过 拓扑感知工作负载调度 引入了 alpha 阶段的KEP-5732。上游的 beta 版本工作正在进行中;建议关注增强功能跟踪器,而非依赖特定的未来版本。

使用 KAI Scheduler 进行拓扑感知的 Gang 调度

KAI Scheduler(由 NVIDIA 捐赠的 CNCF 沙箱项目)将节点标签组织为层级结构

apiVersion: kai.scheduler/v1alpha1
kind: Topology
metadata:
  name: cluster-topology
spec:
  levels:
    - nodeLabel: topology.kubernetes.io/zone
    - nodeLabel: fabric.topograph.run/tier-1
    - nodeLabel: fabric.topograph.run/tier-0
    - nodeLabel: kubernetes.io/hostname

使用 kubectl apply -f cluster-topology.yaml 应用该配置,然后为多 Pod 的 Job 添加注解:

apiVersion: batch/v1
kind: Job
metadata:
  name: topology-aware-workers
  annotations:
    kai.scheduler/topology: cluster-topology
    kai.scheduler/topology-required-placement: fabric.topograph.run/tier-1
    kai.scheduler/topology-preferred-placement: fabric.topograph.run/tier-0
spec:
  parallelism: 4
  completions: 4
  template:
    metadata:
      labels:
        app: inference-worker
    spec:
      schedulerName: kai-scheduler
      restartPolicy: Never
      containers:
        - name: worker
          image: nvcr.io/nvidia/nemo:latest
          resources:
            limits:
              nvidia.com/gpu: 1

必需注解将团伙调度限制在单个 tier-1 域内。优选注解在条件允许时,会请求 KAI 将 Pod 集中在 tier-0 域内,但允许在必需边界内使用多个 tier-0 域。

更多高级拓扑感知调度示例,请参阅 Grove NVIDIA Dynamo 的文档。

Grove 提供 Kubernetes API 和 Operator,用于实现层级化团伙调度、拓扑感知放置及协同扩缩容。Dynamo 是一个开源分布式推理服务框架,可与 Grove 集成以进行 Kubernetes 工作负载编排。

通过 NFD 发布拓扑信息(引擎:nfd)

Topograph 也支持已在使用 Node Feature Discovery 的用户。nfd 引擎会为每个选定的拓扑节点发布一个 NodeFeature,并为每个不同的 fabric-tier、XCLR-domain 和 XCLR-sub-domain 值发布一个 NodeFeatureGroup。NFD master 负责评估这些规格,并维护各组的 status.nodes 成员列表。

请先安装 nfd 并启用 alpha 阶段的 NodeFeatureGroupAPI feature gate(默认关闭)。然后指定引擎和 NFD master 所在的命名空间:

engine:
  name: nfd
nfdNamespace: node-feature-discovery

当下游组件需要消费 NodeFeatureGroup 对象时可以使用这种输出,但它不能替代 Kubernetes 的 topologyKey 标签。如果要用原生 Pod 亲和性、KAI Scheduler 或 Kueue TAS,请继续使用 engine: k8s。Helm chart 会把 NFD 权限限制在 nfd 命名空间内。该引擎在 reconcile 之后会删除由 Topograph 管理的过期对象,但如果某一轮没有生成任何拓扑,则会保留上一次发布的拓扑。

在 Slurm 上解决问题(engine: slurm)

Topograph 可以生成全集群范围的 tree 和 block 格式配置,对应下图 2 的上方中央和下方中央面板。Slurm 25.05 引入了基于分区的 YAML 格式配置,Topograph 同样支持,如图所示。

Representative network topology with a core switch, two spine-to-leaf branches, and two Multi-Node NVLink domains containing example nodes. Topograph translates the discovered topology according to Slurm engine configuration into cluster-wide tree or block topology.conf, or per-partition topology YAML.
图 2. 一个典型的三层集群拓扑,包含 Multi-Node NVLink 域,以及 Topograph 根据配置生成的三种 Slurm 输出模式:全集群 tree、全集群 block,或按分区的 topology YAML

安装 Topograph

Slurm 集群通常运行在 Linux 裸金属服务器或虚拟机上,此时可通过原生包管理器安装 Topograph。仓库中提供了 Debian 和 RPM 构建目标:

make deb    # Debian / Ubuntu
make rpm    # RHEL / Rocky / SUSE


包安装后不会自动启动服务,你可以先检查并编辑配置文件 /etc/topograph/topograph-config.yaml

http:
port: 49021
provider: <provider>
engine: slurm
requestAggregationDelay: 15s

<provider> 替换为符合你环境的值。

更新配置后,启动服务并验证其健康状态:

sudo systemctl enable --now topograph.service
curl http://localhost:49021/healthz

生成 Slurm 拓扑配置

向 Topograph 的 /v1/generate 端点发送 POST 请求即可触发拓扑发现,这会重新生成 Slurm 拓扑配置。

提交请求并轮询结果:

id=$(curl -s -X POST -H 'Content-Type: application/json' \
  -d @payload.json http://localhost:49021/v1/generate)
curl -s "http://localhost:49021/v1/topology?uid=$id"

若需输出集群范围的树形拓扑,使用绝对路径:

{
  "engine": {
    "name": "slurm",
    "params": {
      "plugin": "topology/tree",
      "topologyConfigPath": "/etc/slurm/topology.conf",
      "reconfigure": true
    }
  }
}

使用 topology/block 配合可选的 blockSizes 参数可输出块形拓扑。

可选参数 reconfigure 用于在写入文件后执行 scontrol reconfigure,默认为 false。若省略 topologyConfigPath,Topograph 将直接从结果端点返回生成的内容,而非写入文件。

{
  "engine": {
    "name": "slurm",
    "params": {
      "topologies": {
        "gpu-block": {
          "partition": "gpu",
          "plugin": "topology/block",
          "blockSizes": [8, 16]
        },
        "cpu-tree": {
          "partition": "cpu",
          "plugin": "topology/tree"
        },
        "default": {
          "plugin": "topology/flat",
          "clusterDefault": true
        }
      },
      "topologyConfigPath": "/etc/slurm/topology.yaml",
      "reconfigure": true
    }
  }
}

若希望基于节点状态自动刷新,且使用的 provider 能自动发现 Slurm 节点映射,请以 root 身份运行仓库中的脚本:

scripts/create-topology-update-script.sh -p <provider> -c /etc/slurm/topology.conf

该脚本会注册一个永久的 strigger,响应节点上线和下线事件。它无法检测交换机任意重新接线或所有清单变更。

在 Slinky 上求解(引擎:slinky)

由 SchedMD 开发的 Slinky 在 Kubernetes 上运行 Slurm。NVIDIA 已于 2025 年 12 月收购了 SchedMD。Topograph 的 Slinky 引擎将 Kubernetes 节点映射为 slurmd Pod,并将 Slurm 拓扑数据写入 ConfigMap。

Slinky 引擎支持全集群的 topology/treetopology/block 输出,以及用于分区特定配置的多拓扑 YAML。

将 Topograph 作为 Helm chart 安装:

helm repo add topograph https://dsx-ai-factory.github.io/topograph
helm repo update
helm install topograph topograph/topograph \
  --namespace topograph \
  --create-namespace \
  --values my-values.yaml

该仓库提供了可直接适配的 Helm 示例,涵盖treeblock按分区InfiniBand block部署。

当选定的 slurmd Pod 发生变更时,Topograph 会重新生成并更新 ConfigMap。

dra 提供器是面向 MNNVL 系统的更窄范围的 Slinky 块拓扑选项。它在重新生成拓扑配置时,会读取现有的 nvidia.com/gpu.clique 标签。

对于动态 Slurm 节点,可选的 useDynamicNodes 模式还会为选定的 Kubernetes 节点添加当前 Slurm 拓扑规范的注解。ConfigMap 更新与动态节点协调是两种不同的机制,因此请选择与已部署 Slinky 配置相匹配的模式。

入门指南

随着规模扩大,放置问题会累积并表现为网络拥塞。Topograph 为调度器提供由供应端报告的最新物理网络地图,使拓扑感知决策在云和本地环境中保持一致,且无需人工维护。

通过 KAI Scheduler、Kueue 及原生 Kubernetes,该地图提升了 AI 工厂的效率、每瓦令牌数及成本效益。

你可以从 dsx-ai-factory/topograph GitHub 仓库部署 Topograph,或进一步了解 DSX OS 生态系统

原始来源: NVIDIA 开发者博客

评论 (0)