3 月 19 日下午 2 点,锁定 NVIDIA AI 网络中文专场。立即注册观看
数据科学

在 Kubernetes 上实现 NVIDIA NIM 微服务的水平自动缩放

NVIDIA NIM 微服务是可部署在 Kubernetes 上的模型推理容器。在生产环境中,了解这些微服务的计算和内存配置对于制定成功的自动扩展计划至关重要。

在本文中,我们将介绍如何通过适用于 LLMs 的 NVIDIA NIM 模型设置和使用 Kubernetes 横向 Pod 自动扩展(HPA),以便根据特定的自定义指标自动扩展和缩小微服务。

预备知识 

要遵循本教程,您需要以下预备知识列表:

  • An NVIDIA AI Enterprise license
    • 适用于 LLMs 的 NVIDIA NIM 可根据 NVIDIA AI Enterprise 许可证自行托管。在集群中为 LLMs 部署 NIM 需要生成 NGC API 密钥,以便 Kubernetes 集群可以下载容器镜像。
  • Kubernetes 集群版本 1.29 或更高版本 (我们使用的是 DGX Cloud Clusters )
  • 管理员对 Kubernetes 集群的访问权限
  • Kubernetes CLI 工具 kubectl 已安装
  • HELM CLI 已安装

设置 Kubernetes 集群

本教程中的第一步是使用适当的组件设置 Kubernetes 集群,以启用指标丢弃和 Kubernetes HPA 服务的可用性。这需要以下组件:

  • Kubernetes 指标服务器
  • Prometheus
  • Prometheus 网卡
  • Grafana

Kubernetes 指标服务器 

Metrics Server 负责从 Kubelets 中抓取资源指标,并通过 Metrics API 在 Kubernetes API Server 中公开这些指标。 Horizontal Pod Autoscaler 和 kubectl top 命令均可使用此命令。

要安装 Kubernetes Metric Server 服务器,请使用 Helm

helm repo add metrics-server https://kubernetes-sigs.github.io/metrics-server/
helm upgrade --install metrics-server metrics-server/metrics-server

Prometheus 和 Grafana 

Prometheus 和 Grafana 是用于从 Pod 中抓取指标和创建控制面板的知名工具。要安装 Prometheus 和 Grafana,请使用包含许多不同组件的 kube-prometheus-stack Helm 图表。

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install [RELEASE_NAME] prometheus-community/kube-prometheus-stack

Prometheus 网卡通过 Metrics API 在 Kubernetes apiserver 中公开 Prometheus 中截取的指标。这使 HPA 能够使用 Pod 中的自定义指标来制定扩展策略。

要在与 Prometheus 和 Grafana 相同的命名空间中安装 Prometheus 适配器,请使用以下 Helm 命令:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install <name> prometheus-community/prometheus-adapter -n <namespace>

确保 Prometheus 适配器指向正确的 Prometheus 服务端点。在这种情况下,我必须编辑部署并更正 URL。

kubectl edit deployment prom-adapter-prometheus-adapter -n prometheus
spec:
      affinity: {}
      containers:
      - args:
        - /adapter
        - --secure-port=6443
        - --cert-dir=/tmp/cert
        - --prometheus-url=http://prometheus-prometheus.prometheus.svc:9090
        - --metrics-relist-interval=1m
        - --v=4
        - --config=/etc/adapter/config.yaml
        image: registry.k8s.io/prometheus-adapter/prometheus-adapter:v0.12.0

如果一切设置正确,您应使用以下命令查看 Prometheus 中的指标:

kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/<namespace>/pods/*/gpu_cache_usage_perc?selector=app%3Dmeta-llama3-8b"

{"kind":"MetricValueList","apiVersion":"custom.metrics.k8s.io/v1beta1","metadata":{},"items":[{"describedObject":{"kind":"Pod","namespace":"<namespace>","name":"meta-llama3-70b-5db5f7dd89-tvcwl","apiVersion":"/v1"},"metricName":"gpu_cache_usage_perc","timestamp":"2025-01-02T20:13:15Z","value":"1m","selector":null},{"describedObject":{"kind":"Pod","namespace":"<namespace>","name":"meta-llama3-8b-5c6ddbbfb5-dp2mv","apiVersion":"/v1"},"metricName":"gpu_cache_usage_perc","timestamp":"2025-01-02T20:13:15Z","value":"14m","selector":null}]}

部署 NIM 微服务 

在本教程中,您将 LLM 的 NIM 用作进行扩展的微服务,特别是使用模型 meta/llama-3.1-8b-instruct 。部署 NIM 微服务有多个选项:

部署完成后,您应留意 NIM for LLMs 微服务的服务名称和命名空间,因为这将在许多命令中使用。

适用于 LLM 的 NIM 已经公开了 Prometheus 端点 ,其中包含许多有趣的指标。要查看端点,请使用以下命令:

kubectl -n <namespace> port-forward svc/<service-name> 8080

在浏览器中,转到 localhost:8080/metrics 并查找名为 gpu_cache_usage_perc 的特定指标。在本文中,您将此指标用作自动扩展的基础。此指标显示 KV 缓存的百分比利用率,并由 vLLM 堆栈 报告。

您将使用适用于 LLMs 的 NIM Grafana 控制面板来观察这些指标。下载 JSON 控制面板 并将其上传到您的 Grafana 实例。如需登录控制面板,请参阅 Grafana 访问说明。

加载适用于 LLMs 的 NIM 控制面板后,您应该会看到与图 1 相似的控制面板。(我为该控制面板部署了 70b 和 8b,因此 KV 缓存数量翻倍。)

This diagram shows a NIM LLM Grafana dashboard that displays multiple time series metric charts, for example, KV Cache Percent Utilization, Time to First Token, and Inter Token Latency.
图 1. NIM for LLMs 的 Grafana 控制面板

现在,您已经部署了可观测性堆栈和微服务,您可以开始在 Grafana 控制面板中生成流量和观察指标。生成流量的工具是 genai-perf

要从集群上的 Pod 运行此工具,请按照以下步骤操作,并确保将其安装在与 NIM for LLMs 微服务相同的命名空间中。

使用 NVIDIA Triton 创建 Pod:

kubectl run <pod-name> --image=nvcr.io/nvidia/tritonserver:24.10-py3-sdk -n <namespace> --command -- sleep 100000 

登录 Pod,现在您可以运行 genai-perf CLI:

kubectl exec --stdin --tty <pod-name> -- /bin/bash
genai-perf --help

要将流量发送到模型 meta/llama-3.1-8b-instruct,需要 genai-perf 从 Hugging Face 下载相应的标记器。从 Hugging Face 获取 API 密钥并登录。

pip install --upgrade huggingface_hub[cli]
export HF_TOKEN=<hf-token>
huggingface-cli login --token $HF_TOKEN

设置正确的环境变量并生成流量。有关不同参数的更多信息, 请参阅 genai-perf 文档。 模型名称和服务名称必须准确并反映您的设置。

export INPUT_SEQUENCE_LENGTH=200
export INPUT_SEQUENCE_STD=10
export OUTPUT_SEQUENCE_LENGTH=200
export CONCURRENCY=10
export MODEL=meta/llama-3.1-8b-instruct
genai-perf profile \
             -m $MODEL  \
             --endpoint-type chat  \
             --service-kind openai  \
             --streaming     -u meta-llama3-8b:8080    \ 
             --synthetic-input-tokens-mean $INPUT_SEQUENCE_LENGTH    \             
             --synthetic-input-tokens-stddev $INPUT_SEQUENCE_STD \
             --concurrency $CONCURRENCY    \
             --output-tokens-mean $OUTPUT_SEQUENCE_LENGTH  \
             --extra-inputs max_tokens:$OUTPUT_SEQUENCE_LENGTH   \
             --extra-inputs min_tokens:$OUTPUT_SEQUENCE_LENGTH  \
             --extra-inputs ignore_eos:true  \
             --tokenizer meta-llama/Meta-Llama-3-8B-Instruct   
             --     -v     --max-threads=256

在本文中,我创建了通过改变并发数量 (100、200、300 和 400) 来运行的多次流量生成。在 Grafana 控制面板中,您可以看到 KV 缓存利用率百分比 (图 2)。每次并发试验时,KV 缓存百分比利用率都在增加,从 100 个并发时的 9.40%一直到 400 个并发时的 40.9%。您还可以更改其他相关参数 (例如输入和输出序列长度),并观察其对 KV 缓存利用率的影响。

This diagram shows four NIM for LLMs Grafana dashboards for concurrency 100, 200, 300 and 400. The KV Cache Percent Utilization metric increases accordingly from 9.40% to 40.09%.
图 2、随着并发性的增加,KV 缓存百分比利用率得以提高

现在,您已观察到并发对 KV 缓存利用率的影响,可以创建 HPA 资源。根据 gpu_cache_usage_perc 指标创建要扩展的 HPA 资源:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: gpu-hpa-cache
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: meta-llama3-8b
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: gpu_cache_usage_perc
      target:
        type: AverageValue
        averageValue: 100m

kubectl create -f hpa-gpu-cache.yaml -n <namespace> 
kubectl get hpa -n <namepsace> -w
NAME            REFERENCE                   TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
gpu-hpa-cache   Deployment/meta-llama3-8b   9m/100m   1         10        1          3m37s

在不同并发度 (10、100、200) 下运行 genai-perf,并观察 HPA 指标增长情况:

kubectl get hpa -n <namepsace> -w
NAME            REFERENCE                   TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
gpu-hpa-cache   Deployment/meta-llama3-8b   9m/100m   1         10        1          3m37s
gpu-hpa-cache   Deployment/meta-llama3-8b   8m/100m   1         10        1          4m16s
gpu-hpa-cache   Deployment/meta-llama3-8b   1m/100m   1         10        1          4m46s
gpu-hpa-cache   Deployment/meta-llama3-8b   33m/100m   1         10        1          5m16s
gpu-hpa-cache   Deployment/meta-llama3-8b   56m/100m   1         10        1          5m46s
gpu-hpa-cache   Deployment/meta-llama3-8b   39m/100m   1         10        1          6m16s
gpu-hpa-cache   Deployment/meta-llama3-8b   208m/100m   1         10        1          6m46s
gpu-hpa-cache   Deployment/meta-llama3-8b   208m/100m   1         10        3          7m1s
gpu-hpa-cache   Deployment/meta-llama3-8b   293m/100m   1         10        3          7m16s
gpu-hpa-cache   Deployment/meta-llama3-8b   7m/100m     1         10        3          7m46s

检查 pod 的数量,您应该会看到 autoscaling 添加了两个新的 pod:

kubectl get pods -n <namespace>
NAME                                       READY   STATUS              RESTARTS      AGE
meta-llama3-8b-5c6ddbbfb5-85p6c            1/1     Running             0             25s
meta-llama3-8b-5c6ddbbfb5-dp2mv            1/1     Running             0             146m
meta-llama3-8b-5c6ddbbfb5-sf85v            1/1     Running             0             26s

HPA 也会缩小。缩小之前的等待时间由 --horizontal-pod-autoscaler-downscale-stabilization 标志决定,默认为 5 分钟。这意味着规模缩小会逐渐发生,从而消除指标值快速波动的影响。等待 5 分钟,检查缩小。

kubectl get pods -n <namespace>
NAME                                       READY   STATUS              RESTARTS      AGE
meta-llama3-8b-5c6ddbbfb5-dp2mv            1/1     Running             0             154m

结束语 

在本文中,我介绍了如何设置 Kubernetes 集群以根据自定义指标进行扩展,并展示了如何根据 KV 缓存利用率参数扩展 LLM 的 NIM。

在此主题中,有许多高级领域需要进一步探索。例如,还可以考虑使用许多其他指标进行扩展,例如请求延迟、请求吞吐量和 GPU 计算利用率。您可以 在一个 HPA 资源中基于多个指标进行扩展 ,并进行相应扩展。

另一个值得关注的领域是能够使用 Prometheus 查询语言 (PromQL) 创建新指标,并将其添加 到 Prometheus 适配器的 configmap 中,以便 HPA 进行扩展。

 

标签