针对Kubernetes集群中的LLM推理服务,经典负载均衡方法往往基于简单的流量分配,无法处理LLM推理过程中的复杂请求和动态流量负载。本文介绍如何使用Gateway with Inference Extension组件配置推理服务扩展,以实现智能路由和高效流量管理。
背景信息
大语言模型LLM
大语言模型LLM(Large Language Model)指参数数量达到亿级别的神经网络语言模型,例如GPT、通义千问和Llama。模型在超大规模的预训练数据(预训练数据类型多样且覆盖广泛,包括大量网络文本、专业书籍和代码等内容)上进行训练得到,通常用于文本生成式任务,如补全、对话任务等。
在构建基于LLM的应用时,您可以通过两种方式获取LLM提供的文本生成能力:
可以使用类似OpenAI、阿里云百炼或Moonshot等平台提供的外部LLM API服务。
也可以基于开源或自研大模型、使用vLLM等推理服务框架构建LLM推理服务,并将LLM推理服务部署在Kubernetes集群中。这种方式适用于希望自行控制LLM推理服务或对LLM的推理能力有较高定制化需求的场景。
vLLM
vLLM是一个高效易用流行的构建LLM推理服务的框架,支持包括通义千问在内的多种常见大语言模型。vLLM通过PagedAttention优化、动态批量推理(Continuous Batching)模型量化等优化技术,可以取得较好的大语言模型推理效率。
KV Cache
操作流程
以下为本文操作流程示意图。
网关inference-gateway中,8080端口配置了一个标准的HTTP路由,将请求路由到后端推理服务;而8081端口则将请求路由到基于推理服务的扩展(LLM Route),再向后端推理服务转发请求。
在HTTP Route中,通过配置InferencePool资源来声明一组在集群中运行的LLM推理服务工作负载,配置InferenceModel指定InferencePool中具体模型的流量分发策略。从而将经过inference-gateway网关的8081端口的请求,通过针对推理服务增强的负载均衡算法路由到InferencePool指定的推理服务工作负载中。
前提条件
已创建带有GPU节点池的ACK托管集群。您也可以在ACK托管集群中安装ACK Virtual Node组件,以使用ACS GPU算力。
操作步骤
步骤一:部署示例推理服务
使用以下内容,创建vllm-service.yaml。
说明本文使用的镜像推荐ACK集群使用A10卡型,ACS GPU算力推荐使用L20(GN8IS)卡型。
同时,由于LLM镜像体积较大,建议您提前转存到ACR,使用内网地址进行拉取。直接从公网拉取的速度取决于集群EIP的带宽配置,会有较长的等待时间。
部署示例推理服务。
kubectl apply -f vllm-service.yaml
步骤二:安装Gateway with Inference Extension组件
安装Gateway with Inference Extension组件,请保持勾选启用Gateway API推理扩展。
步骤三:部署推理路由
本步骤创建InferencePool资源和InferenceModel资源。
创建inference-pool.yaml。
apiVersion: inference.networking.x-k8s.io/v1alpha2 kind: InferencePool metadata: name: vllm-qwen-pool spec: targetPortNumber: 8000 selector: app: qwen extensionRef: name: inference-gateway-ext-proc --- apiVersion: inference.networking.x-k8s.io/v1alpha2 kind: InferenceModel metadata: name: inferencemodel-qwen spec: modelName: /model/qwen criticality: Critical poolRef: group: inference.networking.x-k8s.io kind: InferencePool name: vllm-qwen-pool targetModels: - name: /model/qwen weight: 100
部署推理路由。
kubectl apply -f inference-gateway-llm.yaml
步骤四:部署并验证网关
本步骤将创建一个包含8080和8081端口的网关。
创建inference-gateway.yaml。
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: qwen-inference-gateway-class spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: qwen-inference-gateway spec: gatewayClassName: qwen-inference-gateway-class listeners: - name: http protocol: HTTP port: 8080 - name: llm-gw protocol: HTTP port: 8081 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: qwen-backend spec: parentRefs: - name: qwen-inference-gateway sectionName: llm-gw rules: - backendRefs: - group: inference.networking.x-k8s.io kind: InferencePool name: vllm-qwen-pool matches: - path: type: PathPrefix value: / --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: qwen-backend-no-inference spec: parentRefs: - group: gateway.networking.k8s.io kind: Gateway name: qwen-inference-gateway sectionName: http rules: - backendRefs: - group: "" kind: Service name: qwen port: 8000 weight: 1 matches: - path: type: PathPrefix value: / --- apiVersion: gateway.envoyproxy.io/v1alpha1 kind: BackendTrafficPolicy metadata: name: backend-timeout spec: timeout: http: requestTimeout: 1h targetRef: group: gateway.networking.k8s.io kind: Gateway name: qwen-inference-gateway
部署网关。
kubectl apply -f inference-gateway.yaml
上述配置将在集群中创建一个名为
envoy-gateway-system
的命名空间,以及名为envoy-default-inference-gateway-645xxxxx
的服务。获取网关公网IP。
export GATEWAY_HOST=$(kubectl get gateway/qwen-inference-gateway -o jsonpath='{.status.addresses[0].value}')
验证网关在8080端口上通过正常HTTP路由到推理服务。
curl -X POST ${GATEWAY_HOST}:8080/v1/chat/completions -H 'Content-Type: application/json' -d '{ "model": "/model/qwen", "max_completion_tokens": 100, "temperature": 0, "messages": [ { "role": "user", "content": "Write as if you were a critic: San Francisco" } ] }'
预期输出:
{"id":"chatcmpl-aa6438e2-d65b-4211-afb8-ae8e76e7a692","object":"chat.completion","created":1747191180,"model":"/model/qwen","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"San Francisco, a city that has long been a beacon of innovation, culture, and diversity, continues to captivate the world with its unique charm and character. As a critic, I find myself both enamored and occasionally perplexed by the city's multifaceted personality.\n\nSan Francisco's architecture is a testament to its rich history and progressive spirit. The iconic cable cars, Victorian houses, and the Golden Gate Bridge are not just tourist attractions but symbols of the city's enduring appeal. However, the","tool_calls":[]},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":39,"total_tokens":139,"completion_tokens":100,"prompt_tokens_details":null},"prompt_logprobs":null}
验证网关在8081端口上通过推理服务扩展路由到推理服务。
curl -X POST ${GATEWAY_HOST}:8081/v1/chat/completions -H 'Content-Type: application/json' -d '{ "model": "/model/qwen", "max_completion_tokens": 100, "temperature": 0, "messages": [ { "role": "user", "content": "Write as if you were a critic: Los Angeles" } ] }'
预期输出:
{"id":"chatcmpl-cc4fcd0a-6a66-4684-8dc9-284d4eb77bb7","object":"chat.completion","created":1747191969,"model":"/model/qwen","choices":[{"index":0,"message":{"role":"assistant","reasoning_content":null,"content":"Los Angeles, the sprawling metropolis often referred to as \"L.A.,\" is a city that defies easy description. It is a place where dreams are made and broken, where the sun never sets, and where the line between reality and fantasy is as blurred as the smog that often hangs over its valleys. As a critic, I find myself both captivated and perplexed by this city that is as much a state of mind as it is a physical place.\n\nOn one hand, Los","tool_calls":[]},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":39,"total_tokens":139,"completion_tokens":100,"prompt_tokens_details":null},"prompt_logprobs":null}
(可选)步骤五:配置LLM服务可观测指标与可观测大盘
本步骤需要您开通和在集群中使用阿里云Prometheus监控,可能会产生一些额外的费用。
您可以为vLLM服务Pod增加Prometheus指标采集相关的注解,通过Prometheus实例默认的服务发现机制来采集vLLM服务相关指标,监控vLLM服务的内部状态。
... annotations: prometheus.io/path: /metrics # 指标暴露的HTTP Path。 prometheus.io/port: "8000" # 指标暴露端口,即为vLLM Server的监听端口。 prometheus.io/scrape: "true" # 是否抓取当前Pod的指标。 ...
以下为部分vLLM服务提供的监控指标说明:
指标名称
说明
vllm:gpu_cache_usage_perc
vLLM的GPU缓存使用百分比。vLLM启动时,会尽可能多地预先占有一块GPU显存,用于进行KV Cache。对于vLLM服务器,利用率越低,代表GPU还有充足的空间将资源分配给新来的请求。
vllm:request_queue_time_seconds_sum
请求在等待状态排队花费的时间。LLM推理请求在到达vLLM服务器后,可能不会被立刻处理,而是需要等待被vLLM调度器调度运行预填充和解码。
vllm:num_requests_running
vllm:num_requests_waiting
vllm:num_requests_swapped
正在运行推理、正在等待和被交换到内存的请求数量。可以用来评估vLLM服务当前的请求压力。
vllm:avg_generation_throughput_toks_per_s
vllm:avg_prompt_throughput_toks_per_s
每秒被预填充阶段消耗的Token以及解码阶段生成的Token数量。
vllm:time_to_first_token_seconds_bucket
从请求发送到vLLM服务,到响应第一个Token为止的时延水平。该指标通常代表了客户端在输出请求内容后得到首个响应所需的时间,是影响LLM用户体验的重要指标。
您可以基于这些监控指标设置具体的告警规则,方便对LLM服务的运行状态进行实时监控和异常检测。
配置Grafana大盘实时监控LLM推理服务。您可以通过Grafana大盘来观测基于vLLM部署的LLM推理服务:
观测LLM服务的请求速率和整体Token吞吐量。
观测推理工作负载的内部状态。
请确保Grafana使用的数据源Prometheus实例已经采集vLLM的监控指标。将以下内容导入到Grafana,创建LLM推理服务的可观测大盘。
预览效果:
以ACK集群为例,使用vllm benchmark对推理服务进行压测,对比普通HTTP路由和推理拓展路由提供的负载均衡能力。
部署压测工作负载。
kubectl apply -f- <<EOF apiVersion: apps/v1 kind: Deployment metadata: labels: app: vllm-benchmark name: vllm-benchmark namespace: default spec: progressDeadlineSeconds: 600 replicas: 1 revisionHistoryLimit: 10 selector: matchLabels: app: vllm-benchmark strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: vllm-benchmark spec: containers: - command: - sh - -c - sleep inf image: registry-cn-hangzhou.ack.aliyuncs.com/dev/llm-benchmark:random-and-qa imagePullPolicy: IfNotPresent name: vllm-benchmark resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} terminationGracePeriodSeconds: 30 EOF
开始压测。
获取Gateway内网IP。
export GW_IP=$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-namespace=default,gateway.envoyproxy.io/owning-gateway-name=qwen-inference-gateway -o jsonpath='{.items[0].spec.clusterIP}')
执行压测。
普通HTTP路由
kubectl exec -it deploy/vllm-benchmark -- env GW_IP=${GW_IP} python3 /root/vllm/benchmarks/benchmark_serving.py \ --backend vllm \ --model /models/DeepSeek-R1-Distill-Qwen-7B \ --served-model-name /model/qwen \ --trust-remote-code \ --dataset-name random \ --random-prefix-len 10 \ --random-input-len 1550 \ --random-output-len 1800 \ --random-range-ratio 0.2 \ --num-prompts 3000 \ --max-concurrency 200 \ --host $GW_IP \ --port 8080 \ --endpoint /v1/completions \ --save-result \ 2>&1 | tee benchmark_serving.txt
推理服务路由
kubectl exec -it deploy/vllm-benchmark -- env GW_IP=${GW_IP} python3 /root/vllm/benchmarks/benchmark_serving.py \ --backend vllm \ --model /models/DeepSeek-R1-Distill-Qwen-7B \ --served-model-name /model/qwen \ --trust-remote-code \ --dataset-name random \ --random-prefix-len 10 \ --random-input-len 1550 \ --random-output-len 1800 \ --random-range-ratio 0.2 \ --num-prompts 3000 \ --max-concurrency 200 \ --host $GW_IP \ --port 8081 \ --endpoint /v1/completions \ --save-result \ 2>&1 | tee benchmark_serving.txt
两组测试完成后,可以通过大盘看到以下普通HTTP路由和推理服务扩展提供的路由能力对比效果。
可以看到,使用HTTP Route的工作负载Cache Utillzation使用率分布不平均,而LLM Route的工作负载Cache Utillzation使用率分布正常。
相关操作
Gateway with Inference Extension支持配置不同的负载均衡策略,以支持不同的推理服务使用场景。您可以通过为InferencePool资源增加inference.networking.x-k8s.io/routing-strategy
注解来配置发往该InferencePool内Pod的推理请求所应用的负载均衡策略。
以下示例指定了使用app: vllm-app
选中推理服务Pod,并将负载均衡策略指定为默认的基于推理服务器指标的负载均衡策略。
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferencePool
metadata:
name: vllm-app-pool
annotations:
inference.networking.x-k8s.io/routing-strategy: "DEFAULT"
spec:
targetPortNumber: 8000
selector:
app: vllm-app
extensionRef:
name: inference-gateway-ext-proc
目前支持的负载均衡策略有:
策略名称 | 策略说明 |
DEFAULT | 基于推理服务指标的默认负载均衡策略:通过推理服务器多个维度的指标来评估推理服务器的内部状态,并根据内部状态对多个推理服务器工作负载进行负载均衡(主要包括请求队列长度和GPU Cache利用率等指标)。 |
PREFIX_CACHE | 基于请求前缀匹配的负载均衡策略:将共享同一前缀内容的请求尽可能发送到同一个推理服务器的Pod。此策略主要适用于有大量共享前缀请求、同时推理服务器开启了“自动前缀缓存”特性的场景。 典型的使用场景如下:
|