大语言模型 (LLMs) 已广泛应用于聊天机器人、内容生成、摘要、分类、翻译等领域。State-of-the-art LLMs 和基础模型如 Llama , Gemma , GPT 和 Nemotron ,已经展示了类似人类的理解能力和生成能力。借助这些模型,AI 开发者无需从头开始经历昂贵且耗时的训练过程。
可应用 检索增强生成(RAG)、prompt running 和 fine-tuning 等技术来定制基础模型,并在更短的时间内针对特定任务实现更高的准确性,定制化模型可在生产环境中快速部署,满足各种用例的推理请求。
本文分步介绍了如何使用 NVIDIA TensorRT-LLM 优化 Large Language Models、如何使用 NVIDIA Triton Inference Server 部署优化模型,以及如何在 Kubernetes 环境中自动扩展 Large Language Models 部署。
NVIDIA TensorRT-LLM 是一款易于使用的 Python API,可用于定义和优化 LLM。NVIDIA Triton 推理服务器是一款开源推理服务软件,支持多个框架和硬件平台。TensorRT-LLM 提供多种优化,如 kernel fusion、quantization、in-flight batch 和 paged attention,因此可以在 NVIDIA GPUs 上高效执行使用优化模型的推理。
Triton 推理服务器支持多种深度学习和机器学习框架,包括 NVIDIA TensorRT 、TensorFlow、PyTorch 和 ONNX。它支持多种查询类型,包括实时、批处理、ensemble 或流式传输。它可以在 NVIDIA GPU、x86 和 ARM CPU 上的云、数据中心、边缘和嵌入式设备上运行。作为开发者,您可以先构建包含模型优化的 TensorRT 引擎,然后在生产环境中使用 Triton 部署优化的模型。
您可以使用 Kubernetes 将经过优化的大语言模型(LLMs)的部署从单个 GPU 扩展到多个 GPU,以低延迟、高准确度处理数千个实时推理请求,并在推理请求数量减少时缩减 GPU 数量。这对于在线购物和呼叫中心等企业特别有用,因为它们可以在高峰和非高峰时段灵活处理不同数量的推理请求,同时受益于总成本的降低,而不是购买数量最多的硬件资源来处理峰值工作负载。
Prometheus 将 Triton metrics 抓取并将其发送到 Horizontal Pod Autoscaler (HPA),以便根据推理请求的数量决定是否增加或减少部署和 GPUs 的数量。要查看此优化和部署的代码和步骤,请访问 GitHub 上的 triton-inference-server/tutorials 。
硬件和软件要求
要优化和部署模型,您需要拥有支持 TensorRT-LLM 和 Triton 推理服务器的 NVIDIA GPU。建议使用新一代 NVIDIA GPU。你可以在 TensorRT-LLM 支持矩阵 的硬件部分找到受支持的 GPU 列表。你还可以使用适当的 GPU 资源(例如 AWS EKS 、 Azure AKS 、 GCP GKE 或 OCI OKE )在公有云计算实例上部署模型。
Kubernetes 可用于自动扩展您的部署,以处理低延迟的大规模实时推理请求。要使 Kubernetes 能够发现哪些节点具有 GPU,并将其提供给在这些节点上运行的容器,请安装 Kubernetes node feature discovery service、 NVIDIA device plugin for Kubernetes、 GPU Feature Discovery service 和 NVIDIA DCGM Exporter 。你还需要安装 Prometheus ,以收集用于自动扩展的指标。请参阅详细安装步骤。
使用 TensorRT-LLM 优化 LLM
TensorRT-LLM 支持各种 state-of-the-art 模型 。您可以从 Hugging Face 下载模型检查点 ,然后使用 TensorRT-LLM 构建包含模型优化的引擎。要下载 LLM,您需要 访问令牌 。然后,您可以使用访问令牌创建 Kubernetes Secret ,该令牌将在后续的 Kubernetes Deployment 步骤中用于下载模型。
$ kubectl create secret generic hf-model-pull '--from-literal=password=<HF_access_token>'
如需详细了解 TensorRT-LLM 的工作原理,请探索 示例 ,了解如何通过优化构建热门模型的引擎以获得更好的性能,例如添加 gpt_attention_plugin
, paged_kv_cache
, gemm_plugin
, quantization
。
要生成 TensorRT 引擎文件,您可以使用 NVIDIA GPU Cloud (NGC) 上提供的具有 TensorRT-LLM 的 Triton 推理服务器的 Docker 容器镜像。要从 NGC 拉取容器镜像,您需要在 NGC 上生成 API 密钥 ,以便访问 NGC 容器。然后,使用 API 密钥登录 NGC,拉取容器镜像。
使用 TensorRT-LLM 提取 Triton 的 NGC 镜像(例如,基础镜像 nvcr.io/nvidia/tritonserver:24.08-trtllm-python-py3)后,可参考 模型准备步骤 生成 TensorRT-LLM 引擎文件。您可以根据模型大小和 GPU 显存大小配置 TP 张量并行(TP)和 pipeline 并行(PP)。请注意,生成引擎文件时,您需要最低数量的 GPU,TP*PP。
按照“Custom Container Image”步骤 和脚本创建自定义 Triton-TensorRT-LLM 镜像。构建自定义镜像后,您可以将其推送到集群可以访问的存储库。要在部署期间从私有注册表中拉取此自定义镜像,您需要使用 API 密钥创建 Kubernetes docker-registry 密钥 ,并让 Kubernetes 使用此密钥从私有注册表中拉取镜像。
在部署期间,生成的 TensorRT 引擎和计划文件存储在主机节点中,并重新映射到同一节点上的所有 Kubernetes Pod。如果以后扩展更多的 Pod,则无需生成相同的文件。
使用 Kubernetes 自动扩展 LLM 部署
使用 TensorRT-LLM 优化您的 LLM 后,您可以使用 Triton 部署模型,并使用 Kubernetes 自动扩展部署。部署用于 AI 推理的 LLM 需要三个主要步骤:
- 为 Triton 服务器创建 Kubernetes 部署
- 创建 Kubernetes Service 以将 Triton 服务器作为网络服务公开
- 使用基于 Prometheus 提取的 Triton 指标的水平 Pod 自动扩展器 (HPA) 自动扩展开部署。
用于 LLM 部署的 Helm 图表
您可以使用 Helm 图表进行部署,因为 Helm 图表易于修改和在不同环境中部署。要查找 Helm 图表,请参阅 使用 Triton 服务器和 TensorRT-LLM 自动扩展和负载平衡生成式 AI 。在 图表目录 中,Helm 预期文件如下:
chart.yaml
包含您要打包的图表的所有信息;例如,版本号和名称。
values.yaml
定义要注入模板目录的所有值,包括支持的 GPUs、LLMs、Triton 的容器镜像、image pull secrets 等。您可以创建特定于模型、自定义图像和 GPU 类型的自定义值文件,以覆盖 values.yaml
。以下示例是 gpt2_values.yaml
,用于在 NVIDIA A10G GPU 上部署 GPT-2 模型。
gpu:
- NVIDIA-A10G
model:
name: gpt2
tensorrtLlm:
parallelism:
tensor: 1
triton:
image:
pullSecrets:
-name: ngc-container-pull
name: <your custom image>
如果您有一个不适合单个 GPU 的更大模型,则可以根据模型和 GPU 大小配置 TP。例如,您可以为需要两个 GPU 的模型设置 model.tensorrtLlm.parallelism.tensor
为 2,并且每个 Kubernetes Pod 在部署中有两个 GPU。
创建 Kubernetes 部署
Kubernetes 部署 为 Kubernetes Pod 和 ReplicaSets 提供声明性更新。 deployment.yaml
为 Triton 服务器创建了一组已复制的 Pod。你可以指定要使用的 Pod 数量,如 .spec.replicas
字段所示。
.spec.containers
字段告知每个 Kubernetes Pod 在 GPU 上运行一个 Triton 服务器容器。为 Triton 服务器分别指定了端口号 8000 和 8001,用于接收来自客户端的 HPPP 和 GRPC 推理请求。端口 8002 用于收集 Triton 指标 。你可以更改 .resources.ephemeral-storage
字段,以适应模型的大小;例如,GPT-2 模型可容纳 24 GB 的 NVIDIA A10G GPU 内存。
apiVersion: apps/v1
kind: Deployment
metadata:
[…]
spec:
selector:
[…]
replicas: 1
template:
metadata:
labels:
app: {{ $.Release.Name }}
app.kubernetes.io/component: server
……
spec:
[…]
containers:
- name: triton
[...]
image: {{ $image_name }}
imagePullPolicy: IfNotPresent
[...]
ports:
- containerPort: 8000
name: http
- containerPort: 8001
name: grpc
- containerPort: 8002
name: metrics
创建 Kubernetes 服务
Kubernetes Service 是将在一组 Pod 上运行的应用程序公开为网络服务的抽象方式。 service.yaml
将 Triton 服务器公开为网络服务,因此服务器可以随时接收来自客户端的推理请求。
apiVersion: v1
kind: Service
metadata:
name: {{ $.Release.Name }}
labels:
app: {{ $.Release.Name }}
app.kubernetes.io/component: service
……
spec:
ports:
- name: http
port: 8000
targetPort: http
- name: grpc
port: 8001
targetPort: grpc
- name: metrics
port: 8002
targetPort: metrics
selector:
app: {{ $.Release.Name }}
type: ClusterIP
自动扩展 LLM 部署
要自动扩展应用程序,您需要通过检查容器、Pod 和服务来监控应用程序的性能。您可以使用 PodMonitor 或 ServiceMonitor 监控 Kubernetes Pod 或服务,以实现 Prometheus 的目标发现。Kube-Prometheus 可以帮助部署 Prometheus 并将 Prometheus 链接到指标端点。您可以使用 PodMonitor 和 Kube-Prometheus 向 Prometheus 公开 NVIDIA Triton 指标。
下方的 pod-monitor.yaml
文件使用 PodMonitor 来监控 Pod,每个 Pod 都有一个 Triton 服务器:
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: {{ $.Release.Name }}
labels:
app: {{ $.Release.Name }}
app.kubernetes.io/component: autoscaler
release: prometheus
……
spec:
selector:
matchLabels:
app: {{ $.Release.Name }}
app.kubernetes.io/component: server
podMetricsEndpoints:
- port: metrics
path: /metrics
Prometheus 可以从端口号为 8002 的所有 Kubernetes Pod 中抓取 Triton 指标 。您可以为 HPA 选择一个 Triton,或者根据需要使用收集的指标定义新的自定义指标。Prometheus 适配器可以与 Kubernetes 和 Prometheus 通信,充当两者之间的翻译器。在 Prometheus 适配器的帮助下,HPA 可以使用选定的指标根据推理请求的数量自动扩展 Kubernetes Pod 的副本数量。
在此应用中 , 我们使用名为 queue-to-compute ratio 的自定义指标作为 HPA 的指标。queue-to-compute ratio 反映推理请求的响应时间。它定义为队列时间除以 triton-metrics_prometheus-rule.yaml
中推理请求的计算时间。
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: triton-metrics
labels:
app.kubernetes.io/component: autoscaler
release: prometheus
spec:
groups:
- name: autoscaling
interval: 6s
rules:
# Average percentage of time inference requests spend in queue (not including cache hits).
- expr: rate(nv_inference_queue_duration_us[1m])/clamp_min(rate(nv_inference_compute_infer_duration_us[1m]),1)
record: triton:queue_compute:ratio
Prometheus 在 6 秒的时间间隔内抓取 Triton 指标,并使用 Triton 指标志计算自定义指标的值。然后,HPA 根据自定义指标的值上下扩展副本数量。
下方的 hpa.yaml
指定了要部署的最大和最小副本数量;例如,最多 4 个 Pod 和至少 1 个 Pod。使用 Pods
对 metrics-type
取所有 Pod 中队列与计算之比的平均值。平均队列与计算之比高于所需值 1,000(毫单位),意味着队列时间更长,或者副本数量不足以快速响应推理请求。在这种情况下,HPA 应增加副本数量,以降低队列与计算之比,直到自定义指标低于所需值;如果推理请求量减少,则反之亦然。可以根据您的要求将此目标值设置为任意数量。
{{- $metric_name := "triton:queue_compute:ratio" }}
{{- $metric_value := "1000m" }}
{{- $replicasMax := 4 }}
{{- $replicasMin := 1 }}
……
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ $.Release.Name }}
labels:
app: {{ $.Release.Name }}
app.kubernetes.io/component: autoscaler
release: prometheus
……
spec:
maxReplicas: {{ $replicasMax }}
minReplicas: {{ $replicasMin }}
metrics:
- type: Pods
pods:
metric:
name: {{ $metric_name }}
target:
type: AverageValue
averageValue: {{ $metric_value }}
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ $.Release.Name }}
配置好 Kubernetes Deployment、Service、PodMonitor 和 HPA 的 .yaml 文件后,您可以使用以下命令使用 Triton 服务器和 Kubernetes 部署模型:
$ helm install gpt2 --values ./chart/values.yaml --values ./chart/gpt2_values.yaml --set 'triton.image.name=<your custom image>' ./chart/.
NAME: gpt2
LAST DEPLOYED: Mon Aug 26 23:04:42 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
triton_trt-llm_aslb-example (0.1.0) installation complete.
Release Name: gpt2
Namespace: default
Deployment Name: gpt2
Service Name: gpt2
验证 所有 内容 是否 均按 预期 工作 。 您 应该能够看到输出信息,例如 Pod 的 NAME
、READY
和 STATUS
;Service 的 NAME
、TYPE
和 PORTS
;HPA 的 NAME
、MINPODS
、MAXPODS
和 REPLICAS
等。
$ kubectl get deployments,pods,hpa,services,podmonitors --selector='app=gpt2'
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/gpt2 1/1 1 1 11m
NAME READY STATUS RESTARTS AGE
pod/gpt2-85cfd5b6d5-4v87s 1/1 Running 0 11m
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/gpt2 Deployment/gpt2 0/1 1 4 1 11m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/gpt2 ClusterIP 10.100.56.211 <none> 8000/TCP,8001/TCP,8002/TCP 11m
NAME AGE
podmonitor.monitoring.coreos.com/gpt2 11m
例如,如果 Pod 的状态未成功运行(状态显示为 Init:CrashLoopBackOff
或 ImagePullBackOff
),您可以尝试使用以下命令来调试该问题。失败的潜在原因可能是模型或自定义镜像未成功下载、Kubernetes secrets 无法正常工作、内存不足等。
$ kubectl describe pod <pod name>
$ kubectl logs <pod name> -c init
$ kubectl logs <pod name> -c init --previous
负载均衡器
您还需要一个负载均衡器,以便在所有正在运行的 Pod 中分配工作负载。负载均衡器主要有两种类型:Layer 4 和 Layer 7。Layer 4 负载均衡在传输级别运行,并根据网络信息来管理流量,而 Layer 7 负载均衡在应用程序级别运行,并使用协议根据每个消息的内容做出决策。
您可以使用第三方负载均衡器,例如 Traefik ingress 控制器和负载均衡器 , 或 NGINX Plus ,都属于第 7 层。有关如何部署 Traefik 和 NGINX Plus 的更多信息,请参阅。如果您使用的是云服务,您还可以使用云负载均衡器。例如, AWS 负载均衡器控制器 可以同时配置应用程序和 网络负载均衡器 。安装控制器后,如果服务具有 loadBalancer
类型,您可以要求云控制器配置网络负载均衡器,如果您创建 Kubernetes ingress,您可以要求 应用程序负载均衡器 。
发送测试推理请求
最后,您可以通过从客户端发送推理请求来测试 Triton 服务器。我们提供了一个 示例客户端 文件夹,您可以从中构建客户端容器镜像:
$ docker build -f ./containers/client.containerfile -t <name> ./containers/.
接下来,将客户端文件夹中的 .yaml 文件修改为您构建的客户端容器镜像的名称。使用以下命令创建具有一个副本的客户端部署:
$ kubectl apply -f ./clients/gpt2.yaml
deployment.apps/client-gpt2 created
让客户端通过更改客户端的副本数量来增加或减少推理请求量,并检查 Pod:
$ kubectl scale deployment/client-gpt2 --replicas=10
deployment.apps/client-gpt2 scaled
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
client-gpt2-cb4bf7b74-6g82l 1/1 Running 0 16s
client-gpt2-cb4bf7b74-6lt8x 1/1 Running 0 16s
client-gpt2-cb4bf7b74-6nnvn 1/1 Running 0 16s
client-gpt2-cb4bf7b74-b7s88 1/1 Running 0 16s
client-gpt2-cb4bf7b74-fl5c6 1/1 Running 0 36s
client-gpt2-cb4bf7b74-j88ld 1/1 Running 0 16s
client-gpt2-cb4bf7b74-jdmkm 1/1 Running 0 16s
client-gpt2-cb4bf7b74-lqptv 1/1 Running 0 16s
client-gpt2-cb4bf7b74-m66cx 1/1 Running 0 16s
client-gpt2-cb4bf7b74-nt7b7 1/1 Running 0 16s
gpt2-85cfd5b6d5-65ftt 1/1 Running 0 7m57s
您可以看到运行的客户端有 10 个,这显著增加了推理请求的数量。这将增加自定义指标的值,从而导致 HPA 增加使用 GPT-2 模型的 Triton 服务器的副本数量。
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
client-gpt2-cb4bf7b74-6g82l 1/1 Running 0 56s
client-gpt2-cb4bf7b74-6lt8x 1/1 Running 0 56s
client-gpt2-cb4bf7b74-6nnvn 1/1 Running 0 56s
client-gpt2-cb4bf7b74-b7s88 1/1 Running 0 56s
client-gpt2-cb4bf7b74-fl5c6 1/1 Running 0 76s
client-gpt2-cb4bf7b74-j88ld 1/1 Running 0 56s
client-gpt2-cb4bf7b74-jdmkm 1/1 Running 0 56s
client-gpt2-cb4bf7b74-lqptv 1/1 Running 0 56s
client-gpt2-cb4bf7b74-m66cx 1/1 Running 0 56s
client-gpt2-cb4bf7b74-nt7b7 1/1 Running 0 56s
gpt2-85cfd5b6d5-65ftt 1/1 Running 0 8m37s
gpt2-85cfd5b6d5-65wg4 1/1 Running 0 22s
gpt2-85cfd5b6d5-kh9j4 1/1 Running 0 22s
gpt2-85cfd5b6d5-pdg5m 1/1 Running 0 22s
同样,如果您减少推理请求的数量(例如,将客户端数量减少到一个副本),HPA 会在几分钟后相应地将 Triton 服务器的数量减少到一个副本:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
client-gpt2-cb4bf7b74-6g82l 1/1 Running 0 11m
gpt2-85cfd5b6d5-65ftt 1/1 Running 0 19m
您还可以使用 Grafana 查询 NVIDIA Triton 指标和自定义指标,通过导航至其 metrics 端点 localhost:8080
,按时间序列可视化结果。
图 2 显示了反映这一变化的 GPU 利用率和 Queue:Compute Ratio。开始时,一个 GPU 上只运行一个 Triton 服务器副本。因此,GPU 利用率(orange 线)和 Queue:Compute Ratio 有所增加,而推理请求因客户端数量而显著增加。
为了减少 自定义指标,HPA 将 Triton 服务器的数量增加到在四个 GPU 上运行的四个副本,如 GPU 利用率 中的四行所示,这有效降低了 Queue:Compute Ratio。最终,推理请求量减少到一个客户端,因此 GPU 利用率相应降低。
开始使用
本文提供了在 Kubernetes 环境中部署 Large Language Models 和自动扩展部署的分步说明。Large Language Models 可以使用 NVIDIA TensorRT-LLM 进行优化,然后使用 NVIDIA Triton 推理服务器进行部署。Prometheus 收集 Triton 指标并与 Kubernetes 通信。HPA 可以使用自定义指标自动扩展 Pod 数量,具体取决于客户端的推理请求数量。
准备好开始使用了吗?请访问 GitHub 上的 triton-inference-server/tutorials 。学习更多关于使用 TensorRT-LLM 的 Triton。如果您想制作自己的自定义镜像,可以从 NGC 中提取 Docker 容器。