本文說明如何使用 Google Kubernetes Engine (GKE) 多叢集推論閘道和 GKE 自動調整功能,為 AI 推論工作負載設定彈性跨區域高可用性。透過這項設定,您可以在不同地區的多個 GKE 叢集之間,智慧地進行工作負載的負載平衡。
如要進一步瞭解 GKE 多叢集推論閘道,請參閱「關於 GKE 多叢集推論閘道」。
事前準備
啟用 Google Kubernetes Engine API。
如果您打算使用 Google Cloud CLI 執行這項工作,請安裝並初始化該工具。
使用 GKE 1.34.1-gke.1127000 以上版本。
使用 gcloud CLI 480.0.0 以上版本。
請確認節點使用的服務帳戶具備
roles/monitoring.metricWriter和roles/stackdriver.resourceMetadata.writer權限。確認您在專案中具備
roles/container.admin和roles/iam.serviceAccountAdminIdentity and Access Management (IAM) 角色。完成下列 Hugging Face 必要條件:
- 建立 Hugging Face 帳戶。
- 在 Hugging Face 上要求並取得 Llama 3.1 模型存取權。
- 在 Hugging Face 的模型頁面上簽署授權同意聲明協議。
- 生成至少具備讀取權限的 Hugging Face 存取權杖。
建立叢集和節點集區
如要在不同區域建立兩個 GKE 叢集,並設定節點集區,請按照下列步驟操作:
建立第一個叢集:
gcloud container clusters create gke-west --zone \ CLUSTER_1_ZONE \ --project=PROJECT_ID \ --gateway-api=standard \ --cluster-version=GKE_VERSION \ --machine-type="MACHINE_TYPE" \ --disk-type="DISK_TYPE" \ --enable-managed-prometheus --monitoring=SYSTEM,DCGM \ --hpa-profile=performance \ --workload-pool=PROJECT_ID.s3ns.svc.id.goog \ --async更改下列內容:
PROJECT_ID:專案 IDCLUSTER_1_ZONE:第一個叢集的區域,例如europe-west3-cGKE_VERSION:要使用的 GKE 版本,例如1.34.1-gke.1127000MACHINE_TYPE:叢集節點的機型,例如c2-standard-16DISK_TYPE:叢集節點的磁碟類型,例如pd-standard
在第一個叢集中建立 H100 節點集區:
gcloud container node-pools create h100 \ --accelerator "type=nvidia-h100-80gb,count=2,gpu-driver-version=latest" \ --project=PROJECT_ID \ --location=CLUSTER_1_ZONE \ --node-locations=CLUSTER_1_ZONE \ --cluster=CLUSTER_1_NAME \ --machine-type=NODE_POOL_MACHINE_TYPE \ --num-nodes=NUM_NODES \ --spot \ --min-nodes=MIN_NUM_NODES \ --max-nodes=MAX_NUM_NODES \ --enable-autoscaling \ --async更改下列內容:
PROJECT_ID:專案 IDCLUSTER_1_ZONE:第一個叢集的區域,例如europe-west3-cCLUSTER_1_NAME:第一個叢集的名稱,例如gke-westNODE_POOL_MACHINE_TYPE:節點集區的機型,例如a3-highgpu-2gNUM_NODES:節點集區中的節點數量,例如3MIN_NUM_NODES:節點集區中自動調度資源的節點數量下限,例如1MAX_NUM_NODES:節點集區中自動調度資源的節點數量上限,例如10
取得憑證,並在第一個叢集中建立 Hugging Face 權杖密鑰:
gcloud container clusters get-credentials CLUSTER_1_NAME \ --location CLUSTER_1_ZONE \ --project=PROJECT_ID kubectl create secret generic hf-token \ --from-literal=token=HF_TOKEN更改下列內容:
PROJECT_ID:專案 IDCLUSTER_1_NAME:第一個叢集的名稱,例如gke-westCLUSTER_1_ZONE:第一個叢集的區域,例如europe-west3-cHF_TOKEN:您的 Hugging Face 存取權杖
在與第一個叢集不同的區域中建立第二個叢集:
gcloud container clusters create gke-east --zone CLUSTER_2_ZONE \ --project=PROJECT_ID \ --gateway-api=standard \ --cluster-version=GKE_VERSION \ --machine-type="MACHINE_TYPE" \ --disk-type="DISK_TYPE" \ --enable-managed-prometheus \ --monitoring=SYSTEM,DCGM \ --hpa-profile=performance \ --workload-pool=PROJECT_ID.s3ns.svc.id.goog \ --async將
CLUSTER_2_ZONE替換為第二個叢集的區域,例如us-east4-a。為第二個叢集建立 H100 節點集區:
gcloud container node-pools create h100 \ --accelerator "type=nvidia-h100-80gb,count=2,gpu-driver-version=latest" \ --project=PROJECT_ID \ --location=CLUSTER_2_ZONE \ --node-locations=CLUSTER_2_ZONE \ --cluster=CLUSTER_2_NAME \ --machine-type=NODE_POOL_MACHINE_TYPE \ --num-nodes=NUM_NODES \ --spot \ --min-nodes=MIN_NUM_NODES \ --max-nodes=MAX_NUM_NODES \ --enable-autoscaling \ --async更改下列內容:
PROJECT_ID:專案 IDCLUSTER_2_ZONE:第二個叢集的區域,例如us-east4-aCLUSTER_2_NAME:第二個叢集的名稱,例如gke-eastNODE_POOL_MACHINE_TYPE:節點集區的機型,例如a3-highgpu-2gNUM_NODES:節點集區中的節點數量,例如3MIN_NUM_NODES:節點集區中自動調度資源的節點數量下限,例如1MAX_NUM_NODES:節點集區中自動調度資源的節點數量上限,例如10
在第二個叢集上取得憑證,並為 Hugging Face 權杖建立密鑰:
gcloud container clusters get-credentials CLUSTER_2_NAME \ --location CLUSTER_2_ZONE \ --project=PROJECT_ID kubectl create secret generic hf-token --from-literal=token=HF_TOKEN請替換下列項目。如需其他變數的定義,請參閱先前的步驟:
HF_TOKEN:您的 Hugging Face 存取權杖
將叢集註冊至機群
將叢集註冊至專案的機群:
gcloud container fleet memberships register CLUSTER_1_NAME \ --gke-cluster CLUSTER_1_ZONE/CLUSTER_1_NAME \ --location=global \ --project=PROJECT_ID gcloud container fleet memberships register CLUSTER_2_NAME \ --gke-cluster CLUSTER_2_ZONE/CLUSTER_2_NAME \ --location=global \ --project=PROJECT_ID請替換下列項目,並參閱先前的步驟,瞭解其他變數的定義:
CLUSTER_1_NAME:第一個叢集的名稱,例如gke-westCLUSTER_2_NAME:第二個叢集的名稱,例如gke-east
啟用多叢集 Ingress 功能,並指定設定叢集:
gcloud container fleet ingress enable \ --config-membership=projects/PROJECT_ID/locations/global/memberships/CLUSTER_1_NAME請替換下列項目。如需其他變數的定義,請參閱先前的步驟:
PROJECT_ID:專案 IDCLUSTER_1_NAME:第一個叢集的名稱,例如gke-west
建立僅限 Proxy 的子網路
警告: Cloud de Confiance by S3NS 每個虛擬私有雲網路在每個區域只能有一個僅限 Proxy 的子網路。如果目標地區已包含具有 purpose=REGIONAL_MANAGED_PROXY 設定的僅限 Proxy 子網路,則無法建立 GLOBAL_MANAGED_PROXY 子網路。您必須先刪除現有的區域僅限 Proxy 子網路。刪除區域僅限 Proxy 的子網路會影響該區域中所有使用該子網路的區域 Envoy 型負載平衡器,因此請據此規劃變更。
在第一個叢集的區域中建立子網路:
gcloud compute networks subnets create CLUSTER_1_REGION-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=CLUSTER_1_REGION \ --network=default \ --range=SUBNET_RANGE_1 \ --project=PROJECT_ID更改下列內容:
PROJECT_ID:專案 IDCLUSTER_1_REGION:第一個叢集的區域,例如europe-west3SUBNET_RANGE_1:第一個叢集區域中僅限 Proxy 子網路的子網路 IP 範圍,例如10.0.0.0/23
在第二個叢集的區域中建立子網路:
gcloud compute networks subnets create CLUSTER_2_REGION-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=CLUSTER_2_REGION \ --network=default \ --range=SUBNET_RANGE_2 \ --project=PROJECT_ID更改下列內容:
PROJECT_ID:專案 IDCLUSTER_2_REGION:第二個叢集的區域,例如us-east4SUBNET_RANGE_2:第二個叢集區域中僅限 Proxy 子網路的子網路 IP 範圍,例如10.5.0.0/23
安裝必要的自訂資源
定義叢集的環境變數:
CLUSTER1_CONTEXT="gke_PROJECT_ID_CLUSTER_1_ZONE_CLUSTER_1_NAME" CLUSTER2_CONTEXT="gke_PROJECT_ID_CLUSTER_2_ZONE_CLUSTER_2_NAME"更改下列內容:
PROJECT_ID:專案 IDCLUSTER_1_ZONE:第一個叢集的區域,例如europe-west3-cCLUSTER_1_NAME:第一個叢集的名稱,例如gke-westCLUSTER_2_ZONE:第二個叢集的區域,例如us-east4-aCLUSTER_2_NAME:第二個叢集的名稱,例如gke-east
在兩個叢集上安裝 InferencePool 和 InferenceObjective 自訂資源:
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v1.0.1/manifests.yaml --context=$CLUSTER1_CONTEXT kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v1.0.1/manifests.yaml --context=$CLUSTER2_CONTEXT
將資源部署至目標叢集
將模型伺服器部署至這兩個叢集:
kubectl apply -f \ https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/release-1.0/config/manifests/vllm/gpu-deployment.yaml \ --context=$CLUSTER1_CONTEXT kubectl apply -f \ https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/release-1.0/config/manifests/vllm/gpu-deployment.yaml \ --context=$CLUSTER2_CONTEXT將下列資訊清單儲存至名為
inference-objective.yaml的檔案:apiVersion: inference.networking.x-k8s.io/v1alpha2 kind: InferenceObjective metadata: name: food-review spec: priority: 10 poolRef: name: llama3-8b-instruct group: "inference.networking.k8s.io"將資訊清單套用至兩個叢集:
kubectl apply -f inference-objective.yaml --context=$CLUSTER1_CONTEXT kubectl apply -f inference-objective.yaml --context=$CLUSTER2_CONTEXT使用 Helm 將 InferencePool 資源部署至兩個叢集:
helm install vllm-llama3-8b-instruct \ --kube-context $CLUSTER1_CONTEXT \ --set inferencePool.modelServers.matchLabels.app=vllm-llama3-8b-instruct \ --set provider.name=gke \ --set inferenceExtension.monitoring.gke.enabled=true \ --version v1.0.1 \ oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepool helm install vllm-llama3-8b-instruct \ --kube-context $CLUSTER2_CONTEXT \ --set inferencePool.modelServers.matchLabels.app=vllm-llama3-8b-instruct \ --set provider.name=gke \ --set inferenceExtension.monitoring.gke.enabled=true \ --version v1.0.1 \ oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepool在兩個叢集中,將
InferencePool資源標示為已匯出:kubectl annotate inferencepool vllm-llama3-8b-instruct networking.gke.io/export="True" \ --context=$CLUSTER1_CONTEXT kubectl annotate inferencepool vllm-llama3-8b-instruct networking.gke.io/export="True" \ --context=$CLUSTER2_CONTEXT
部署跨區域 Inference Gateway
將下列資訊清單儲存為
mygateway.yaml:--- kind: Gateway apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: cross-region-gateway namespace: default spec: gatewayClassName: gke-l7-cross-regional-internal-managed-mc addresses: - type: networking.gke.io/ephemeral-ipv4-address/europe-west3 value: "europe-west3" - type: networking.gke.io/ephemeral-ipv4-address/us-east4 value: "us-east4" listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute namespaces: from: All --- apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: vllm-llama3-8b-instruct-default spec: parentRefs: - name: cross-region-gateway kind: Gateway rules: - backendRefs: - group: networking.gke.io kind: GCPInferencePoolImport name: vllm-llama3-8b-instruct --- kind: HealthCheckPolicy apiVersion: networking.gke.io/v1 metadata: name: health-check-policy namespace: default spec: targetRef: group: "networking.gke.io" kind: GCPInferencePoolImport name: vllm-llama3-8b-instruct default: config: type: HTTP httpHealthCheck: requestPath: /health port: 8000將資訊清單套用至設定叢集:
kubectl apply -f mygateway.yaml --context=CLUSTER1_CONTEXT更改下列內容:
CLUSTER1_CONTEXT:第一個叢集的情境,例如gke_my-project_europe-west3-c_gke-west
啟用自訂指標回報功能
建立名為
metrics.yaml的檔案,並加入以下內容:apiVersion: autoscaling.gke.io/v1beta1 kind: AutoscalingMetric metadata: name: gpu-cache namespace: default spec: selector: matchLabels: app: vllm-llama3-8b-instruct endpoints: - port: 8000 path: /metrics metrics: - name: vllm:kv_cache_usage_perc exportName: kv-cache - name: vllm:gpu_cache_usage_perc exportName: kv-cache-old針對每個叢集套用指標設定:
kubectl apply -f metrics.yaml --context=CLUSTER1_CONTEXT kubectl apply -f metrics.yaml --context=CLUSTER2_CONTEXT如要瞭解
CLUSTER1_CONTEXT和CLUSTER2_CONTEXT的定義,請參閱安裝必要的自訂資源。
設定負載平衡政策
本節說明如何設定負載平衡政策。這項政策會根據自訂指標和地區偏好設定,定義流量在推論集區的分配方式。下列設定會將 us-east4 設為偏好區域。只有當 us-east4 區域的 gke.named_metrics.kv-cache 自訂指標達到 80% 的使用率時,流量才會溢流至其他區域。
- 如果是 vLLM v0.10.2 以上版本,請使用
gke.named_metrics.kv-cache指標。 - 如果是較舊版本,請使用
gke.named_metrics.kv-cache-old指標。
建立名為
backend-policy.yaml的檔案,並加入以下內容:kind: GCPBackendPolicy apiVersion: networking.gke.io/v1 metadata: name: my-backend-policy spec: targetRef: group: "networking.gke.io" kind: GCPInferencePoolImport name: vllm-llama3-8b-instruct default: timeoutSec: 600 balancingMode: CUSTOM_METRICS trafficDuration: LONG customMetrics: - name: gke.named_metrics.kv-cache maxUtilizationPercent: 80 dryRun: false scopes: - selector: gke.io/region: "us-east4" backendPreference: PREFERRED套用新政策:
kubectl apply -f backend-policy.yaml --context=CLUSTER1_CONTEXT將
CLUSTER1_CONTEXT替換為第一個叢集的內容,例如gke_my-project_europe-west3-c_gke-west
設定自動調度資源功能
為確保每個叢集都能處理不斷增加的負載,避免流量溢出至其他區域,您需要為模型伺服器部署作業設定 Horizontal-Pod-Autoscaler (HPA)。
重要設定原則
使用相同的自訂指標:應將 HPA 設為根據您在
GCPBackendPolicy中使用的相同自訂指標,調整多叢集推論閘道 (例如vllm:kv_cache_usage_perc) 的資源配置。這種做法可確保負載平衡和資源調度決策都是根據推論伺服器發出的相同信號。所選指標的值必須介於 0 到 1 之間,代表使用率。如果指標值大於 1,表示負載平衡器使用率為 100%,可能會導致非預期的路由行為。設定較低的 HPA 目標:HPA 設定中的指標目標值必須低於
maxUtilizationPercent設定中定義的GCPBackendPolicy。將 HPA 的目標使用率調低 (例如,HPA 在平均使用率達到 50% 時進行資源調度),即可在負載平衡器的門檻 (例如使用率達到 80%) 之前,讓叢集新增更多副本。這種做法有助於在偏好區域內盡量提高容量。此外,如果使用率目標較低,系統就會預留彈性跨區域高可用性,以防目前區域的流量接近上限,有助於避免流量過早溢出。
授予使用者權限,使其能夠建立必要的授權角色:
kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole cluster-admin --user "$(gcloud config get-value account)" --context=CLUSTER1_CONTEXT kubectl create clusterrolebinding cluster-admin-binding \ --clusterrole cluster-admin --user "$(gcloud config get-value account)" --context=CLUSTER2_CONTEXT針對每個叢集套用資訊清單:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml --context=CLUSTER1_CONTEXT kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml --context=CLUSTER2_CONTEXT允許
custom-metrics-stackdriver-adapter服務帳戶讀取 Cloud Monitoring 指標:PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") 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.s3ns.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter將
PROJECT_ID替換為您的專案 ID將下列資訊清單儲存至名為
pod-monitoring.yaml的檔案:apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: inference-server-podmon spec: selector: matchLabels: app: vllm-llama3-8b-instruct endpoints: - port: 8000 path: /metrics interval: 5s將資訊清單套用至兩個叢集:
kubectl apply -f pod-monitoring.yaml --context=CLUSTER1_CONTEXT kubectl apply -f pod-monitoring.yaml --context=CLUSTER2_CONTEXT將下列資訊清單儲存至名為
hpa.yaml的檔案:apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: inference-server-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: vllm-llama3-8b-instruct minReplicas: 1 maxReplicas: 10 metrics: - type: Pods pods: metric: name: prometheus.googleapis.com|vllm:gpu_cache_usage_perc|gauge target: type: AverageValue averageValue: "0.5"將資訊清單套用至兩個叢集:
kubectl apply -f hpa.yaml --context=CLUSTER1_CONTEXT kubectl apply -f hpa.yaml --context=CLUSTER2_CONTEXT
驗證 Deployment
取得閘道 IP 位址:
export GW_IP=$(kubectl get gateway/cross-region-gateway -n default --context=CLUSTER1_CONTEXT -o jsonpath='{.status.addresses[0].value}') echo ${GW_IP}在臨時 Pod 中啟動互動式
sh工作階段:kubectl run -it --rm --image=curlimages/curl curly --context=CLUSTER1_CONTEXT -- /bin/sh從
curlyPod 內部傳送測試要求:curl -i -X POST <var>GW_IP</var>:80/v1/completions \ -H 'Content-Type: application/json' \ -d '{ "model": "food-review-1", "prompt": "What is the best pizza in the world?", "max_tokens": 100, "temperature": 0 }'將
GW_IP替換為上一個步驟中的閘道 IP 位址。
對閘道執行負載測試
使用相同虛擬私有雲網路中的負載產生器,對閘道 IP 位址套用持續負載。
首先,請從您預期偏好區域 (
us-east4) 可處理的適中負載開始。逐漸提高負載測試的要求比率或並行數量。
執行負載測試時,請在 Cloud de Confiance 控制台或使用
kubectl監控系統:- Pod 調度 (HPA):檢查兩個叢集中的
vllm-llama3-8b-instructDeployment 內 Pod 數量。 - 節點調度 (叢集自動配置器):監控兩個叢集中的
h100節點集區內的節點數量。 - 自訂指標:在兩個叢集的模型伺服器部署作業中,於 Monitoring 監控
vllm:kv_cache_usage_perc指標 (適用於 vllm v0.10.2 以上版本) 或vllm:gpu_cache_usage_perc指標 (適用於 vllm v.0.10.2 以下版本)。 - 負載平衡器指標:在 Monitoring 中檢查與
cross-region-gateway相關聯的負載平衡器指標。
- Pod 調度 (HPA):檢查兩個叢集中的
隨著負載增加,us-east4中的使用率也會提高。當 gke-east 叢集中的 HPA 擴大,且平均用量接近 GCPBackendPolicy 中定義的 maxUtilization 值 (80%) 時,負載平衡器就會開始將要求路由至 europe-west3 中的 gke-west 叢集。
後續步驟
- 進一步瞭解 GKE 閘道 API。
- 進一步瞭解 GKE 多叢集推論閘道。
- 進一步瞭解多叢集 Ingress。