このドキュメントでは、Google Kubernetes Engine(GKE)マルチクラスタ推論ゲートウェイを設定して、異なるリージョンにまたがる複数の GKE クラスタ間で AI/ML 推論ワークロードをインテリジェントにロード バランシングする方法について説明します。この設定では、Gateway API、マルチクラスタ Ingress、InferencePool や InferenceObjective などのカスタム リソースを使用して、スケーラビリティを向上させ、高可用性を確保し、モデル サービング デプロイのリソース使用率を最適化します。
このドキュメントを理解するには、次の内容を理解しておく必要があります。
- GKE での AI / ML オーケストレーション。
- 生成 AI の用語。
- GKE ネットワーキングのコンセプト(次を含む)。
- Google Cloudでのロード バランシング、特にロードバランサが GKE とやり取りする方法。
このドキュメントは、次のペルソナを対象としています。
- AI / ML ワークロードの提供に GKE のコンテナ オーケストレーション機能を使用する ML エンジニア、プラットフォーム管理者 / オペレーター、データ / 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 を有効にします。
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 に指標を書き込む権限が必要です。
- プロジェクトに
roles/container.adminとroles/iam.serviceAccountAdminの IAM ロールが必要です。
マルチクラスタ推論ゲートウェイを設定する
GKE マルチクラスタ Inference Gateway を設定する手順は次のとおりです。
クラスタとノードプールを作成する
AI/ML 推論ワークロードをホストし、クロスリージョン ロード バランシングを有効にするには、異なるリージョンに 2 つの 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_TOKENHF_TOKENは、Hugging Face アクセス トークンに置き換えます。最初のクラスタとは異なるリージョンに 2 番目のクラスタを作成します。
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: 2 番目のクラスタのリージョン。これは、最初のクラスタとは異なるリージョンにする必要があります。例:us-east4PROJECT_ID: プロジェクト ID。GKE_VERSION: 使用する GKE のバージョン(1.34.1-gke.1127000など)。MACHINE_TYPE: クラスタノードのマシンタイプ(例:c2-standard-16)。DISK_TYPE: クラスタノードのディスクタイプ(例:pd-standard)。
2 番目のクラスタに 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: 2 番目のクラスタのゾーン(us-east4-aなど)。CLUSTER_2_NAME: 2 番目のクラスタの名前(例:gke-east)。NODE_POOL_MACHINE_TYPE: ノードプールのマシンタイプ(例:a3-highgpu-2g)。NUM_NODES: ノードプール内のノード数(例:3)。
2 番目のクラスタで、認証情報を取得し、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: 2 番目のクラスタの名前(例:gke-east)。CLUSTER_2_ZONE: 2 番目のクラスタのゾーン(us-east4-aなど)。PROJECT_ID: プロジェクト ID。HF_TOKEN: Hugging Face アクセス トークン。
クラスタをフリートに登録する
GKE マルチクラスタ推論 Gateway などのマルチクラスタ機能を有効にするには、クラスタをフリートに登録します。
両方のクラスタをプロジェクトのフリートに登録します。
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: 2 番目のクラスタの名前(例:gke-east)。CLUSTER_2_ZONE: 2 番目のクラスタのゾーン(us-east4-aなど)。
単一の Gateway で複数のクラスタ間のトラフィックを管理できるようにするには、マルチクラスタ 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)。
プロキシ専用サブネットを作成する
内部ゲートウェイの場合は、各リージョンにプロキシ専用サブネットを作成します。内部 Gateway の Envoy プロキシは、これらの専用サブネットを使用して VPC ネットワーク内のトラフィックを処理します。
最初のクラスタのリージョンにサブネットを作成します。
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_ID2 番目のクラスタのリージョンにサブネットを作成します。
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: 2 番目のクラスタのリージョン(例:us-east4)。
必要な CRD をインストールする
GKE マルチクラスタ推論 Gateway は、InferencePool や InferenceObjective などのカスタム リソースを使用します。GKE Gateway API コントローラは、InferencePool カスタム リソース定義(CRD)を管理します。ただし、アルファ版の 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: 2 番目のクラスタのゾーン(us-east4-aなど)。CLUSTER_2_NAME: 2 番目のクラスタの名前(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: 2 番目のクラスタのコンテキスト(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: 2 番目のクラスタのコンテキスト(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: 2 番目のクラスタのコンテキスト(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: 2 番目のクラスタのコンテキスト(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: 2 番目のクラスタのコンテキスト(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_CONTEXTCLUSTER1_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: 2 番目のクラスタのコンテキスト(gke_my-project_us-east4-a_gke-eastなど)。
ロード バランシング ポリシーを構成する
AI/ML 推論リクエストが GKE クラスタに分散される方法を最適化するには、ロード バランシング ポリシーを構成します。適切なバランシング モードを選択すると、リソースを効率的に使用し、個々のクラスタの過負荷を防ぎ、推論サービスの全体的なパフォーマンスと応答性を向上させることができます。
タイムアウトを構成する
リクエストの所要時間が長くなることが予想される場合は、ロードバランサのタイムアウトを長く構成します。GCPBackendPolicy で、timeoutSec フィールドを推定 P99 リクエスト レイテンシの 2 倍以上に設定します。
たとえば、次のマニフェストは、ロードバランサのタイムアウトを 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 でこれらのモードのいずれか 1 つのみを構成します。
デプロイのロード バランシング モードを選択します。
カスタム指標
ロード バランシングを最適化するには、まず目標使用率を 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_CONTEXTCLUSTER1_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_CONTEXTCLUSTER1_CONTEXTは、最初のクラスタのコンテキスト(gke_my-project_europe-west3-c_gke-westなど)に置き換えます。
デプロイを確認する
内部ロードバランサはプライベート IP アドレスを使用するため、内部ロードバランサを確認するには、VPC ネットワーク内からリクエストを送信する必要があります。クラスタの 1 つに一時 Pod を実行して、VPC ネットワークからリクエストを送信し、内部ロードバランサを確認します。
一時 Pod でインタラクティブ シェル セッションを開始します。
kubectl run -it --rm --image=curlimages/curl curly --context=CLUSTER1_CONTEXT -- /bin/shCLUSTER1_CONTEXTは、最初のクラスタのコンテキスト(gke_my-project_europe-west3-c_gke-westなど)に置き換えます。新しいシェルから、Gateway の 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 マルチクラスタ Inference Gateway の詳細を確認する。
- マルチクラスタ Ingress の詳細を確認する。