Infrastructure de service des modèles
Déployez et configurez les endpoints de modèles pour IBM Bob on-premises lorsque votre environnement ne fournit pas encore de solution de service des modèles.
Avant de connecter IBM Bob à un grand modèle de langage (LLM), vous devez avoir accès à un endpoint de modèle déployé. Bob IDE ne provisionne, n'héberge et ne gère pas l'infrastructure de service des modèles. Si votre organisation fournit déjà des endpoints de modèles via Red Hat OpenShift Container Platform (OCP) AI, des serveurs d'inférence GPU, des services IA cloud ou d'autres plateformes d'inférence, passez directement à Configuration de la passerelle d'inférence de modèles.
Choisissez l'option qui correspond le mieux à votre environnement et à vos exigences opérationnelles.
| Option | Quand l'utiliser |
|---|---|
| OpenShift AI (sur cluster, OCI/ModelCar) | Modèles air-gapped ou auto-hébergés ; Red Hat OpenShift AI déjà disponible sur le cluster |
| Endpoints de modèles cloud public | Modèles frontier via AWS Bedrock, Azure OpenAI ou Google Vertex AI |
| Endpoints de modèles sur infrastructure privée | Modèle servi sur des serveurs GPU séparés ou un cluster d'inférence dédié |
Déployer des modèles avec OpenShift AI (sur cluster, OCI/ModelCar)
Red Hat OpenShift AI (RHOAI) est la plateforme recommandée pour servir des modèles sur cluster, y compris pour les déploiements air-gapped. L'approche privilégiée pour charger les poids des modèles est le pattern OCI/ModelCar : les fichiers du modèle sont intégrés dans une image OCI sous /models/ et poussés vers un registre privé. Lors du déploiement de l'InferenceService, KServe injecte un init container modelcar-init qui récupère l'image et copie les poids dans un volume partagé à /mnt/models/, à partir duquel le runtime de service (par exemple, vLLM) les charge. L'image du modèle est mise en cache sur le nœud après le premier pull ; les redémarrages ultérieurs sur le même nœud ignorent entièrement le téléchargement.
Prérequis :
- Opérateur Red Hat OpenShift AI installé sur le cluster
- KServe activé et configuré
- Nœuds worker avec GPU activé avec l'opérateur NVIDIA GPU (ou équivalent) configuré
- CLI
ocauthentifié auprès du cluster cible avec la permission de créer des ressources dans le namespace cible - Un registre de conteneurs privé accessible depuis le cluster, avec les identifiants pour y pousser des images
Configurer Red Hat OpenShift AI
Configurez les ressources DataScienceClusterInitialization et DataScienceCluster comme suit :
- Désactivez
serviceMesh. - Activez KServe en définissant
managementState: Managed. - Configurez KServe pour utiliser le mode
RawDeployment. - Supprimez tous les composants Red Hat OpenShift AI inutilisés.
Exemple de configuration KServe :
kserve:
defaultDeploymentMode: RawDeployment
nim:
managementState: Managed
rawDeploymentServiceConfig: Headed
serving:
ingressGateway:
certificate:
type: OpenshiftDefaultIngress
managementState: Removed
name: knative-serving
managementState: ManagedActiver la prise en charge de ModelCar
La prise en charge de ModelCar est contrôlée par le ConfigMap inferenceservice-config dans le namespace redhat-ods-applications. La clé storageInitializer doit contenir "enableModelcar": true.
Vérifiez la configuration actuelle :
oc get configmap inferenceservice-config \
-n redhat-ods-applications \
-o jsonpath='{.data.storageInitializer}'La sortie doit contenir :
{
"enableModelcar": true,
"cpuModelcar": "10m",
"memoryModelcar": "15Mi"
}Si enableModelcar est absent ou à false, mettez à jour le ConfigMap :
# Récupérer la valeur actuelle, fusionner l'indicateur et appliquer le patch
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()))')}}"Redémarrez le contrôleur KServe pour appliquer la modification :
oc rollout restart deployment kserve-controller-manager -n redhat-ods-applications
oc rollout status deployment kserve-controller-manager -n redhat-ods-applicationsEmpaqueter les fichiers du modèle dans une image OCI
Téléchargez les poids du modèle depuis Hugging Face et empaquetez-les dans une image OCI. L'image doit avoir tous les fichiers du modèle sous le répertoire /models. Pour plus d'informations, voir la documentation KServe sur la préparation d'une image OCI avec des données de modèle. Pour les déploiements vLLM, incluez les fragments de modèle safetensors et excluez les anciens fichiers de checkpoint tels que .bin, .pt et original/*.
Exemple de Dockerfile :
FROM busybox:latest
# Poids du modèle -- fragments safetensors et index
COPY <model-name>/model-*.safetensors /models/
COPY <model-name>/model.safetensors.index.json /models/
# Configuration du modèle
COPY <model-name>/config.json /models/
COPY <model-name>/generation_config.json /models/
# Tokenizer
COPY <model-name>/tokenizer.json /models/
COPY <model-name>/tokenizer_config.json /models/
COPY <model-name>/special_tokens_map.json /models/Si le modèle inclut un template de chat (par exemple, chat_template.jinja), ajoutez-le. Vous pouvez également copier l'intégralité du répertoire en une seule instruction, ce qui est plus simple mais inclut des fichiers dont vLLM n'a pas besoin :
FROM busybox:latest
COPY <model-name>/ /models/Pousser l'image vers un registre privé
Poussez l'image OCI vers un registre de conteneurs privé accessible depuis le cluster :
<registry>/<project>/<model-name>:latestUtilisez l'outil qui correspond à votre environnement (podman push, skopeo copy, un pipeline CI, etc.).
Créer le namespace cible et le secret d'extraction d'image
Créez le namespace du projet et configurez les identifiants pour extraire l'image du modèle.
Créez le namespace :
oc new-project <namespace>Créez le secret d'extraction du registre :
# Secret d'extraction pour que KServe puisse extraire l'image du modèle de votre registre privé
oc create secret docker-registry model-registry-secret \
--docker-server=<registry> \
--docker-username=<username> \
--docker-password=<password-or-token> \
-n <namespace>Créez un compte de service :
# Compte de service utilisé par le prédicteur KServe
oc create sa model-puller-sa -n <namespace>Associez le secret d'extraction au compte de service :
# Attacher le secret d'extraction -- les deux commandes sont requises :
# oc secrets link couvre l'utilisation générale des secrets ;
# imagePullSecrets est nécessaire par le init container ModelCar de KServe spécifiquement
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"}]}'Les deux commandes sont requises. L'entrée imagePullSecrets est utilisée par le container d'initialisation ModelCar lors de la récupération de l'image du modèle.
Créer un ServingRuntime
Déployez un ServingRuntime basé sur vLLM dans le namespace cible.
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: 60Appliquez la configuration du runtime :
oc apply -n <namespace> -f serving-runtime-vllm.yamlDéployer l'InferenceService
Créez un InferenceService qui référence l'image OCI du modèle en utilisant un URI de stockage oci://.
Exigences de configuration clés :
- Référencer le
ServingRuntimecréé précédemment. - Spécifier l'emplacement de l'image OCI dans
storageUri. - Configurer les limites de ressources CPU, mémoire et GPU correspondant aux exigences du modèle.
- Monter la mémoire partagée (
/dev/shm) pour vLLM. - Configurer les arguments de runtime vLLM et les variables d'environnement.
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>" # ex. "8"
limits:
cpu: "<cpu-limit>" # ex. "16"
memory: <memory-limit> # ex. 96Gi -- dimensionner selon les besoins VRAM du modèle
nvidia.com/gpu: "<gpu-count>" # ex. "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" # tronquer les lignes de log vLLM pour éviter la surcharge des logs
- 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>" # doit correspondre à la limite nvidia.com/gpu ci-dessus
- name: CUDA_VISIBLE_DEVICES
value: "<gpu-indices>" # ex. "0" pour un seul GPU ; "0,1" pour deux
- name: VLLM_WORKER_MULTIPROC_METHOD
value: spawn
- name: LOGNAME
value: vllm
- name: USER
value: vllmAppliquez le manifeste InferenceService :
oc apply -n <namespace> -f isvc-<model-name>.yamlVérifier le déploiement
Surveillez l'état du déploiement, le démarrage du pod et les logs du runtime :
# Suivre l'InferenceService jusqu'à l'état Ready
oc get inferenceservice <model-name> -n <namespace> -w
# Suivre le démarrage du pod prédicteur
oc get pods -n <namespace> -w
# Suivre les logs du prédicteur (le chargement du modèle peut prendre plusieurs minutes une fois Running)
oc logs -f deployment/<model-name>-predictor -n <namespace>Lorsque l'InferenceService signale READY: True, validez l'endpoint.
Vérifiez l'enregistrement du modèle et envoyez une requête d'inférence de test :
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
}'Résolution des problèmes
| Problème | Cause possible | Résolution |
|---|---|---|
ErrImagePull | Identifiants de registre manquants ou invalides | Vérifiez que model-registry-secret existe, possède des identifiants valides et est lié à model-puller-sa en utilisant à la fois oc secrets link et le patch imagePullSecrets. |
ImagePullBackOff | Secret d'extraction d'image non configuré pour ModelCar | Assurez-vous que le compte de service inclut l'entrée imagePullSecrets. Voir la commande oc patch serviceaccount à l'étape 3. |
Le prédicteur reste dans Init:0/1 | Téléchargement de l'image du modèle en cours | Vérifiez les événements oc describe pod pour la progression Pulling/Pulled ; le temps d'extraction augmente avec la taille de l'image et la bande passante du registre. |
Le prédicteur reste indéfiniment dans Init:0/1 | Fichiers du modèle introuvables | Vérifiez que les fichiers du modèle sont stockés sous /models dans l'image OCI. |
Engine core initialization failed | Délai d'expiration de la compilation CUDA initiale | Le premier démarrage peut prendre plus de temps pendant la génération des caches. Redémarrez et réessayez. |
| Échec du chargement du modèle | Format de fichier de modèle non pris en charge | Utilisez les fichiers safetensors de Hugging Face et excluez les anciens checkpoints. |
| Erreurs d'auto-test FIPS OpenSSL | L'image du conteneur n'est pas compatible FIPS | Utilisez une image vLLM compatible FIPS. |
OutOfMemory / OOMKilled | Mémoire GPU insuffisante | Augmentez les ressources GPU, réduisez la longueur du contexte ou utilisez un modèle quantifié. |
L'InferenceService reste en Pending | Ressources du cluster indisponibles | Vérifiez la disponibilité des GPU et libérez des ressources des charges de travail inutilisées. |
Ressources supplémentaires
- Red Hat OpenShift AI - Serving models
- Documentation KServe
- KServe ModelCar - Empaquetage de modèles OCI
Utiliser des endpoints de modèles cloud public
Utilisez cette option lorsque les modèles sont hébergés par un fournisseur cloud, tel qu'IBM watsonx, AWS Bedrock, Azure OpenAI ou Google Vertex AI.
Prérequis :
- Connectivité HTTPS sortante (port 443) du cluster Red Hat OpenShift Container Platform (OCP) vers l'endpoint du service cloud.
- Clés API valides, identifiants IAM ou identifiants d'authentification équivalents.
Avant de commencer :
Assurez-vous que :
- Le déploiement du modèle est provisionné et actif.
- Les identifiants d'authentification sont générés et stockés de manière sécurisée.
- Les exigences de mise en réseau ou d'accès spécifiques au fournisseur sont satisfaites.
Une fois l'endpoint disponible, passez à Configuration de la passerelle d'inférence de modèles.
Utiliser des endpoints de modèles sur infrastructure privée
Utilisez cette option lorsque les modèles sont hébergés sur une infrastructure gérée par le client en dehors du cluster IBM Bob, telle que :
- Des serveurs GPU dédiés
- Des clusters OpenShift séparés
- Des serveurs d'inférence bare-metal
- Des plateformes IA d'entreprise
Prérequis :
- L'endpoint du modèle expose une API compatible OpenAI.
- La connectivité HTTPS existe entre le cluster IBM Bob et l'endpoint.
- Les identifiants d'authentification sont disponibles en tant que secrets Kubernetes.
Avant de commencer :
Validez les points suivants :
- La connectivité réseau du cluster vers l'endpoint.
- La configuration TLS ou TLS mutuel, si requis.
- Les politiques réseau et les pare-feux autorisent l'accès.
- L'authentification de l'endpoint fonctionne correctement.
Une fois la connectivité et l'authentification vérifiées, passez à Configuration de la passerelle d'inférence de modèles.