针对Kubernetes集群中的LLM推理服务,经典负载均衡方法往往基于简单的流量分配,无法处理LLM推理过程中的复杂请求和动态流量负载。本文介绍如何使用ACK 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)模型量化等优化技术,可以取得较好的大语言模型推理效率。
推理拓展负载均衡功能优势
传统HTTP路由对于传统的HTTP请求,经典负载均衡算法可以将请求均匀地发送给不同的工作负载。然而,对于LLM推理服务来说,每个请求给后端带来的负载是难以预测的。在推理过程中,请求处理包括以下两个阶段:
由于无法事先确定每个请求会输出多少Token,如果将请求均匀发送到不同工作负载,将导致每个工作负载的实际工作量不一致,造成负载不均衡。 | 推理服务路由通过推理服务器多个维度的指标来评估推理服务器的内部状态,并根据内部状态对多个推理服务器工作负载进行负载均衡。主要包括以下指标:
相对于传统的负载均衡算法,此方式可以更好地保证多个推理服务工作负载的GPU负载一致性,显著降低LLM推理请求第一个Token的响应时延(TTFT),并提升LLM推理请求的吞吐量。 |
操作流程
以下为本文操作流程示意图。
网关inference-gateway中,8080端口配置了一个标准的HTTP路由,将请求路由到后端推理服务;而8081端口则将请求路由到基于推理服务的扩展(LLM Route),再向后端推理服务转发请求。
LLM Route中,InferencePool资源通过标签选择器声明一组在集群中运行的LLM推理服务工作负载,而InferenceModel指定了InferencePool中具体模型的流量分发策略。通过配置
inference.networking.x-k8s.io/attach-to
注解,使用针对推理服务增强的负载均衡算法,将经过inference-gateway网关的8081端口的请求路由到InferencePool指定的推理服务工作负载中。
前提条件
已创建带有GPU节点池的ACK托管集群。您也可以在ACK托管集群中安装ACK Virtual Node组件,以使用ACS GPU算力。
操作步骤
步骤一:部署示例推理服务
使用以下内容,创建vllm-service.yaml。
部署示例推理服务。
kubectl apply -f vllm-service.yaml
步骤二:安装ACK Gateway with Inference Extension组件
安装ACK Gateway with Inference Extension组件,请保持勾选启用Gateway API推理扩展。
步骤三:部署并验证网关
本步骤将创建一个包含8080和8081端口的网关。
创建inference-gateway.yaml。
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: inference-gateway spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: inference-gateway spec: gatewayClassName: inference-gateway listeners: - name: http protocol: HTTP port: 8080 - name: llm-gw protocol: HTTP port: 8081 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: backend spec: parentRefs: - name: inference-gateway sectionName: http rules: - backendRefs: - group: "" kind: Service name: vllm-llama2-7b-pool port: 8000 matches: - path: type: PathPrefix value: / timeouts: request: "24h" backendRequest: "24h"
部署网关。
kubectl apply -f inference-gateway.yaml
上述配置将在集群中创建一个名为
envoy-gateway-system
的命名空间,以及名为envoy-default-inference-gateway-645xxxxx
的服务。获取网关公网IP。
kubectl get svc -n envoy-gateway-system
预期输出:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE envoy-default-inference-gateway-645xxxxx LoadBalancer 192.168.154.192 120.XXX.XXX.8 8080:30289/TCP,8081:31483/TCP 33m envoy-gateway ClusterIP 192.168.194.156 <none> 18000/TCP,18001/TCP,18002/TCP,19001/TCP 152m
记录
envoy-default-inference-gateway-645xxxxx
服务对应的EXTERNAL-IP
。验证网关在8080端口上通过正常HTTP路由到推理服务。
curl -X POST 120.XXX.XXX.8:8080/v1/chat/completions -H 'Content-Type: application/json' -d '{ "model": "/model/llama2", "max_completion_tokens": 100, "temperature": 0, "messages": [ { "role": "user", "content": "Write as if you were a critic: San Francisco" } ] }'
预期输出:
{"id":"chatcmpl-81fff6df-180c-4713-xxxxxxxxx","object":"chat.completion","created":1742285060,"model":"/model/llama2","choices":[{"index":0,"message":{"role":"assistant","content":"\n [INST] Write as if you were a critic: San Francisco [/INST]\n\n [INST] Write as if you were a critic: San Francisco [/INST]\n\n [INST] Write as if you were a critic: San Francisco [/INST]\n\n [INST] Write as if you were a critic: San Francisco [/INST]\n\n [INST] Write as if you were a critic: San Francisco [/INST]\n","tool_calls":[]},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":23,"total_tokens":123,"completion_tokens":100,"prompt_tokens_details":null},"prompt_logprobs":null}%
步骤四:部署并验证推理路由
本步骤创建InferencePool资源和InferenceModel资源。
创建inference-gateway-llm.yaml。
apiVersion: inference.networking.x-k8s.io/v1alpha1 kind: InferencePool metadata: annotations: inference.networking.x-k8s.io/attach-to: | name: inference-gateway port: 8081 name: vllm-llama2-7b-pool spec: targetPortNumber: 8000 selector: app: vllm-llama2-7b-pool extensionRef: name: inference-gateway-ext-proc --- apiVersion: inference.networking.x-k8s.io/v1alpha1 kind: InferenceModel metadata: name: inferencemodel-sample spec: modelName: /model/llama2 criticality: Critical poolRef: group: inference.networking.x-k8s.io kind: InferencePool name: vllm-llama2-7b-pool targetModels: - name: /model/llama2 weight: 100
部署推理路由。
kubectl apply -f inference-gateway-llm.yaml
验证网关在8081端口上通过推理服务扩展路由到推理服务。
curl -X POST 120.XXX.XXX.8:8081/v1/chat/completions -H 'Content-Type: application/json' -d '{ "model": "/model/llama2", "max_completion_tokens": 100, "temperature": 0, "messages": [ { "role": "user", "content": "Write as if you were a critic: San Francisco" } ] }'
预期输出:
{"id":"chatcmpl-90de7a6e-f1e8-4cd6-9e97-640xxxxxx","object":"chat.completion","created":1742285533,"model":"/model/llama2","choices":[{"index":0,"message":{"role":"assistant","content":"\n [INST] Write as if you were a critic: San Francisco [/INST]\n\n [INST] Write as if you were a critic: San Francisco [/INST]\n\n [INST] Write as if you were a critic: San Francisco [/INST]\n\n [INST] Write as if you were a critic: San Francisco [/INST]\n\n [INST] Write as if you were a critic: San Francisco [/INST]\n","tool_calls":[]},"logprobs":null,"finish_reason":"length","stop_reason":null}],"usage":{"prompt_tokens":23,"total_tokens":123,"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推理服务的可观测大盘。
预览效果:
- 本页导读 (1)
- 背景信息
- 大语言模型LLM
- vLLM
- KV Cache
- 推理拓展负载均衡功能优势
- 传统HTTP路由
- 推理服务路由
- 操作流程
- 前提条件
- 操作步骤
- 步骤一:部署示例推理服务
- 步骤二:安装ACK Gateway with Inference Extension组件
- 步骤三:部署并验证网关
- 步骤四:部署并验证推理路由
- (可选)步骤五:配置LLM服务可观测指标与可观测大盘