このドキュメントでは、Google Kubernetes Engine(GKE)Multi-Cluster Inference Gateway と 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 トークン シークレットを作成します。
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など)
Multi-Cluster Ingress 機能を有効にして、構成クラスタを指定します。
gcloud container fleet ingress enable \ --config-membership=projects/PROJECT_ID/locations/global/memberships/CLUSTER_1_NAME次のように置き換えます。他の変数の定義については、前の手順をご覧ください。
PROJECT_ID: プロジェクト IDCLUSTER_1_NAME: 最初のクラスタの名前(gke-westなど)
プロキシ専用サブネットを作成する
警告: Cloud de Confiance by S3NS では、VPC ネットワークごとにリージョンごとに 1 つの
プロキシ専用サブネットのみを使用できます。ターゲット
リージョンに purpose=REGIONAL_MANAGED_PROXY 設定のプロキシ専用サブネットがすでに含まれている場合、GLOBAL_MANAGED_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-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: 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_CONTEXTCLUSTER1_CONTEXTは、最初のクラスタのコンテキスト(gke_my-project_europe-west3-c_gke-westなど)に置き換えます。
自動スケーリングを構成する
トラフィックが他のリージョンにオーバーフローする前に各クラスタが増加する負荷を処理できるようにするには、モデルサーバー デプロイの Horizontal-Pod-Autoscaler(HPA)を構成する必要があります。
構成の主な原則
同じカスタム指標を使用する: HPA は、
GCPBackendPolicyの Multi-Cluster Inference Gateway で使用するのと同じカスタム指標(vllm:kv_cache_usage_percなど)に 基づいてスケーリングするように構成する必要があります。 この方法により、ロード バランシングとスケーリングの両方の決定が、推論サーバーからの同じシグナルによって行われるようになります。選択する指標の値は、使用率を表す 0 ~ 1 の範囲にする必要があります。指標の値が 1 より大きい場合、ロードバランサは 100% の使用率と解釈するため、予期しないルーティング動作が発生する可能性があります。HPA ターゲットを低く設定する: HPA 構成の指標のターゲット値は、
maxUtilizationPercent設定 よりも低く設定する必要があります。GCPBackendPolicyHPA のターゲット使用率を低く設定すると(たとえば、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 ネットワーク内のロードジェネレータを使用して、Gateway IP アドレスに持続的な負荷を適用します。
優先リージョン(
us-east4)で処理できると想定される適度な負荷から開始します。負荷テストのリクエスト率または同時実行数を徐々に増やします。
負荷テストの実行中に、 Cloud de Confiance コンソールまたは
kubectlを使用してシステムをモニタリングします。- Pod のスケーリング(HPA): 両方のクラスタの
vllm-llama3-8b-instructデプロイの 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 Multi-Cluster Inference Gateway の詳細を確認する。
- マルチクラスタ Ingress の詳細を確認する。