本教程介绍如何使用 Cloud Run 外部指标自动扩缩 (CREMA),根据自定义 GPU 指标,使用 vLLM 自动扩缩提供 LLM 服务的 Cloud Run 服务。
虽然 Cloud Run 默认使用 CPU 利用率和并发性进行自动扩缩,但 GPU 密集型推理工作负载通常需要根据队列指标(例如正在运行的请求数或 KV 缓存利用率)进行自动扩缩。CREMA 将基于 Kubernetes 的事件驱动型自动伸缩 (KEDA) 与 Cloud Run 集成,以实现由 Prometheus 指标驱动的动态伸缩。vLLM 会公开 Prometheus 指标并将其发送到 Cloud Monitoring。
目标
在此教程中,您将学习以下操作:
费用
在本文档中,您将使用 Google Cloud的以下收费组件:
如需根据您的预计使用量来估算费用,请使用价格计算器。
准备工作
- 登录您的 Google Cloud 账号。如果您是 Google Cloud新手,请 创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
Roles required to select or create a project
- Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
-
Create a project: To create a project, you need the Project Creator role
(
roles/resourcemanager.projectCreator), which contains theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
启用 Cloud Run API、Parameter Manager API、Artifact Registry API、Cloud Build API、Secret Manager API 和 Cloud Monitoring API(如果尚未启用)。
启用 API 所需的角色
如需启用 API,您需要拥有
serviceusage.services.enable权限。如果您创建了项目,则可能已经通过 Owner 角色 (roles/owner) 拥有此权限。否则,您可以通过 Service Usage Admin 角色 (roles/serviceusage.serviceUsageAdmin) 获取此权限。 了解如何授予角色。- 安装并初始化 gcloud CLI。
- 设置本教程中使用的环境变量:
将 PROJECT_ID 替换为您的 Google Cloud 项目 ID。export PROJECT_ID=PROJECT_ID export REGION=us-central1 export VLLM_SERVICE_NAME=vllm-service export MODEL_NAME=gemma-2-2b-it export REPO_NAME=vllm-repo export BUCKET_NAME=my-vllm-models-${PROJECT_ID} export CREMA_SERVICE_NAME=crema-service
- 设置项目配置:
gcloud config set project $PROJECT_ID
- 如果您还没有账号,请在 Hugging Face 上创建一个。然后,在 Hugging Face 网站上创建读取令牌。 Hugging Face 只会显示一次令牌。请将其保存在安全的位置,因为您将无法再次查看。
- 前往 Hugging Face 上的 gemma-2-2b-it 模型页面,并接受该模型的协议条款。
所需的角色
如需获得完成本教程所需的权限,请让您的管理员为您授予项目的以下 IAM 角色:
- Artifact Registry Repository Administrator (
roles/artifactregistry.repoAdmin) - Cloud Run Admin (
roles/run.admin) - IAM Admin (
roles/resourcemanager.projectIamAdmin) - Create Service Accounts (
roles/iam.serviceAccountCreator) - Service Account User (
roles/iam.serviceAccountUser) - Parameter Manager Admin (
roles/parametermanager.admin) - Monitoring Viewer (
roles/monitoring.viewer)
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
下载模型权重并将其上传到 Cloud Storage
从 Hugging Face 下载模型权重,然后将其转移到 Cloud Storage 存储桶,以便用于模型部署:
安装 Hugging Face CLI:
pip install -U "huggingface_hub[cli]"使用 Hugging Face CLI 在本地下载模型权重:
export HF_TOKEN="HF_TOKEN" export LOCAL_DIR="/tmp/$MODEL_NAME" HF_HOME=/tmp/huggingface python -m huggingface_hub.cli.hf download google/$MODEL_NAME --token $HF_TOKEN --local-dir=$LOCAL_DIR将 HF_TOKEN 替换为您的 Hugging Face 用户访问令牌。令牌应以
hf_开头,后跟 35 个随机字母数字字符(例如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)。创建 Cloud Storage 存储桶并复制下载的权重:
gcloud storage buckets create gs://$BUCKET_NAME \ --project=$PROJECT_ID \ --location=$REGION \ --uniform-bucket-level-access gcloud storage cp -r $LOCAL_DIR gs://$BUCKET_NAME/
将 vLLM 容器映像推送到 Artifact Registry
拉取模型部署容器映像,并将其推送到 Artifact Registry 中的制品库:
在 Artifact Registry 中创建 Docker 代码库:
gcloud artifacts repositories create $REPO_NAME \ --repository-format=docker \ --location=$REGION \ --description="vLLM Docker Images"向注册表验证本地 Docker 守护程序的身份:
gcloud auth configure-docker ${REGION}-docker.pkg.dev拉取 vLLM 映像,为其添加标记,然后将其推送到 Artifact Registry:
docker pull docker.io/vllm/vllm-openai:latest docker tag docker.io/vllm/vllm-openai:latest ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/vllm-openai:latest docker push ${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPO_NAME}/vllm-openai:latest
部署 CREMA 自动扩缩器服务
在部署自动扩缩器服务之前,请为 CREMA 配置服务账号角色和参数清单。
创建自定义服务账号
创建一个具有使用已配置资源所需的最低权限的自定义服务账号。 此服务账号充当自动扩缩器的身份。运行以下命令以创建 CREMA 服务账号:
export CREMA_SA="crema-autoscaler@${PROJECT_ID}.iam.gserviceaccount.com"
gcloud iam service-accounts create crema-autoscaler \
--description="Service account for Cloud Run CREMA to read metrics and scale workloads" \
--display-name="CREMA Autoscaler System"
向自定义服务账号授予其他权限
如需扩缩服务,请为自定义服务账号授予以下权限:
向您的 CREMA 服务账号授予从 Parameter Manager 读取数据的权限:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$CREMA_SA" \ --role="roles/parametermanager.parameterViewer"向您的 CREMA 服务账号授予扩缩服务的权限:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$CREMA_SA" \ --role="roles/run.developer"向您的 CREMA 服务账号授予服务账号用户角色:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$CREMA_SA" \ --role="roles/iam.serviceAccountUser"向您的 CREMA 服务账号授予查看指标的权限:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$CREMA_SA" \ --role="roles/monitoring.viewer"
创建并注册 CREMA 配置
在 CREMA 配置清单中定义伸缩阈值和规则,并在 Parameter Manager 中注册该清单:
将以下配置保存为
my-crema-config.yaml。此配置会在运行的请求数 (vllm:num_requests_running) 超过 2 时触发伸缩:apiVersion: crema/v1 kind: CremaConfig spec: pollingInterval: 15 triggerAuthentications: - metadata: name: adc-trigger-auth spec: podIdentity: provider: gcp scaledObjects: - spec: scaleTargetRef: name: projects/PROJECT_ID/locations/us-central1/services/vllm-service minReplicaCount: 1 maxReplicaCount: 5 triggers: - type: prometheus authenticationRef: name: adc-trigger-auth metadata: serverAddress: https://monitoring.googleapis.com/v1/projects/PROJECT_ID/location/global/prometheus metric: vllm:num_requests_running query: sum(vllm:num_requests_running) threshold: '2'在 Parameter Manager 中注册配置文件:
gcloud parametermanager parameters create crema-config \ --location=global \ --parameter-format=YAML gcloud parametermanager parameters versions create 1 \ --location=global \ --parameter=crema-config \ --payload-data-from-file=my-crema-config.yaml
部署 CREMA 服务
将 CREMA 映像部署为 Cloud Run 上的内部后台服务:
gcloud run deploy $CREMA_SERVICE_NAME \
--image=us-central1-docker.pkg.dev/cloud-run-oss-images/crema-v1/autoscaler:1.0 \
--region=$REGION \
--service-account="$CREMA_SA" \
--no-allow-unauthenticated \
--no-cpu-throttling \
--cpu=1 \
--memory=1Gi \
--min-instances=1 \
--max-instances=1 \
--ingress=internal \
--base-image=us-central1-docker.pkg.dev/serverless-runtimes/google-24/runtimes/java25 \
--set-env-vars="CREMA_CONFIG=projects/$PROJECT_ID/locations/global/parameters/crema-config/versions/1,OUTPUT_SCALER_METRICS=True"
配置 vLLM 服务权限
向默认的 Compute Engine 服务账号授予从 Cloud Storage 导出指标和读取模型权重的权限:
检索您的项目编号:
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')向您的服务账号授予写入指标的权限:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role="roles/monitoring.metricWriter"向您的服务账号授予从 Cloud Storage 读取模型权重的权限:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role="roles/storage.objectViewer"
部署带有 OpenTelemetry 边车的 vLLM 服务
将主 vLLM 服务容器部署到 Cloud Run,并从 Cloud Storage 装载模型权重。由于在 Cloud Run 上部署带边车容器的多容器服务需要声明性 YAML 服务规范,因此您需要配置主 vLLM 引擎以及 OpenTelemetry 边车容器收集器,以抓取和导出 vLLM 指标:
将以下多容器部署规范保存为
vllm-service.yaml:apiVersion: serving.knative.dev/v1 kind: Service metadata: name: vllm-service labels: cloud.googleapis.com/location: us-central1 annotations: run.googleapis.com/scalingMode: manual run.googleapis.com/manualInstanceCount: "1" spec: template: metadata: annotations: run.googleapis.com/execution-environment: gen2 run.googleapis.com/cpu-throttling: "false" run.googleapis.com/gpu-zonal-redundancy-disabled: "true" autoscaling.knative.dev/minScale: "1" spec: containerConcurrency: 80 nodeSelector: run.googleapis.com/accelerator: nvidia-l4 volumes: - name: gcs-volume csi: driver: gcsfuse.run.googleapis.com volumeAttributes: bucketName: my-vllm-models-PROJECT_ID containers: # Primary container: vLLM serving engine - name: vllm-container image: us-central1-docker.pkg.dev/PROJECT_ID/vllm-repo/vllm-openai:latest ports: - containerPort: 8080 resources: limits: cpu: "4" memory: 16Gi nvidia.com/gpu: "1" args: - "--model" - "/gcs/gemma-2-2b-it" - "--port" - "8080" - "--max-model-len" - "2048" - "--chat-template" - "{% for msg in messages %}{{ msg['content'] }}{% endfor %}" volumeMounts: - name: gcs-volume mountPath: /gcs startupProbe: httpGet: path: /health port: 8080 periodSeconds: 10 failureThreshold: 24 # Sidecar container: OpenTelemetry Collector - name: otel-collector image: otel/opentelemetry-collector-contrib:latest resources: limits: cpu: "1" memory: 1Gi args: - | --config=yaml: receivers: prometheus: config: scrape_configs: - job_name: 'vllm' scrape_interval: 10s metrics_path: '/metrics' static_configs: - targets: ['localhost:8080'] processors: resourcedetection: detectors: [gcp] timeout: 2s transform: metric_statements: - context: datapoint statements: - set(attributes["exported_location"], attributes["location"]) - delete_key(attributes, "location") - set(attributes["exported_cluster"], attributes["cluster"]) - delete_key(attributes, "cluster") - set(attributes["exported_namespace"], attributes["namespace"]) - delete_key(attributes, "namespace") - set(attributes["exported_job"], attributes["job"]) - delete_key(attributes, "job") - set(attributes["exported_instance"], attributes["instance"]) - delete_key(attributes, "instance") exporters: googlemanagedprometheus: service: pipelines: metrics: receivers: [prometheus] processors: [resourcedetection, transform] exporters: [googlemanagedprometheus]将现有服务配置替换为多容器清单:
gcloud run services replace vllm-service.yaml
检查 CREMA 服务日志
- 在 Google Cloud 控制台中,前往 Cloud Run 页面。
- 选择您的
crema-service。 点击日志标签页,并验证指标轮询周期是否处于活跃状态:
[INFO] [METRIC-PROVIDER] Starting metric collection cycle [INFO] [METRIC-PROVIDER] Successfully fetched scaled object metrics ... [INFO] [METRIC-PROVIDER] Sending scale request ... [INFO] [SCALER] Received ScaleRequest ... [INFO] [SCALER] Current instances ... [INFO] [SCALER] Recommended instances ...
运行负载测试
如需测试自动扩缩,请运行负载测试脚本以向 vLLM 服务发送并发请求:
在工作目录中,创建一个名为
load-test.sh的文件,并添加以下代码:#!/bin/bash export SERVICE_URL=$(gcloud run services describe $VLLM_SERVICE_NAME --region $REGION --format='value(status.url)') echo "Launching 5 parallel heavy requests to trigger autoscaling..." for i in {1..5}; do curl -s -X POST "${SERVICE_URL}/v1/chat/completions" \ -H "Authorization: Bearer $(gcloud auth print-identity-token)" \ -H "Content-Type: application/json" \ -d "{ \"model\": \"/gcs/${MODEL_NAME}\", \"messages\": [{\"role\": \"user\", \"content\": \"Write an exceptionally long, detailed, and exhaustive essay about the entire history of the universe from the Big Bang to the modern day.\"}] }" > /dev/null & done echo "All 5 requests dispatched. Waiting for requests to complete..." wait echo "Done."使脚本可执行并运行负载测试:
chmod +x load-test.sh ./load-test.sh重新检查
crema-service日志和 Cloud Run 指标信息中心,验证建议的实例数量是否会随着排队的请求而增加。
在 Cloud Monitoring 中探索 vLLM 指标
运行负载测试后,探索流量如何在 Cloud Monitoring 中影响模型部署指标:
在 Google Cloud 控制台中,前往 Cloud Monitoring 中的 Metrics Explorer 页面。
点击选择指标。
依次展开 Prometheus Target > Vllm,然后选择以
/gauge结尾的任何可用指标。例如,选择prometheus/vllm:num_requests_running/gauge可查看在负载测试期间的有效请求数。
如 vLLM 生产指标文档中所述,导出到 Cloud Monitoring 的其他 vLLM 指标包括:
prometheus/vllm:num_requests_waiting/gauge:队列中等待 vLLM 引擎处理的请求数量。prometheus/vllm:num_requests_running/gauge:在模型批次中执行的请求数。prometheus/vllm:gpu_cache_usage_perc/gauge:已使用的 GPU KV 缓存内存百分比。prometheus/vllm:num_requests_swapped/gauge:由于内存压力,KV 缓存被交换到主机 CPU 内存的请求数量。
虽然本教程是根据 vllm:num_requests_running 进行扩缩,但您可以在 CREMA 配置中使用任何这些 vLLM 指标,以根据队列大小、KV 缓存利用率或请求交换为工作负载自定义自动扩缩规则。
与将所有请求同等对待的标准 HTTP 请求并发指标不同,vLLM 的内部指标考虑了不同提示长度的动态 GPU 内存占用空间。基于 vllm:num_requests_running 的扩缩可帮助您根据实际 GPU 负载主动进行扩缩。这样一来,在服务器被迫将请求排入 vllm:num_requests_waiting 之前,系统会保持一个有效的容量缓冲区,从而保护用户免受严重的首 token 延迟时间 (TTFT) 峰值的影响。
清理
为避免您的 Google Cloud 账号产生额外费用,请删除您在本教程中部署的所有资源。
删除项目
如果您为本教程创建了一个新项目,请删除项目。 如果您使用的是某个现有项目,并且需要保留此项目但不保留在本教程中所做的更改,请删除为本教程创建的资源。
为了避免产生费用,最简单的方法是删除您为本教程创建的项目。
要删除项目,请执行以下操作:
- 在 Google Cloud 控制台中,前往管理资源页面。
- 在项目列表中,选择要删除的项目,然后点击删除。
- 在对话框中输入项目 ID,然后点击关闭以删除项目。
删除教程资源
删除您在本教程中部署的 Cloud Run 服务。Cloud Run 服务在收到请求之前不会产生费用。
如需删除 Cloud Run 服务,请运行以下命令:
gcloud run services delete SERVICE-NAME
将 SERVICE-NAME 替换为服务的名称。
您还可以通过Google Cloud 控制台删除 Cloud Run 服务。
移除您在教程设置过程中添加的
gcloud默认区域配置:gcloud config unset run/region移除项目配置:
gcloud config unset project删除分配给 Parameter Manager 的 CREMA 配置:
gcloud parametermanager parameters delete crema-config \ --location=global \ --quiet删除为 CREMA 创建的自定义服务账号:
gcloud iam service-accounts delete $CREMA_SA \ --quiet删除包含模型的 Cloud Storage 存储桶:
gcloud storage rm --recursive gs://$BUCKET_NAME删除在本教程中创建的其他 Google Cloud 资源:
- 删除 Cloud Run vLLM 服务
- 删除 CREMA 服务
- 删除 Artifact Registry 中的 Docker 代码库
后续步骤
- 详细了解 Cloud Run 上的 CREMA 自动扩缩。
- 详细了解如何在 Cloud Run 上部署 Gemma 模型。