Infraestructura de servicio de modelos
Aprende a desplegar y configurar endpoints de modelos cuando tu entorno no dispone ya de una solución de servicio de modelos.
Antes de poder conectar IBM Bob a un modelo de lenguaje grande (LLM), debes tener acceso a un endpoint de modelo desplegado. Bob no aprovisiona, aloja ni gestiona la infraestructura de servicio de modelos. Si tu organización ya proporciona endpoints de modelos a través de OpenShift AI, servidores de inferencia basados en GPU, servicios de IA en cloud u otras plataformas de inferencia, ve directamente a Configurar el gateway de modelos.
Opciones de despliegue
Elige la opción que mejor se adapte a tu entorno y tus requisitos operativos.
| Opción | Cuándo usar |
|---|---|
| OpenShift AI (en clúster, OCI/ModelCar) | Modelos air-gapped o autoalojados; RHOAI ya disponible en el clúster |
| Cloud pública | Modelos frontier a través de AWS Bedrock, Azure OpenAI o Google Vertex AI |
| Infraestructura privada | Modelo servido en servidores GPU separados o un clúster de inferencia dedicado |
OpenShift AI (en clúster, OCI/ModelCar)
Red Hat OpenShift AI (RHOAI) es la plataforma recomendada para servir modelos en el clúster, incluyendo los despliegues air-gapped. El enfoque preferido para cargar los pesos del modelo es el patrón OCI/ModelCar: los archivos del modelo se incluyen en una imagen OCI bajo /models/ y se envían a un registro privado. Cuando se despliega el InferenceService, KServe inyecta un contenedor init modelcar-init que extrae la imagen y copia los pesos en un volumen compartido en /mnt/models/, desde donde los carga el runtime de servicio (por ejemplo, vLLM). La imagen del modelo se almacena en caché en el nodo tras la primera extracción; los reinicios posteriores en el mismo nodo omiten la descarga por completo.
Prerequisitos:
- Operador de Red Hat OpenShift AI instalado en el clúster
- KServe habilitado y configurado
- Nodos worker con GPU con el operador GPU de NVIDIA (o equivalente) configurado
- CLI
ocautenticada en el clúster de destino con permisos para crear recursos en el namespace de destino - Un registro de contenedores privado accesible desde el clúster, con credenciales para enviar imágenes
Configurar Red Hat OpenShift AI
Configura los recursos DataScienceClusterInitialization y DataScienceCluster de la siguiente manera:
- Deshabilita
serviceMesh. - Habilita KServe estableciendo
managementState: Managed. - Configura KServe para usar el modo
RawDeployment. - Elimina todos los componentes de Red Hat OpenShift AI que no se usen.
Ejemplo de configuración de KServe:
kserve:
defaultDeploymentMode: RawDeployment
nim:
managementState: Managed
rawDeploymentServiceConfig: Headed
serving:
ingressGateway:
certificate:
type: OpenshiftDefaultIngress
managementState: Removed
name: knative-serving
managementState: ManagedHabilitar el soporte de ModelCar
El soporte de ModelCar se controla mediante el ConfigMap inferenceservice-config en el namespace redhat-ods-applications. La clave storageInitializer debe contener "enableModelcar": true.
Verifica la configuración actual:
oc get configmap inferenceservice-config \
-n redhat-ods-applications \
-o jsonpath='{.data.storageInitializer}'La salida debe contener:
{
"enableModelcar": true,
"cpuModelcar": "10m",
"memoryModelcar": "15Mi"
}Si enableModelcar falta o es false, actualiza el ConfigMap:
# Recupera el valor actual, fusiona el flag y aplica el parche
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()))')}}"Reinicia el controlador de KServe para aplicar el cambio:
oc rollout restart deployment kserve-controller-manager -n redhat-ods-applications
oc rollout status deployment kserve-controller-manager -n redhat-ods-applicationsEmpaquetar los archivos del modelo en una imagen OCI
Descarga los pesos del modelo desde Hugging Face y empaquétalos en una imagen OCI. La imagen debe tener todos los archivos del modelo bajo el directorio /models. Para más información, consulta la documentación de KServe. Para despliegues con vLLM, incluye los fragmentos del modelo safetensors y excluye los archivos de checkpoint heredados como .bin, .pt y original/*.
Ejemplo de Dockerfile:
FROM busybox:latest
# Pesos del modelo — fragmentos safetensors e índice
COPY <model-name>/model-*.safetensors /models/
COPY <model-name>/model.safetensors.index.json /models/
# Configuración del modelo
COPY <model-name>/config.json /models/
COPY <model-name>/generation_config.json /models/
# Tokenizador
COPY <model-name>/tokenizer.json /models/
COPY <model-name>/tokenizer_config.json /models/
COPY <model-name>/special_tokens_map.json /models/Si el modelo incluye una plantilla de chat (por ejemplo, chat_template.jinja), añádela. Como alternativa, copia el directorio completo en una sola instrucción — más sencillo, pero incluye archivos que vLLM no necesita:
FROM busybox:latest
COPY <model-name>/ /models/Enviar la imagen a un registro privado
Envía la imagen OCI a un registro de contenedores privado accesible desde el clúster:
<registry>/<project>/<model-name>:latestPuedes usar cualquier herramienta de gestión de imágenes compatible, incluyendo:
- Podman
- Skopeo
- Pipelines de CI/CD
- Herramientas específicas del registro
Crear el namespace de destino y el secreto de extracción de imágenes
Crea el namespace del proyecto y configura las credenciales para extraer la imagen del modelo:
oc new-project <namespace>Crea el secreto de extracción del registro:
# Secreto de extracción para que KServe pueda extraer la imagen del modelo desde tu registro privado
oc create secret docker-registry model-registry-secret \
--docker-server=<registry> \
--docker-username=<username> \
--docker-password=<password-or-token> \
-n <namespace>Crea una cuenta de servicio:
# Cuenta de servicio usada por el predictor de KServe
oc create sa model-puller-sa -n <namespace>Asocia el secreto de extracción con la cuenta de servicio:
# Vincula el secreto de extracción — ambos comandos son necesarios:
# oc secrets link cubre el uso general de secretos;
# imagePullSecrets es necesario específicamente para el contenedor 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"}]}'Ambos comandos son necesarios. La entrada imagePullSecrets la usa el contenedor de inicialización ModelCar durante la recuperación de la imagen del modelo.
Crear un ServingRuntime
Despliega un ServingRuntime basado en vLLM en el namespace de destino:
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: 60Aplica la configuración del runtime:
oc apply -n <namespace> -f serving-runtime-vllm.yamlDesplegar el InferenceService
Crea un InferenceService que haga referencia a la imagen del modelo OCI usando un URI de almacenamiento oci://.
Requisitos clave de configuración:
- Referencia el
ServingRuntimecreado anteriormente. - Especifica la ubicación de la imagen OCI en
storageUri. - Configura los límites de recursos de CPU, memoria y GPU que coincidan con los requisitos del modelo.
- Monta la memoria compartida (
/dev/shm) para vLLM. - Configura los argumentos de runtime de vLLM y las variables de entorno.
Ejemplo:
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>" # p. ej. "8"
limits:
cpu: "<cpu-limit>" # p. ej. "16"
memory: <memory-limit> # p. ej. 96Gi — ajusta a los requisitos de VRAM del modelo
nvidia.com/gpu: "<gpu-count>" # p. ej. "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" # trunca las líneas de log de vLLM para evitar flooding
- 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>" # debe coincidir con el límite de nvidia.com/gpu anterior
- name: CUDA_VISIBLE_DEVICES
value: "<gpu-indices>" # p. ej. "0" para una GPU; "0,1" para dos
- name: VLLM_WORKER_MULTIPROC_METHOD
value: spawn
- name: LOGNAME
value: vllm
- name: USER
value: vllmAplica el manifiesto del InferenceService:
oc apply -n <namespace> -f isvc-<model-name>.yamlVerificar el despliegue
Monitoriza el estado del despliegue, el inicio de los pods y los logs del runtime:
# Observa cómo el InferenceService alcanza el estado Ready
oc get inferenceservice <model-name> -n <namespace> -w
# Observa el inicio del pod predictor
oc get pods -n <namespace> -w
# Sigue los logs del predictor (la carga del modelo puede tardar varios minutos una vez en Running)
oc logs -f deployment/<model-name>-predictor -n <namespace>Cuando el InferenceService reporte READY: True, valida el endpoint.
Verifica el registro del modelo y envía una solicitud de inferencia de prueba:
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
}'Solución de problemas
| Problema | Posible causa | Resolución |
|---|---|---|
ErrImagePull | Credenciales de registro faltantes o inválidas | Confirma que model-registry-secret existe, tiene credenciales válidas y está vinculado a model-puller-sa usando tanto oc secrets link como el parche imagePullSecrets. |
ImagePullBackOff | Secreto de extracción de imágenes no configurado para ModelCar | Asegúrate de que la cuenta de servicio incluye la configuración imagePullSecrets. Ejecuta oc patch serviceaccount model-puller-sa -n <namespace> -p '{"imagePullSecrets": [{"name": "model-registry-secret"}]}' |
El predictor permanece en Init:0/1 | Descarga de la imagen del modelo en progreso | Comprueba los eventos de oc describe pod para el progreso de Pulling/Pulled; el tiempo de extracción escala con el tamaño de la imagen y el ancho de banda del registro. |
El predictor permanece en Init:0/1 indefinidamente | Archivos del modelo no encontrados | Verifica que los archivos del modelo estén almacenados bajo /models en la imagen OCI. |
Engine core initialization failed | Tiempo de espera agotado en la compilación CUDA inicial | El primer inicio puede tardar más mientras se generan las cachés. Reinicia y vuelve a intentarlo. |
| La carga del modelo falla | Formato de archivo del modelo no compatible | Usa archivos safetensors de Hugging Face y excluye los checkpoints heredados. |
| Errores de autocomprobación FIPS de OpenSSL | La imagen del contenedor no es compatible con FIPS | Usa una imagen de vLLM compatible con FIPS. |
OutOfMemory / OOMKilled | Memoria GPU insuficiente | Aumenta los recursos GPU, reduce la longitud del contexto o usa un modelo cuantizado. |
El InferenceService permanece en Pending | Recursos del clúster no disponibles | Verifica la disponibilidad de GPU y libera recursos de las cargas de trabajo no utilizadas. |
Para más información, consulta:
- Red Hat OpenShift AI — Serving models
- Documentación de KServe
- KServe ModelCar — empaquetado de modelos OCI
Endpoints de modelos en cloud pública
Usa esta opción cuando los modelos están alojados por un proveedor cloud, como IBM watsonx, AWS Bedrock, Azure OpenAI o Google Vertex AI.
Prerequisitos:
- Conectividad HTTPS saliente (puerto 443) desde el clúster de OpenShift al endpoint del servicio cloud.
- Claves API, credenciales IAM o credenciales de autenticación equivalentes válidas.
Antes de configurar IBM Bob
Asegúrate de que:
- El despliegue del modelo está aprovisionado y activo.
- Las credenciales de autenticación están generadas y almacenadas de forma segura.
- Se han completado los requisitos de red o acceso específicos del proveedor.
Una vez que el endpoint esté disponible, procede a Configurar el gateway de modelos.
Endpoints de modelos en infraestructura privada
Usa esta opción cuando los modelos están alojados en infraestructura gestionada por el cliente fuera del clúster de IBM Bob, como:
- Servidores GPU dedicados
- Clústeres de OpenShift separados
- Servidores de inferencia bare-metal
- Plataformas de IA empresariales
Prerequisitos:
- El endpoint del modelo expone una API compatible con OpenAI.
- Existe conectividad HTTPS entre el clúster de IBM Bob y el endpoint.
- Las credenciales de autenticación están disponibles como secretos de Kubernetes.
Antes de configurar IBM Bob
Valida lo siguiente:
- Conectividad de red desde el clúster al endpoint.
- Configuración TLS o TLS mutuo, si es necesario.
- Las políticas de red y los firewalls permiten el acceso.
- La autenticación del endpoint funciona correctamente.
Una vez verificadas la conectividad y la autenticación, procede a Configurar el gateway de modelos.