Kubernetes Gang Scheduling:多 GPU 推理任务要一起调度

📅 2026/7/17 15:02:17
Kubernetes Gang Scheduling:多 GPU 推理任务要一起调度
Kubernetes Gang Scheduling多 GPU 推理任务要一起调度一、分片推理的痛点部分 Pod 跑起来了但有些永远调度不上大模型推理的典型部署模式是张量并行Tensor Parallelism——把一个模型切分到多张 GPU 上每张卡负责一部分计算推理时所有卡必须同时工作。在 Kubernetes 中这意味着一个推理服务需要 4 或 8 个 Pod 同时运行每个 Pod 独占一张 GPU。问题在于Kubernetes 默认调度器逐个调度 Pod。当集群中只有 5 张空闲 GPU、但你的推理服务需要 4 张时前 4 个 Pod 调度成功占满 4 张卡第 5 个 Pod 处于 Pending 状态被卡住——但前 4 个 Pod 已经运行起来了占着资源却不工作因为缺少第 5 个 Pod 无法完成模型加载。更糟的是如果同时有多个推理服务在部署它们的 Pod 会交错获取 GPU形成死锁。服务 A 拿到 3 张卡、服务 B 拿到 2 张都不够各自需要的 4 张但也没有一张卡被释放。这就是 Gang Scheduling 要解决的核心问题要么全部 Pod 一起调度成功要么全部不调度。二、Gang Scheduling 的实现原理Gang Scheduling 的核心思想是引入调度组的概念。依赖所有组成员必须同时满足调度条件才进行实际的节点绑定。工作流程分三个阶段Accumulate 阶段调度器逐个为 Pod 找节点。每找到一个通过 Filter Score不立即 Bind而是通过 Permit 插件将其放入 Gang 组中等待。Pod 在 Permit 状态等待不会占用 GPU 资源也不会被其他调度器抢占。Decision 阶段Gang 组的计数达到 minMember 时所有 Pod 同时被放行进入 Bind 阶段。如果超时未达到 minMember可以选择全部拒绝所有等待的 Pod 重新入队或部分放行允许已达到的 Pod 绑定但这违背了 Gang Scheduling 的本意。Bind 阶段调度器并行完成所有 Pod 的节点绑定。此时 Pod 从 Pending 变为 Running。Kubernetes 生态中实现 Gang Scheduling 的主要方案Volcano 的 PodGroup CRD最成熟、Coscheduling 插件轻量级、YunikornApache 项目。选型的核心差异在于对额外组件的依赖程度和与现有调度器的兼容性。三、基于 Volcano PodGroup 的 Gang Scheduling 实现Volcano 通过 PodGroup CRD 定义调度组配合 Volcano Scheduler 实现 Gang Scheduling。# 1. 创建 PodGroup 定义调度组 apiVersion: scheduling.volcano.sh/v1beta1 kind: PodGroup metadata: name: llm-infer-7b-gang spec: minMember: 4 # 至少 4 个 Pod 同时就绪才调度 minResources: nvidia.com/gpu: 4 # 最小资源需求 queue: gpu-inference # 所属队列 priorityClassName: high-priority --- # 2. StatefulSet 部署推理 Pod关联 PodGroup apiVersion: apps/v1 kind: StatefulSet metadata: name: llm-infer-7b spec: serviceName: llm-infer-7b replicas: 4 selector: matchLabels: app: llm-infer-7b template: metadata: labels: app: llm-infer-7b annotations: # 关键注解关联到 PodGroup scheduling.k8s.io/group-name: llm-infer-7b-gang spec: schedulerName: volcano # 使用 Volcano 调度器 containers: - name: infer image: llm-infer:v2.3 env: - name: TP_SIZE value: 4 # 张量并行度 - name: RANK valueFrom: fieldRef: fieldPath: metadata.name resources: requests: nvidia.com/gpu: 1 limits: nvidia.com/gpu: 1 volumeMounts: - name: shared-memory mountPath: /dev/shm volumes: - name: shared-memory emptyDir: medium: Memory sizeLimit: 32Gi关键点说明minMember: 4是核心参数。只有 4 个 Pod 都找到满足条件的节点后调度器才执行绑定。schedulerName: volcano将调度权交给 Volcano 调度器它理解 PodGroup 语义。使用 StatefulSet 而非 Deployment 的原因推理 Pod 需要稳定的网络标识和持久存储。每个 Pod 通过RANK环境变量知道自己在张量并行中的位置。四、Gang Scheduling 的边界与权衡超时处理Gang 等待不会无限进行。PodGroup 可以设置scheduleTimeoutSeconds超时后所有等待的 Pod 标记为失败。这个值的设置需要谨慎——太小会在集群繁忙时产生过多假失败太大会导致调度延迟不可控。部分资源碎片Gang Scheduling 要求全部 Pod 同时满足当集群 GPU 碎片化严重时例如 5 个节点各剩 1 张卡但推理需要 4 张同一节点的卡Gang 无法调度。这是调度策略本身的限制需要配合资源碎片整理策略Descheduler 驱逐低优 Pod来缓解。调度延迟逐个 Pod 的 Filter Score 阶段仍然串行执行Pod 数量多时调度延迟会增长。Volcano 通过 Gang 级别的批量调度优化了这一阶段但基础开销依然存在。对于推理服务调度是低频操作部署和扩缩时才会触发延迟在秒级是可接受的。与 Cluster Autoscaler 的协作Gang 等待期间如果节点资源不足CA 可能需要扩容节点。但这形成了一个循环依赖——CA 在等待 Pod 调度失败后扩容而 Gang 在等待 CA 扩容完成后调度。需要配置minResources让 CA 提前感知资源缺口。五、总结Gang Scheduling 是多 GPU 推理任务在 Kubernetes 上正确部署的基础保障。核心价值在于消除了 Pod 部分调度导致的部分资源占用和死锁问题。Volcano 的 PodGroup CRD 是目前最成熟的实现方案使用minMember和scheduleTimeoutSeconds两个参数即可定义调度组的行为。实际生产部署中需要特别关注 Gang 超时设置与 Cluster Autoscaler 扩容时机之间的时序对齐。