大模型推理服务的弹性伸缩架构——基于 GPU 指标的 HPA 策略
大模型推理服务的弹性伸缩架构——基于 GPU 指标的 HPA 策略一、问题背景与核心矛盾大模型推理服务与传统的无状态 Web 服务在资源需求上存在本质差异。传统服务以 CPU 和内存为核心指标通过 Kubernetes HPAHorizontal Pod Autoscaler即可实现较为准确的弹性伸缩。然而大模型推理服务的核心瓶颈在于 GPU 显存占用和计算利用率CPU 使用率与服务质量之间并不存在线性映射关系。在实际生产环境中曾经出现这样一个典型场景某对话服务的 GPU 利用率已经接近 95%但 CPU 使用率仅为 30%按照默认的 CPU-based HPA 策略系统并不会触发扩容导致请求排队时间从 200ms 飙升至 5s 以上。这说明基于 CPU 的伸缩策略在面对 GPU 密集型工作负载时存在根本性缺陷。核心矛盾可以归纳为以下三点GPU 利用率与 CPU 利用率不耦合CPU 指标无法反映 GPU 瓶颈。模型加载时间较长数十秒到分钟级冷启动延迟严重影响弹性响应速度。GPU 资源成本高昂过度扩容会造成显著的资源浪费。二、GPU 指标的采集与暴露要实现基于 GPU 指标的 HPA第一步是在 Kubernetes 集群中采集并暴露 GPU 相关指标。在技术选型层面DCGMNVIDIA Data Center GPU Manager是目前较为成熟的方案。/** * GPU指标采集器——通过 DCGM Exporter 的 Prometheus 接口拉取 GPU 指标 * 并将其转换为 Kubernetes Metrics API 可消费的格式。 * * 为什么用 Pull 模式而非 Push 模式避免 GPU 节点上的采集 Agent 成为性能瓶颈 * 同时保持指标采集链路与现有 Prometheus 体系的一致性。 */ Service public class GpuMetricsCollector { private static final Logger log LoggerFactory.getLogger(GpuMetricsCollector.class); private final RestTemplate restTemplate; private final String dcgmExporterUrl; public GpuMetricsCollector( Value(${monitor.dcgm.exporter.url}) String dcgmExporterUrl, RestTemplateBuilder builder) { this.dcgmExporterUrl dcgmExporterUrl; // 为什么设置较长超时GPU 指标采集涉及硬件查询响应时间可能超过默认的 1s this.restTemplate builder .connectTimeout(Duration.ofSeconds(5)) .readTimeout(Duration.ofSeconds(10)) .build(); } /** * 采集指定 GPU 设备的利用率指标。 * * param gpuDevice GPU 设备编号如 nvidia0 * return GPU 利用率0.0~1.0采集失败返回 -1 表示不可用 */ public double collectGpuUtilization(String gpuDevice) { try { String query String.format( DCGM_FI_DEV_GPU_UTIL{device\%s\}, gpuDevice); String url dcgmExporterUrl /api/v1/query?query URLEncoder.encode(query, StandardCharsets.UTF_8); ResponseEntityPrometheusResponse response restTemplate.getForEntity( url, PrometheusResponse.class); if (response.getStatusCode() HttpStatus.OK response.getBody() ! null) { return parseGpuUtilization(response.getBody()); } } catch (RestClientException e) { // 为什么记录 WARN 而非 ERROR单次采集失败不影响整体伸缩决策 // 多次失败后会通过指标缺失自动触发告警 log.warn(GPU指标采集失败, device{}, 原因{}, gpuDevice, e.getMessage()); } return -1.0; } private double parseGpuUtilization(PrometheusResponse response) { if (response.getData() null || response.getData().getResult() null || response.getData().getResult().isEmpty()) { return -1.0; } try { String value response.getData().getResult().get(0).getValue()[1]; return Double.parseDouble(value); } catch (NumberFormatException e) { log.warn(GPU利用率数值解析异常, rawValue{}, response.getData().getResult().get(0).getValue()[1]); return -1.0; } } }DCGM Exporter 将 GPU 指标暴露为 Prometheus 格式再通过 Prometheus Adapter 转换为 Kubernetes Custom Metrics API。Prometheus Adapter 的配置决定了哪些指标可供 HPA 使用。三、HPA 策略设计基于 GPU 指标的 HPA 不能简单地照搬 CPU-based HPA 的配置模式需要针对业务场景进行差异化设计。apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: llm-inference-hpa namespace: ai-inference spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: llm-inference-service minReplicas: 2 maxReplicas: 10 metrics: # GPU利用率指标 —— 在70%时扩容避免GPU算力瓶颈导致排队 - type: Pods pods: metric: name: gpu_utilization_avg target: type: AverageValue averageValue: 70 # 请求队列长度指标 —— 兜底策略防止GPU指标滞后导致的响应延迟 - type: Pods pods: metric: name: inference_request_queue_depth target: type: AverageValue averageValue: 5 behavior: scaleUp: stabilizationWindowSeconds: 60 policies: - type: Pods value: 2 periodSeconds: 60 scaleDown: stabilizationWindowSeconds: 300 policies: - type: Pods value: 1 periodSeconds: 120上述配置中包含两个关键设计GPU 利用率作为主指标目标值设为 70% 而非更高预留 30% 的缓冲空间以吸收突发流量。请求队列深度作为辅助指标在 GPU 指标尚未反映压力时提前触发扩容例如模型切换导致单请求耗时增加的情况。缩容策略设计上stabilizationWindowSeconds设为 300s5分钟避免因流量短暂回落后立即缩容而导致反复的模型加载。四、冷启动优化与模型预热大模型推理服务的一个显著痛点是冷启动时间。容器启动后需要加载模型权重到 GPU 显存对于 7B 参数级别的模型加载时间通常在 30~90 秒之间。为解决这一问题引入模型预热机制Model Pre-warming/** * 模型预热调度器——在 HPA 扩容完成后自动触发模型加载 * 确保新 Pod 在接收流量前已完成模型初始化。 * * 为什么在 PostConstruct 中执行而非构造函数 * Spring 依赖注入完成后才能获取 Service 引用构造函数阶段依赖尚未就绪。 */ Component public class ModelPreWarmScheduler { private static final Logger log LoggerFactory.getLogger(ModelPreWarmScheduler.class); private final InferenceService inferenceService; private final PodMetadataProvider podMetadataProvider; public ModelPreWarmScheduler( InferenceService inferenceService, PodMetadataProvider podMetadataProvider) { this.inferenceService inferenceService; this.podMetadataProvider podMetadataProvider; } EventListener(ContextRefreshedEvent.class) public void onApplicationReady() { String podName podMetadataProvider.getCurrentPodName(); log.info(容器启动完成, pod{}, 开始模型预热加载, podName); try { // 为什么设置 180s 超时7B 模型加载一般在 90s 内完成 // 保留 2 倍 margin 应对峰值负载下的 GPU 驱动排队 boolean success inferenceService.loadModelWithTimeout( qwen-7b-chat, Duration.ofSeconds(180)); if (success) { log.info(模型预热完成, pod{}, 准备接收流量, podName); } else { log.error(模型预热超时, pod{}, 容器将被驱逐重建, podName); // 为什么主动退出而非等待重试 // 加载超时说明 GPU 驱动或显存存在问题继续运行只会接收流量后返回错误 System.exit(1); } } catch (Exception e) { log.error(模型预热异常, pod{}, 原因{}, podName, e.getMessage(), e); System.exit(1); } } }此外配合 Kubernetes 的 Readiness Probe只有模型加载完成后才将 Pod 标记为就绪状态。五、架构总览graph TD A[Prometheus] --|Pull Metrics| B[DCGM Exporter] B --|Query GPU Stats| C[NVIDIA GPU Driver] D[Prometheus Adapter] --|Custom Metrics API| E[Kubernetes API Server] A --|Remote Write| D E --|Metrics Query| F[HPA Controller] F --|Scale Decision| G[llm-inference Deployment] G --|Create Pod| H[New Inference Pod] H --|Readiness Gate| I[Model PreWarmScheduler] I --|Load Model| C I --|Ready Signal| J[Service Endpoint] J --|Route Traffic| K[Ingress / Gateway] style F fill:#f9f,stroke:#333,stroke-width:2px style I fill:#bbf,stroke:#333,stroke-width:2px六、总结大模型推理服务的弹性伸缩是一项需要综合考虑 GPU 特性、模型加载时间、成本控制与服务质量保障的系统工程。基于 GPU 指标的多维度 HPA 策略配合模型预热机制能够在保障服务可用性的同时将 GPU 资源利用率维持在合理区间。在实际落地过程中还需要根据业务流量特征持续调优 HPA 的扩缩容参数建议配合混沌工程手段验证极端场景下的弹性能力。同时对于成本敏感的场景可以考虑配合 Spot 实例或竞价实例来降低 GPU 使用成本。GPU 显存利用率的监控与优化GPU 利用率指标并不完全等于显存利用率。一个常见误区是 GPU 利用率 70% 就认为还有 30% 的扩容空间但实际上可能是 GPU 计算单元闲置但显存已满——新的模型加载或新请求的 KV Cache 分配被显存不足阻断。DCGM 提供的DCGM_FI_DEV_FB_USEDFrame Buffer Used和DCGM_FI_DEV_FB_FREEFrame Buffer Free指标是显存监控的关键。我们在 HPA 中额外增加了显存使用率指标作为扩容信号当显存使用率超过 85% 且 GPU 利用率未达到扩容阈值时触发扩容而非缩容——因为显存已饱和意味着模型无法处理更多并发请求。HPA 与 VPA 的配合策略对于推理服务的 Batching 场景HPA 的横向扩容和 VPAVertical Pod Autoscaler的纵向扩容可以互补。HPA 增加 Pod 数量提升并发吞吐VPA 增加单 Pod 的 GPU 显存配额提升批处理上限更大的 KV Cache 空间可容纳更大的 Batch Size。两者的配合策略是优先使用 HPA 扩容到 maxReplicas若仍无法满足吞吐需求GPU 利用率持续 85% 且显存已满则触发 VPA 提升单 Pod 的 GPU 规格。