跳到主要内容

GPU 资源管理

EKS 环境中 GPU 资源管理策略由三个轴构成。

核心问题主要技术
配置何时创建什么 GPU 节点?Karpenter、EKS Auto Mode、Managed Node Group
调度GPU Pod 放置在哪个节点?Device Plugin、DRA、Topology-Aware Routing
伸缩如何应对流量变化?KEDA、HPA、Cluster Autoscaler

本文档涵盖各轴的架构和设计判断标准。GPU 硬件分区(MIG、Time-Slicing)和 NVIDIA 软件栈请参阅 NVIDIA GPU 栈


Karpenter GPU NodePool

Karpenter v1.2+ GA

Karpenter 从 v1.0 起为 GA 状态,本文档所有示例使用 karpenter.sh/v1 API。

GPU 节点自动配置概念

Karpenter 分析 Pending Pod 的资源请求(nvidia.com/gpu、内存、CPU)自动配置最优 EC2 实例。GPU 工作负载中 Karpenter 的核心价值如下:

  • 实例多样性:单一 NodePool 支持 p4d、p5、g5、g6e 等多种 GPU 实例
  • Spot/On-Demand 混合:通过 capacity-type 调节成本和稳定性平衡
  • Consolidation:自动清理闲置 GPU 节点节省成本
  • 基于 Taint 的隔离:在 GPU 节点设置 nvidia.com/gpu taint 排除非 GPU 工作负载

NodePool 配置示例

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-inference-pool
spec:
template:
metadata:
labels:
node-type: gpu-inference
workload: genai
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand", "spot"]
- key: node.kubernetes.io/instance-type
operator: In
values:
- p4d.24xlarge # 8x A100 40GB
- p5.48xlarge # 8x H100 80GB
- g5.48xlarge # 8x A10G 24GB
- key: karpenter.k8s.aws/instance-gpu-count
operator: Gt
values: ["0"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: gpu-nodeclass
taints:
- key: nvidia.com/gpu
value: "true"
effect: NoSchedule
limits:
cpu: 1000
memory: 4000Gi
nvidia.com/gpu: 64
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30s
weight: 100

设计要点:

  • limits.nvidia.com/gpu: 64 — 集群全局 GPU 上限防止成本失控
  • disruption.consolidateAfter: 30s — GPU 节点成本高,快速清理是关键
  • weight: 100 — 多 NodePool 中本池的优先级设置

GPU 实例类型对比

实例类型GPUGPU 内存vCPU内存网络用途
p4d.24xlarge8x A10040GB x 8961152 GiB400 Gbps EFA大规模 LLM 推理
p5.48xlarge8x H10080GB x 81922048 GiB3200 Gbps EFA超大规模模型、训练
p5e.48xlarge8x H200141GB x 81922048 GiB3200 Gbps EFA大规模模型训练/推理
g5.48xlarge8x A10G24GB x 8192768 GiB100 Gbps中小规模模型推理
g6e.xlarge ~ g6e.48xlargeNVIDIA L40S最大 8x48GB最大 192最大 768 GiB最大 100 Gbps性价比推理
trn2.48xlarge16x Trainium2-1922048 GiB1600 GbpsAWS 原生训练
实例选择指南
  • p5e.48xlarge:100B+ 参数模型,利用 H200 最大内存
  • p5.48xlarge:70B+ 参数模型,需要最高性能时
  • p4d.24xlarge:13B-70B 参数模型,性价比均衡
  • g6e:13B-70B 模型,L40S 高性价比推理
  • g5.48xlarge:7B 以下模型,高性价比推理
  • trn2.48xlarge:AWS 原生训练工作负载
EKS Auto Mode

EKS Auto Mode 自动检测 GPU 工作负载并配置合适的 GPU 实例。无需单独 NodePool 设置,根据 Pod 的资源请求自动选择最优实例。


Kubernetes GPU 调度

Device Plugin 模型

Kubernetes 中使用 GPU 的基本方式是 NVIDIA Device Plugin。向 kubelet 注册 nvidia.com/gpu 扩展资源,Pod 在 resources.requests 中指定 GPU 数量。

resources:
requests:
nvidia.com/gpu: 1
limits:
nvidia.com/gpu: 1

Device Plugin 简单稳定,但只能以整 GPU 单位分配,不支持基于属性的选择(如 MIG 配置文件、特定 GPU 型号)。

Topology-Aware Routing

K8s 1.33+ 稳定化的 Topology-Aware Routing 最小化 GPU 节点间网络延迟。优先将流量路由到同一 AZ(可用区)内的 GPU 节点,特别改善多节点 Tensor 并行化工作负载的性能。

apiVersion: v1
kind: Service
metadata:
name: vllm-inference
annotations:
service.kubernetes.io/topology-mode: "Auto"
spec:
selector:
app: vllm
ports:
- port: 8000
trafficDistribution: PreferClose

Gang Scheduling

大规模 LLM 训练或 Tensor 并行推理中,多个 GPU Pod 必须同时调度。如果只有部分被放置,其余在 Pending 状态占用资源会导致死锁。

解决方法:

  • Coscheduling Plugin(scheduler-plugins):通过 PodGroup CRD 指定最小 Pod 数实现 all-or-nothing 调度
  • Volcano:批处理调度器原生支持 Gang Scheduling
  • KAI Scheduler:NVIDIA 的 GPU 感知调度器,GPU 拓扑感知 Gang Scheduling(详见 NVIDIA GPU 栈

DRA(Dynamic Resource Allocation)

概念与必要性

DRA 是克服 Device Plugin 局限的 Kubernetes 新一代 GPU 资源管理范式。

⚠️ Device Plugin 模型的根本限制
限制说明影响
静态分配节点启动时固定资源数量无法部分分配 GPU,利用率低
无法细粒度控制只能将整个 GPU 分配给 Pod不支持 GPU 分区(无法使用 MIG)
不支持优先级只能先到先得分配QoS 类不适用,难以公平分配资源
无法响应动态需求无法在运行时更改资源初始请求值固定,难以扩展
无法协调多资源无法协调多种资源类型Pod 只收到 1 个 GPU 但内存不足的情况
DRA 版本历史
  • K8s 1.26-1.30:Alpha(v1alpha2 API,需要 feature gate)
  • K8s 1.31:升级为 Beta,默认启用
  • K8s 1.32:新实现(KEP #4381),v1beta1 API
  • K8s 1.33+v1beta1 稳定化
  • K8s 1.34+DRA GA(Stable),优先级替代(prioritized alternatives)支持
  • K8s 1.35:GA,推荐生产使用

DRA 核心模型

DRA 将声明式资源请求(ResourceClaim)和即时分配分离。Pod 以属性方式请求 GPU(如"H100 GPU 1 个,MIG 3g.20gb 配置文件"),DRA Driver 与实际硬件匹配。

DRA vs Device Plugin 对比

项目Device PluginDRA
资源分配节点启动时静态注册Pod 调度时动态分配
分配单位仅完整 GPUGPU 可分割(MIG、Time-Slicing)
属性选择不可(基于索引)通过 CEL 表达式匹配 GPU 属性
多资源协调不可Pod 级别同时协调多个资源
Karpenter 兼容完全支持不支持(需要 MNG)
成熟度生产级K8s 1.34+ GA

节点配置兼容性

DRA 与 Karpenter/Auto Mode 不兼容
节点配置DRA 兼容备注
Managed Node Group支持推荐
Self-Managed Node Group支持需要手动配置
Karpenter不支持有 ResourceClaim 的 Pod 会跳过
EKS Auto Mode不支持内部基于 Karpenter,相同限制

Karpenter 无法支持 DRA 的原因:

Karpenter 分析 Pod 需求计算尚不存在节点的最优实例。在 DRA 中此计算不可能。

  1. ResourceSlice 在节点存在后才创建:DRA Driver 在节点上检测 GPU 后发布 ResourceSlice,但 Karpenter 在节点创建前就需要这些信息(鸡和蛋问题)
  2. 实例→ResourceSlice 映射缺失:Device Plugin 中 p5.48xlarge → nvidia.com/gpu: 8 可静态得知,但 DRA 中内容随 Driver 实现而变
  3. CEL 表达式模拟不可能:评估所需的 ResourceSlice 属性值在节点创建前不存在

Cluster Autoscaler 无需解析 DRA 也能工作。因为它只需"有 Pending Pod 所以扩容 MNG"这样简单的判断。

DRA 选择指南

何时使用 DRA

需要 DRA 的情况:

  • 需要 GPU 分区(MIG、Time-Slicing、MPS)
  • 多租户环境中基于 CEL 的 GPU 属性选择
  • 拓扑感知调度(NVLink、NUMA)
  • P6e-GB200 UltraServer 环境(DRA 必须)
  • K8s 1.34+ 环境

Device Plugin 足够的情况:

  • 仅需完整 GPU 单位分配
  • 正在使用 Karpenter 或 EKS Auto Mode
  • K8s 1.33 以下

KEDA GPU 自动伸缩

伸缩架构

GPU 工作负载的自动伸缩以两阶段链运作。

  1. 工作负载伸缩(KEDA/HPA):基于 GPU 指标调整 Pod 数
  2. 节点伸缩(Karpenter/CA):Pending Pod 出现时自动配置 GPU 节点

LLM 服务指标 ScaledObject

LLM 服务中比简单 GPU 使用率更敏感的伸缩信号是 KV Cache 饱和率TTFT等待队列长度

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: llm-serving-scaler
spec:
scaleTargetRef:
name: llm-serving
minReplicaCount: 2
maxReplicaCount: 10
triggers:
# KV Cache 饱和 — LLM 服务最敏感的信号
- type: prometheus
metadata:
query: avg(vllm_gpu_cache_usage_perc{model="exaone"})
threshold: "80"
# 等待中的请求数
- type: prometheus
metadata:
query: sum(vllm_num_requests_waiting{model="exaone"})
threshold: "10"
# TTFT SLO 违约临近
- type: prometheus
metadata:
query: |
histogram_quantile(0.95,
rate(vllm_time_to_first_token_seconds_bucket[5m]))
threshold: "2"

Disaggregated Serving 伸缩标准

Prefill 和 Decode 分离运营时,各角色的瓶颈信号不同。

PrefillDecode
瓶颈信号TTFT 增加、输入队列积压TPS 下降、KV Cache 饱和
伸缩标准输入 Token 处理等待时间并发生成会话数
伸缩单位GPU compute 密集GPU memory 密集

伸缩阈值推荐

工作负载类型扩容阈值缩容阈值Cooldown
实时推理GPU 70%GPU 30%60 秒
批处理GPU 85%GPU 40%300 秒
对话服务GPU 60%GPU 25%30 秒

DRA 工作负载的扩容

DRA 工作负载无法使用 Karpenter,因此以 MNG + Cluster Autoscaler + KEDA 组合构成。

LLM 指标 (KV Cache, TTFT, Queue)
→ KEDA: Pod 扩容
→ kube-scheduler: ResourceClaim 匹配尝试
├─ 成功 → 放置在现有节点
└─ 失败 → Pod Pending
→ Cluster Autoscaler: MNG +1
→ 新 GPU 节点 → 安装 DRA Driver
→ 创建 ResourceSlice → Pod 放置

成本优化策略

GPU 工作负载成本对比

推理工作负载(每小时)

Spot Instance Pricing (Inference)
ComponentPurposeAWS Integration
DCGM-ExporterCollect GPU metricsCloudWatch Container Insights
Karpenter GPU NodePoolProvision GPU nodesEC2 Spot API, CloudWatch metrics
CloudWatch DashboardVisualize GPU healthNative AWS service
CloudWatch AlarmsAlert on GPU issuesSNS notifications
IAM Roles (IRSA)Secure S3 model accessPod-level permissions

训练工作负载(每小时)

Savings Plans Pricing (Training)
ComponentPurposeScaling Trigger
KEDAPod autoscalingRedis queue depth, SQS, CloudWatch
KarpenterNode autoscalingPod pressure from KEDA scaling
ALB IngressMulti-model routingPath-based routing
Redis StreamsTask queuePersistent, distributed queue
CloudWatchObservabilityCustom metrics for latency, throughput

各成本优化策略效果

Cost Optimization Strategies Summary
ComponentPurposeCost Optimization
Dedicated NodePoolIsolate training from inferenceSpot instances, right-sized for training
Kubeflow/AWS BatchDistributed training orchestrationMulti-node GPU utilization
CheckpointingSpot interruption recoveryMinimize wasted compute
FSx for LustreHigh-throughput data accessReduce training time
EFA NetworkingLow-latency GPU communicationFaster distributed training

Karpenter 4 大成本优化策略

Karpenter GPU Workload Optimization
FeatureBenefitConfiguration
Spot + On-Demand Mix70% cost savings with automatic fallback`capacity-type: [spot, on-demand]`
Multi-Instance SupportSelect optimal GPU type per workload`instance-family: [g5, g6, p4d, p5]`
ConsolidationBin-pack pods to minimize GPU waste`consolidationPolicy: WhenUnderutilized`
Graceful DisruptionRespect PDBs during node replacement`budgets: nodes: 10%`
Fast ScalingProvision GPU nodes in under 60 secondsDirect EC2 API calls
Custom AMIsPre-loaded models and drivers`amiSelectorTerms`
策略核心机制预期节省适用对象
Spot 实例优先capacity-type: spot + 多种实例类型指定60-90%推理(stateless)工作负载
按时段 Disruption Budget工作时间 nodes: 10%,非工作时间 nodes: 50%30-40%工作时间模式明显的服务
ConsolidationWhenEmptyOrUnderutilized + consolidateAfter: 30s20-30%所有 GPU 工作负载
按工作负载实例优化小模型→g5、大模型→p5、weight 设置优先级15-25%运营多种模型大小
成本优化组合效果

推理工作负载: Spot(70%) + Consolidation(20%) + 按时段调度(30%) = 总约 85% 节省

训练工作负载: Savings Plans 1 年约定(35%) + 实验用 Spot(40%) + 检查点重启 = 总约 60% 节省

LLMOps 成本治理

与基础设施成本一起追踪 Token 级成本才能获得完整的成本可见性。

  • 基础设施层(Bifrost/LiteLLM):模型级 Token 单价、团队/项目级预算分配、月度成本报告
  • 应用层(Langfuse):Agent 工作流步骤级 Token 消费、端到端成本、基于 Trace 的瓶颈分析
Spot 实例注意事项
  • 中断处理:2 分钟前中断通知。必须通过 terminationGracePeriodSecondspreStop hook 实现优雅关闭
  • 工作负载适用性:适合无状态(stateless)推理工作负载
  • 可用性:特定实例类型的 Spot 可用性可能较低,建议指定多种类型

成本优化清单

项目说明预期节省
Spot 实例利用非生产及容错工作负载60-90%
Consolidation 启用闲置节点自动清理20-30%
Right-sizing选择匹配工作负载的实例15-25%
基于调度的伸缩非工作时间缩减资源30-40%

相关文档

参考资料