GKE 推論ゲートウェイを使用して LLM を提供する


このチュートリアルでは、GKE 推論 Gateway を使用して Google Kubernetes Engine(GKE)に大規模言語モデル(LLM)をデプロイする方法について説明します。このチュートリアルでは、クラスタの設定、モデルのデプロイ、GKE Inference Gateway の構成、LLM リクエストの処理の手順について説明します。

このチュートリアルは、GKE Inference Gateway を使用して GKE で LLM を使用して LLM アプリケーションをデプロイおよび管理する機械学習(ML)エンジニア、プラットフォーム管理者とオペレーター、データおよび AI のスペシャリストを対象としています。

このページを読む前に、次の内容を理解しておいてください。

背景

このセクションでは、このチュートリアルで使用されている重要なテクノロジーについて説明します。モデル サービングのコンセプトと用語、GKE の生成 AI 機能を使用してモデル サービングのパフォーマンスを強化してサポートする方法の詳細については、GKE でのモデル推論についてをご覧ください。

vLLM

vLLM は、GPU のサービング スループットを向上させる、高度に最適化されたオープンソースの LLM サービング フレームワークであり、次のような機能を備えています。

  • PagedAttention による Transformer の実装の最適化
  • サービング スループットを全体的に向上させる連続的なバッチ処理
  • 複数の GPU でのテンソル並列処理と分散サービング

詳細については、vLLM のドキュメントをご覧ください。

GKE Inference Gateway

GKE Inference Gateway は、LLM を提供する GKE の機能を強化します。推論ワークロードを最適化するために、次のような機能を使用します。

  • 負荷指標に基づく推論最適化ロード バランシング。
  • LoRA アダプタの密なマルチワークロード サービングをサポート。
  • モデル対応ルーティングによるオペレーションの簡素化。

詳細については、GKE 推論 Gateway についてをご覧ください。

目標

  1. モデルへのアクセス権を取得する
  2. 環境を準備する
  3. Google Cloud リソースを作成して構成する
  4. InferenceModel CRD と InferencePool CRD をインストールします
  5. モデルサーバーをデプロイする
  6. Inference Gateway のオブザーバビリティを構成する

始める前に

  • Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  • Make sure that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Enable the API

  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  • Make sure that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Enable the API

  • Make sure that you have the following role or roles on the project: roles/container.admin, roles/iam.serviceAccountAdmin

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the project.
    3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

    4. For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      [IAM] に移動
    2. プロジェクトを選択します。
    3. [ アクセスを許可] をクリックします。
    4. [新しいプリンシパル] フィールドに、ユーザー ID を入力します。 これは通常、Google アカウントのメールアドレスです。

    5. [ロールを選択] リストでロールを選択します。
    6. 追加のロールを付与するには、 [別のロールを追加] をクリックして各ロールを追加します。
    7. [保存] をクリックします。
  • Hugging Face アカウントを作成します(まだ作成していない場合)。
  • プロジェクトに、H100 GPU に対する十分な割り当てがあることを確認します。詳細については、GPU 割り当てを計画する割り当てをご覧ください。

モデルへのアクセス権を取得する

Llama3.1 モデルを GKE にデプロイするには、ライセンス同意契約に署名し、Hugging Face アクセス トークンを生成します。

Llama3.1 モデルを使用するには、同意契約に署名する必要があります。手順は次のとおりです。

  1. 同意ページにアクセスし、Hugging Face アカウントの使用に対する同意を確認します。
  2. モデルの規約に同意します。

アクセス トークンを生成する

Hugging Face からモデルにアクセスするには、Hugging Face トークンが必要です。

トークンをまだ生成していない場合は、次の手順に沿って生成します。

  1. [Your Profile] > [Settings] > [Access Tokens] の順にクリックします。
  2. [New Token] を選択します。
  3. 任意の名前と、少なくとも Read ロールを指定します。
  4. [Generate a token] を選択します。
  5. トークンをクリップボードにコピーします。

環境を準備する

このチュートリアルでは、Cloud Shell を使用してGoogle Cloudでホストされているリソースを管理します。Cloud Shell には、このチュートリアルに必要な kubectl gcloud CLI などのソフトウェアがプリインストールされています。

Cloud Shell を使用して環境を設定するには、次の操作を行います。

  1. Google Cloud コンソールで、Google Cloud コンソールCloud Shell 有効化アイコン [Cloud Shell をアクティブにする] をクリックして、Cloud Shell セッションを起動します。これにより、 Google Cloud コンソールの下部ペインでセッションが起動されます。

  2. デフォルトの環境変数を設定します。

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    export REGION=REGION
    export CLUSTER_NAME=CLUSTER_NAME
    export HF_TOKEN=HF_TOKEN
    

    次の値を置き換えます。

    • PROJECT_ID: Google Cloudのプロジェクト ID
    • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、H100 GPU の場合は us-central1)。
    • CLUSTER_NAME: クラスタの名前。
    • HF_TOKEN: 先ほど生成した Hugging Face トークン。

Google Cloud リソースを作成して構成する

必要なリソースを作成するには、次の手順を使用します。

GKE クラスタとノードプールを作成する

GKE Autopilot クラスタまたは GKE Standard クラスタの GPU で LLM を提供します。フルマネージドの Kubernetes エクスペリエンスを実現するには、Autopilot クラスタを使用することをおすすめします。ワークロードに最適な GKE の運用モードを選択するには、GKE の運用モードを選択するをご覧ください。

Autopilot

Cloud Shell で、次のコマンドを実行します。

gcloud container clusters create-auto CLUSTER_NAME \
    --project=PROJECT_ID \
    --region=REGION \
    --release-channel=rapid \
    --cluster-version=1.32.3-gke.1170000

次の値を置き換えます。

  • PROJECT_ID: Google Cloudのプロジェクト ID
  • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、H100 GPU の場合は us-central1)。
  • CLUSTER_NAME: クラスタの名前。

GKE は、デプロイされたワークロードからのリクエストに応じた CPU ノードと GPU ノードを持つ Autopilot クラスタを作成します。

Standard

  1. Cloud Shell で、次のコマンドを実行して Standard クラスタを作成します。

    gcloud container clusters create CLUSTER_NAME \
        --project=PROJECT_ID \
        --region=REGION \
        --workload-pool=PROJECT_ID.svc.id.goog \
        --release-channel=rapid \
        --num-nodes=1 \
        --enable-managed-prometheus \
        --monitoring=SYSTEM,DCGM \
        --cluster-version=1.32.3-gke.1170000
    

    次の値を置き換えます。

    • PROJECT_ID: Google Cloudのプロジェクト ID
    • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、H100 GPU の場合は us-central1)。
    • CLUSTER_NAME: クラスタの名前。

    クラスタの作成には数分かかることもあります。

  2. Llama-3.1-8B-Instruct モデルの実行に適したディスクサイズのノードプールを作成するには、次のコマンドを実行します。

    gcloud container node-pools create gpupool \
        --accelerator type=nvidia-h100-80gb,count=2,gpu-driver-version=latest \
        --project=PROJECT_ID \
        --location=REGION \
        --node-locations=REGION-a \
        --cluster=CLUSTER_NAME \
        --machine-type=a3-highgpu-2g \
        --num-nodes=1 \
        --disk-type="pd-standard"
    

    GKE は、H100 GPU を含む単一のノードプールを作成します。

  1. 指標をスクレイピングするための認可を設定するには、inference-gateway-sa-metrics-reader-secret シークレットを作成します。

    kubectl apply -f - <<EOF
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: inference-gateway-metrics-reader
    rules:
    - nonResourceURLs:
      - /metrics
      verbs:
      - get
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: inference-gateway-sa-metrics-reader
      namespace: default
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: inference-gateway-sa-metrics-reader-role-binding
      namespace: default
    subjects:
    - kind: ServiceAccount
      name: inference-gateway-sa-metrics-reader
      namespace: default
    roleRef:
      kind: ClusterRole
      name: inference-gateway-metrics-reader
      apiGroup: rbac.authorization.k8s.io
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: inference-gateway-sa-metrics-reader-secret
      namespace: default
      annotations:
        kubernetes.io/service-account.name: inference-gateway-sa-metrics-reader
    type: kubernetes.io/service-account-token
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: inference-gateway-sa-metrics-reader-secret-read
    rules:
    - resources:
      - secrets
      apiGroups: [""]
      verbs: ["get", "list", "watch"]
      resourceNames: ["inference-gateway-sa-metrics-reader-secret"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: gmp-system:collector:inference-gateway-sa-metrics-reader-secret-read
      namespace: default
    roleRef:
      name: inference-gateway-sa-metrics-reader-secret-read
      kind: ClusterRole
      apiGroup: rbac.authorization.k8s.io
    subjects:
    - name: collector
      namespace: gmp-system
      kind: ServiceAccount
    EOF
    

Hugging Face の認証情報用の Kubernetes Secret を作成する

Cloud Shell で、次の操作を行います。

  1. クラスタと通信するには、kubectl を構成します。

      gcloud container clusters get-credentials CLUSTER_NAME \
          --location=REGION
    

    次の値を置き換えます。

    • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、H100 GPU の場合は us-central1)。
    • CLUSTER_NAME: クラスタの名前。
  2. Hugging Face トークンを含む Kubernetes Secret を作成します。

      kubectl create secret generic HF_SECRET \
          --from-literal=token=HF_TOKEN \
          --dry-run=client -o yaml | kubectl apply -f -
    

    次のように置き換えます。

    • HF_TOKEN: 先ほど生成した Hugging Face トークン。
    • HF_SECRET: Kubernetes Secret の名前。例: hf-secret

InferenceModel CRD と InferencePool CRD をインストールする

このセクションでは、GKE 推論 Gateway に必要なカスタム リソース定義(CRD)をインストールします。

CRD は Kubernetes API を拡張します。これにより、新しいリソースタイプを定義できます。GKE Inference Gateway を使用するには、次のコマンドを実行して、GKE クラスタに InferencePool CRD と InferenceModel CRD をインストールします。

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

モデルサーバーをデプロイする

この例では、vLLM モデルサーバーを使用して Llama3.1 モデルをデプロイします。デプロイメントには app:vllm-llama3-8b-instruct というラベルが付けられています。このデプロイでは、Hugging Face の food-reviewcad-fabricator という 2 つの LoRA アダプターも使用します。このデプロイメントは、独自のモデルサーバー、モデルコンテナ、サービング ポート、デプロイ名で更新できます。必要に応じて、デプロイで LoRA アダプタを構成するか、ベースモデルをデプロイします。

  1. nvidia-h100-80gb アクセラレータ タイプにデプロイするには、次のマニフェストを vllm-llama3-8b-instruct.yaml として保存します。このマニフェストでは、モデルとモデルサーバーを含む Kubernetes Deployment を定義します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-llama3-8b-instruct
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: vllm-llama3-8b-instruct
      template:
        metadata:
          labels:
            app: vllm-llama3-8b-instruct
        spec:
          containers:
            - name: vllm
              image: "vllm/vllm-openai:latest"
              imagePullPolicy: Always
              command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
              args:
              - "--model"
              - "meta-llama/Llama-3.1-8B-Instruct"
              - "--tensor-parallel-size"
              - "1"
              - "--port"
              - "8000"
              - "--enable-lora"
              - "--max-loras"
              - "2"
              - "--max-cpu-loras"
              - "12"
              env:
                # Enabling LoRA support temporarily disables automatic v1, we want to force it on
                # until 0.8.3 vLLM is released.
                - name: VLLM_USE_V1
                  value: "1"
                - name: PORT
                  value: "8000"
                - name: HUGGING_FACE_HUB_TOKEN
                  valueFrom:
                    secretKeyRef:
                      name: hf-token
                      key: token
                - name: VLLM_ALLOW_RUNTIME_LORA_UPDATING
                  value: "true"
              ports:
                - containerPort: 8000
                  name: http
                  protocol: TCP
              lifecycle:
                preStop:
                  # vLLM stops accepting connections when it receives SIGTERM, so we need to sleep
                  # to give upstream gateways a chance to take us out of rotation. The time we wait
                  # is dependent on the time it takes for all upstreams to completely remove us from
                  # rotation. Older or simpler load balancers might take upwards of 30s, but we expect
                  # our deployment to run behind a modern gateway like Envoy which is designed to
                  # probe for readiness aggressively.
                  sleep:
                    # Upstream gateway probers for health should be set on a low period, such as 5s,
                    # and the shorter we can tighten that bound the faster that we release
                    # accelerators during controlled shutdowns. However, we should expect variance,
                    # as load balancers may have internal delays, and we don't want to drop requests
                    # normally, so we're often aiming to set this value to a p99 propagation latency
                    # of readiness -> load balancer taking backend out of rotation, not the average.
                    #
                    # This value is generally stable and must often be experimentally determined on
                    # for a given load balancer and health check period. We set the value here to
                    # the highest value we observe on a supported load balancer, and we recommend
                    # tuning this value down and verifying no requests are dropped.
                    #
                    # If this value is updated, be sure to update terminationGracePeriodSeconds.
                    #
                    seconds: 30
                  #
                  # IMPORTANT: preStop.sleep is beta as of Kubernetes 1.30 - for older versions
                  # replace with this exec action.
                  #exec:
                  #  command:
                  #  - /usr/bin/sleep
                  #  - 30
              livenessProbe:
                httpGet:
                  path: /health
                  port: http
                  scheme: HTTP
                # vLLM's health check is simple, so we can more aggressively probe it.  Liveness
                # check endpoints should always be suitable for aggressive probing.
                periodSeconds: 1
                successThreshold: 1
                # vLLM has a very simple health implementation, which means that any failure is
                # likely significant. However, any liveness triggered restart requires the very
                # large core model to be reloaded, and so we should bias towards ensuring the
                # server is definitely unhealthy vs immediately restarting. Use 5 attempts as
                # evidence of a serious problem.
                failureThreshold: 5
                timeoutSeconds: 1
              readinessProbe:
                httpGet:
                  path: /health
                  port: http
                  scheme: HTTP
                # vLLM's health check is simple, so we can more aggressively probe it.  Readiness
                # check endpoints should always be suitable for aggressive probing, but may be
                # slightly more expensive than readiness probes.
                periodSeconds: 1
                successThreshold: 1
                # vLLM has a very simple health implementation, which means that any failure is
                # likely significant,
                failureThreshold: 1
                timeoutSeconds: 1
              # We set a startup probe so that we don't begin directing traffic or checking
              # liveness to this instance until the model is loaded.
              startupProbe:
                # Failure threshold is when we believe startup will not happen at all, and is set
                # to the maximum possible time we believe loading a model will take. In our
                # default configuration we are downloading a model from HuggingFace, which may
                # take a long time, then the model must load into the accelerator. We choose
                # 10 minutes as a reasonable maximum startup time before giving up and attempting
                # to restart the pod.
                #
                # IMPORTANT: If the core model takes more than 10 minutes to load, pods will crash
                # loop forever. Be sure to set this appropriately.
                failureThreshold: 3600
                # Set delay to start low so that if the base model changes to something smaller
                # or an optimization is deployed, we don't wait unnecessarily.
                initialDelaySeconds: 2
                # As a startup probe, this stops running and so we can more aggressively probe
                # even a moderately complex startup - this is a very important workload.
                periodSeconds: 1
                httpGet:
                  # vLLM does not start the OpenAI server (and hence make /health available)
                  # until models are loaded. This may not be true for all model servers.
                  path: /health
                  port: http
                  scheme: HTTP
    
              resources:
                limits:
                  nvidia.com/gpu: 1
                requests:
                  nvidia.com/gpu: 1
              volumeMounts:
                - mountPath: /data
                  name: data
                - mountPath: /dev/shm
                  name: shm
                - name: adapters
                  mountPath: "/adapters"
          initContainers:
            - name: lora-adapter-syncer
              tty: true
              stdin: true
              image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/lora-syncer:main
              restartPolicy: Always
              imagePullPolicy: Always
              env:
                - name: DYNAMIC_LORA_ROLLOUT_CONFIG
                  value: "/config/configmap.yaml"
              volumeMounts: # DO NOT USE subPath, dynamic configmap updates don't work on subPaths
              - name: config-volume
                mountPath:  /config
          restartPolicy: Always
    
          # vLLM allows VLLM_PORT to be specified as an environment variable, but a user might
          # create a 'vllm' service in their namespace. That auto-injects VLLM_PORT in docker
          # compatible form as `tcp://<IP>:<PORT>` instead of the numeric value vLLM accepts
          # causing CrashLoopBackoff. Set service environment injection off by default.
          enableServiceLinks: false
    
          # Generally, the termination grace period needs to last longer than the slowest request
          # we expect to serve plus any extra time spent waiting for load balancers to take the
          # model server out of rotation.
          #
          # An easy starting point is the p99 or max request latency measured for your workload,
          # although LLM request latencies vary significantly if clients send longer inputs or
          # trigger longer outputs. Since steady state p99 will be higher than the latency
          # to drain a server, you may wish to slightly this value either experimentally or
          # via the calculation below.
          #
          # For most models you can derive an upper bound for the maximum drain latency as
          # follows:
          #
          #   1. Identify the maximum context length the model was trained on, or the maximum
          #      allowed length of output tokens configured on vLLM (llama2-7b was trained to
          #      4k context length, while llama3-8b was trained to 128k).
          #   2. Output tokens are the more compute intensive to calculate and the accelerator
          #      will have a maximum concurrency (batch size) - the time per output token at
          #      maximum batch with no prompt tokens being processed is the slowest an output
          #      token can be generated (for this model it would be about 100ms TPOT at a max
          #      batch size around 50)
          #   3. Calculate the worst case request duration if a request starts immediately
          #      before the server stops accepting new connections - generally when it receives
          #      SIGTERM (for this model that is about 4096 / 10 ~ 40s)
          #   4. If there are any requests generating prompt tokens that will delay when those
          #      output tokens start, and prompt token generation is roughly 6x faster than
          #      compute-bound output token generation, so add 20% to the time from above (40s +
          #      16s ~ 55s)
          #
          # Thus we think it will take us at worst about 55s to complete the longest possible
          # request the model is likely to receive at maximum concurrency (highest latency)
          # once requests stop being sent.
          #
          # NOTE: This number will be lower than steady state p99 latency since we stop       receiving
          #       new requests which require continuous prompt token computation.
              # NOTE: The max timeout for backend connections from gateway to model servers should
          #       be configured based on steady state p99 latency, not drain p99 latency
          #
          #   5. Add the time the pod takes in its preStop hook to allow the load balancers have
          #      stopped sending us new requests (55s + 30s ~ 85s)
          #
          # Because the termination grace period controls when the Kubelet forcibly terminates a
          # stuck or hung process (a possibility due to a GPU crash), there is operational safety
          # in keeping the value roughly proportional to the time to finish serving. There is also
          # value in adding a bit of extra time to deal with unexpectedly long workloads.
          #
          #   6. Add a 50% safety buffer to this time since the operational impact should be low
          #      (85s * 1.5 ~ 130s)
          #
          # One additional source of drain latency is that some workloads may run close to
          # saturation and have queued requests on each server. Since traffic in excess of the
          # max sustainable QPS will result in timeouts as the queues grow, we assume that failure
          # to drain in time due to excess queues at the time of shutdown is an expected failure
          # mode of server overload. If your workload occasionally experiences high queue depths
          # due to periodic traffic, consider increasing the safety margin above to account for
          # time to drain queued requests.
          terminationGracePeriodSeconds: 130
          nodeSelector:
            cloud.google.com/gke-accelerator: "nvidia-h100-80gb"
          volumes:
            - name: data
              emptyDir: {}
            - name: shm
              emptyDir:
                medium: Memory
            - name: adapters
              emptyDir: {}
            - name: config-volume
              configMap:
                name: vllm-llama3-8b-adapters
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: vllm-llama3-8b-adapters
    data:
      configmap.yaml: |
          vLLMLoRAConfig:
            name: vllm-llama3.1-8b-instruct
            port: 8000
            defaultBaseModel: meta-llama/Llama-3.1-8B-Instruct
            ensureExist:
              models:
              - id: food-review
                source: Kawon/llama3.1-food-finetune_v14_r8
              - id: cad-fabricator
                source: redcathode/fabricator
    ---
    kind: HealthCheckPolicy
    apiVersion: networking.gke.io/v1
    metadata:
      name: health-check-policy
      namespace: default
    spec:
      targetRef:
        group: "inference.networking.x-k8s.io"
        kind: InferencePool
        name: vllm-llama3-8b-instruct
      default:
        config:
          type: HTTP
          httpHealthCheck:
              requestPath: /health
              port: 8000
    
  2. マニフェストをクラスタに適用します。

    kubectl apply -f vllm-llama3-8b-instruct.yaml
    

InferencePool リソースを作成する

InferencePool Kubernetes カスタム リソースは、共通のベース LLM とコンピューティング構成を持つ Pod のグループを定義します。

InferencePool カスタム リソースには、次のキーフィールドが含まれています。

  • selector: このプールに属する Pod を指定します。このセレクタのラベルは、モデルサーバー Pod に適用されるラベルと完全に一致している必要があります。
  • targetPort: Pod 内のモデルサーバーで使用されるポートを定義します。

InferencePool リソースを使用すると、GKE Inference Gateway はモデルサーバー Pod にトラフィックを転送できます。

Helm を使用して InferencePool を作成する手順は次のとおりです。

helm install vllm-llama3-8b-instruct \
  --set inferencePool.modelServers.matchLabels.app=vllm-llama3-8b-instruct \
  --set provider.name=gke \
  --set healthCheckPolicy.create=false \
  --version v0.3.0 \
  oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepool

次のフィールドを Deployment に合わせて変更します。

  • inferencePool.modelServers.matchLabels.app: モデルサーバー Pod の選択に使用されるラベルのキー。

このコマンドは、モデルサーバーのデプロイを論理的に表す InferencePool オブジェクトを作成し、Selector が選択した Pod 内のモデル エンドポイント サービスを参照します。

サービングの重要度を持つ InferenceModel リソースを作成する

InferenceModel Kubernetes カスタム リソースは、LoRA チューニング済みモデルなどの特定のモデルと、そのサービス提供の重要度を定義します。

InferenceModel カスタム リソースには、次のキーフィールドが含まれています。

  • modelName: ベースモデルまたは LoRA アダプタの名前を指定します。
  • Criticality: モデルの提供の重要度を指定します。
  • poolRef: モデルが提供される InferencePool を参照します。

InferenceModel を使用すると、GKE Inference Gateway はモデル名と重大度に基づいてモデルサーバー Pod にトラフィックをルーティングできます。

InferenceModel を作成するには、次の操作を行います。

  1. 次のサンプル マニフェストを inferencemodel.yaml として保存します。

    apiVersion: inference.networking.x-k8s.io/v1alpha2
    kind: InferenceModel
    metadata:
      name: inferencemodel-sample
    spec:
      modelName: MODEL_NAME
      criticality: CRITICALITY
      poolRef:
        name: INFERENCE_POOL_NAME
    

    次のように置き換えます。

    • MODEL_NAME: ベースモデルまたは LoRA アダプターの名前。例: food-review
    • CRITICALITY: 選択したサービング クリティカル性。CriticalStandardSheddable から選択します。例: Standard
    • INFERENCE_POOL_NAME: 前の手順で作成した InferencePool の名前。例: vllm-llama3-8b-instruct
  2. サンプル マニフェストをクラスタに適用します。

    kubectl apply -f inferencemodel.yaml
    

次の例では、Standard サービス重大度で vllm-llama3-8b-instruct InferencePoolfood-review LoRA モデルを構成する InferenceModel オブジェクトを作成します。InferenceModel オブジェクトは、Critical 優先度レベルで提供されるようにベースモデルを構成します。

apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferenceModel
metadata:
  name: food-review
spec:
  modelName: food-review
  criticality: Standard
  poolRef:
    name: vllm-llama3-8b-instruct
  targetModels:
  - name: food-review
    weight: 100

---
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferenceModel
metadata:
  name: llama3-base-model
spec:
  modelName: meta-llama/Llama-3.1-8B-Instruct
  criticality: Critical
  poolRef:
    name: vllm-llama3-8b-instruct

ゲートウェイを作成する

Gateway リソースは、Kubernetes クラスタへの外部トラフィックのエントリ ポイントとして機能します。受信接続を受け入れるリスナーを定義します。

GKE Inference Gateway は、gke-l7-rilbgke-l7-regional-external-managed の Gateway クラスをサポートしています。詳細については、Gateway クラスに関する GKE のドキュメントをご覧ください。

Gateway を作成するには、次の操作を行います。

  1. 次のサンプル マニフェストを gateway.yaml として保存します。

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: GATEWAY_NAME
    spec:
      gatewayClassName: gke-l7-regional-external-managed
      listeners:
        - protocol: HTTP # Or HTTPS for production
          port: 80 # Or 443 for HTTPS
          name: http
    

    GATEWAY_NAME は、Gateway リソースの一意の名前に置き換えます。例: inference-gateway

  2. マニフェストをクラスタに適用します。

    kubectl apply -f gateway.yaml
    

HTTPRoute リソースを作成する

このセクションでは、HTTPRoute リソースを作成し、Gateway が受信した HTTP リクエストを InferencePool に転送する方法を定義します。

HTTPRoute リソースは、GKE Gateway が受信した HTTP リクエストをバックエンド サービス(InferencePool)に転送する方法を定義します。一致ルール(ヘッダーやパスなど)と、トラフィックを転送するバックエンドを指定します。

HTTPRoute を作成するには、次の操作を行います。

  1. 次のサンプル マニフェストを 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.x-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
    

推論リクエストを送信する

GKE Inference Gateway を構成したら、デプロイされたモデルに推論リクエストを送信できます。

推論リクエストを送信する手順は次のとおりです。

  • Gateway エンドポイントを取得します。
  • 正しい形式の JSON リクエストを作成します。
  • curl を使用して、/v1/completions エンドポイントにリクエストを送信します。

これにより、入力プロンプトと指定したパラメータに基づいてテキストを生成できます。

  1. Gateway エンドポイントを取得するには、次のコマンドを実行します。

    IP=$(kubectl get gateway/GATEWAY_NAME -o jsonpath='{.status.addresses[0].address}')
    PORT=PORT_NUMBER # Use 443 for HTTPS, or 80 for HTTP
    

    次のように置き換えます。

    • GATEWAY_NAME: Gateway リソースの名前。
    • PORT_NUMBER: Gateway で構成したポート番号。
  2. curl を使用して /v1/completions エンドポイントにリクエストを送信するには、次のコマンドを実行します。

    curl -i -X POST https://${IP}:${PORT}/v1/completions \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer $(gcloud auth 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 を使用し、より創造的な出力の場合はより大きな値を使用します。

次の動作に注意してください。

  • リクエスト本文: リクエスト本文には、stoptop_p などの追加パラメータを指定できます。オプションの一覧については、OpenAI API 仕様をご覧ください。
  • エラー処理: クライアント コードに適切なエラー処理を実装して、レスポンスで発生する可能性のあるエラーを処理します。たとえば、curl レスポンスの HTTP ステータス コードを確認します。通常、200 以外のステータス コードはエラーを示します。
  • 認証と認可: 本番環境のデプロイでは、認証と認可メカニズムを使用して API エンドポイントを保護します。適切なヘッダー(Authorization など)をリクエストに含めます。

Inference Gateway のオブザーバビリティを構成する

GKE Inference Gateway は、推論ワークロードの健全性、パフォーマンス、動作のオブザーバビリティを提供します。これにより、問題を特定して解決し、リソース使用率を最適化し、アプリケーションの信頼性を保証できます。これらのオブザーバビリティ指標は、Cloud Monitoring の Metrics Explorer で確認できます。

GKE Inference Gateway のオブザーバビリティを構成するには、オブザーバビリティを構成するをご覧ください。

デプロイされたリソースを削除する

このガイドで作成したリソースについて Google Cloud アカウントに課金されないようにするには、次のコマンドを実行します。

gcloud container clusters delete CLUSTER_NAME \
    --region=REGION

次の値を置き換えます。

  • REGION: 使用するアクセラレータ タイプをサポートするリージョン(たとえば、H100 GPU の場合は us-central1)。
  • CLUSTER_NAME: クラスタの名前。

次のステップ