Instalación de la Plataforma Serverless Nuclio

Nuclio es una plataforma serverless de alto rendimiento orientada al procesamiento de datos en tiempo real, con soporte nativo para GPU y latencias de microsegundos. A diferencia de otras plataformas serverless, Nuclio está optimizado para cargas de trabajo intensivas en datos como machine learning, procesamiento de streams y análisis en tiempo real. Esta guía cubre la instalación de Nuclio en Linux con Docker y Kubernetes, la configuración de funciones, el uso del dashboard y la integración con pipelines de datos.

Requisitos Previos

  • Linux (Ubuntu 20.04/22.04 o CentOS/Rocky 8/9) o Kubernetes 1.26+
  • Docker 24.x o superior instalado
  • Para GPU: NVIDIA drivers y NVIDIA Container Toolkit instalados
  • Mínimo 4 GB RAM y 2 vCPU
  • Puerto 8070 disponible para el dashboard
# Verificar la versión de Docker
docker version

# Verificar que Docker está activo
systemctl status docker

# Para soporte GPU: verificar drivers NVIDIA
nvidia-smi

Instalación con Docker

La forma más rápida de probar Nuclio es usando Docker Compose:

# Crear el directorio de trabajo para Nuclio
mkdir -p /opt/nuclio && cd /opt/nuclio

# Crear la red Docker para Nuclio
docker network create nuclio-net

# Iniciar el dashboard de Nuclio (incluye el controlador)
docker run -d \
  --name nuclio-dashboard \
  --network nuclio-net \
  -p 8070:8070 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /tmp/nuclio:/tmp/nuclio \
  -e NUCLIO_CHECK_FUNCTION_CONTAINERS_EXISTENCE=true \
  quay.io/nuclio/dashboard:stable

# Verificar que el dashboard está corriendo
docker logs nuclio-dashboard --tail=20

# El dashboard estará disponible en http://localhost:8070
echo "Dashboard disponible en: http://$(hostname -I | awk '{print $1}'):8070"

Con Docker Compose

# Crear el archivo docker-compose.yml
cat > /opt/nuclio/docker-compose.yml << 'EOF'
version: '3.8'

services:
  dashboard:
    image: quay.io/nuclio/dashboard:stable
    container_name: nuclio-dashboard
    ports:
      - "8070:8070"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - nuclio-data:/tmp/nuclio
    environment:
      - NUCLIO_CHECK_FUNCTION_CONTAINERS_EXISTENCE=true
      - NUCLIO_REGISTRY_URL=registry.tudominio.com
    restart: unless-stopped

volumes:
  nuclio-data:
EOF

# Iniciar con Docker Compose
docker compose -f /opt/nuclio/docker-compose.yml up -d

Instalación en Kubernetes con Helm

# Añadir el repositorio de Helm de Nuclio
helm repo add nuclio https://nuclio.github.io/nuclio/charts
helm repo update

# Crear el namespace
kubectl create namespace nuclio

# Instalar Nuclio
helm install nuclio nuclio/nuclio \
  --namespace nuclio \
  --set dashboard.enabled=true \
  --set dashboard.serviceType=LoadBalancer \
  --set registry.secretName=registry-credentials

# Crear el secreto para el registro de contenedores
kubectl create secret docker-registry registry-credentials \
  --namespace nuclio \
  --docker-server=registry.tudominio.com \
  --docker-username=tu-usuario \
  --docker-password=tu-password

# Verificar la instalación
kubectl get pods -n nuclio
kubectl get svc -n nuclio

# Obtener la URL del dashboard
kubectl get svc nuclio-dashboard -n nuclio

Configurar RBAC para Nuclio

# Crear roles necesarios para que Nuclio gestione recursos
kubectl apply -f - << 'EOF'
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nuclio-function-deployer
rules:
  - apiGroups: ["nuclio.io"]
    resources: ["nucliofunctions", "nuclioprojects"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
EOF

Instalación del CLI nuctl

# Descargar nuctl para Linux
curl -Lo nuctl https://github.com/nuclio/nuclio/releases/download/1.13.0/nuctl-1.13.0-linux-amd64

# Dar permisos y mover al PATH
chmod +x nuctl
sudo mv nuctl /usr/local/bin/

# Verificar la instalación
nuctl version

# Configurar el endpoint del dashboard (para instalación con Docker)
export NUCLIO_DASHBOARD_URL=http://localhost:8070

# Para instalación en Kubernetes
export NUCLIO_DASHBOARD_URL=http://$(kubectl get svc nuclio-dashboard -n nuclio -o jsonpath='{.status.loadBalancer.ingress[0].ip}'):8070

Creación y Despliegue de Funciones

Función Python básica

# Crear el archivo de la función
cat > mi-funcion.py << 'EOF'
import json

def handler(context, event):
    """
    Función serverless básica en Nuclio
    context: objeto con logger y configuración
    event: evento de entrada con body, headers, etc.
    """
    # Registrar el evento recibido
    context.logger.info(f"Evento recibido: {event.trigger.kind}")
    
    # Obtener el cuerpo del evento
    body = event.body
    if isinstance(body, bytes):
        body = body.decode('utf-8')
    
    # Procesar y responder
    respuesta = {
        "mensaje": "Procesado correctamente",
        "datos_recibidos": body,
        "trigger": event.trigger.kind
    }
    
    return context.Response(
        body=json.dumps(respuesta),
        headers={"Content-Type": "application/json"},
        status_code=200
    )
EOF

# Desplegar la función con nuctl
nuctl deploy mi-funcion \
  --path mi-funcion.py \
  --runtime python:3.9 \
  --handler mi-funcion:handler \
  --platform local

# Probar la función
nuctl invoke mi-funcion \
  --method POST \
  --body '{"dato": "valor"}' \
  --content-type application/json

Función con archivo de configuración YAML

# Crear la configuración completa de la función
cat > funcion-config.yaml << 'EOF'
apiVersion: "nuclio.io/v1beta1"
kind: "NuclioFunction"
metadata:
  name: "procesador-eventos"
  namespace: "nuclio"
spec:
  runtime: python:3.9
  handler: handler:main
  # Recursos asignados a la función
  resources:
    requests:
      cpu: "100m"
      memory: "128Mi"
    limits:
      cpu: "2"
      memory: "1Gi"
  # Variables de entorno
  env:
    - name: DB_HOST
      value: "mi-base-datos.interno"
    - name: LOG_LEVEL
      value: "info"
  # Configuración de escalado
  minReplicas: 1
  maxReplicas: 10
  # Build de la imagen
  build:
    commands:
      - pip install pandas numpy requests
EOF

# Desplegar usando el archivo de configuración
kubectl apply -f funcion-config.yaml -n nuclio

# O usando nuctl en Kubernetes
nuctl deploy procesador-eventos \
  --file funcion-config.yaml \
  --platform kube \
  --namespace nuclio

Configuración de Triggers

Nuclio soporta múltiples tipos de triggers para iniciar la ejecución de funciones:

# Función con trigger HTTP y Kafka simultáneos
cat > funcion-multi-trigger.yaml << 'EOF'
apiVersion: "nuclio.io/v1beta1"
kind: "NuclioFunction"
metadata:
  name: "multi-trigger-fn"
spec:
  runtime: python:3.9
  handler: handler:procesar
  triggers:
    # Trigger HTTP en el puerto 8080
    http:
      kind: http
      maxWorkers: 4
      attributes:
        port: 8080
    # Trigger Kafka para consumir mensajes
    kafka-stream:
      kind: kafka-cluster
      maxWorkers: 8
      attributes:
        brokers:
          - kafka-broker:9092
        topics:
          - eventos-entrada
        consumerGroup: nuclio-consumer
        initialOffset: earliest
    # Trigger de temporizador (cada minuto)
    timer:
      kind: cron
      attributes:
        interval: 60s
EOF

kubectl apply -f funcion-multi-trigger.yaml -n nuclio

Soporte para GPU

Nuclio incluye soporte nativo para procesamiento con GPU mediante CUDA:

# Verificar que el plugin de GPU está disponible en el clúster
kubectl get nodes -o json | jq '.items[].status.allocatable | select(."nvidia.com/gpu" != null)'

# Función con soporte GPU para inferencia de ML
cat > funcion-gpu.yaml << 'EOF'
apiVersion: "nuclio.io/v1beta1"
kind: "NuclioFunction"
metadata:
  name: "inferencia-ml"
spec:
  runtime: python:3.9
  handler: modelo:predecir
  resources:
    limits:
      # Solicitar 1 GPU para esta función
      nvidia.com/gpu: "1"
      memory: "4Gi"
      cpu: "2"
    requests:
      memory: "2Gi"
      cpu: "500m"
  # Variables para configurar CUDA
  env:
    - name: CUDA_VISIBLE_DEVICES
      value: "0"
    - name: MODEL_PATH
      value: "/models/mi-modelo"
  # Montar el modelo desde un volumen
  volumes:
    - volume:
        name: modelos
        persistentVolumeClaim:
          claimName: modelos-pvc
      volumeMount:
        name: modelos
        mountPath: /models
  build:
    # Usar imagen base con CUDA
    baseImage: nvcr.io/nvidia/cuda:12.3-cudnn9-runtime-ubuntu22.04
    commands:
      - pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
EOF

kubectl apply -f funcion-gpu.yaml -n nuclio

Procesamiento de Datos en Tiempo Real

Nuclio es especialmente eficiente para pipelines de datos en tiempo real:

# Función para procesar streams de datos de sensores
cat > procesador-sensores.py << 'EOF'
import json
import statistics

# Ventana deslizante para cálculo de estadísticas
_ventana_datos = []
TAMAÑO_VENTANA = 100

def procesar_lectura(context, event):
    """
    Procesa lecturas de sensores IoT en tiempo real
    y calcula estadísticas sobre una ventana deslizante
    """
    global _ventana_datos
    
    try:
        # Parsear el mensaje del sensor
        lectura = json.loads(event.body)
        valor = float(lectura.get("temperatura", 0))
        sensor_id = lectura.get("sensor_id", "desconocido")
        
        # Añadir a la ventana deslizante
        _ventana_datos.append(valor)
        if len(_ventana_datos) > TAMAÑO_VENTANA:
            _ventana_datos.pop(0)
        
        # Calcular estadísticas
        media = statistics.mean(_ventana_datos)
        desv = statistics.stdev(_ventana_datos) if len(_ventana_datos) > 1 else 0
        
        # Detectar anomalías (más de 3 desviaciones estándar)
        es_anomalia = abs(valor - media) > (3 * desv) if desv > 0 else False
        
        if es_anomalia:
            context.logger.warn(f"ANOMALÍA detectada en {sensor_id}: {valor} (media: {media:.2f})")
        
        resultado = {
            "sensor_id": sensor_id,
            "valor": valor,
            "media_ventana": round(media, 3),
            "desviacion": round(desv, 3),
            "anomalia": es_anomalia
        }
        
        return context.Response(
            body=json.dumps(resultado),
            headers={"Content-Type": "application/json"},
            status_code=200
        )
        
    except Exception as e:
        context.logger.error(f"Error procesando lectura: {str(e)}")
        return context.Response(body=str(e), status_code=500)
EOF

# Desplegar la función de procesamiento en tiempo real
nuctl deploy procesador-sensores \
  --path procesador-sensores.py \
  --runtime python:3.9 \
  --handler procesador-sensores:procesar_lectura \
  --max-workers 16 \
  --platform kube \
  --namespace nuclio

Uso del Dashboard

El dashboard web de Nuclio permite gestionar funciones visualmente:

# Acceder al dashboard (asegúrate de que el puerto está expuesto)
# http://localhost:8070 (instalación con Docker)
# http://<IP-LOADBALANCER>:8070 (instalación en Kubernetes)

# Ver el estado de todas las funciones desde CLI
nuctl get functions --platform local

# Para Kubernetes
nuctl get functions --platform kube --namespace nuclio

# Ver los logs de una función específica
nuctl get function mi-funcion --platform kube --namespace nuclio

# Actualizar una función desplegada
nuctl deploy mi-funcion \
  --path mi-funcion-actualizada.py \
  --runtime python:3.9 \
  --handler mi-funcion:handler \
  --platform kube \
  --namespace nuclio

# Eliminar una función
nuctl delete function mi-funcion --platform kube --namespace nuclio

Solución de Problemas

La función no arranca:

# Ver los logs del controlador de Nuclio
kubectl logs -n nuclio deployment/nuclio-controller --tail=50

# Ver el estado de la función
kubectl describe nucliofunctions mi-funcion -n nuclio

# Verificar que la imagen se ha construido correctamente
docker images | grep nuclio

Error de permisos al acceder al registro:

# Verificar el secreto del registro
kubectl get secret registry-credentials -n nuclio -o yaml

# Recrear el secreto con las credenciales correctas
kubectl delete secret registry-credentials -n nuclio
kubectl create secret docker-registry registry-credentials \
  --namespace nuclio \
  --docker-server=tu-registro.com \
  --docker-username=usuario \
  --docker-password=password

La función GPU no puede acceder a la tarjeta:

# Verificar que el device plugin de NVIDIA está instalado
kubectl get pods -n kube-system | grep nvidia

# Verificar los recursos GPU disponibles en los nodos
kubectl describe node | grep -A 5 "nvidia.com/gpu"

Latencia alta en las respuestas:

# Aumentar el número de workers de la función
nuctl deploy mi-funcion \
  --max-workers 32 \
  --platform kube \
  --namespace nuclio

# Verificar el uso de recursos
kubectl top pods -n nuclio

Conclusión

Nuclio destaca entre las plataformas serverless por su rendimiento excepcional en escenarios de procesamiento de datos en tiempo real y soporte nativo para GPU, siendo la elección ideal para cargas de trabajo de machine learning y análisis de streams. Su arquitectura orientada al alto rendimiento, con soporte para múltiples triggers simultáneos y workers concurrentes, permite procesar millones de eventos por segundo con latencias mínimas. Con el dashboard integrado y el CLI nuctl, gestionar el ciclo de vida completo de las funciones es sencillo tanto en Docker como en Kubernetes.