Skip to content

Latest commit

 

History

History
471 lines (357 loc) · 13.3 KB

File metadata and controls

471 lines (357 loc) · 13.3 KB

Ray + Triton Single - Predicción de Ganancias

Sistema de predicción de ganancias que ejecuta Ray Serve y Triton Server en el mismo contenedor, combinando flexibilidad y alto rendimiento con latencia mínima.

📋 Descripción General

Esta arquitectura implementa Ray Serve y Triton Server dentro del mismo contenedor, donde Ray maneja el API y preprocesamiento, mientras Triton se encarga de la inferencia, comunicándose localmente sin overhead de red.

Arquitectura

Cliente → [Contenedor único]
           ├─ Ray Serve (API) → Preprocesamiento
           └─ Triton Server → ONNX Runtime
          → Respuesta

Componentes:

  • Ray Serve: API REST, validación, preprocesamiento
  • Triton Server: Motor de inferencia ONNX (proceso interno)
  • Comunicación local: Ray y Triton en el mismo contenedor (localhost)
  • Dockerfile único: Una sola imagen con ambos servicios

✅ Ventajas

  • Latencia mínima: Sin overhead de red entre servicios
  • Balance perfecto: Flexibilidad de Ray + Performance de Triton
  • Despliegue simple: Un solo pod/contenedor para gestionar
  • Menor uso de recursos: Memoria compartida entre procesos
  • Configuración simplificada: No requiere networking entre contenedores
  • Debugging más fácil: Todo en un solo lugar
  • Costo reducido: Menos pods = menos infraestructura

⚠️ Consideraciones

  • Escalado acoplado: Ray y Triton escalan juntos (no independientemente)
  • Recursos combinados: Pico de uso de ambos servicios simultáneo
  • Tamaño de imagen: Imagen Docker grande (~10GB con Triton)
  • Menos aislamiento: Problemas en Triton pueden afectar a Ray y viceversa
  • Actualizaciones acopladas: Cambio en uno requiere redesplegar ambos

🎯 Ideal Para

  • ✅ Clusters con recursos limitados (menos pods)
  • ✅ Proyectos que necesitan balance entre características
  • ✅ Cuando la latencia de red entre servicios es crítica (<5ms)
  • ✅ Simplificación operacional es prioritaria
  • ✅ Equipos pequeños que manejan todo el stack
  • ✅ Casos de uso donde Ray y Triton escalan similarmente

📦 Obtención de Modelos

Los modelos no están incluidos en este repositorio. Debes obtenerlos y colocarlos en la estructura correcta.

Estructura Requerida

ray+triton-combinados/
└── model_repository/
    └── profit/
        ├── 1/
        │   ├── model.onnx              # ← DESCARGAR
        │   ├── model.onnx.data         # ← DESCARGAR (si aplica)
        │   └── preprocessing_info.pkl  # ← DESCARGAR
        └── config.pbtxt                # ← Ya incluido

Opción 1: Descargar Modelos Pre-entrenados

# Descargar modelo ONNX y preprocessing info
gsutil cp gs://tu-bucket/models/serving/model.onnx \
    model_repository/serving/1/
gsutil cp gs://tu-bucket/models/serving/model.onnx.data \
    model_repository/serving/1/
gsutil cp gs://tu-bucket/models/serving/preprocessing_info.pkl \
    model_repository/serving/1/

# O desde S3 (AWS)
aws s3 cp s3://tu-bucket/models/serving/model.onnx \
    model_repository/serving/1/
aws s3 cp s3://tu-bucket/models/serving/model.onnx.data \
    model_repository/serving/1/
aws s3 cp s3://tu-bucket/models/serving/preprocessing_info.pkl \
    model_repository/serving/1/

Opción 2: Entrenar tu Propio Modelo

import torch.onnx
import pickle

# 1. Exportar modelo ONNX
torch.onnx.export(
    model,
    dummy_input,
    "model_repository/serving/1/model.onnx",
    input_names=['input'],
    output_names=['output'],
    dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}}
)

# 2. Guardar preprocessing_info.pkl
preprocessing_info = {
    'encoders': {...},              # LabelEncoders
    'scaler': scaler,               # StandardScaler
    'feature_columns': [...],       # Lista de 15 features
    'categorical_columns': [...]    # Lista de columnas categóricas
}

with open('model_repository/serving/1/preprocessing_info.pkl', 'wb') as f:
    pickle.dump(preprocessing_info, f)

Requisitos del Modelo

Modelo ONNX:

  • Input: input - Tensor FP32 de forma [-1, 15]
  • Output: output - Tensor FP32 de forma [-1, 1]
  • Opset: 11 o superior
  • Backend: Compatible con ONNX Runtime

Preprocessing Info:

  • Debe contener: encoders, scaler, feature_columns, categorical_columns
  • Compatible con Scikit-learn
  • Produce exactamente 15 features normalizadas

📋 Descripción Técnica

Este proyecto despliega modelos ONNX usando Triton Inference Server dentro de Ray Serve en Kubernetes (Kind).

📋 Estructura del Proyecto

ray+triton/
├── Dockerfile                    # Imagen con Triton Server + Ray Serve
├── requirements.txt              # Dependencias Python (Ray, FastAPI, etc.)
├── serve.py                      # Deployment de Ray Serve con Triton
├── config-serve-docker.yaml      # Configuración de RayService para Kubernetes
└── model_repository/             # Repositorio de modelos de Triton
    ├── mnist_onnx/
    │   ├── 1/
    │   │   └── model.onnx
    │   └── config.pbtxt
    ├── profit/
    │   ├── 1/
    │   │   └── model.onnx
    │   ├── config.pbtxt
    │   └── model.onnx.data
    └── profit/
        ├── 1/
        │   └── model.onnx
        └── config.pbtxt

🚀 Instalación y Despliegue

Prerrequisitos

  • Docker
  • Kind (Kubernetes in Docker)
  • kubectl
  • Helm

1. Crear el clúster de Kind (si no existe)

kind create cluster --name sandbox-cluster

2. Instalar el operador de KubeRay

# Agregar el repositorio de Helm
helm repo add kuberay https://ray-project.github.io/kuberay-helm/
helm repo update

# Instalar el operador
helm install kuberay-operator kuberay/kuberay-operator --version 1.4.2

3. Construir la imagen Docker

# Construir la imagen con Triton Server + Ray Serve
docker build -t ray-triton-models:latest .

⏱️ Nota: Este paso puede tardar 5-10 minutos la primera vez, ya que descarga la imagen base de Triton (~10GB).

4. Cargar la imagen en Kind

# Cargar la imagen en el clúster de Kind
kind load docker-image ray-triton-models:latest --name sandbox-cluster

⏱️ Nota: Este paso puede tardar 2-5 minutos dependiendo del tamaño de la imagen.

5. Desplegar el RayService

# Aplicar la configuración de RayService
kubectl apply -f config-serve-docker.yaml

6. Verificar el despliegue

# Ver el estado de los pods
kubectl get pods -w

# Ver los logs del pod head
kubectl logs -f <pod-head-name> -c ray-head

# O usar k9s para monitoreo interactivo
k9s

Espera a que los pods estén en estado Running y Ready (puede tardar 1-2 minutos).

🔄 Comandos Todo-en-Uno

Redesplegar después de cambios

# Eliminar el deployment actual, reconstruir y redesplegar
kubectl delete -f config-serve-docker.yaml && \
docker build -t ray-triton-models:latest . && \
kind load docker-image ray-triton-models:latest --name sandbox-cluster && \
kubectl apply -f config-serve-docker.yaml && \
kubectl get pods -w

Limpieza de Docker (si te quedas sin espacio)

# Limpiar imágenes no usadas
docker image prune -a -f

# Limpiar volúmenes no usados
docker volume prune -f

# Limpieza completa (cuidado: elimina todo lo no usado)
docker system prune -a --volumes -f

🧪 Probar el Servicio

Port-forward para acceder al servicio

# Encontrar el servicio
kubectl get services

# Hacer port-forward
kubectl port-forward service/triton-sd-service-docker-serve-svc 8000:8000

Llamar al endpoint

# Hacer una predicción con el modelo profit
curl -X POST http://localhost:8000/predict \
  -H "Content-Type: application/json" \
  -d '{
    "input": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
  }'

Nota: El modelo profit espera exactamente 70 features.

📡 Endpoints API

Ray Serve expone el siguiente endpoint en el puerto 8000:

Endpoint Método Descripción
/predict POST Predicción de ganancias (principal)

POST /predict

Realiza una predicción de ganancias usando el modelo ONNX ejecutado en Triton.

URL: http://localhost:8000/predict

Nota: Este endpoint espera 70 features preprocesadas, no datos raw como los otros módulos.

Request Body:

{
  "input": [
    0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
    0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
    0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
    0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
    0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
    0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
    0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0
  ]
}

Response (Success):

{
  "status": "ok",
  "model": "profit",
  "scores": [2410.5]
}

Response (Error - Wrong Features):

{
  "status": "error",
  "message": "Se esperaban exactamente 70 features, pero llegaron (15,)."
}

Response (Error - Model Not Loaded):

{
  "status": "error",
  "message": "No se pudo cargar el modelo 'profit' en Triton."
}

Ejemplo con curl:

curl -X POST http://localhost:8000/predict \
  -H "Content-Type: application/json" \
  -d '{
    "input": [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
              0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]
  }'

Ejemplo con Python:

import requests

url = "http://localhost:8000/predict"

# 70 features preprocesadas
features = [0.1] * 70  # Ejemplo simplificado

response = requests.post(url, json={"input": features})
result = response.json()

print(f"Status: {result['status']}")
if result['status'] == 'ok':
    print(f"Prediction: {result['scores'][0]}")

Acceso a Triton Server (Interno)

Triton Server está disponible internamente en localhost:8001 (gRPC) para comunicación con Ray Serve.

No se recomienda acceder directamente a Triton desde fuera del contenedor, pero si necesitas debuggear:

# Dentro del contenedor
curl http://localhost:8000/v2/health/ready  # HTTP
curl http://localhost:8000/v2/models        # Ver modelos

📊 Modelos Disponibles

1. profit (Activo por defecto)

  • Input: input - FP32, dims: [-1, 70]
  • Output: variable - FP32, dims: [-1, 1]
  • Backend: ONNX Runtime
  • Device: CPU

2. profit

  • Input: input - FP32, dims: [-1, 15]
  • Output: output - FP32, dims: [1, 1]
  • Backend: ONNX Runtime
  • Device: CPU

3. mnist_onnx

  • Input: Input3 - FP32, dims: [1, 1, 28, 28]
  • Output: Plus214_Output_0 - FP32, dims: [1, 10]
  • Backend: ONNX Runtime
  • Device: CPU

🔧 Troubleshooting

Los pods están en CrashLoopBackOff

# Ver los logs del pod que falla
kubectl logs <pod-name> -c ray-head

# Describir el pod para más detalles
kubectl describe pod <pod-name>

Error: "No space left on device" al cargar imagen en Kind

# Limpiar Docker
docker system prune -a --volumes -f

# Recrear el clúster de Kind
kind delete cluster --name sandbox-cluster
kind create cluster --name sandbox-cluster

Error: "ModuleNotFoundError: No module named 'tritonserver'"

  • Asegúrate de usar la imagen base correcta: nvcr.io/nvidia/tritonserver:24.03-py3
  • NO uses la imagen -sdk (solo cliente)
  • NO incluyas tritonserver en requirements.txt

El readiness probe falla

  • Es normal durante el inicio (1-2 minutos)
  • Espera a que Ray Serve termine de cargar
  • Si persiste después de 3 minutos, revisa los logs

🗑️ Limpieza

Eliminar el RayService

kubectl delete -f config-serve-docker.yaml

Eliminar el clúster de Kind

kind delete cluster --name sandbox-cluster

Eliminar la imagen Docker

docker rmi ray-triton-models:latest

📝 Notas

  • La configuración actual usa CPU only para compatibilidad con Kind local
  • Para usar GPU en producción:
    • Cambia num_cpus: 1 a num_gpus: 1 en serve.py y config-serve-docker.yaml
    • Añade recursos GPU en el spec del worker
    • Asegúrate de que los nodos de Kubernetes tengan GPU disponibles
  • Ray version: 2.46.0
  • Triton Server version: 24.03

🔗 Referencias