モデルサービングインフラ

環境にモデルサービングソリューションがまだない場合に、モデルエンドポイントをデプロイおよび設定する方法について説明します。

IBM Bob を大規模言語モデル (LLM) に接続する前に、デプロイされたモデルエンドポイントへのアクセスが必要です。Bob はモデルサービングインフラのプロビジョニング、ホスティング、管理を行いません。組織が OpenShift AI、GPU ベースの推論サーバー、クラウド AI サービス、またはその他の推論プラットフォームを通じてすでにモデルエンドポイントを提供している場合は、モデルゲートウェイの設定に直接進んでください。

デプロイメントオプション

環境と運用要件に最適なオプションを選択してください。

オプション使用する場面
OpenShift AI (オンクラスター、OCI/ModelCar)エアギャップまたはセルフホスト型モデル;RHOAI がすでにクラスターで利用可能
パブリッククラウドAWS Bedrock、Azure OpenAI、または Google Vertex AI 経由のフロンティアモデル
プライベートインフラ別の GPU サーバーまたは専用推論クラスターで提供されるモデル

OpenShift AI (オンクラスター、OCI/ModelCar)

Red Hat OpenShift AI (RHOAI) は、エアギャップデプロイメントを含むオンクラスターでのモデルサービングに推奨されるプラットフォームです。モデルウェイトを読み込む推奨アプローチは OCI/ModelCar パターンです: モデルファイルを OCI イメージの /models/ 以下に焼き込み、プライベートレジストリにプッシュします。InferenceService がデプロイされると、KServe は modelcar-init init コンテナを注入してイメージをプルし、サービングランタイム (例: vLLM) がそこから読み込む共有ボリュームの /mnt/models/ にウェイトをコピーします。モデルイメージは最初のプル後にノードにキャッシュされ、同じノードでの後続の再起動ではダウンロードをスキップします。

前提条件:

  • クラスターに Red Hat OpenShift AI オペレーターがインストール済みであること
  • KServe が有効化および設定済みであること
  • NVIDIA GPU オペレーター (または同等のもの) が設定された GPU 対応ワーカーノード
  • ターゲットクラスターへの認証済み oc CLI とターゲット名前空間でリソースを作成する権限
  • クラスターからアクセス可能なプライベートコンテナレジストリと、そこにイメージをプッシュするためのクレデンシャル

Red Hat OpenShift AI の設定

以下のように DataScienceClusterInitialization と DataScienceCluster リソースを設定してください。

  • serviceMesh を無効化します。
  • managementState: Managed を設定して KServe を有効化します。
  • KServe が RawDeployment モードを使用するよう設定します。
  • 未使用の Red Hat OpenShift AI コンポーネントをすべて削除します。

KServe 設定例:

kserve:
  defaultDeploymentMode: RawDeployment
  nim:
    managementState: Managed
  rawDeploymentServiceConfig: Headed
  serving:
    ingressGateway:
      certificate:
        type: OpenshiftDefaultIngress
    managementState: Removed
    name: knative-serving
  managementState: Managed

ModelCar サポートの有効化

ModelCar サポートは redhat-ods-applications 名前空間の inferenceservice-config ConfigMap で制御されます。storageInitializer キーには "enableModelcar": true が含まれている必要があります。

現在の設定を確認します。

oc get configmap inferenceservice-config \
  -n redhat-ods-applications \
  -o jsonpath='{.data.storageInitializer}'

出力には以下が含まれている必要があります。

{
  "enableModelcar": true,
  "cpuModelcar": "10m",
  "memoryModelcar": "15Mi"
}

enableModelcar がない場合や false の場合は、ConfigMap を更新します。

# 現在の値を取得し、フラグをマージしてパッチを適用
CURRENT=$(oc get configmap inferenceservice-config \
  -n redhat-ods-applications \
  -o jsonpath='{.data.storageInitializer}')
PATCHED=$(echo "$CURRENT" | python3 -c "
import json, sys
d = json.load(sys.stdin)
d['enableModelcar'] = True
print(json.dumps(d))
")
oc patch configmap inferenceservice-config \
  -n redhat-ods-applications \
  --type merge \
  -p "{\"data\":{\"storageInitializer\":$(echo $PATCHED | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}}"

変更を適用するために KServe コントローラーを再起動します。

oc rollout restart deployment kserve-controller-manager -n redhat-ods-applications
oc rollout status deployment kserve-controller-manager -n redhat-ods-applications

モデルファイルを OCI イメージにパッケージング

Hugging Face からモデルウェイトをダウンロードし、OCI イメージにパッケージングします。イメージには /models ディレクトリ以下にすべてのモデルファイルが必要です。詳細については KServe ドキュメントを参照してください。vLLM デプロイメントの場合は safetensors モデルシャードを含め、.bin、.pt、original/* などのレガシーチェックポイントファイルは除外してください。

Dockerfile の例:

FROM busybox:latest

# モデルウェイト — safetensors シャードとインデックス
COPY <model-name>/model-*.safetensors         /models/
COPY <model-name>/model.safetensors.index.json /models/

# モデル設定
COPY <model-name>/config.json             /models/
COPY <model-name>/generation_config.json  /models/

# トークナイザー
COPY <model-name>/tokenizer.json           /models/
COPY <model-name>/tokenizer_config.json    /models/
COPY <model-name>/special_tokens_map.json  /models/

モデルにチャットテンプレートが含まれている場合 (例: chat_template.jinja)、それを追加してください。または、ディレクトリ全体を 1 つの命令でコピーする方が簡単ですが、vLLM に不要なファイルも含まれます。

FROM busybox:latest
COPY <model-name>/ /models/

プライベートレジストリへのイメージのプッシュ

OCI イメージをクラスターから到達可能なプライベートコンテナレジストリにプッシュします。

<registry>/<project>/<model-name>:latest

以下を含むサポートされているイメージ管理ツールを使用できます。

  • Podman
  • Skopeo
  • CI/CD パイプライン
  • レジストリ固有のツール

ターゲット名前空間とイメージプルシークレットの作成

プロジェクト名前空間を作成し、モデルイメージをプルするためのクレデンシャルを設定します。

oc new-project <namespace>

レジストリプルシークレットを作成します。

# KServe がプライベートレジストリからモデルイメージをプルできるようにプルシークレットを作成
oc create secret docker-registry model-registry-secret \
  --docker-server=<registry> \
  --docker-username=<username> \
  --docker-password=<password-or-token> \
  -n <namespace>

サービスアカウントを作成します。

# KServe predictor が使用するサービスアカウント
oc create sa model-puller-sa -n <namespace>

プルシークレットをサービスアカウントに関連付けます。

# プルシークレットをアタッチ — 両方のコマンドが必要:
# oc secrets link は一般的なシークレット使用をカバー;
# imagePullSecrets は特に KServe の ModelCar init コンテナに必要
oc secrets link model-puller-sa model-registry-secret --for=pull -n <namespace>
oc patch serviceaccount model-puller-sa -n <namespace> \
  -p '{"imagePullSecrets": [{"name": "model-registry-secret"}]}'
注意:

両方のコマンドが必要です。imagePullSecrets エントリはモデルイメージ取得時の ModelCar 初期化コンテナが使用します。

ServingRuntime の作成

ターゲット名前空間に vLLM ベースの ServingRuntime をデプロイします。

apiVersion: serving.kserve.io/v1alpha1
kind: ServingRuntime
metadata:
  name: vllm-runtime
  namespace: <namespace>
spec:
  multiModel: false
  supportedModelFormats:
    - name: pytorch
      autoSelect: true
  containers:
    - name: kserve-container
      image: vllm/vllm-openai:<version>
      ports:
        - containerPort: 3000
          protocol: TCP
      livenessProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 30
        timeoutSeconds: 5
        failureThreshold: 3
      readinessProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 3
      startupProbe:
        httpGet:
          path: /health
          port: 3000
        periodSeconds: 10
        timeoutSeconds: 5
        failureThreshold: 60

ランタイム設定を適用します。

oc apply -n <namespace> -f serving-runtime-vllm.yaml

InferenceService のデプロイ

oci:// ストレージ URI を使用して OCI モデルイメージを参照する InferenceService を作成します。

主要な設定要件:

  • 以前に作成した ServingRuntime を参照します。
  • storageUri に OCI イメージの場所を指定します。
  • モデル要件に合った CPU、メモリ、GPU リソース制限を設定します。
  • vLLM 用の共有メモリ (/dev/shm) をマウントします。
  • vLLM ランタイム引数と環境変数を設定します。

例:

apiVersion: serving.kserve.io/v1beta1
kind: InferenceService
metadata:
  name: <model-name>
  annotations:
    serving.kserve.io/autoscalerClass: external
    serving.kserve.io/deploymentMode: RawDeployment
spec:
  predictor:
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
          nodeSelectorTerms:
            - matchExpressions:
                - key: kubernetes.io/arch
                  operator: In
                  values:
                    - amd64
    tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
    volumes:
      - name: shm
        emptyDir:
          medium: Memory
          sizeLimit: 64Gi
    model:
      modelFormat:
        name: pytorch
      runtime: vllm-runtime
      storageUri: "oci://<registry>/<namespace-or-project>/<model-name>:latest"
      resources:
        requests:
          cpu: "<cpu-request>"          # 例: "8"
        limits:
          cpu: "<cpu-limit>"            # 例: "16"
          memory: <memory-limit>        # 例: 96Gi — モデルの VRAM 要件に合わせてサイズ設定
          nvidia.com/gpu: "<gpu-count>" # 例: "1"
      volumeMounts:
        - name: shm
          mountPath: /dev/shm
      args:
        - /mnt/models/
        - --served-model-name=<model-name>
        - --port=3000
        - --enable-auto-tool-choice
        - --tool-call-parser=openai
      env:
        - name: HOME
          value: /tmp
        - name: MAX_LOG_LEN
          value: "100"        # vLLM ログ行を切り詰めてログ溢れを防ぐ
        - name: HF_HUB_CACHE
          value: /tmp
        - name: TRITON_CACHE_DIR
          value: /tmp
        - name: XDG_CACHE_HOME
          value: /tmp
        - name: HF_HOME
          value: /tmp/hf_home
        - name: NUM_GPUS
          value: "<gpu-count>" # 上記の nvidia.com/gpu 制限と一致する必要があります
        - name: CUDA_VISIBLE_DEVICES
          value: "<gpu-indices>" # 例: シングル GPU の場合 "0"; 2 GPU の場合 "0,1"
        - name: VLLM_WORKER_MULTIPROC_METHOD
          value: spawn
        - name: LOGNAME
          value: vllm
        - name: USER
          value: vllm

InferenceService マニフェストを適用します。

oc apply -n <namespace> -f isvc-<model-name>.yaml

デプロイメントの確認

デプロイメントステータス、Pod の起動、ランタイムログを監視します。

# InferenceService が Ready 状態になるまで監視
oc get inferenceservice <model-name> -n <namespace> -w

# predictor Pod の起動を監視
oc get pods -n <namespace> -w

# predictor ログをテール (Running になってからモデルの読み込みに数分かかる場合があります)
oc logs -f deployment/<model-name>-predictor -n <namespace>

InferenceService が READY: True を報告したら、エンドポイントを検証します。

モデルの登録を確認してテスト推論リクエストを送信します。

POD=$(oc get pods -n <namespace> \
  -l app=isvc.<model-name>-predictor \
  -o jsonpath='{.items[0].metadata.name}')

oc exec -n <namespace> "$POD" -c kserve-container -- \
  curl -fsS http://127.0.0.1:3000/v1/models

oc exec -n <namespace> "$POD" -c kserve-container -- \
  curl -fsS http://127.0.0.1:3000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "<model-name>",
    "messages": [{"role": "user", "content": "Hello"}],
    "max_tokens": 50
  }'

トラブルシューティング

問題考えられる原因解決策
ErrImagePullレジストリクレデンシャルが欠落または無効model-registry-secret が存在し、有効なクレデンシャルを持ち、oc secrets link と imagePullSecrets パッチの両方を使用して model-puller-sa にリンクされていることを確認してください。
ImagePullBackOffModelCar 用のイメージプルシークレットが設定されていないサービスアカウントに imagePullSecrets 設定が含まれていることを確認してください。oc patch serviceaccount model-puller-sa -n <namespace> -p '{"imagePullSecrets": [{"name": "model-registry-secret"}]}' を実行してください。
predictor が Init:0/1 のままモデルイメージのダウンロード中oc describe pod のイベントで Pulling/Pulled の進捗を確認してください。プル時間はイメージサイズとレジストリ帯域幅によって変わります。
predictor が Init:0/1 のままモデルファイルが見つからないOCI イメージの /models 以下にモデルファイルが保存されていることを確認してください。
Engine core initialization failed初期 CUDA コンパイルタイムアウトキャッシュが生成される最初の起動は時間がかかる場合があります。再起動して再試行してください。
モデルの読み込み失敗サポートされていないモデルファイル形式Hugging Face の safetensors ファイルを使用し、レガシーチェックポイントを除外してください。
OpenSSL FIPS 自己テストエラーコンテナイメージが FIPS 対応でないFIPS 対応の vLLM イメージを使用してください。
OutOfMemory / OOMKilledGPU メモリ不足GPU リソースを増やすか、コンテキスト長を減らすか、量子化モデルを使用してください。
InferenceService が Pending のままクラスターリソースが利用不可GPU の可用性を確認し、未使用のワークロードからリソースを解放してください。

詳細については以下を参照してください。

パブリッククラウドモデルエンドポイント

IBM watsonx、AWS Bedrock、Azure OpenAI、Google Vertex AI などのクラウドプロバイダーによってモデルがホストされている場合にこのオプションを使用します。

前提条件:

  • OpenShift クラスターからクラウドサービスエンドポイントへのアウトバウンド HTTPS (ポート 443) 接続。
  • 有効な API キー、IAM クレデンシャル、または同等の認証クレデンシャル。

IBM Bob を設定する前に

以下を確認してください。

  • モデルデプロイメントがプロビジョニングされ、アクティブであること。
  • 認証クレデンシャルが生成され、安全に保管されていること。
  • プロバイダー固有のネットワークまたはアクセス要件が完了していること。

エンドポイントが利用可能になったら、モデルゲートウェイの設定に進んでください。

プライベートインフラモデルエンドポイント

以下のような、IBM Bob クラスター外の顧客管理インフラでモデルがホストされている場合にこのオプションを使用します。

  • 専用 GPU サーバー
  • 別の OpenShift クラスター
  • ベアメタル推論サーバー
  • エンタープライズ AI プラットフォーム

前提条件:

  • モデルエンドポイントが OpenAI 互換 API を公開していること。
  • IBM Bob クラスターとエンドポイント間に HTTPS 接続が存在すること。
  • 認証クレデンシャルが Kubernetes シークレットとして利用可能であること。

IBM Bob を設定する前に

以下を検証してください。

  • クラスターからエンドポイントへのネットワーク接続。
  • 必要に応じた TLS または相互 TLS 設定。
  • ネットワークポリシーとファイアウォールがアクセスを許可していること。
  • エンドポイント認証が正常に機能していること。

接続と認証が検証されたら、モデルゲートウェイの設定に進んでください。

このトピックはいかがですか?