4. 算力调度与编排:资源管理、任务调度、容器化与编排(K8s)
4.1 核心原理:从“裸金属分配”到“声明式编排”
在端到端算力链路中,调度与编排层承担着“算力操作系统”的职责。传统HPC集群通常采用静态资源分配:作业提交后由调度器(如Slurm)锁定节点,直到作业结束。这种方式对独占型批处理任务有效,但对微服务、AI推理等弹性负载则显得僵化——资源利用率低、扩缩容周期长。
容器化与Kubernetes(K8s)改变了这一范式。其核心思想是声明式编排:用户描述“期望状态”(如副本数、CPU/内存请求),控制器(Controller)持续对比“当前状态”并驱动系统收敛。调度器(kube-scheduler)则负责为待调度的Pod选择最合适的节点,而资源请求(Requests)与限制(Limits)成为调度决策的基础输入。
上图展示了K8s调度与编排的基本架构。调度器并非直接与节点通信,而是通过API Server读取节点资源水位和Pod调度请求,做出绑定决策。kubelet负责执行并持续上报状态,形成闭环。
4.2 方法流程:资源模型与调度策略
K8s的资源管理建立在可压缩资源(CPU)与不可压缩资源(内存、GPU)的区分之上。GPU作为典型的扩展资源(Extended Resource),只能以整数形式申请,且不支持超卖。在调度流程中,核心步骤包括:
- 节点预选(Predicates):过滤掉不满足Pod资源请求的节点,例如检查GPU型号与数量是否匹配。
- 节点优选(Priorities):对通过预选的节点打分,考虑资源碎片率、已分配负载、亲和性等。
- 绑定(Binding):将Pod与最优节点写入etcd,由该节点kubelet启动容器。
对于GPU算力集群,通常需要结合设备插件(Device Plugin)机制。NVIDIA/k8s-device-plugin将GPU资源上报给kubelet,使调度器感知GPU数量与健康状态。以下是一个GPU Pod的资源声明示例:
apiVersion: v1
kind: Pod
metadata:
name: gpu-training-job
spec:
containers:
- name: trainer
image: registry.example.com/ai-trainer:v2.1
resources:
requests:
cpu: "8"
memory: "32Gi"
nvidia.com/gpu: 4 # 请求4张GPU
limits:
cpu: "16"
memory: "64Gi"
nvidia.com/gpu: 4
4.3 案例场景:混合负载下的算力调度策略
某自动驾驶公司同时运行三类工作负载:离线训练任务(长时、GPU密集)、在线推理服务(延迟敏感、波动大)、数据预处理(CPU密集、可中断)。最初将所有任务混部在同一个K8s集群,出现以下问题:
- 训练任务抢占CPU资源,导致推理服务P99延迟从20ms恶化到200ms。
- GPU节点因显存碎片化,无法调度新的训练任务。
- 节点资源分配不均,部分节点CPU利用率达95%,另一些仅30%。
优化后的调度策略如下表所示:
| 策略维度 | 离线训练 | 在线推理 | 数据预处理 |
|---|---|---|---|
| 节点池 | GPU节点池(A100) | GPU节点池(L4)+ CPU兜底 | CPU节点池 |
| 优先级类 | 低(可抢占) | 高(不可抢占) | 中(可排队) |
| 调度策略 | binpack(紧凑放置) | spread(分散放置) | most-requested |
| 资源限额 | CPU 16C/GPU 8 | CPU 4C/GPU 2 | CPU 32C |
| 弹性策略 | 无(固定副本) | HPA(QPS驱动) | 队列长度驱动 |
通过节点池隔离与PriorityClass结合,推理服务延迟恢复至30ms以内。同时引入Descheduler定期驱逐低优先级Pod,将碎片节点上的训练任务重新调度,集群整体GPU利用率从55%提升至78%。
4.4 误区与复盘:调度器不是万能的
常见误区一:依赖默认调度器处理所有GPU任务。默认调度器不感知GPU显存、NVLink拓扑或MIG实例。对于大模型训练,应使用节点亲和性(nodeAffinity)将任务固定到同一物理机,避免跨机通信瓶颈。
常见误区二:将资源Requests设置过小。部分团队为了提升节点密度,将CPU请求设为实际用量的50%。当突发流量到来时,CPU被压缩(throttling),推理延迟飙升。建议在线服务Requests/实际用量比例不低于0.8。
复盘要点:在一次大模型训练任务中,由于未设置Pod拓扑分布约束,8个训练Worker被调度到4台节点上,每台2个Worker共享同一GPU的NVLink域,导致通信效率下降30%。修正方案是添加 podAntiAffinity 规则,确保每个GPU Worker独占一台节点,训练吞吐恢复至理论值的92%。
调度与编排的最终目标不是“把Pod放上去”,而是在正确的时间、把正确的算力资源、以正确的拓扑结构、分配给正确的任务。这需要资源模型、调度策略、节点池设计、弹性机制与业务SLA的深度协同。K8s提供了强大的基础能力,但真正的优化仍依赖于对业务负载特征的理解和对调度器行为的精细调校。