在 Kubernetes 上部署大模型并不难,难的是把每个请求送到真正合适的 GPU Pod。传统 Service 通常只关心 Pod 是否存活,并不了解 GPU 是否繁忙、某个实例是否正在处理长上下文请求,结果可能是部分 GPU 排队,而另一些 GPU 仍有余量。
Amazon SageMaker HyperPod Inference Gateway 是面向 Amazon EKS 的 Kubernetes 原生、GPU 感知路由组件。它利用实时 GPU 信号选择更适合处理当前推理请求的 Pod。根据发布信息,这种路由方式可将首个 token 延迟最多降低 82%,并且不要求修改模型服务器或客户端应用。
普通 Kubernetes 负载均衡为什么不够
一个典型的推理服务会在 Deployment 后面放置多个模型副本,再通过 Service 暴露统一入口:
Client -> Kubernetes Service -> model-pod-a
-> model-pod-b
-> model-pod-c
这套结构适合请求成本相近的普通 Web 服务,但生成式推理的负载并不均匀。同一个接口可能同时收到短问答、长文档总结和大批量生成请求。即使三个 Pod 都处于 Ready 状态,它们的实际压力也可能完全不同。
仅依赖通用负载均衡时,路由层通常无法回答这些问题:
- 哪个 Pod 的 GPU 当前更繁忙?
- 哪个 Pod 已经积压了推理请求?
- 哪个副本更可能尽快产出第一个 token?
- Pod 存活但 GPU 已接近饱和时,是否仍应继续分配请求?
Inference Gateway 的核心变化,就是把实时 GPU 状态纳入路由决策,而不是只在一组 Ready Pod 之间做通用分发。它优化的重点是请求落点,不是替换模型运行时。
无侵入接入意味着什么
“不修改模型服务器或客户端应用”对已有生产系统很重要。理想的迁移方式是保持两端契约不变:
- 客户端继续发送原来的 HTTP 请求;
- 模型 Pod 继续提供原来的推理 API;
- Gateway 在中间根据 GPU 信号选择后端 Pod;
- 对外保留稳定的 DNS 名称、路径和鉴权方式。
这降低了接入成本,但不代表完全不需要平台侧配置。团队仍需要按照实际版本的官方安装方式,把 add-on 部署到 EKS,并将现有服务纳入它的路由范围。具体 CRD、注解和安装参数可能随版本变化,不应在未核对文档时写死在业务清单中。
可以这样准备一个可切换的 EKS 服务
下面是一个通用的 Kubernetes 示例。假设你的模型服务器监听 8080,并提供兼容现有客户端的推理接口。运行前需要把 YOUR_REGISTRY/YOUR_MODEL_SERVER:TAG、资源规格和健康检查路径替换成实际值。
apiVersion: v1
kind: Namespace
metadata:
name: llm-serving
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: text-generation
namespace: llm-serving
spec:
replicas: 3
selector:
matchLabels:
app: text-generation
template:
metadata:
labels:
app: text-generation
spec:
containers:
- name: server
image: YOUR_REGISTRY/YOUR_MODEL_SERVER:TAG
ports:
- name: http
containerPort: 8080
resources:
limits:
nvidia.com/gpu: "1"
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: text-generation
namespace: llm-serving
spec:
selector:
app: text-generation
ports:
- name: http
port: 80
targetPort: http
应用清单并检查 GPU Pod:
kubectl apply -f inference-workload.yaml
kubectl -n llm-serving rollout status deployment/text-generation
kubectl -n llm-serving get pods -o wide
kubectl -n llm-serving get service text-generation
这段 YAML 没有假设 Inference Gateway 的具体 CRD 或注解。安装 Gateway 后,可以根据对应版本的配置方式将 text-generation 作为后端,同时尽量保持客户端访问地址不变。这样回滚时也更容易恢复原有路由路径。
用首字节时间近似检查首 token 改善
首 token 延迟应优先使用模型服务器或网关暴露的原生指标。如果暂时没有,可以用流式 HTTP 响应的首字节时间做近似验证。它不等同于严格的 TTFT,因为响应头、流式协议帧或代理缓冲也可能产生首字节,但适合快速比较切换前后的趋势。
将下面脚本保存为 measure_first_byte.py。它只使用 Python 标准库,默认发送一个 JSON 请求;请通过环境变量修改地址、模型名和提示词。
#!/usr/bin/env python3
import json
import os
import statistics
import time
import urllib.request
URL = os.environ.get("INFERENCE_URL", "http://localhost:8080/v1/chat/completions")
MODEL = os.environ.get("MODEL", "your-model")
PROMPT = os.environ.get("PROMPT", "Explain GPU-aware routing in two sentences.")
RUNS = int(os.environ.get("RUNS", "10"))
payload = json.dumps({
"model": MODEL,
"stream": True,
"messages": [{"role": "user", "content": PROMPT}],
}).encode("utf-8")
samples = []
for i in range(RUNS):
request = urllib.request.Request(
URL,
data=payload,
headers={"Content-Type": "application/json"},
method="POST",
)
started = time.perf_counter()
with urllib.request.urlopen(request, timeout=120) as response:
first_byte = response.read(1)
elapsed_ms = (time.perf_counter() - started) * 1000
if not first_byte:
raise RuntimeError("The server returned no response body")
samples.append(elapsed_ms)
print(f"run={i + 1} first_byte_ms={elapsed_ms:.1f}")
ordered = sorted(samples)
p95_index = max(0, int(len(ordered) * 0.95) - 1)
print(f"mean_ms={statistics.mean(samples):.1f}")
print(f"median_ms={statistics.median(samples):.1f}")
print(f"p95_ms={ordered[p95_index]:.1f}")
执行示例:
INFERENCE_URL="https://inference.example.com/v1/chat/completions" \
MODEL="your-model" \
RUNS=30 \
python3 measure_first_byte.py
更可靠的对比应使用相同模型、相同副本数和相同请求集,分别测试原有 Service 路由与 Gateway 路由。不要只观察平均值,还要记录 P50、P95 和 P99,并在并发压力下检查尾延迟。
上线前别只盯着 82%
“最多降低 82%”是特定测试条件下的上限结果,不是每个集群都能复现的固定收益。实际效果取决于模型大小、请求长度、批处理策略、GPU 类型、并发模式以及模型服务器自身的调度能力。
建议按以下顺序推进:
- 建立基线:记录 TTFT、请求总延迟、吞吐量、错误率和 GPU 利用率。
- 保持变量一致:对比测试期间不要同时更换模型、GPU 实例或批处理参数。
- 执行渐进式切流:先导入少量流量,确认路径、鉴权和流式响应均正常。
- 观察分布而非均值:GPU 感知路由通常更值得从尾延迟和负载偏斜角度评估。
- 保留回滚入口:确保可以迅速恢复原有 Kubernetes Service 路由。
- 核对边界条件:检查长连接、流式输出、超时、重试及客户端断开后的资源回收。
对于 GPU 负载差异明显、首 token 延迟敏感的 EKS 推理集群,这类路由层值得优先验证。它最大的价值不是改变模型,而是减少请求被送到繁忙 GPU 的概率,让已有算力得到更均衡的使用。