Infrastructure de service de modèles

Découvrez comment déployer et configurer des endpoints de modèles lorsque votre environnement ne fournit pas déjà de solution de service de modèles.

Avant de pouvoir connecter IBM Bob à un grand modèle de langage (LLM), vous devez avoir accès à un endpoint de modèle déployé. Bob ne provisionne, n'héberge ni ne gère l'infrastructure de service de modèles. Si votre organisation fournit déjà des endpoints de modèles via OpenShift AI, des serveurs d'inférence basés sur GPU, des services d'IA dans le cloud ou d'autres plateformes d'inférence, passez directement à la Configuration du Model Gateway.

Options de déploiement

Choisissez l'option qui correspond le mieux à votre environnement et à vos exigences opérationnelles.

OptionQuand l'utiliser
OpenShift AI (sur le cluster, OCI/ModelCar)Modèles air-gapped ou auto-hébergés ; RHOAI déjà disponible sur le cluster
Cloud publicModèles frontier via AWS Bedrock, Azure OpenAI ou Google Vertex AI
Infrastructure privéeModèle servi sur des serveurs GPU séparés ou un cluster d'inférence dédié

OpenShift AI (sur le cluster, OCI/ModelCar)

Red Hat OpenShift AI (RHOAI) est la plateforme recommandée pour servir des modèles sur le cluster, y compris pour les déploiements air-gapped. L'approche privilégiée pour charger les poids des modèles est le modèle OCI/ModelCar : les fichiers du modèle sont intégrés dans une image OCI sous /models/ et poussés vers un registre privé. Lorsque l'InferenceService est déployé, KServe injecte un conteneur init modelcar-init qui extrait l'image et copie les poids dans un volume partagé sur /mnt/models/, à partir duquel le runtime de service (par exemple, vLLM) effectue ensuite le chargement. L'image du modèle est mise en cache sur le nœud après la première extraction — les redémarrages ultérieurs sur le même nœud ignorent totalement le téléchargement.

Prérequis :

  • Opérateur Red Hat OpenShift AI installé sur le cluster
  • KServe activé et configuré
  • Nœuds de travail compatibles GPU avec l'opérateur NVIDIA GPU (ou équivalent) configuré
  • CLI oc authentifiée sur le cluster cible avec l'autorisation de créer des ressources dans le namespace cible
  • Un registre de conteneurs privé accessible depuis le cluster, avec des 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: Managed

Activer la prise en charge de ModelCar

La prise en charge de ModelCar est contrôlée par la 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 manquant ou défini sur false, mettez à jour la ConfigMap :

# Récupérer la valeur actuelle, fusionner le drapeau 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-applications

Empaqueter 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 contenir tous les fichiers de modèle sous le répertoire /models. Pour plus d'informations, consultez la documentation KServe. Pour les déploiements vLLM, incluez les fragments de modèle safetensors et excluez les fichiers de point de contrôle (checkpoints) hérités 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 modèle de chat (par exemple, chat_template.jinja), ajoutez-le. Vous pouvez également copier l'intégralité du répertoire en une seule instruction — plus simple, mais inclut des fichiers non nécessaires pour vLLM :

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>:latest

Vous pouvez utiliser n'importe quel outil de gestion d'images pris en charge, notamment :

  • Podman
  • Skopeo
  • Pipelines CI/CD
  • Outils spécifiques au registre

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 :

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 depuis 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 (ServiceAccount) :

# 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 :

# Associer le secret d'extraction — les deux commandes sont requises :
# oc secrets link couvre l'utilisation générale des secrets ;
# imagePullSecrets est requis spécifiquement par le conteneur init ModelCar de KServe
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"}]}'
Remarque :

Les deux commandes sont requises. L'entrée imagePullSecrets est utilisée par le conteneur 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: 60

Appliquez la configuration du runtime :

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

Déployer l'InferenceService

Créez un InferenceService qui fait référence à l'image OCI du modèle à l'aide d'un URI de stockage oci://.

Exigences clés de configuration :

  • Faire référence au ServingRuntime précédemment créé.
  • 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 d'exécution et les variables d'environnement de vLLM.

Exemple :

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>"          # par ex. "8"
        limits:
          cpu: "<cpu-limit>"            # par ex. "16"
          memory: <memory-limit>        # par ex. 96Gi — dimensionner selon les besoins VRAM du modèle
          nvidia.com/gpu: "<gpu-count>" # par 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 journal vLLM pour éviter la saturation
        - 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>" # par ex. "0" pour un seul GPU ; "0,1" pour deux
        - name: VLLM_WORKER_MULTIPROC_METHOD
          value: spawn
        - name: LOGNAME
          value: vllm
        - name: USER
          value: vllm

Appliquez le manifeste de l'InferenceService :

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

Vérifier le déploiement

Surveillez le statut du déploiement, le démarrage des pods et les journaux d'exécution :

# Surveiller que l'InferenceService atteigne l'état Ready
oc get inferenceservice <model-name> -n <namespace> -w

# Surveiller le démarrage du pod du prédicteur
oc get pods -n <namespace> -w

# Suivre les journaux du prédicteur (le chargement du modèle peut prendre plusieurs minutes une fois en état Running)
oc logs -f deployment/<model-name>-predictor -n <namespace>

Lorsque l'InferenceService indique 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
  }'

Dépannage

ProblèmeCause possibleRésolution
ErrImagePullIdentifiants de registre manquants ou non validesConfirmez que model-registry-secret existe, contient des identifiants valides et est associé à model-puller-sa à l'aide de oc secrets link et du patch imagePullSecrets.
ImagePullBackOffSecret d'extraction d'image non configuré pour ModelCarAssurez-vous que le compte de service inclut la configuration imagePullSecrets. Exécutez oc patch serviceaccount model-puller-sa -n <namespace> -p '{"imagePullSecrets": [{"name": "model-registry-secret"}]}'
Le prédicteur reste en Init:0/1Téléchargement de l'image du modèle en coursVérifiez les événements oc describe pod pour suivre la progression Pulling/Pulled ; le temps d'extraction dépend de la taille de l'image et de la bande passante du registre.
Le prédicteur reste indéfiniment en Init:0/1Fichiers du modèle introuvablesVérifiez que les fichiers du modèle sont stockés sous /models dans l'image OCI.
Engine core initialization failedDélai d'attente dépassé pour la compilation CUDA initialeLe premier démarrage peut être plus long pendant la génération des caches. Redémarrez et réessayez.
Échec du chargement du modèleFormat de fichier de modèle non pris en chargeUtilisez les fichiers safetensors de Hugging Face et excluez les checkpoints hérités.
Erreurs d'auto-test FIPS OpenSSLL'image du conteneur n'est pas compatible FIPSUtilisez une image vLLM compatible FIPS.
OutOfMemory / OOMKilledMémoire GPU insuffisanteAugmentez les ressources GPU, réduisez la longueur du contexte ou utilisez un modèle quantifié.
L'InferenceService reste en PendingRessources du cluster indisponiblesVérifiez la disponibilité des GPU et libérez les ressources des charges de travail inutilisées.

Pour plus d'informations, consultez :

Endpoints de modèles dans le cloud public

Utilisez cette option lorsque les modèles sont hébergés par un fournisseur de cloud, tel qu'IBM watsonx, AWS Bedrock, Azure OpenAI ou Google Vertex AI.

Prérequis :

  • Connectivité HTTPS sortante (port 443) depuis le cluster OpenShift vers l'endpoint du service cloud.
  • Clés d'API valides, identifiants IAM ou identifiants d'authentification équivalents.

Avant de configurer IBM Bob

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 en toute sécurité.
  • Toutes les exigences réseau ou d'accès spécifiques au fournisseur sont satisfaites.

Une fois l'endpoint disponible, passez à la Configuration du Model Gateway.

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 distincts
  • Des serveurs d'inférence bare-metal
  • Des plateformes d'IA d'entreprise

Prérequis :

  • L'endpoint du modèle expose une API compatible OpenAI.
  • Une connectivité HTTPS existe entre le cluster IBM Bob et l'endpoint.
  • Les identifiants d'authentification sont disponibles sous forme de secrets Kubernetes.

Avant de configurer IBM Bob

Validez les éléments suivants :

  • La connectivité réseau depuis le cluster vers l'endpoint.
  • La configuration TLS ou mutual TLS, si nécessaire.
  • 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 à la Configuration du Model Gateway.

Comment trouvez-vous ce sujet ?