本教程介绍如何使用 KEDA 将 GKE 工作负载缩减至零个 Pod。在非活动期间(例如周末和非办公时间),或对于间歇性工作负载(例如定期作业),将部署缩减至零个 Pod 可以节省资源。
目标
本教程介绍以下应用场景:
- 将 Pub/Sub 工作负载缩减为零:根据 Pub/Sub 主题上排队的消息数量,按比例缩放 Pod 数量。当队列为空时,工作负载会自动缩减至零个 Pod。
- 将 LLM 工作负载缩减至零。在具有 GPU 的节点上部署 LLM 模型服务器。当服务处于空闲状态时,工作负载会自动缩减至零个 Pod。
费用
在本文档中,您将使用 Google Cloud的以下收费组件:
- GKE
- GPU resources used by GKE
- Pub/Sub
您可使用价格计算器根据您的预计使用情况来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
在本教程中,您将使用 Cloud Shell 运行命令。Cloud Shell 是一种 shell 环境,用于管理在 Google Cloud上托管的资源。它预装了 Google Cloud CLI、kubectl、Helm 和 Terraform 命令行工具。如果您不使用 Cloud Shell,则必须安装 Google Cloud CLI 和 Helm。
-
如需运行此页面中的命令,请在以下开发环境之一中设置 gcloud CLI:
Cloud Shell
如需使用已设置 gcloud CLI 的在线终端,请激活 Cloud Shell:
Cloud Shell 会话会在页面底部启动,并显示命令行提示符。该会话可能需要几秒钟来完成初始化。
本地 shell
如需使用本地开发环境,请按照以下步骤操作:
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the Resource Manager, Compute Engine, GKE, Pub/Sub APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Verify that billing is enabled for your Google Cloud project.
-
Enable the Resource Manager, Compute Engine, GKE, Pub/Sub APIs.
设置环境变量:
export PROJECT_ID=PROJECT_ID export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)') export LOCATION=LOCATION
将
PROJECT_ID
替换为您的 Google Cloud项目 ID,将LOCATION
替换为应创建 GKE 集群的区域或可用区。如果您未在单次会话中完成整个教程,或者您的环境变量因某种原因而未设置,请务必再次运行此命令以再次设置变量。
创建一个启用了集群自动扩缩和 Workload Identity Federation for GKE 的 Standard GKE 集群:
gcloud container clusters create scale-to-zero \ --project=${PROJECT_ID} --location=${LOCATION} \ --machine-type=n1-standard-2 \ --enable-autoscaling --min-nodes=1 --max-nodes=5 \ --workload-pool=${PROJECT_ID}.svc.id.goog
安装 KEDA
KEDA 是一个与 Kubernetes Pod 横向自动扩缩器相辅相成的组件。借助 KEDA,您可以将 Deployment 缩减到零个 Pod,以及从零个 Pod 扩容到一个 Pod。Deployment 是一个 Kubernetes API 对象,可让您运行在集群节点中分布的多个 Pod 副本。 在 GKE 至少创建一个 Pod 后,系统会应用标准的 Pod 横向自动扩缩器算法。
GKE 将 Deployment 缩减到零个 Pod 后,由于没有 Pod 在运行,自动扩缩无法依赖 CPU 利用率等 Pod 指标。因此,KEDA 允许使用 Kubernetes External Metrics API 的实现来提取来自集群外部的指标。您可以使用此 API 根据 Pub/Sub 订阅中的未完成消息数量等指标进行自动扩缩。如需查看所有受支持的指标来源的列表,请参阅 KEDA 文档。
使用 Helm 或
kubectl
在集群上安装 KEDA。Helm
运行以下命令来添加 KEDA Helm 仓库、安装 KEDA Helm 图表并向 KEDA 服务账号授予 Cloud Monitoring 的读取权限:
helm repo add kedacore https://kedacore.github.io/charts helm repo update helm install keda kedacore/keda --create-namespace --namespace keda gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \ --role roles/monitoring.viewer \ --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda/sa/keda-operator
请注意,此命令还会设置授权规则,这些规则要求集群使用 Workload Identity Federation for GKE 进行设置。
kubectl
运行以下命令,使用
kubectl apply
安装 KEDA,并向 KEDA 服务账号授予 Cloud Monitoring 的读取权限:kubectl apply --server-side -f https://github.com/kedacore/keda/releases/download/v2.15.1/keda-2.15.1.yaml gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \ --role roles/monitoring.viewer \ --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda/sa/keda-operator
请注意,此命令还会设置授权规则,这些规则要求集群使用 Workload Identity Federation for GKE 进行设置。
确认所有 KEDA 资源都显示在
keda
命名空间下:kubectl get all -n keda
如需详细了解 KEDA 设计和资源,请参阅 KEDA 文档。
将 Pub/Sub 工作负载缩减至零
本部分介绍了一种工作负载,它会处理来自 Pub/Sub 订阅的每条消息并确认其完成。该工作负载会动态扩缩:随着未确认消息数量的增加,自动扩缩功能会实例化更多 Pod 以确保及时处理。
缩减至零可确保当一段时间内未收到任何消息时不会实例化任何 Pod。这样可以节省资源,因为避免了 Pod 长时间处于空闲状态。
部署 Pub/Sub 工作负载
部署处理在 Pub/Sub 主题上排队的消息的示例工作负载。为了模拟真实的工作负载,此示例程序会在确认消息之前等待 3 秒。工作负载配置为在
keda-pubsub-sa
服务账号下运行。运行以下命令以创建 Pub/Sub 主题和订阅、配置其权限,并在
keda-pubsub
命名空间下创建启动工作负载的 Deployment。gcloud pubsub topics create keda-echo gcloud pubsub subscriptions create keda-echo-read --topic=keda-echo gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \ --role=roles/pubsub.subscriber \ --member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda-pubsub/sa/keda-pubsub-sa kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-with-workload-identity.yaml
配置缩减至零
如需将 Pub/Sub 工作负载配置为缩减至零,请使用 KEDA 定义
ScaledObject
资源,以指定部署应如何扩缩。然后,KEDA 将自动创建和管理底层HorizontalPodAutoscaler
(HPA) 对象。创建
ScaledObject
资源以描述预期的自动扩缩行为:curl https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-scaledobject.yaml | envsubst | kubectl apply -f -
这会创建以下对象:
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: keda-pubsub namespace: keda-pubsub spec: maxReplicaCount: 5 scaleTargetRef: name: keda-pubsub triggers: - type: gcp-pubsub authenticationRef: name: keda-auth metadata: subscriptionName: "projects/${PROJECT_ID}/subscriptions/keda-echo-read"
检查 KEDA 基于
ScaledObject
对象创建的HorizontalPodAutoscaler
(HPA) 对象:kubectl get hpa keda-hpa-keda-pubsub -n keda-pubsub -o yaml
您可以在 Kubernetes 文档中详细了解自动扩缩。
等待 KEDA 确认 Pub/Sub 订阅为空,并将 Deployment 缩减为零副本。
检查工作负载自动扩缩器:
kubectl describe hpa keda-hpa-keda-pubsub -n keda-pubsub
可以看到,在命令响应中,
ScalingActive
条件为 false。关联的消息显示,Pod 横向自动扩缩器确认 KEDA 已将 Deployment 缩减至零,此时它会停止运行,直到 Deployment 重新扩容为一个 Pod。Name: keda-hpa-keda-pubsub Namespace: keda-pubsub Metrics: ( current / target ) "s0-gcp-ps-projects-[...]]" (target average value): 0 / 10 Min replicas: 1 Max replicas: 5 Deployment pods: 5 current / 5 desired Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ScaleDownStabilized recent recommendations were higher than current one [...] ScalingActive False ScalingDisabled scaling is disabled since the replica count of the target is zero ScalingLimited True TooManyReplicas the desired replica count is more than the maximum replica count
触发扩容
如需促使 Deployment 扩容,请执行以下操作:
将消息加入 Pub/Sub 主题的队列:
for num in {1..20} do gcloud pubsub topics publish keda-echo --project=${PROJECT_ID} --message="Test" done
验证 Deployment 正在扩容:
kubectl get deployments -n keda-pubsub
在输出中,可以看到到“Ready”列显示一个副本:
NAME READY UP-TO-DATE AVAILABLE AGE keda-pubsub 1/1 1 1 2d
KEDA 在观察到队列不为空后会将 Deployment 扩容。
将 LLM 工作负载缩减至零
本部分介绍部署挂接 GPU 的 Ollama 服务器的大语言模型 (LLM) 工作负载。Ollama 支持运行 Gemma 和 Llama 2 等热门 LLM,并主要通过 HTTP 公开其功能。
安装 KEDA-HTTP 插件
在非活跃期间将 HTTP 服务缩减至零个 Pod 会导致请求失败,因为没有后端来处理请求。
本部分介绍如何使用 KEDA-HTTP 插件来解决此问题。KEDA-HTTP 会启动一个 HTTP 代理,该代理接收用户请求并将其转发到已配置为缩减至零的 Service。当 Service 没有 Pod 时,代理会触发 Service 进行扩容,并缓冲请求,直到 Service 扩容到至少一个 Pod。
使用 Helm 安装 KEDA-HTTP 插件。如需了解详情,请参阅 KEDA-HTTP 文档。
helm repo add ollama-helm https://otwld.github.io/ollama-helm/ helm repo update # Set the proxy timeout to 120s, giving Ollama time to start. helm install http-add-on kedacore/keda-add-ons-http \ --create-namespace --namespace keda \ --set interceptor.responseHeaderTimeout=120s
部署 Ollama LLM 工作负载
如需部署 Ollama LLM 工作负载,请执行以下操作:
创建一个包含挂接了 GPU 的
g2-standard-4
节点的节点池,并配置集群自动扩缩功能以提供 0 到 2 个节点:gcloud container node-pools create gpu --machine-type=g2-standard-4 \ --location=${LOCATION} --cluster=scale-to-zero \ --min-nodes 0 --max-nodes 2 --num-nodes=1 --enable-autoscaling
添加官方 Ollama Helm 图表仓库,并更新本地 Helm 客户端的仓库:
helm repo add ollama-helm https://otwld.github.io/ollama-helm/ helm repo update
使用 Helm 图表部署 Ollama 服务器:
helm install ollama ollama-helm/ollama --create-namespace --namespace ollama \ -f https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/ollama/helm-values-ollama.yaml
helm-values-ollama.yaml
配置指定要加载的 LLM 模型、GPU 要求以及 Ollama 服务器的 TCP 端口。
配置缩减至零
为了将 Ollama 工作负载配置为缩减至零,KEDA-HTTP 使用
HTTPScaledObject
。创建
HTTPScaledObject
资源以描述预期的自动扩缩行为:kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/ollama/keda-ollama-httpscaledobject.yaml
这会创建
HTTPScaledObject
对象,该对象定义了以下字段:scaleTargetRef
:指定 KEDA-HTTP 应将请求转发到的 Service。在此示例中,主机为ollama.ollama
的所有请求都会路由到 Ollama 服务器。scaledownPeriod
:指定在未收到任何请求时缩减的速度(以秒为单位)。replicas
:指定要为 Ollama 部署维护的 Pod 数量下限和上限。scalingMetric
:指定用于驱动自动扩缩的指标,例如本示例中的请求速率。如需了解更多指标选项,请参阅 KEDA-HTTP 文档。
kind: HTTPScaledObject apiVersion: http.keda.sh/v1alpha1 metadata: namespace: ollama name: ollama spec: hosts: - ollama.ollama scaleTargetRef: name: ollama kind: Deployment apiVersion: apps/v1 service: ollama port: 11434 replicas: min: 0 max: 2 scaledownPeriod: 3600 scalingMetric: requestRate: targetValue: 20
运行以下命令,验证 KEDA-HTTP 已成功处理上一步中创建的
HTTPScaledObject
:kubectl get hpa,scaledobject -n ollama
输出显示
HorizontalPodAutoscaler
(由 KEDA 创建)和ScaledObject
(由 KEDA-HTTP 创建)资源:NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/keda-hpa-ollama Deployment/ollama 0/100 (avg) 1 2 1 2d NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK PAUSED AGE scaledobject.keda.sh/ollama apps/v1.Deployment ollama 0 2 external-push True False False Unknown 2d
验证 Deployment 缩减至零个 Pod。
等待
scaledownPeriod
字段中设置的时长,然后运行以下命令:kubectl get deployments -n ollama
输出显示 KEDA 缩减了 Ollama 部署,并且没有 Pod 正在运行:
NAME READY UP-TO-DATE AVAILABLE AGE ollama 0/0 0 0 2d
触发扩容
如需促使 Deployment 扩容,请使用 KEDA-HTTP 插件设置的代理来调用 Ollama 服务。这会导致请求速率指标的值增加,并触发第一个 Pod 的创建。
由于代理未对外公开,因此请使用
kubectl
端口转发功能来访问代理。kubectl port-forward svc/keda-add-ons-http-interceptor-proxy -n keda 8080:8080 & # Set the 'Host' HTTP header so that the proxy routes requests to the Ollama server. curl -H "Host: ollama.ollama" \ http://localhost:8080/api/generate \ -d '{ "model": "gemma:7b", "prompt": "Hello!" }'
curl
命令将提示“Hello!”发送到 Gemma 模型。观察响应中返回的回答令牌。如需了解 API 的规范,请参阅 Ollama 指南。清理
为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。
清理 Pub/Sub 订阅和主题:
gcloud pubsub subscriptions delete keda-echo-read gcloud pubsub topics delete keda-echo
删除 GKE 集群:
gcloud container clusters delete scale-to-zero --location=${LOCATION}
后续步骤
- 详细了解如何在 GKE 中自动扩缩 LLM 推理工作负载。
- 浏览 KEDA GitHub 代码库和文档。
设置您的环境
如需使用 Cloud Shell 设置您的环境,请按照以下步骤操作: