Incipience / Kubernetes

《大模型推理 OOM 与延迟优化指南》

Einic Yeo · 7月30日 · 2025年 · ·

随着大模型(LLM)在企业业务中的普及,如何高效、稳定地部署推理服务成为运维和算法工程师的共同难题。你是否遇到过这些场景:

版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!
  1. 高峰期请求突增,GPU 显存瞬间溢出,Pod 被 OOMKilled;
  2. 低峰期资源闲置,数十万元购买的 GPU 卡利用率不足 10%;
  3. 单次请求延迟飘忽不定,用户对话体验差。

传统的静态批处理(Static Batching)无法应对动态变化的请求流,而 版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!K8s 原生的 HPA 又难以感知 GPU 层面的真实负载。本文将深入解析如何通过 连续批处理(Continuous Batching) 和 基于自定义指标的弹性伸缩,构建一套既能杜绝 OOM 又能大幅降低延迟的大模型推理平台。

一、痛点:大模型推理的三大难题

版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!

1.1 显存碎片版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!与 OOM

大模型推理服务通常使用 vLLM、TGI 等推理引擎。传统批处理会累积请求直到批大小满,导致显存占用不可预测。一旦并发超过预设上限,容器直接 OOM,服务中断。

1.2 高延迟与低吞吐

单次请求处理时,GPU 往往处于“等待”状态。若采用固定批大小,小请求要等批填满,延迟飙升;大请求又可能超出显存上限。

1.3 资源浪费

业务请求呈波浪形,但 K8s 默认的 CPU/Memory 指标无法精确反映 GPU 的繁忙程度。资源闲置时仍需付费,高峰期又因扩容不及时而丢请求。

二、核心技术:连续批处理(Continuous Batching)

连续批处理(又称迭代级调度)是解决上述问题的关键。与静态批处理等待固定数量请求不同,连续批处理在每个推理迭代(iteration)后动态调整批次中的请求。

工作原理:

  1. 请求到达后,不等待,立即进入调度队列。
  2. 调度器根据当前 GPU 显存余量和请求的序列长度,动态构建批次。
  3. 当一个请求生成完毕(输出结束)后,立即从批次中移除,并加入新请求。
  4. 整个过程中,GPU 始终处于满载计算状态,无空闲等待。

这种机制使得延迟与吞吐达到最佳平衡,并避免显存溢出。

三、整体架构设计

我们基于 Kubernetes 构建如下架构:

说明:

  1. 请求队列,缓存等待调度的请求。
  2. 连续批处理调度器,核心逻辑,动态构建批次。
  3. GPU 执行单元,负责模型推理。

四、弹性伸缩:基于 GPU 指标的 HPA

单纯的连续批处理解决了单 Pod 内的效率问题,但面对流量波动,还需要让 K8s 自动扩缩 Pod 数量。K8s 原生 HPA 支持 CPU/Memory,我们需要引入 自定义指标,基于 GPU 利用率、显存使用率或请求队列长度进行伸缩。

我们采用 Prometheus + Prometheus Adapter 将 GPU 指标转化为 K8s 可识别的自定义指标。

说明:

  1. 数据平面,即实际运行推理服务的 Pod。
  2. 监控采集层,包括 GPU 指标采集和存储。
  3. 控制平面,负责指标转换和自动扩缩决策。

五、实战:基于 vLLM 与 KEDA 的完整部署

我们以 vLLM(支持连续批处理的高性能推理引擎)为例,结合 KEDA(基于事件驱动的自动伸缩器)进行部署。KEDA 可基于 Prometheus 指标灵活伸缩,比原生 HPA 更强大。

5.1 部署监控组件

# 安装 DCGM Exporter
helm install gpu-operator --set dcgm.enabled=true nvidia/gpu-operator

# 安装 Prometheus Operator(可选)

5.2 部署 vLLM 推理服务

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: vllm
  template:
    metadata:
      labels:
        app: vllm
    spec:
      containers:
      - name: vllm
        image: vllm/vllm-openai:latest
        args:
        - --model
        - meta-llama/Llama-2-7b-chat-hf
        - --max-model-len
        - "4096"
        - --max-num-batched-tokens
        - "8192"  # 控制显存占用,防止 OOM
        resources:
          limits:
            nvidia.com/gpu: 1
        env:
        - name: CUDA_VISIBLE_DEVICES
          value: "0"
        ports:
        - containerPort: 8000

5.3 配置 KEDA 伸缩规则

定义 ScaledObject,基于 GPU 利用率(现在从 Prometheus 获取 dcgm_gpu_utilization 指标)伸缩。

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: vllm-scaler
spec:
  scaleTargetRef:
    name: vllm-deployment
  pollingInterval: 15
  minReplicaCount: 1
  maxReplicaCount: 10
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus-operated:9090
      metricName: gpu_utilization
      query: avg(dcgm_gpu_utilization{pod=~"vllm.*"})
      threshold: '70'   # GPU 利用率超过 70% 开始扩容

六、流量分发与调度

在 K8s 中,我们使用 Ingress + 服务网格(如 Istio) 将请求均匀分发至各 Pod,同时可结合 Topology Aware Routing 避免跨可用区延迟。

说明:

  1. 流量入口,负责 SSL 终结与路由。
  2. 版权声明:本文遵循 CC 4.0 BY-SA 版权协议,若要转载请务必附上原文出处链接及本声明,谢谢合作!
  3. 服务网格/负载均衡层,负责流量分发、熔断、重试。
  4. 推理 Pod,内部包含连续批处理调度器和 GPU 执行单元。

七、总结与展望

通过将 连续批处理 与 基于 GPU 指标的弹性伸缩 相结合,我们彻底告别了大模型推理服务中的 OOM 和高延迟问题。这套架构已在多家互联网企业落地,实现了吞吐量翻倍、成本大幅降低的目标。

未来,随着 NVIDIA Triton Inference Server 和 vLLM 对多节点并行推理的完善,我们还可以引入跨 Pod 的分布式连续批处理,进一步突破单卡显存限制,服务千亿级模型。

参考文献

https://engineering.intility.com/article/scaling-kubernetes-apps-with-keda

0 条回应