本文說明如何設定 Google Kubernetes Engine (GKE) 多叢集推論閘道,在多個 GKE 叢集之間智慧地平衡 AI/機器學習推論工作負載,這些叢集可跨越不同區域。這項設定會使用 Gateway API、Multi Cluster Ingress,以及 InferencePool 和 InferenceObjective 等自訂資源,提升模型服務部署作業的可擴充性、確保高可用性,並提高資源使用率。
如要瞭解本文內容,請先熟悉下列主題:
- GKE 的 AI/機器學習自動化調度管理機制。
- 生成式 AI 術語。
- GKE 網路概念,包括:
- 負載平衡Google Cloud,特別是負載平衡器與 GKE 的互動方式。
本文件適用於下列角色:
- 機器學習工程師、平台管理員和營運人員,或想使用 GKE 的容器自動化調度管理功能,提供 AI/機器學習工作負載的資料和 AI 專家。
- 與 GKE 網路互動的雲端架構師或網路專家。
如要進一步瞭解Google Cloud 內容中提及的常見角色和範例工作,請參閱「常見的 GKE Enterprise 使用者角色和工作」。
事前準備
開始之前,請確認你已完成下列工作:
- 啟用 Google Kubernetes Engine API。 啟用 Google Kubernetes Engine API
- 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行
gcloud components update指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文件中的指令。
啟用 Compute Engine API、Google Kubernetes Engine API、Model Armor 和 Network Services API。
啟用 Autoscaling API。
前往 Autoscaling API,然後按照指示操作。
Hugging Face 先決條件:
- 如果沒有 Hugging Face 帳戶,請先建立一個。
- 在 Hugging Face 上要求並取得 Llama 3.1 模型的存取權。
- 在 Hugging Face 的模型頁面簽署授權同意協議。
- 產生至少具備
Read權限的 Hugging Face 存取權杖。
需求條件
- 確認專案有足夠的 H100 GPU 配額。詳情請參閱「規劃 GPU 配額」和「分配配額」。
- 使用 GKE 1.34.1-gke.1127000 以上版本。
- 使用 gcloud CLI 480.0.0 以上版本。
- 節點服務帳戶必須具有寫入指標至 Autoscaling API 的權限。
- 您必須在專案中具備下列 IAM 角色:
roles/container.admin和roles/iam.serviceAccountAdmin。
設定多叢集推論閘道
如要設定 GKE 多叢集推論閘道,請按照下列步驟操作:
建立叢集和節點集區
如要代管 AI/機器學習推論工作負載,並啟用跨區域負載平衡,請在不同區域建立兩個 GKE 叢集,每個叢集都包含 H100 GPU 節點集區。
建立第一個叢集:
gcloud container clusters create CLUSTER_1_NAME \ --region LOCATION \ --project=PROJECT_ID \ --gateway-api=standard \ --release-channel "rapid" \ --cluster-version=GKE_VERSION \ --machine-type="MACHINE_TYPE" \ --disk-type="DISK_TYPE" \ --enable-managed-prometheus --monitoring=SYSTEM,DCGM \ --hpa-profile=performance \ --async # Allows the command to return immediately更改下列內容:
CLUSTER_1_NAME:第一個叢集的名稱,例如gke-west。LOCATION:第一個叢集的區域,例如europe-west3。PROJECT_ID:您的專案 ID。GKE_VERSION:要使用的 GKE 版本,例如1.34.1-gke.1127000。MACHINE_TYPE:叢集節點的機型,例如c2-standard-16。DISK_TYPE:叢集節點的磁碟類型,例如pd-standard。
為第一個叢集建立 H100 節點集區:
gcloud container node-pools create NODE_POOL_NAME \ --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 \ --async # Allows the command to return immediately更改下列內容:
NODE_POOL_NAME:節點集區的名稱,例如h100。PROJECT_ID:您的專案 ID。CLUSTER_1_ZONE:第一個叢集的可用區,例如europe-west3-c。CLUSTER_1_NAME:第一個叢集的名稱,例如gke-west。NODE_POOL_MACHINE_TYPE:節點集區的機型,例如a3-highgpu-2g。NUM_NODES:節點集區中的節點數量,例如3。
取得憑證:
gcloud container clusters get-credentials CLUSTER_1_NAME \ --location CLUSTER_1_ZONE \ --project=PROJECT_ID更改下列內容:
PROJECT_ID:您的專案 ID。CLUSTER_1_NAME:第一個叢集的名稱,例如gke-west。CLUSTER_1_ZONE:第一個叢集的可用區,例如europe-west3-c。
在第一個叢集上,為 Hugging Face 權杖建立密鑰:
kubectl create secret generic hf-token \ --from-literal=token=HF_TOKEN將
HF_TOKEN取代為您的 Hugging Face 存取權杖。在與第一個叢集不同的區域中建立第二個叢集:
gcloud container clusters create gke-east --region LOCATION \ --project=PROJECT_ID \ --gateway-api=standard \ --release-channel "rapid" \ --cluster-version=GKE_VERSION \ --machine-type="MACHINE_TYPE" \ --disk-type="DISK_TYPE" \ --enable-managed-prometheus \ --monitoring=SYSTEM,DCGM \ --hpa-profile=performance \ --async # Allows the command to return immediately while the cluster is created in the background.更改下列內容:
LOCATION:第二個叢集的區域。這個區域必須與第一個叢集不同。例如:us-east4。PROJECT_ID:您的專案 ID。GKE_VERSION:要使用的 GKE 版本,例如1.34.1-gke.1127000。MACHINE_TYPE:叢集節點的機型,例如c2-standard-16。DISK_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_2_ZONE \ --node-locations=CLUSTER_2_ZONE \ --cluster=CLUSTER_2_NAME \ --machine-type=NODE_POOL_MACHINE_TYPE \ --num-nodes=NUM_NODES \ --spot \ --async # Allows the command to return immediately更改下列內容:
PROJECT_ID:您的專案 ID。CLUSTER_2_ZONE:第二個叢集的可用區,例如us-east4-a。CLUSTER_2_NAME:第二個叢集的名稱,例如gke-east。NODE_POOL_MACHINE_TYPE:節點集區的機型,例如a3-highgpu-2g。NUM_NODES:節點集區中的節點數量,例如3。
針對第二個叢集,取得憑證並建立 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更改下列內容:
CLUSTER_2_NAME:第二個叢集的名稱,例如gke-east。CLUSTER_2_ZONE:第二個叢集的可用區,例如us-east4-a。PROJECT_ID:您的專案 ID。HF_TOKEN:您的 Hugging Face 存取權杖。
將叢集註冊至機群
如要啟用多叢集功能 (例如 GKE 多叢集推論閘道),請向機群註冊叢集。
將兩個叢集註冊至專案的機群:
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-west。CLUSTER_1_ZONE:第一個叢集的可用區,例如europe-west3-c。PROJECT_ID:您的專案 ID。CLUSTER_2_NAME:第二個叢集的名稱,例如gke-east。CLUSTER_2_ZONE:第二個叢集的可用區,例如us-east4-a。
如要讓單一閘道管理多個叢集的流量,請啟用多叢集 Ingress 功能,並指定設定叢集:
gcloud container fleet ingress enable \ --config-membership=projects/PROJECT_ID/locations/global/memberships/CLUSTER_1_NAME更改下列內容:
PROJECT_ID:您的專案 ID。CLUSTER_1_NAME:第一個叢集的名稱,例如gke-west。
建立僅限 Proxy 的子網路
如果是內部閘道,請在每個區域中建立僅限 Proxy 的子網路。內部閘道的 Envoy Proxy 會使用這些專屬子網路,處理虛擬私有雲網路內的流量。
在第一個叢集的區域中建立子網路:
gcloud compute networks subnets create CLUSTER_1_REGION-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=CLUSTER_1_REGION \ --network=default \ --range=10.0.0.0/23 \ --project=PROJECT_ID在第二個叢集的區域中建立子網路:
gcloud compute networks subnets create CLUSTER_2_REGION-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=CLUSTER_2_REGION \ --network=default \ --range=10.5.0.0/23 \ --project=PROJECT_ID更改下列內容:
PROJECT_ID:您的專案 ID。CLUSTER_1_REGION:第一個叢集的區域,例如europe-west3。CLUSTER_2_REGION:第二個叢集的區域,例如us-east4。
安裝必要的 CRD
GKE 多叢集推論閘道會使用 InferencePool 和 InferenceObjective 等自訂資源。GKE Gateway API 控制器會管理 InferencePool 自訂資源定義 (CRD)。不過,您必須在叢集上手動安裝 Alpha 版的 InferenceObjective CRD。
定義叢集的環境變數:
CLUSTER1_CONTEXT="gke_PROJECT_ID_CLUSTER_1_ZONE_CLUSTER_1_NAME" CLUSTER2_CONTEXT="gke_PROJECT_ID_CLUSTER_2_ZONE_CLUSTER_2_NAME"更改下列內容:
PROJECT_ID:您的專案 ID。CLUSTER_1_ZONE:第一個叢集的可用區,例如europe-west3-c。CLUSTER_1_NAME:第一個叢集的名稱,例如gke-west。CLUSTER_2_ZONE:第二個叢集的可用區,例如us-east4-a。CLUSTER_2_NAME:第二個叢集的名稱,例如gke-east。
在兩個叢集上安裝
InferenceObjectiveCRD:kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/v1.1.0/config/crd/bases/inference.networking.x-k8s.io_inferenceobjectives.yaml --context=CLUSTER1_CONTEXT kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/v1.1.0/config/crd/bases/inference.networking.x-k8s.io_inferenceobjectives.yaml --context=CLUSTER2_CONTEXT更改下列內容:
CLUSTER1_CONTEXT:第一個叢集的情境,例如gke_my-project_europe-west3-c_gke-west。CLUSTER2_CONTEXT:第二個叢集的情境,例如gke_my-project_us-east4-a_gke-east。
將資源部署至目標叢集
如要在每個叢集上提供 AI/ML 推論工作負載,請部署必要資源,例如模型伺服器和InferenceObjective自訂資源。
將模型伺服器部署至兩個叢集:
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/v1.1.0/config/manifests/vllm/gpu-deployment.yaml --context=CLUSTER1_CONTEXT kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api-inference-extension/v1.1.0/config/manifests/vllm/gpu-deployment.yaml --context=CLUSTER2_CONTEXT更改下列內容:
CLUSTER1_CONTEXT:第一個叢集的情境,例如gke_my-project_europe-west3-c_gke-west。CLUSTER2_CONTEXT:第二個叢集的情境,例如gke_my-project_us-east4-a_gke-east。
將
InferenceObjective資源部署至兩個叢集。將下列範例資訊清單儲存至名為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更改下列內容:
CLUSTER1_CONTEXT:第一個叢集的情境,例如gke_my-project_europe-west3-c_gke-west。CLUSTER2_CONTEXT:第二個叢集的情境,例如gke_my-project_us-east4-a_gke-east。
使用 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 \ --version v1.1.0 \ oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepoolhelm 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.1.0 \ oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepool更改下列內容:
CLUSTER1_CONTEXT:第一個叢集的情境,例如gke_my-project_europe-west3-c_gke-west。CLUSTER2_CONTEXT:第二個叢集的情境,例如gke_my-project_us-east4-a_gke-east。
在兩個叢集上,將
InferencePool資源標示為已匯出。這個註解可讓設定叢集匯入InferencePool,這是多叢集轉送的必要步驟。kubectl annotate inferencepool vllm-llama3-8b-instruct networking.gke.io/export="True" \ --context=CLUSTER1_CONTEXTkubectl annotate inferencepool vllm-llama3-8b-instruct networking.gke.io/export="True" \ --context=CLUSTER2_CONTEXT更改下列內容:
CLUSTER1_CONTEXT:第一個叢集的情境,例如gke_my-project_europe-west3-c_gke-west。CLUSTER2_CONTEXT:第二個叢集的情境,例如gke_my-project_us-east4-a_gke-east。
將資源部署至設定叢集
如要定義流量在所有已註冊叢集中的 InferencePool 資源之間,如何進行路由和負載平衡,請部署 Gateway、HTTPRoute 和 HealthCheckPolicy 資源。您只能將這些資源部署至指定的設定叢集,也就是本文中的 gke-west。
建立名為
mcig.yaml的檔案,並加入以下內容:--- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway 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 --- apiVersion: gateway.networking.k8s.io/v1 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 --- apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy 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 mcig.yaml --context=CLUSTER1_CONTEXT將
CLUSTER1_CONTEXT替換為第一個叢集 (設定叢集) 的環境,例如gke_my-project_europe-west3-c_gke-west。
啟用自訂指標回報功能
如要啟用自訂指標報表功能並改善跨區域負載平衡,請從所有叢集匯出 KV 快取用量指標。負載平衡器會使用這項匯出的 KV 快取用量資料做為自訂負載信號。使用這項自訂負載信號,可根據每個叢集的實際工作負載,做出更智慧的負載平衡決策。
建立名為
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 # For vLLM versions v0.10.2 and newer exportName: kv-cache - name: vllm:gpu_cache_usage_perc # For vLLM versions v0.6.2 and newer exportName: kv-cache-old將指標設定套用至兩個叢集:
kubectl apply -f metrics.yaml --context=CLUSTER1_CONTEXT kubectl apply -f metrics.yaml --context=CLUSTER2_CONTEXT更改下列內容:
CLUSTER1_CONTEXT:第一個叢集的情境,例如gke_my-project_europe-west3-c_gke-west。CLUSTER2_CONTEXT:第二個叢集的情境,例如gke_my-project_us-east4-a_gke-east。
設定負載平衡政策
如要最佳化 AI/機器學習推論要求在 GKE 叢集中的分配方式,請設定負載平衡政策。選擇適當的平衡模式有助於確保資源使用效率、避免個別叢集過度負載,並提升推論服務的整體效能和回應速度。
設定逾時
如果要求預計會持續較長時間,請為負載平衡器設定較長的逾時時間。在 GCPBackendPolicy 中,將 timeoutSec 欄位設為至少是預估 P99 要求延遲時間的兩倍。
舉例來說,以下資訊清單會將負載平衡器逾時設為 100 秒。
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
name: my-backend-policy
spec:
targetRef:
group: "networking.gke.io"
kind: GCPInferencePoolImport
name: vllm-llama3-8b-instruct
default:
timeoutSec: 100
balancingMode: CUSTOM_METRICS
trafficDuration: LONG
customMetrics:
- name: gke.named_metrics.kv-cache
dryRun: false
詳情請參閱「多叢集 Gateway 限制」一節。
由於「自訂指標」和「處理中要求」負載平衡模式互斥,請在 GCPBackendPolicy 中只設定其中一種模式。
為部署項目選擇負載平衡模式。
自訂指標
如要達到最佳負載平衡,請先將目標使用率設為 60%。如要達成這個目標,請在 GCPBackendPolicy 的 customMetrics 設定中設定 maxUtilization: 60。
建立名為
backend-policy.yaml的檔案,並在其中加入下列內容,啟用以kv-cache自訂指標為依據的負載平衡:apiVersion: networking.gke.io/v1 kind: GCPBackendPolicy metadata: name: my-backend-policy spec: targetRef: group: "networking.gke.io" kind: GCPInferencePoolImport name: vllm-llama3-8b-instruct default: balancingMode: CUSTOM_METRICS trafficDuration: LONG customMetrics: - name: gke.named_metrics.kv-cache dryRun: false maxUtilization: 60套用新政策:
kubectl apply -f backend-policy.yaml --context=CLUSTER1_CONTEXT將
CLUSTER1_CONTEXT替換為第一個叢集的環境,例如gke_my-project-europe-west3-c-gke-west。
處理中的要求
如要使用「處理中」平衡模式,請估算每個後端可處理的處理中要求數量,並明確設定容量值。
建立名為
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: balancingMode: IN_FLIGHT trafficDuration: LONG maxInFlightRequestsPerEndpoint: 1000 dryRun: false套用新政策:
kubectl apply -f backend-policy.yaml --context=CLUSTER1_CONTEXT將
CLUSTER1_CONTEXT替換為第一個叢集的環境,例如gke_my-project_europe-west3-c_gke-west。
驗證 Deployment
如要驗證內部負載平衡器,您必須從虛擬私有雲網路內傳送要求,因為內部負載平衡器使用私人 IP 位址。在其中一個叢集中執行暫時性 Pod,從 VPC 網路傳送要求,並驗證內部負載平衡器:
在臨時 Pod 中啟動互動式殼層工作階段:
kubectl run -it --rm --image=curlimages/curl curly --context=CLUSTER1_CONTEXT -- /bin/sh將
CLUSTER1_CONTEXT替換為第一個叢集的環境,例如gke_my-project_europe-west3-c_gke-west。從新的殼層取得閘道 IP 位址,然後傳送測試要求:
GW_IP=$(kubectl get gateway/cross-region-gateway -n default -o jsonpath='{.status.addresses[0].value}') curl -i -X POST ${GW_IP}: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 }'以下是成功的回應範例:
{ "id": "cmpl-...", "object": "text_completion", "created": 1704067200, "model": "food-review-1", "choices": [ { "text": "The best pizza in the world is subjective, but many argue for Neapolitan pizza...", "index": 0, "logprobs": null, "finish_reason": "length" } ], "usage": { "prompt_tokens": 10, "completion_tokens": 100, "total_tokens": 110 } }
後續步驟
- 進一步瞭解 GKE Gateway API。
- 進一步瞭解 GKE 多叢集推論閘道。
- 進一步瞭解多叢集 Ingress。