透過 GKE Inference Gateway 提供 LLM

本教學課程說明如何使用 GKE Inference Gateway,在 Google Kubernetes Engine (GKE) 上部署大型語言模型 (LLM)。本教學課程包含叢集設定、模型部署、GKE Inference Gateway 設定,以及處理 LLM 要求等步驟。

本教學課程適用於機器學習 (ML) 工程師、平台管理員和營運人員,以及想在 GKE 上使用 GKE Inference Gateway 部署及管理 LLM 應用程式的資料和 AI 專家。

閱讀本頁面之前,請先熟悉下列項目:

GKE Inference Gateway 可強化 Google Kubernetes Engine (GKE) Gateway,在 GKE 上提供最佳的生成式 AI 應用程式和工作負載服務。可有效管理及擴充 AI 工作負載、達成工作負載專屬的效能目標 (例如延遲),並提升資源用量、觀測能力和 AI 安全性。

事前準備

開始之前,請務必先完成下列工作:

  • 啟用 Google Kubernetes Engine API。
  • 啟用 Google Kubernetes Engine API
  • 如要使用 Google Cloud CLI 執行這項工作,請安裝並初始化 gcloud CLI。如果您先前已安裝 gcloud CLI,請執行 gcloud components update 指令,取得最新版本。較舊的 gcloud CLI 版本可能不支援執行本文件中的指令。
  • 視需要啟用 Compute Engine API、Kubernetes Engine API、Network Services API 和 Model Armor API。

    前往「啟用 API 存取權」頁面,然後按照指示操作。

  • 請確認您在專案中擁有下列角色:roles/container.admin、roles/iam.serviceAccountAdmin。

  • 請確認專案有足夠的 H100 GPU 配額。詳情請參閱「規劃 GPU 配額」和「分配配額」。

  • 如果還沒有 Hugging Face 帳戶,請建立一個。您需要這個存取權,才能存取本教學課程的模型資源。

  • 要求存取 Llama 3.1 模型,並產生存取權杖。如要存取這個模型,必須先在 Hugging Face 提出要求並獲得核准,否則部署作業會失敗。

    • 簽署授權同意聲明協議:您必須簽署同意聲明協議,才能使用 Llama 3.1 模型。前往 Hugging Face 上的模型頁面,驗證帳戶並接受條款。
    • 產生存取權杖:如要存取模型,您需要 Hugging Face 權杖。在 Hugging Face 帳戶中,依序前往「Your Profile」>「Settings」>「Access Tokens」,建立至少具備讀取權限的新權杖,然後複製到剪貼簿。
  • 為虛擬私有雲網路設定僅限 Proxy 的子網路。Gateway 控制器需要區域中有效的 Proxy 專用子網路,才能佈建應用程式負載平衡器。

GKE Gateway 控制器需求

  • GKE 1.32.3 以上版本。
  • Google Cloud CLI 407.0.0 以上版本。
  • 閘道 API 僅支援虛擬私有雲原生叢集。
  • 叢集必須啟用 HttpLoadBalancing 外掛程式。
  • 如果您使用 Istio,請務必將 Istio 升級至下列其中一個版本:
    • 1.15.2 以上版本
    • 1.14.5 以上版本
    • 1.13.9 以上版本
  • 如果您使用 Shared VPC,則須在主專案中,將 Compute Network User 角色指派給服務專案的 GKE 服務帳戶。

規定與限制

請注意下列限制:

  • GKE Inference Gateway 僅支援 gke-l7-regional-external-managed 和 gke-l7-rilb GatewayClass 資源。
  • 不支援跨區域內部應用程式負載平衡器。
  • InferencePool 最多可以有八個 targetPorts。

設定 GKE Inference Gateway

如要設定 GKE Inference Gateway,請參考以下範例。團隊會執行 vLLM 和 Llama3 模型,並積極實驗兩種不同的 LoRA 微調轉接程式:「food-review」和「cad-fabricator」。

設定 GKE Inference Gateway 的高階工作流程如下:

  1. 準備環境:設定必要基礎架構和元件。
  2. 建立推論集區:使用 InferencePool 自訂資源定義模型伺服器集區。
  3. 指定推論目標:使用 InferenceObjective 自訂資源指定推論目標
  4. 建立閘道:使用 Gateway API 公開推論服務。
  5. 建立 HTTPRoute:定義 HTTP 流量如何路由至推論服務。
  6. 傳送推論要求:向已部署的模型提出要求。

建立閘道

Gateway 資源是外部流量進入 Kubernetes 叢集的進入點。定義接受連入連線的接聽程式。

GKE Inference Gateway 適用於下列 Gateway 類別:

  • gke-l7-rilb:適用於區域性內部應用程式負載平衡器。
  • gke-l7-regional-external-managed:適用於區域性外部應用程式負載平衡器。

詳情請參閱 Gateway 類別說明文件。

如要建立閘道,請按照下列步驟操作:

  1. 將下列範例資訊清單儲存為 gateway.yaml:

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: GATEWAY_NAME
    spec:
      gatewayClassName: GATEWAY_CLASS
      listeners:
        - protocol: HTTP
          port: 80
          name: http
    

    更改下列內容:

    • GATEWAY_NAME:閘道資源的專屬名稱。例如:inference-gateway。
    • GATEWAY_CLASS:要使用的閘道類別。 例如:gke-l7-regional-external-managed。
  2. 將資訊清單套用至叢集:

    kubectl apply -f gateway.yaml
    

注意:如要進一步瞭解如何設定 TLS,透過 HTTPS 保護 Gateway 安全,請參閱 GKE 說明文件中的 TLS 設定。

準備環境

  1. 安裝 Helm。

  2. 建立 GKE 叢集:

    • 建立 GKE Autopilot 或 Standard 叢集,版本須為 1.32.3 以上。如要參考一鍵部署設定,請參閱cluster-toolkit gke-a3-highgpu範例。
    • 使用偏好的運算系列和加速器設定節點。
    • 根據您選取的加速器、模型和效能需求,使用 GKE Inference Quickstart 取得預先設定及測試的部署資訊清單。
  3. 在 GKE 叢集中安裝必要的自訂資源定義 (CRD):

    • 如果是 GKE 1.34.0-gke.1626000 以上版本,系統預設會納入 InferencePool CRD。因此,請只安裝 Alpha 版 InferenceObjective CRD:

      kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/raw/v1.5.0/config/crd/bases/inference.networking.x-k8s.io_inferenceobjectives.yaml
      
    • 如果是 GKE 1.34.0-gke.1626000 之前的版本,請同時安裝 v1 InferencePool 和 Alpha InferenceObjective CRD:

      kubectl apply -f  https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v1.5.0/manifests.yaml
      

      詳情請參閱相容性矩陣。

  4. 如果您使用的 GKE 版本早於 v1.32.2-gke.1182001,且想搭配 GKE Inference Gateway 使用 Model Armor,請務必安裝流量和路由擴充功能 CRD:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcptrafficextensions.yaml
    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-gateway-api/refs/heads/main/config/crd/networking.gke.io_gcproutingextensions.yaml
    
  5. 請設定下列環境變數:

    export GAIE_VERSION=v1.5.0
    export GUIDE_NAME="optimized-baseline"
    export NAMESPACE=llm-d-optimized-baseline
    export INFRA_PROVIDER=gke   # gke | base
    
  6. 安裝 llm-d 端點挑選器 (EPP) 要求的 Gateway API 推論擴充功能自訂資源定義 (CRD):

    kubectl apply -k \
      "https://github.com/kubernetes-sigs/gateway-api-inference-extension/config/crd?ref=${GAIE_VERSION}"
    
  7. 建立目標命名空間:

    kubectl create namespace ${NAMESPACE}
    

建立模型伺服器和模型部署作業

本節說明如何部署模型伺服器和模型。這個範例使用 vLLM 模型伺服器和 Llama3 模型。部署作業會標示為 app:vllm-llama3-8b-instruct。這項部署作業也會使用 Hugging Face 的兩個 LoRA 轉接器,分別命名為 food-review 和 cad-fabricator。

您可以根據自己的模型伺服器容器和模型、服務通訊埠和部署名稱,調整這個範例。您也可以在部署作業中設定 LoRA 轉換器,或部署基礎模型。下列步驟說明如何建立必要的 Kubernetes 資源。

  1. 建立 Kubernetes Secret 來儲存 Hugging Face 權杖。這個權杖可用於存取基礎模型和 LoRA 轉換器:

    kubectl create secret generic hf-token --from-literal=token=HF_TOKEN
    

    將 HF_TOKEN 替換為您的 Hugging Face 權杖。

  2. 使用 llm-d 最佳化基準指南中的 GKE 專屬 Kustomize 疊加層,部署 vLLM 模型伺服器。設定 INFRA_PROVIDER=gke 會套用 GKE 專屬設定,包括 Cloud Monitoring 整合:

    kubectl apply -n ${NAMESPACE} \
      -k guides/${GUIDE_NAME}/modelserver/gpu/vllm/${INFRA_PROVIDER}/
    

注意:GKE 預設會自動監控應用程式。GKE 不需要 llm-d 監控堆疊,但如果您偏好使用,也可以選擇安裝。

如果模型伺服器需要多個通訊埠,請確保容器規格會公開每個通訊埠。以下範例定義的 Deployment 中,容器會公開三個通訊埠:

多埠部署範例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: multiport-model-server
spec:
  replicas: 3
  selector:
    matchLabels:
      app: multiport-model-server
  template:
    metadata:
      labels:
        app: multiport-model-server
    spec:
      containers:
      - name: model-server
        image: your-model-server-image
        ports:
        - containerPort: 8080
        - containerPort: 8081
        - containerPort: 9000

建立推論集區

InferencePool Kubernetes 自訂資源會定義一組 Pod,這些 Pod 具有共同的基礎大型語言模型 (LLM) 和運算設定。selector 欄位會指定哪些 Pod 屬於這個集區。這個選取器中的標籤必須與套用至模���伺服器 Pod 的標籤完全一致。targetPorts 欄位會定義模型伺服器在 Pod 中使用的通訊埠。最多可以指定八個通訊埠。extensionRef 欄位會參照擴充功能服務,為推論集區提供額外功能。InferencePool 可讓 GKE Inference Gateway 將流量轉送至模型伺服器 Pod。

下列 InferencePool 資訊清單指定多個 targetPort,對應於模型伺服器 Deployment 公開的通訊埠:

Multiport InferencePool 範例

apiVersion: inference.networking.k8s.io/v1
kind: InferencePool
metadata:
  name: my-multiport-pool
  namespace: default
spec:
  selector:
    matchLabels:
      app: multiport-model-server
  targetPorts:
    - number: 8080
    - number: 8081
    - number: 9000

建立 InferencePool 前,請先確認 InferencePool 選取的模型伺服器 Pod 已在執行中。

從 llm-d GitHub 存放區複製 InferencePool 的食譜和建議。這是必填步驟:

git clone https://github.com/llm-d/llm-d -b v0.7.0 && cd llm-d

如要使用 Helm 建立 InferencePool 和 Endpoint Picker,請執行下列步驟:

helm install ${GUIDE_NAME} \
  -f guides/recipes/scheduler/base.values.yaml \
  -f guides/${GUIDE_NAME}/scheduler/${GUIDE_NAME}.values.yaml \
  --set provider.name=gke \
  --set inferenceExtension.monitoring.gke.enabled=true \
  -n ${NAMESPACE} \
  --version ${GAIE_VERSION} \
  oci://LLM_D_REGISTRY_PATH

更改下列內容:

  • GAIE_VERSION:Helm 資訊套件版本。例如:v1.5.0。
  • LLM_D_REGISTRY_PATH:Helm 資訊圖表的 OCI 登錄路徑。例如:registry.k8s.io/gateway-api-inference-extension/charts/inferencepool。

在 guides/recipes/scheduler/base.values.yaml 檔案中,變更下列欄位,使其符合模型 Deployment Pod 的標籤:

  • inferencePool.modelServers.matchLabels:用於選取模型伺服器 Pod 的標籤鍵和值。

    注意:鍵和值與optimized-baseline指南範例一致,因此我們將其取代為符合 Deployment Pod 標籤。

根據預設,系統會啟用 Google Cloud Managed Service for Prometheus 的指標擷取功能,以進行監控。

  • 如要停用這項功能,請在指令中新增 --set inferenceExtension.monitoring.prometheus.enabled=false 旗標。
  • 如果您在 GKE Autopilot 叢集上使用預設監控功能,也必須新增 --set provider.gke.autopilot=true 旗標。

Helm 安裝作業會自動安裝必要的逾時政策、端點選擇器,以及可觀測性所需的 Pod。

這會建立 InferencePool 物件:vllm-llama3-8b-instruct 參照 Pod 內的模型端點服務。此外,系統也會為這個建立的 InferencePool 建立名為 app:vllm-llama3-8b-instruct-epp 的 Endpoint Picker 部署作業。

部署高可用性端點挑選器

部署 Endpoint Picker (EPP) 時,如果偏好的後端啟用,就能透過 Cloud Load Balancing 支援主動-被動式轉送拓撲。

使用端點挑選器搭配偏好的後端,可協助您達成下列目標:

  • 狀態一致性:Cloud Load Balancing 會將 100% 的穩定狀態 ext_proc 流量導向主要端點選擇器副本 (epp-0),保留鍵/值 (KV) 快取狀態和要求排程內容。
  • 零停機時間容錯移轉:如果主要端點選擇器 Pod 發生當機或維護作業,Cloud Load Balancing 會使用主動式 gRPC 健康狀態檢查偵測到故障,並立即將流量導向待命副本 (epp-1)。
  • 容錯開放韌性:搭配 failureMode: FailOpen 使用時,暫時性路由失敗會略過端點選擇器,讓要求直接轉送至模型伺服器,不會捨棄使用者要求。

啟用偏好的後端後,GKE 會以以下方式修改架構和路由:

  • 端點挑選器 StatefulSet 架構:端點挑選器會部署為 StatefulSet,而非 Deployment。Pod 序數會指定副本角色:序數 epp-0 是釘選至 PREFERRED 後端層的主要副本,序數 epp-1 則是釘選至 DEFAULT 層的待命副本。
  • 路由狀態維持集中式:穩定狀態的 ext_proc 流量會專門路由至主要端點選擇器副本 (epp-0),以集中管理鍵/值 (KV) 快取追蹤和要求排程狀態。如果 epp-0 健康狀態不佳,Cloud Load Balancing 會將流量轉移至待命副本 (epp-1)。
  • 雙服務架構:Helm 範本會建立主要服務 (Service/${GUIDE_NAME}-epp) 和備用備份服務 (Service/${GUIDE_NAME}-epp-backup)。InferencePool 資源會以宣告方式指定備用備份服務。將宣告式 Gateway 擁有權錨定至待命服務,可確保 GKE Gateway 控制器協調迴圈不會分離您附加至後端服務的主要網路端點群組 (NEG)。

如要使用 Helm 建立高可用性的 InferencePool 和 Endpoint Picker,請執行下列步驟:

  1. 使用 Helm 部署 InferencePool 和端點挑選器,並指定偏好的後端:

    helm install ${GUIDE_NAME} \
      -f guides/recipes/scheduler/base.values.yaml \
      -f guides/${GUIDE_NAME}/scheduler/${GUIDE_NAME}.values.yaml \
      --set provider.name=gke \
      --set inferenceExtension.monitoring.gke.enabled=true \
      --set provider.gke.preferredBackends.enabled=true \
      --set provider.gke.preferredBackends.preferredReplicas=1 \
      --set provider.gke.preferredBackends.defaultReplicas=1 \
      -n ${NAMESPACE} \
      --version ${GAIE_VERSION} \
      oci://LLM_D_REGISTRY_PATH
    

    更改下列內容:

    • GAIE_VERSION:Helm 圖表的 Gateway API Inference Extension (GAIE) 版本。例如:v1.5.0。偏好後端需要使用 Helm 資訊套件 v1.5.0 以上版本。
    • LLM_D_REGISTRY_PATH:Helm 資訊套件的 OCI 登錄路徑。例如:registry.k8s.io/gateway-api-inference-extension/charts/inferencepool。

    如需完整的參數清單,請參閱 values.yaml。

  2. 將主要 NEG 附加至 BackendService:

    export PROJECT_ID=PROJECT_ID
    export REGION=REGION
    
    export BACKEND_SERVICE=$(gcloud compute backend-services list --project=${PROJECT_ID} --format="value(name)" | grep "${GUIDE_NAME}-epp")
    
    export PRIMARY_NEG=$(kubectl get svc ${GUIDE_NAME}-epp -n ${NAMESPACE} -o jsonpath='{.metadata.annotations.cloud\.google\.com/neg-status}' | jq -r '.network_endpoint_groups["9002"]')
    
    for ZONE in $(kubectl get svc ${GUIDE_NAME}-epp -n ${NAMESPACE} -o jsonpath='{.metadata.annotations.cloud\.google\.com/neg-status}' | jq -r '.zones[]'); do
      gcloud compute backend-services add-backend ${BACKEND_SERVICE} \
        --network-endpoint-group=${PRIMARY_NEG} \
        --network-endpoint-group-zone=${ZONE} \
        --region=${REGION} \
        --project=${PROJECT_ID} \
        --balancing-mode=RATE \
        --max-rate-per-endpoint=100 \
        --preference=PREFERRED
      sleep 15
    done
    

    更改下列內容:

    • PROJECT_ID:您的 Google Cloud 專案 ID。
    • REGION:叢集和後端服務的 Google Cloud 區域。

將區域 NEG 附加至 Google Cloud BackendService 後,您就不必再次執行 gcloud 指令,即可調整副本數量 (preferredReplicas 或 defaultReplicas) 或重新啟動 Pod。GKE NEG 控制器會自動將個別 Pod IP 位址同步至已註冊的區域 NEG。

如果您刪除並重新建立父項 Gateway 或 InferencePool 資源,GKE Gateway 控制器會使用新的雲端 ID 重新建立基礎 Google Cloud BackendService。在這種情況下,請執行先前的附加工作流程,將主要區域性 NEG 附加至新建立的 BackendService。

建立 HTTPRoute

HTTPRoute 資源會定義 GKE 閘道如何將傳入的 HTTP 要求,路由至後端服務 (例如 InferencePool)。HTTPRoute 資源會指定相符規則 (例如標頭或路徑),以及流量應轉送的後端。

  1. 如要建立 HTTPRoute,請將下列範例資訊清單儲存為 httproute.yaml:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: HTTPROUTE_NAME
    spec:
      parentRefs:
      - name: GATEWAY_NAME
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: PATH_PREFIX
        backendRefs:
        - name: INFERENCE_POOL_NAME
          group: "inference.networking.k8s.io"
          kind: InferencePool
    

    更改下列內容:

    • HTTPROUTE_NAME:HTTPRoute資源的專屬名稱。例如:my-route。
    • GATEWAY_NAME:您建立的 Gateway 資源名稱。例如:inference-gateway。
    • PATH_PREFIX:用於比對傳入要求的路徑前置字元。例如,/ 可比對所有項目。
    • INFERENCE_POOL_NAME:要將流量導向的 InferencePool 資源名稱。例如:vllm-llama3-8b-instruct。
  2. 將資訊清單套用至叢集:

    kubectl apply -f httproute.yaml
    

指定推論目標

InferenceObjective 自訂資源可讓您指定要求的優先順序。

InferenceObjective 資源的 metadata.name 欄位會指定推論目標的名稱,Priority 欄位會指定其服務重要性,poolRef 欄位則會指定模型服務所在的 InferencePool。

apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferenceObjective
metadata:
  name: NAME
spec:
  priority: VALUE
  poolRef:
    name: INFERENCE_POOL_NAME
    group: "inference.networking.k8s.io"

更改下列內容:

  • NAME:推論目標的名稱。例如:food-review。
  • VALUE:推論目標的優先順序。這是整數,值越大表示要求越重要。例如 10。
  • INFERENCE_POOL_NAME:您在上一個步驟中建立的 InferencePool 名稱。例如:vllm-llama3-8b-instruct。

如要建立 InferenceObjective,請按照下列步驟操作:

  1. 將下列資訊清單儲存為 inference-objectives.yaml。這個資訊清單會建立兩個 InferenceObjective 資源。第一個會設定 vllm-llama3-8b-instruct InferencePool 的 food-review 推論目標,優先順序為 10。第二個設定會將 llama3-base-model 推論目標的優先順序設為 20,因此會優先放送。

    apiVersion: inference.networking.x-k8s.io/v1alpha2
    kind: InferenceObjective
    metadata:
      name: food-review
    spec:
      priority: 10
      poolRef:
        name: vllm-llama3-8b-instruct
        group: "inference.networking.k8s.io"
    ---
    apiVersion: inference.networking.x-k8s.io/v1alpha2
    kind: InferenceObjective
    metadata:
      name: llama3-base-model
    spec:
      priority: 20 # Higher priority
      poolRef:
        name: vllm-llama3-8b-instruct
    
  2. 將範例資訊清單套用至叢集:

    kubectl apply -f inference-objectives.yaml
    

驗證 Deployment

如要確認所有元件是否正在執行,請執行下列指令:

kubectl get inferencepool
kubectl get inferenceobjective
kubectl get pods -l app=vllm-llama3-8b-instruct-epp

傳送推論要求

設定 GKE Inference Gateway 後,您可以將推論要求傳送至已部署的模型。根據輸入的提示和指定參數生成文字。

如要傳送推論要求,請按照下列步驟操作:

  1. 請設定下列環境變數:

    export GATEWAY_NAME=GATEWAY_NAME
    export PORT_NUMBER=PORT_NUMBER # Use 80 for HTTP
    

    更改下列內容:

    • GATEWAY_NAME:閘道資源的名稱。
    • PORT_NUMBER:您在閘道中設定的通訊埠編號。
  2. 如要取得 Gateway 端點,請執行下列指令:

    echo "Waiting for the Gateway IP address..."
    IP=""
    while [ -z "$IP" ]; do
      IP=$(kubectl get gateway/${GATEWAY_NAME} -o jsonpath='{.status.addresses[0].value}' 2>/dev/null)
      if [ -z "$IP" ]; then
        echo "Gateway IP not found, waiting 5 seconds..."
        sleep 5
      fi
    done
    
    echo "Gateway IP address is: $IP"
    PORT=${PORT_NUMBER}
    
  3. 如要使用 curl 將要求傳送至 /v1/completions 端點,請執行下列指令:

    curl -i -X POST ${IP}:${PORT}/v1/completions \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer $(gcloud auth application-default print-access-token)' \
    -d '{
        "model": "MODEL_NAME",
        "prompt": "PROMPT_TEXT",
        "max_tokens": MAX_TOKENS,
        "temperature": "TEMPERATURE"
    }'
    

    更改下列內容:

    • MODEL_NAME:要使用的模型或 LoRA 轉接器名稱。
    • PROMPT_TEXT:模型的輸入提示。
    • MAX_TOKENS:回覆中可生成的權杖數量上��。
    • TEMPERATURE:控制輸出內容的隨機性。如要取得可預測的輸出內容,請使用 0 值;如要取得更具創意的輸出內容,請使用較高的值。

以下範例說明如何將範例要求傳送至 GKE Inference Gateway:

curl -i -X POST ${IP}:${PORT}/v1/completions -H 'Content-Type: application/json' -H 'Authorization: Bearer $(gcloud auth application-default print-access-token)' -d '{
    "model": "food-review-1",
    "prompt": "What is the best pizza in the world?",
    "max_tokens": 2048,
    "temperature": 0
}'

請注意下列行為:

  • 要求主體:要求主體可包含其他參數,例如 stop 和 top_p。如需完整的選項清單,請參閱 OpenAI API 規格。
  • 錯誤處理:在用戶端程式碼中實作適當的錯誤處理機制,處理回應中可能發生的錯誤。舉例來說,請檢查 curl 回應中的 HTTP 狀態碼。如果不是 200 狀態碼,通常表示發生錯誤。
  • 驗證和授權:在正式部署時,請使用驗證和授權機制保護 API 端點。在要求中加入適當的標頭 (例如 Authorization)。

後續步驟