本教學課程說明如何使用 KEDA,將 GKE 工作負載縮減至零個 Pod。將部署項目縮減為零個 Pod,可在閒置期間 (例如週末和非上班時間) 節省資源,或用於間歇性工作負載 (例如週期性工作)。
目標
本教學課程將說明下列用途:
- 將 Pub/Sub 工作負載縮減為零:根據 Pub/Sub 主題中排入佇列的訊息數量,按比例縮減 Pod 數量。佇列為空時,工作負載會自動縮減至零個 Pod。
- 將 LLM 工作負載縮放至零。 在搭載 GPU 的節點上部署 LLM 模型伺服器。服務閒置時,工作負載會自動縮減至零個 Pod。
費用
在本文件中,您會使用下列 Google Cloud的計費元件:
- GKE
- GPU resources used by GKE
- Pub/Sub
您可以使用 Pricing Calculator,根據預測用量估算費用。
完成本文所述工作後,您可以刪除建立的資源,避免繼續計費,詳情請參閱「清除所用資源」。
事前準備
在本教學課程中,您將使用 Cloud Shell 執行指令。Cloud 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 工作階段,並顯示指令列提示。工作階段可能要幾秒鐘的時間才能初始化。
本機殼層
如要使用本機開發環境,請按照下列步驟操作:
- 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.
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.
-
Enable the Resource Manager, Compute Engine, GKE, Pub/Sub APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles. -
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.
-
Enable the Resource Manager, Compute Engine, GKE, Pub/Sub APIs.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles. 設定環境變數:
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 叢集的區域或可用區。如果您未在單一工作階段中完成整個教學課程,或環境變數因故未設定,請務必再次執行這項指令,重新設定變數。
建立啟用叢集自動調度和 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建立
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將訊息加入 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建立包含
g2-standard-4個節點的節點集區,並附加 GPU,然後將叢集自動調度資源功能設為提供零到兩個節點: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.yamlhelm-values-ollama.yaml設定會指定要載入的 LLM 模型、GPU 需求,以及 Ollama 伺服器的 TCP 連接埠。建立
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 應將要求轉送至的服務。在本範例中,所有含有主機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清除 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 中自動調度大型語言模型推論工作負載。
- 探索 KEDA GitHub 存放區和說明文件。
正在設定環境
如要使用 Cloud Shell 設定環境,請按照下列步驟操作:
安裝 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 的實作項目,擷取叢集外部的指標。您可以根據指標 (例如 Pub/Sub 訂閱中未處理的訊息數) 使用這項 API 自動調度資源。如需所有支援的指標來源清單,請參閱 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。這樣可節省資源,因為不會有 Pod 長時間閒置。
部署 Pub/Sub 工作負載
部署範例工作負載,處理 Pub/Sub 主題中排入佇列的訊息。為模擬實際工作負載,這個範例程式會在確認訊息前等待三秒。工作負載已設定為在 keda-pubsub-sa 服務帳戶下執行。
執行下列指令,在 keda-pubsub 命名空間下建立 Pub/Sub 主題和訂閱項目、設定權限,並建立啟動工作負載的部署。
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) 物件。
觸發擴大作業
如要刺激 Deployment 擴大規模,請執行下列步驟:
KEDA 觀察到佇列不為空後,會擴大 Deployment。
將 LLM 工作負載的資源調度降到零
本節說明如何部署大型語言模型 (LLM) 工作負載,並附加 GPU 來部署 Ollama 伺服器。Ollama 可執行熱門的 LLM,例如 Gemma 和 Llama 2,並主要透過 HTTP 公開其功能。
安裝 KEDA-HTTP 外掛程式
在閒置期間將 HTTP 服務縮減至零個 Pod,會導致要求失敗,因為沒有後端可處理要求。
本節說明如何使用 KEDA-HTTP 外掛程式解決這個問題。KEDA-HTTP 會啟動 HTTP Proxy,接收使用者要求並轉送至設定為縮減至零的服務。如果 Service 沒有 Pod,Proxy 會觸發 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 工作負載,請按照下列步驟操作:
設定將資源調度率降至零
如要將 Ollama 工作負載設定為縮減至零,KEDA-HTTP 會使用 HTTPScaledObject。
觸發擴大作業
如要刺激 Deployment 擴充,請使用 KEDA-HTTP 外掛程式設定的 Proxy 呼叫 Ollama 服務。這會導致要求率指標值增加,並觸發第一個 Pod 的建立作業。
由於 Proxy 不會向外公開,因此請使用 kubectl 通訊埠轉送功能存取 Proxy。
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 收取費用,請刪除含有相關資源的專案,或者保留專案但刪除個別資源。