このドキュメントでは、Google Kubernetes Engine(GKE)マルチクラスタ推論ゲートウェイと GKE 自動スケーリング機能を使用して、AI 推論ワークロードの弾力的なクロスリージョン高可用性を構成する方法について説明します。この設定により、異なるリージョンの複数の GKE クラスタ間でワークロードの負荷をインテリジェントに分散できます。
GKE Multi-Cluster Inference Gateway の詳細については、GKE Multi-Cluster Inference Gateway についてをご覧ください。
始める前に
Google Kubernetes Engine API を有効にします。
このタスクに Google Cloud CLI を使用する場合は、インストールして初期化します。
H100 GPU 用にプロジェクトに十分な割り当てがあることを確認します。詳細については、GPU 割り当てとリソース割り当てをご覧ください。
GKE バージョン 1.34.1-gke.1127000 以降を使用します。
gcloud CLI バージョン 480.0.0 以降を使用します。
ノードで使用されるサービス アカウントに
roles/monitoring.metricWriter権限とroles/stackdriver.resourceMetadata.writer権限があることを確認します。プロジェクトに
roles/container.adminとroles/iam.serviceAccountAdminの Identity and Access Management(IAM)ロールがあることを確認します。次の Hugging Face の前提条件を満たします。
- Hugging Face アカウントを作成します。
- Hugging Face で Llama 3.1 モデルへのアクセス権をリクエストして承認を取得します。
- Hugging Face のモデルのページでライセンス同意契約に署名します。
- 少なくとも読み取り権限を持つ Hugging Face アクセス トークンを生成します。
クラスタとノードプールを作成する
異なるリージョンに 2 つの 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-c)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_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-c)CLUSTER_1_NAME: 最初のクラスタの名前(例:gke-west)NODE_POOL_MACHINE_TYPE: ノードプールのマシンタイプ(例:a3-highgpu-2g)NUM_NODES: ノードプール内のノード数(3など)MIN_NUM_NODES: ノードプール内の自動スケーリングの最小ノード数(1など)MAX_NUM_NODES: ノードプールで自動スケーリングするノードの最大数(10など)
認証情報を取得し、最初のクラスタに Hugging Face トークン Secret を作成します。
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-west)CLUSTER_1_ZONE: 最初のクラスタのゾーン(例:europe-west3-c)HF_TOKEN: Hugging Face アクセス トークン
最初のクラスタとは異なるリージョンに 2 番目のクラスタを作成します。
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 \ --asyncCLUSTER_2_ZONEは、2 番目のクラスタのゾーン(us-east4-aなど)に置き換えます。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 \ --min-nodes=MIN_NUM_NODES \ --max-nodes=MAX_NUM_NODES \ --enable-autoscaling \ --async次のように置き換えます。
PROJECT_ID: プロジェクト IDCLUSTER_2_ZONE: 2 番目のクラスタのゾーン(例:us-east4-a)CLUSTER_2_NAME: 2 番目のクラスタの名前(例:gke-east)NODE_POOL_MACHINE_TYPE: ノードプールのマシンタイプ(例:a3-highgpu-2g)NUM_NODES: ノードプール内のノード数(3など)MIN_NUM_NODES: ノードプール内の自動スケーリングの最小ノード数(1など)MAX_NUM_NODES: ノードプールで自動スケーリングするノードの最大数(10など)
認証情報を取得し、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次のように置き換えます。その他の変数の定義については、前の手順を参照してください。
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-west)CLUSTER_2_NAME: 2 番目のクラスタの名前(例: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)
プロキシ専用サブネットを作成する
最初のクラスタのリージョンにサブネットを作成します。
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-west3)SUBNET_RANGE_1: 最初のクラスタのリージョンのプロキシ専用サブネットのサブネット IP 範囲(10.0.0.0/23など)
2 番目のクラスタのリージョンにサブネットを作成します。
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: 2 番目のクラスタのリージョン(例:us-east4)SUBNET_RANGE_2: 2 番目のクラスタのリージョンのプロキシ専用サブネットのサブネット 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-c)CLUSTER_1_NAME: 最初のクラスタの名前(例:gke-west)CLUSTER_2_ZONE: 2 番目のクラスタのゾーン(例:us-east4-a)CLUSTER_2_NAME: 2 番目のクラスタの名前(例: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_CONTEXTHelm を使用して、両方のクラスタに 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_CONTEXTCLUSTER1_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: 100 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_CONTEXTCLUSTER1_CONTEXTは、最初のクラスタのコンテキスト(gke_my-project_europe-west3-c_gke-westなど)に置き換えます。
自動スケーリングを構成する
トラフィックが他のリージョンに溢れる前に、各クラスタで負荷の増加を処理できるようにするには、モデルサーバー デプロイの HorizontalPodAutoscaler(HPA)を構成する必要があります。
構成に関する重要な原則
同じカスタム指標を使用する: HPA は、Multi-Cluster Inference Gateway の
GCPBackendPolicyで使用するのと同じカスタム指標(vllm:kv_cache_usage_percなど)に基づいてスケーリングするように構成する必要があります。このアプローチにより、ロード バランシングとスケーリングの両方の決定が、推論サーバーからの同じシグナルに基づいて行われるようになります。選択する指標は、使用率を表す 0 ~ 1 の値を持つ必要があります。指標値が 1 より大きい場合、ロードバランサによる使用率が 100% と解釈され、予期しないルーティング動作が発生する可能性があります。HPA ターゲットを低く設定する: HPA 構成の指標のターゲット値は、
GCPBackendPolicyで定義されているmaxUtilizationPercent設定よりも低く設定する必要があります。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_CONTEXTCLUSTER1_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_CONTEXTcustom-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-adapterPROJECT_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
デプロイを確認する
Gateway の IP アドレスを取得します。
export GW_IP=$(kubectl get gateway/cross-region-gateway -n default --context=CLUSTER1_CONTEXT -o jsonpath='{.status.addresses[0].value}') echo ${GW_IP}CLUSTER1_CONTEXT変数は、必要なカスタム リソースをインストールするセクションで定義されています。一時 Pod でインタラクティブ
shセッションを開始します。kubectl run -it --rm --image=curlimages/curl curly --context=CLUSTER1_CONTEXT -- /bin/shCLUSTER1_CONTEXT変数は、必要なカスタム リソースをインストールするセクションで定義されています。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 アドレスに置き換えます。
ゲートウェイの負荷テストを行う
同じ VPC ネットワーク内のロード ジェネレータを使用して、ゲートウェイ 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 Gateway API の詳細を確認する。
- GKE マルチクラスタ推論 Gateway の詳細を確認する。
- マルチクラスタ Ingress の詳細を確認する。