Infrastruttura di model serving

Deploya e configura gli endpoint dei modelli per IBM Bob on-premises quando il tuo ambiente non fornisce già una soluzione di model serving.

Prima di poter connettere IBM Bob a un large language model (LLM), devi avere accesso a un endpoint di modello deployato. Bob IDE non esegue il provisioning, l'hosting o la gestione dell'infrastruttura di model serving. Se la tua organizzazione fornisce già endpoint di modelli tramite Red Hat OpenShift Container Platform (OCP) AI, server di inference basati su GPU, servizi cloud AI o altre piattaforme di inference, procedi direttamente a Configurazione del model inference gateway.

Scegli l'opzione più adatta al tuo ambiente e ai tuoi requisiti operativi.

OpzioneQuando usarla
OpenShift AI (on-cluster, OCI/ModelCar)Modelli air-gapped o self-hosted; Red Hat OpenShift AI già disponibile nel cluster
Endpoint di modelli cloud pubbliciModelli frontier tramite AWS Bedrock, Azure OpenAI o Google Vertex AI
Endpoint di modelli su infrastruttura privataModello servito su server GPU separati o un cluster di inference dedicato

Deployment di modelli con OpenShift AI (on-cluster, OCI/ModelCar)

Red Hat OpenShift AI (RHOAI) è la piattaforma consigliata per servire modelli on-cluster, inclusi i deployment air-gapped. L'approccio preferito per il caricamento dei pesi del modello è il pattern OCI/ModelCar: i file del modello vengono incorporati in un'immagine OCI sotto /models/ e inviati a un registry privato. Quando viene deployato l'InferenceService, KServe inietta un init container modelcar-init che scarica l'immagine e copia i pesi in un volume condiviso in /mnt/models/, da cui il runtime di serving (ad esempio vLLM) li carica. L'immagine del modello viene memorizzata nella cache del nodo dopo il primo pull; i riavvii successivi sullo stesso nodo saltano completamente il download.

Prerequisiti:

  • Operator Red Hat OpenShift AI installato nel cluster
  • KServe abilitato e configurato
  • Nodi worker con GPU abilitata con l'NVIDIA GPU Operator (o equivalente) configurato
  • CLI oc autenticata al cluster di destinazione con permesso di creare risorse nel namespace di destinazione
  • Un container registry privato accessibile dal cluster, con credenziali per inviare immagini

Configurazione di Red Hat OpenShift AI

Configura le risorse DataScienceClusterInitialization e DataScienceCluster come segue:

  • Disabilita serviceMesh.
  • Abilita KServe impostando managementState: Managed.
  • Configura KServe per usare la modalità RawDeployment.
  • Rimuovi tutti i componenti Red Hat OpenShift AI non utilizzati.

Esempio di configurazione KServe:

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

Abilitazione del supporto ModelCar

Il supporto ModelCar è controllato dal ConfigMap inferenceservice-config nel namespace redhat-ods-applications. La chiave storageInitializer deve contenere "enableModelcar": true.

Verifica la configurazione attuale:

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

L'output deve contenere:

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

Se enableModelcar è assente o false, aggiorna il ConfigMap:

# Recupera il valore corrente, unisci il flag e applica la 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()))')}}"

Riavvia il controller KServe per applicare la modifica:

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

Pacchettizza i file del modello in un'immagine OCI

Scarica i pesi del modello da Hugging Face e pacchettizzali in un'immagine OCI. L'immagine deve avere tutti i file del modello nella directory /models. Per ulteriori informazioni, vedere la documentazione KServe sulla preparazione di un'immagine OCI con dati del modello. Per i deployment vLLM, includi gli shard del modello safetensors ed escludi i file checkpoint legacy come .bin, .pt e original/*.

Dockerfile di esempio:

FROM busybox:latest

# Pesi del modello -- shard e indice safetensors
COPY <model-name>/model-*.safetensors        /models/
COPY <model-name>/model.safetensors.index.json /models/

# Configurazione del modello
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/

Se il modello include un chat template (ad esempio chat_template.jinja), aggiungilo. In alternativa, copia l'intera directory con un'unica istruzione, che è più semplice ma include file non necessari per vLLM:

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

Invia l'immagine a un registry privato

Invia l'immagine OCI a un container registry privato raggiungibile dal cluster:

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

Usa gli strumenti più adatti al tuo ambiente (podman push, skopeo copy, una CI pipeline e così via).

Crea il namespace di destinazione e il pull secret dell'immagine

Crea il namespace del progetto e configura le credenziali per il pull dell'immagine del modello.

Crea il namespace:

oc new-project <namespace>

Crea il registry pull secret:

# Pull secret affinché KServe possa scaricare l'immagine del modello dal tuo registry privato
oc create secret docker-registry model-registry-secret \
  --docker-server=<registry> \
  --docker-username=<username> \
  --docker-password=<password-or-token> \
  -n <namespace>

Crea un service account:

# Service account usato dal predictor KServe
oc create sa model-puller-sa -n <namespace>

Associa il pull secret al service account:

# Collega il pull secret -- entrambi i comandi sono necessari:
# oc secrets link copre l'uso generale del secret;
# imagePullSecrets è richiesto specificamente dall'init container ModelCar di 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"}]}'
Nota:

Entrambi i comandi sono necessari. La voce imagePullSecrets è usata dall'init container di inizializzazione ModelCar durante il recupero dell'immagine del modello.

Crea un ServingRuntime

Deploya un ServingRuntime basato su vLLM nel namespace di destinazione.

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

Applica la configurazione del runtime:

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

Deploya l'InferenceService

Crea un InferenceService che fa riferimento all'immagine OCI del modello usando un URI di storage oci://.

Requisiti principali di configurazione:

  • Fai riferimento al ServingRuntime creato in precedenza.
  • Specifica la posizione dell'immagine OCI in storageUri.
  • Configura i limiti di risorse CPU, memoria e GPU che corrispondono ai requisiti del modello.
  • Monta la memoria condivisa (/dev/shm) per vLLM.
  • Configura gli argomenti di runtime vLLM e le variabili d'ambiente.
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>"          # es. "8"
        limits:
          cpu: "<cpu-limit>"            # es. "16"
          memory: <memory-limit>        # es. 96Gi -- dimensiona in base ai requisiti VRAM del modello
          nvidia.com/gpu: "<gpu-count>" # es. "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"        # tronca le righe di log vLLM per evitare il flooding dei log
        - 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>" # deve corrispondere al limite nvidia.com/gpu sopra
        - name: CUDA_VISIBLE_DEVICES
          value: "<gpu-indices>" # es. "0" per una singola GPU; "0,1" per due
        - name: VLLM_WORKER_MULTIPROC_METHOD
          value: spawn
        - name: LOGNAME
          value: vllm
        - name: USER
          value: vllm

Applica il manifest InferenceService:

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

Verifica il deployment

Monitora lo stato del deployment, l'avvio del pod e i log del runtime:

# Osserva l'InferenceService raggiungere lo stato Ready
oc get inferenceservice <model-name> -n <namespace> -w

# Osserva l'avvio del pod predictor
oc get pods -n <namespace> -w

# Visualizza i log del predictor (il caricamento del modello può richiedere diversi minuti una volta in Running)
oc logs -f deployment/<model-name>-predictor -n <namespace>

Quando l'InferenceService riporta READY: True, valida l'endpoint.

Verifica la registrazione del modello e invia una richiesta di inference di 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
  }'

Risoluzione dei problemi

ProblemaPossibile causaSoluzione
ErrImagePullCredenziali del registry mancanti o non valideVerifica che model-registry-secret esista, abbia credenziali valide e sia collegato a model-puller-sa usando sia oc secrets link che la patch imagePullSecrets.
ImagePullBackOffPull secret dell'immagine non configurato per ModelCarAssicurati che il service account includa la voce imagePullSecrets. Vedi il comando oc patch serviceaccount al punto 3.
Il predictor rimane in Init:0/1Download dell'immagine del modello in corsoControlla gli eventi oc describe pod per il progresso Pulling/Pulled; il tempo di pull scala con le dimensioni dell'immagine e la banda del registry.
Il predictor rimane in Init:0/1 indefinitamenteFile del modello non trovatiVerifica che i file del modello siano archiviati sotto /models nell'immagine OCI.
Engine core initialization failedTimeout iniziale di compilazione CUDAIl primo avvio può richiedere più tempo durante la generazione delle cache. Riavvia e riprova.
Il caricamento del modello fallisceFormato file del modello non supportatoUsa i file safetensors di Hugging Face ed escludi i checkpoint legacy.
Errori self-test OpenSSL FIPSL'immagine container non è compatibile FIPSUsa un'immagine vLLM compatibile FIPS.
OutOfMemory / OOMKilledMemoria GPU insufficienteAumenta le risorse GPU, riduci la lunghezza del contesto o usa un modello quantizzato.
InferenceService rimane PendingRisorse del cluster non disponibiliVerifica la disponibilità GPU e libera risorse dai workload non utilizzati.

Risorse aggiuntive

Utilizzo di endpoint di modelli cloud pubblici

Usa questa opzione quando i modelli sono ospitati da un provider cloud, come IBM watsonx, AWS Bedrock, Azure OpenAI o Google Vertex AI.

Prerequisiti:

  • Connettività HTTPS in uscita (porta 443) dal cluster Red Hat OpenShift Container Platform (OCP) all'endpoint del servizio cloud.
  • Chiavi API, credenziali IAM o credenziali di autenticazione equivalenti valide.

Prima di iniziare:

Assicurati che:

  • Il deployment del modello sia provisioned e attivo.
  • Le credenziali di autenticazione siano generate e archiviate in modo sicuro.
  • Siano completati eventuali requisiti di rete o accesso specifici del provider.

Dopo che l'endpoint è disponibile, procedi a Configurazione del model inference gateway.

Utilizzo di endpoint di modelli su infrastruttura privata

Usa questa opzione quando i modelli sono ospitati su infrastruttura gestita dal cliente al di fuori del cluster IBM Bob, come:

  • Server GPU dedicati
  • Cluster OpenShift separati
  • Server di inference bare-metal
  • Piattaforme AI enterprise

Prerequisiti:

  • L'endpoint del modello espone un'API compatibile con OpenAI.
  • Esiste connettività HTTPS tra il cluster IBM Bob e l'endpoint.
  • Le credenziali di autenticazione sono disponibili come Kubernetes secret.

Prima di iniziare:

Verifica quanto segue:

  • Connettività di rete dal cluster all'endpoint.
  • Configurazione TLS o mutual TLS, se richiesta.
  • Le policy di rete e i firewall consentono l'accesso.
  • L'autenticazione dell'endpoint funziona correttamente.

Dopo che la connettività e l'autenticazione sono verificate, procedi a Configurazione del model inference gateway.

Come valuti questo argomento?