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.
| Opzione | Quando 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 pubblici | Modelli frontier tramite AWS Bedrock, Azure OpenAI o Google Vertex AI |
| Endpoint di modelli su infrastruttura privata | Modello 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
ocautenticata 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: ManagedAbilitazione 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-applicationsPacchettizza 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>:latestUsa 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"}]}'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: 60Applica la configurazione del runtime:
oc apply -n <namespace> -f serving-runtime-vllm.yamlDeploya 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
ServingRuntimecreato 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: vllmApplica il manifest InferenceService:
oc apply -n <namespace> -f isvc-<model-name>.yamlVerifica 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
| Problema | Possibile causa | Soluzione |
|---|---|---|
ErrImagePull | Credenziali del registry mancanti o non valide | Verifica che model-registry-secret esista, abbia credenziali valide e sia collegato a model-puller-sa usando sia oc secrets link che la patch imagePullSecrets. |
ImagePullBackOff | Pull secret dell'immagine non configurato per ModelCar | Assicurati che il service account includa la voce imagePullSecrets. Vedi il comando oc patch serviceaccount al punto 3. |
Il predictor rimane in Init:0/1 | Download dell'immagine del modello in corso | Controlla 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 indefinitamente | File del modello non trovati | Verifica che i file del modello siano archiviati sotto /models nell'immagine OCI. |
Engine core initialization failed | Timeout iniziale di compilazione CUDA | Il primo avvio può richiedere più tempo durante la generazione delle cache. Riavvia e riprova. |
| Il caricamento del modello fallisce | Formato file del modello non supportato | Usa i file safetensors di Hugging Face ed escludi i checkpoint legacy. |
| Errori self-test OpenSSL FIPS | L'immagine container non è compatibile FIPS | Usa un'immagine vLLM compatibile FIPS. |
OutOfMemory / OOMKilled | Memoria GPU insufficiente | Aumenta le risorse GPU, riduci la lunghezza del contesto o usa un modello quantizzato. |
InferenceService rimane Pending | Risorse del cluster non disponibili | Verifica la disponibilità GPU e libera risorse dai workload non utilizzati. |
Risorse aggiuntive
- Red Hat OpenShift AI - Serving models
- Documentazione KServe
- KServe ModelCar - Packaging di modelli OCI
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.