モデルサービングインフラ
環境にモデルサービングソリューションがまだない場合に、モデルエンドポイントをデプロイおよび設定する方法について説明します。
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 対応ワーカーノード
- ターゲットクラスターへの認証済み
ocCLI とターゲット名前空間でリソースを作成する権限 - クラスターからアクセス可能なプライベートコンテナレジストリと、そこにイメージをプッシュするためのクレデンシャル
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: ManagedModelCar サポートの有効化
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.yamlInferenceService のデプロイ
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: vllmInferenceService マニフェストを適用します。
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 にリンクされていることを確認してください。 |
ImagePullBackOff | ModelCar 用のイメージプルシークレットが設定されていない | サービスアカウントに 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 / OOMKilled | GPU メモリ不足 | 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 設定。
- ネットワークポリシーとファイアウォールがアクセスを許可していること。
- エンドポイント認証が正常に機能していること。
接続と認証が検証されたら、モデルゲートウェイの設定に進んでください。