引言
随着开源大语言模型(LLM)生态的爆发,将LLM推理服务部署到生产环境的需求急剧增长。Amazon EKS(Elastic Kubernetes Service)凭借其与AWS原生服务的深度集成、强大的可观测性以及成熟的容器编排能力,成为承载大模型推理工作负载的主流选择之一。无论是面向终端用户的实时对话接口,还是后台批量文本处理,“EKS 部署 LLM 推理服务”都能够提供企业级的高可用与弹性。本文由CnCloud(AWS官方授权高级服务合作伙伴)供稿,从推理容器化、自动扩缩和显存规划三个层面拆解部署流程,并融入实战中的常见陷阱与应对思路,帮助团队用更短的时间将模型服务平稳推上生产。
推理容器化
将LLM推理代码打包为标准的容器镜像,是EKS上运行LLM推理服务的基石。推理容器化不仅仅是编写一个Dockerfile,更涉及模型加载策略、推理框架选型、资源声明以及健康检查等一系列决策,这些决策直接影响服务的启动速度、资源利用率和可维护性。
首先,需要明确基础镜像。由于多数LLM推理框架依赖CUDA环境和特定版本的Python,推荐直接从NVIDIA官方CUDA镜像(如nvcr.io/nvidia/pytorch:23.10-py3)构建,或使用Amazon ECR上预置的Deep Learning Container(DLC)。两者均经过GPU驱动兼容性验证,能有效避免在GPU节点上因库版本不匹配导致的推理失败。接下来,将模型文件与推理代码封装进镜像。常见做法有两种:一是将模型文件直接打包进镜像,但该方法会导致镜像体积膨胀至数十GB,拖慢Pod拉取与滚动更新速度;二是采用模型挂载方式,即镜像中只包含推理代码,通过PersistentVolume(如EFS或FSx for Lustre)在Pod启动时动态挂载模型目录。第二种方案更为灵活,尤其适合多模型切换或频繁更新模型版本的场景。需要特别注意的是,使用EFS或FSx时,务必测试其吞吐和延迟是否满足推理接口的首次加载要求。例如,对于Llama-2-13B这样的模型,挂载读取阶段若IO不足会使Pod就绪时间从十秒级恶化到分钟级,此时可选择FSx for Lustre以获得更高的并行IO性能。
选定模型挂载方式后,必须认真设计容器启动命令与入口脚本。典型的推理服务会在启动时先检测模型文件是否存在,若不存在则从S3或Hugging Face Hub下载,但在生产环境更推荐将模型预置在共享存储上,避免每次Pod重启都经历漫长下载。同时,为应对大模型启动时的显存预分配与KV缓存初始化,应将就绪探针(Readiness Probe)设计为请求一次轻量推理,只有任务真正能接受请求才标记为就绪,防止Service将流量导入尚未完全就绪的Pod而引发大量5xx错误。
另一个容器化环节的常见坑是日志与标准输出的处理。LLM推理框架通常会输出大量调试信息,若直接写入标准输出,会导致容器日志膨胀并冲击EFK/Loki等日志系统的成本。建议在代码内部配置日志级别为WARN或ERROR,并利用Sidecar容器将结构化日志分流至CloudWatch Logs或S3,以降低长期存储费用。
最后,资源请求与限制的声明尤为关键。对于GPU资源,必须显式设置nvidia.com/gpu: 1(或所需数量),并利用NodeSelector与Taints/Tolerations将推理Pod调度到带有GPU的节点组上。CPU与内存的请求值应根据实际压测设定,避免因请求值过低造成节点调度拥挤,同时为内存设置硬限制以防止OOM时Pod被直接Kill从而丢失请求上下文。通过合理设计容器化清单,EKS 部署 LLM 推理服务的第一步就具备了坚实的安全性与可移植性基础。
自动扩缩
当推理服务上线后,流量往往呈现明显的潮汐特征,依靠人工调整副本数既不经济也不可靠。自动扩缩能力的强弱,直接决定EKS部署LLM推理服务的服务等级协议(SLA)达成率与资源成本。不同于常规Web服务仅参考CPU和内存利用率,大模型推理的瓶颈更多体现在GPU利用率、请求排队长度以及单次推理延迟等指标上,因此需要构建一套基于自定义指标的弹性伸缩体系。
原生的Horizontal Pod Autoscaler(HPA)虽然支持CPU/内存,但难以捕捉LLM推理负载的真实压力。一个常见做法是使用Prometheus采集推理服务的队列深度或推理延迟的百分位数(P99),然后通过KEDA(Kubernetes Event-driven Autoscaling)将自定义指标转换为HPA可消费的metric。例如,可以设置当并发请求数超过GPU数量的一定倍数(如4倍)时触发扩容,而当队列为空且持续时间超过5分钟时则执行缩容。KEDA还支持直接对接AWS SQS、Kafka等事件源,对于离线批量推理场景非常便利。另一条路径是结合AWS Karpenter作为节点级自动扩缩组件,它能根据待调度的Pod的资源需求快速启动最合适的GPU实例,弥补Cluster Autoscaler在响应速度与实例选择灵活性上的不足。
实现可靠的自动扩缩,不能只依赖无差别的线性指标,还必须设置冷却窗口与伸缩速率限制。推理服务的启动耗时往往达到2~5分钟,若缩容过快会导致Pod被终止而新请求却被拒绝;而扩容过于激进又会消耗大量GPU实例导致成本飙升。通过配置KEDA的scaleDownStabilizationWindow(如300秒)和scaledown策略,可以避免“抖动式”扩缩。同时,可利用AWS的Savings Plans或预留实例抵扣BASE层的GPU消耗,由代理渠道获得的专属折扣进一步将长期推理成本压低约30%,让弹性部分用完即走的Spot实例与预留部分形成最优组合。
以下对比表格梳理了常用的三种自动扩缩机制在LLM推理场景下的适用性:
| 扩缩机制 | 触发指标类型 | 优点 | 在LLM推理中的局限 | 建议组合使用 |
|---|---|---|---|---|
| HPA(CPU/内存) | Pod平均CPU/内存 | 配置简单,开箱即用 | LLM推理中CPU利用率与GPU压力不线性相关,扩缩滞后 | 作为基础保底,确保不因内存泄露崩溃 |
| KEDA(自定义指标) | Prometheus指标、队列长度等 | 可精准依据推理延迟、GPU利用率、请求排队数扩缩 | 需额外部署Prometheus和指标暴露逻辑 | 推荐作为主要扩缩依据,搭配HPA后备 |
| Karpenter(节点伸缩) | 待调度Pod的资源需求 | 快速选择最佳GPU实例,节省节点空闲成本 | 仅负责节点层,需配合Pod层HPA/KEDA | 用于无缝供应GPU节点,与KEDA联动 |
在工程落地中,一个容易犯错的地方是忽略推理框架的会话亲和性。如果某个请求需要维持多轮对话的KV缓存,弹性扩缩可能导致用户被路由到一个没有历史上下文的新Pod,从而使对话中断。针对这一情况,可以引入Smart Routing层或在应用侧将对话状态外置到Redis,减轻对Pod亲和性的依赖。此外,通过正确的金丝雀发布策略也能避免新版本扩容瞬间击穿后端服务,最好的实践是逐步增加新Pod权重,同时观察错误率和延迟,确保自动扩缩策略与发布流程充分对齐。
显存规划
大语言模型对GPU显存的渴求,是EKS部署LLM推理服务中最具挑战性的部分。显存规划不到位,轻则导致批处理大小被迫减小、吞吐率下降,重则引发OOM(Out of Memory)导致Pod频繁重启,服务完全不可用。因此,在启动任何Pod之前,必须对目标模型的显存占用做出精算,并结合AWS提供的多种GPU实例做出经济匹配。
估算显存占用的基础公式为:模型参数×每参数字节数 + KV缓存及激活内存。以半精度(FP16)为例,每参数占2字节,那么Llama-2-7B模型仅权重部分就需要约14 GB显存;若使用INT8量化,则降至约7 GB。除此之外,推理过程中还要为KV缓存留出大量空间,在长序列推理时KV缓存可能远超模型权重本身。例如,对于2048 token上下文、batch size为1的Llama-2-70B推理,KV缓存可能额外需要约12 GB显存。因此,部署70B模型时,通常推荐使用NVIDIA A100 80 GB实例(如p4d.24xlarge),并为张量并行预留跨GPU通信开销。
有一个典型的企业情境可帮助直观理解显存规划的决策链路:某在线教育公司希望将自训练的13B参数模型部署到EKS上,提供实时作文批改功能,要求单个请求的端到端延迟不超过2秒。技术团队首先使用vLLM框架在单张NVIDIA A10G(g5.12xlarge,24 GB显存)上测试,发现即使INT8量化,模型权重已占用13 GB,剩余的11 GB在批处理超过2时就会出现OOM。为了提升吞吐并保持低延迟,团队将模型切换至g5.24xlarge实例(4×A10G,每卡24 GB),通过vLLM的张量并行将模型切分到2张卡上,每张卡仅需负责一半参数,剩余显存足以支持batch size=4的并行推理,单请求延迟成功降至1.2秒以下。该方案的总算力成本虽高于单卡实例,但通过经由官方授权代理商购买预留实例并享受专属折扣,最终GPU成本相比按需价格节省了约30%。同时,代理渠道提供的USDT实时到账和对公转账1~2个工作日到账的支付灵活性,也方便了企业按周甚至按天动态调整云预算。这个例子表明,显存规划不是一味选择最高配实例,而是在模型精度、批处理大小和成本之间找到最佳平衡点。
在规划显存时,还需关注内存碎片化和KV缓存管理策略。推理框架如vLLM采用PagedAttention机制,能有效减少碎片并提高显存利用率,使用该技术后,同一GPU上可支持的并发用户数往往能提升2~4倍。另外,如采用DeepSpeed-Inference,可以利用ZeRO-Inference将部分权重卸载到CPU或NVMe上,进一步降低GPU显存要求,但会引入额外的PCIe延迟,适用于对延迟不太敏感的离线场景。
另一个常被忽视的陷阱是Driver与CUDA版本兼容性。随着EKS节点的AMI更新,GPU驱动版本可能发生变化,突然的升级有可能导致推理框架内置的CUDA库不匹配,进而加载模型时出现“CUDA error”或“no kernel image available”。因此,建议在容器化阶段锁定特定版本的NVIDIA驱动和CUDA工具包,并通过DaemonSet安装与容器匹配的驱动管理层。同时,利用EKS的GPU plugin监控GPU显存使用率,设置接近阈值时的告警,能有效防止突然的显存耗尽引发的服务雪崩。
结论
在EKS上部署LLM推理服务,本质上是一个将模型工程与云原生生态深度融合的过程。通过精细的容器化设计保证交付一致性,基于自定义指标的自动扩缩实现服务SLA与成本的最优平衡,以及严谨的显存规划让每一分算力都花在刀刃上,团队能够把大模型的能力稳定、经济地交付给最终用户。建议企业在落地过程中,充分压测不同实例与量化方案,并结合正规授权代理商提供的成本优化与支付便利性,持续迭代推理服务的架构,以适应未来更大规模模型落地的需求。