Nuclio Serverless Platform Installation
Nuclio is a high-performance serverless platform designed for real-time data processing and AI/ML workloads, featuring native GPU support, ultra-low latency function execution, and integrations with data platforms like Kafka, Kinesis, and Iguazio. This guide covers deploying Nuclio on Docker and Kubernetes, configuring functions, enabling GPU support, and using the dashboard.
Prerequisites
- Ubuntu 20.04+ or CentOS/Rocky 8+ with root access
- Docker installed (for standalone mode) or Kubernetes cluster
- At least 4GB RAM, 2 CPUs
- Optional: NVIDIA GPU with CUDA drivers for GPU functions
- Optional: Kafka or Kinesis for streaming triggers
Installing Nuclio with Docker
The simplest way to run Nuclio is with Docker:
# Create a Docker network for Nuclio
docker network create nuclio
# Start the Nuclio dashboard and controller
docker run -d \
--name nuclio-dashboard \
--network nuclio \
-p 8070:8070 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /tmp/nuclio-local:/opt/nuclio \
-e NUCLIO_CHECK_FUNCTION_CONTAINERS_EXISTENCE=true \
nuclio/dashboard:stable
# Verify it's running
docker logs nuclio-dashboard --tail 20
curl http://localhost:8070/ready
Access the dashboard:
# Open in browser
echo "Dashboard: http://YOUR_SERVER_IP:8070"
# Create a namespace in the dashboard or via CLI
Installing Nuclio on Kubernetes
# Add Nuclio Helm chart repository
helm repo add nuclio https://nuclio.github.io/nuclio/charts
helm repo update
# Create namespace
kubectl create namespace nuclio
# Create an image pull secret if using a private registry
kubectl create secret docker-registry registry-credentials \
--docker-server=registry.example.com \
--docker-username=user \
--docker-password=pass \
-n nuclio
# Install Nuclio
helm install nuclio nuclio/nuclio \
--namespace nuclio \
--set dashboard.enabled=true \
--set dashboard.serviceType=LoadBalancer \
--set registry.pushPullUrl=registry.example.com/myorg \
--set registry.defaultBaseRegistryURL=docker.io
# Check installation
kubectl get pods -n nuclio
# Get dashboard URL
kubectl get svc nuclio-dashboard -n nuclio
Using the Nuclio Dashboard
# Access dashboard
DASHBOARD_IP=$(kubectl get svc nuclio-dashboard -n nuclio -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo "Dashboard: http://$DASHBOARD_IP:8070"
Install the nuctl CLI:
# Download nuctl
NUCLIO_VERSION="1.13.0"
wget https://github.com/nuclio/nuclio/releases/download/${NUCLIO_VERSION}/nuctl-${NUCLIO_VERSION}-linux-amd64
chmod +x nuctl-${NUCLIO_VERSION}-linux-amd64
sudo mv nuctl-${NUCLIO_VERSION}-linux-amd64 /usr/local/bin/nuctl
# Configure nuctl to connect to the dashboard
export NUCLIO_PLATFORM=kube
export NUCLIO_NAMESPACE=nuclio
# Or for Docker mode:
export NUCLIO_PLATFORM=local
nuctl version
nuctl get functions --namespace nuclio
Creating and Deploying Functions
Python function example:
cat > /tmp/hello_nuclio.py << 'EOF'
import nuclio
def handler(context, event):
"""
Nuclio function handler.
context: function execution context (logger, user_data)
event: incoming event (body, headers, method, path, etc.)
"""
# Log using the provided logger
context.logger.info(f"Received request: {event.method} {event.path}")
# Parse request body
body = event.body
if isinstance(body, bytes):
body = body.decode('utf-8')
# Return response
return nuclio.Response(
headers={"Content-Type": "application/json"},
body=f'{{"message": "Hello from Nuclio!", "received": "{body}"}}',
status_code=200
)
EOF
Deploy with nuctl:
# Deploy to Docker (local mode)
nuctl deploy hello \
--path /tmp/hello_nuclio.py \
--runtime python:3.9 \
--handler hello_nuclio:handler \
--platform local \
--namespace nuclio
# Deploy to Kubernetes
nuctl deploy hello \
--path /tmp/hello_nuclio.py \
--runtime python:3.9 \
--handler hello_nuclio:handler \
--namespace nuclio \
--registry registry.example.com/myorg \
--replicas 2
# Test the function
nuctl invoke hello \
--method POST \
--body '{"test": "data"}' \
--content-type "application/json" \
--platform local
# For Kubernetes:
nuctl invoke hello \
--method GET \
--namespace nuclio
Function with dependencies:
mkdir -p /tmp/my-function
cat > /tmp/my-function/function.py << 'EOF'
import requests
import nuclio
import json
def handler(context, event):
url = event.body.decode('utf-8') if event.body else "https://api.github.com"
try:
resp = requests.get(url, timeout=10)
return nuclio.Response(
headers={"Content-Type": "application/json"},
body=json.dumps({
"url": url,
"status": resp.status_code,
"content_length": len(resp.content)
}),
status_code=200
)
except Exception as e:
return nuclio.Response(
body=str(e),
status_code=500
)
EOF
cat > /tmp/my-function/requirements.txt << 'EOF'
requests==2.31.0
nuclio-sdk==0.3.0
EOF
# Deploy with requirements
nuctl deploy http-checker \
--path /tmp/my-function \
--runtime python:3.9 \
--handler function:handler \
--platform local \
--namespace nuclio
Function Configuration and Triggers
Nuclio function YAML specification:
cat > /tmp/my-function/function.yaml << 'EOF'
apiVersion: nuclio.io/v1beta1
kind: NuclioFunction
metadata:
name: data-processor
namespace: nuclio
spec:
description: "Real-time data processing function"
runtime: python:3.9
handler: handler:main
# Resources
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "1"
memory: "512Mi"
# Scaling
minReplicas: 1
maxReplicas: 20
targetCPU: 70
# Environment variables
env:
- name: DB_HOST
value: postgres.default.svc.cluster.local
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
# Triggers
triggers:
http:
kind: http
attributes:
port: 8080
kafka-input:
kind: kafka-cluster
attributes:
brokers:
- kafka:9092
topics:
- name: input-events
consumerGroup: nuclio-processor
initialOffset: latest
# Build configuration
build:
commands:
- pip install -r requirements.txt
image: nuclio/handler-builder-python-onbuild:latest
EOF
Apply the function configuration:
kubectl apply -f /tmp/my-function/function.yaml
kubectl get nucliofunctions -n nuclio
GPU Support for AI/ML Functions
# Verify NVIDIA GPU is available
nvidia-smi
kubectl describe node | grep -i gpu
# Enable NVIDIA device plugin for Kubernetes
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.14.0/nvidia-device-plugin.yml
# Verify GPU is allocatable
kubectl get nodes -o json | jq '.items[].status.allocatable | {"nvidia.gpu": .["nvidia.com/gpu"]}'
Deploy a GPU-enabled function:
cat > /tmp/gpu-function/function.yaml << 'EOF'
apiVersion: nuclio.io/v1beta1
kind: NuclioFunction
metadata:
name: ml-inference
namespace: nuclio
spec:
runtime: python:3.9
handler: inference:handler
# Request GPU resources
resources:
requests:
nvidia.com/gpu: "1"
limits:
nvidia.com/gpu: "1"
memory: "8Gi"
cpu: "4"
# Use CUDA-enabled base image
build:
baseImage: "nvidia/cuda:11.8-runtime-ubuntu20.04"
commands:
- apt-get update && apt-get install -y python3 python3-pip
- pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118
env:
- name: CUDA_VISIBLE_DEVICES
value: "0"
EOF
cat > /tmp/gpu-function/inference.py << 'EOF'
import torch
import nuclio
import json
import base64
from io import BytesIO
# Load model at startup (not in handler to avoid cold start on every request)
_model = None
def init_context(context):
global _model
context.logger.info("Loading ML model...")
# Load your model here
# _model = torch.load('/opt/models/my_model.pt')
context.logger.info(f"GPU available: {torch.cuda.is_available()}")
context.logger.info("Model loaded successfully")
def handler(context, event):
global _model
if _model is None:
return nuclio.Response(body="Model not loaded", status_code=503)
# Process inference request
try:
data = json.loads(event.body)
# Run inference on GPU
with torch.no_grad():
# result = _model(torch.tensor(data['input']).cuda())
result = {"prediction": [0.85, 0.15], "device": str(torch.device("cuda" if torch.cuda.is_available() else "cpu"))}
return nuclio.Response(
headers={"Content-Type": "application/json"},
body=json.dumps(result),
status_code=200
)
except Exception as e:
context.logger.error(f"Inference error: {e}")
return nuclio.Response(body=str(e), status_code=500)
EOF
Real-Time Data Processing
Kafka-triggered function for stream processing:
cat > /tmp/stream-processor.py << 'EOF'
import json
import nuclio
def handler(context, event):
"""Process Kafka messages in real time."""
# Kafka event metadata
partition = event.trigger.annotation.get("nuclio.io/kafka-partition", "unknown")
offset = event.trigger.annotation.get("nuclio.io/kafka-offset", "unknown")
context.logger.debug(f"Processing message from partition={partition} offset={offset}")
try:
message = json.loads(event.body)
# Process the message
processed = {
"original": message,
"processed_at": __import__("datetime").datetime.utcnow().isoformat(),
"processed": True
}
# Return processed data (sent to output topic if configured)
return nuclio.Response(
headers={"Content-Type": "application/json"},
body=json.dumps(processed),
status_code=200
)
except Exception as e:
context.logger.error(f"Processing error: {e}")
# Returning non-200 causes message to be retried
return nuclio.Response(body=str(e), status_code=500)
EOF
# Deploy with Kafka trigger
nuctl deploy stream-processor \
--path /tmp/stream-processor.py \
--runtime python:3.9 \
--handler stream-processor:handler \
--namespace nuclio \
--trigger '{"kafka-in":{"kind":"kafka-cluster","attributes":{"topics":[{"name":"sensor-data"}],"brokers":["kafka:9092"],"consumerGroup":"nuclio-processor"}}}'
Monitoring and Performance
# View function metrics
nuctl get function data-processor --namespace nuclio -o json | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(json.dumps(d['status'], indent=2))"
# Get function logs
nuctl get function data-processor --namespace nuclio
kubectl logs -n nuclio -l nuclio.io/function-name=data-processor -f
# Check function replicas
kubectl get pods -n nuclio -l nuclio.io/function-name=data-processor
# Port-forward to Prometheus metrics
kubectl port-forward -n nuclio svc/nuclio-dashboard 8070:8070 &
# Visit: http://localhost:8070
Configure Prometheus scraping:
# Nuclio exposes Prometheus metrics at /metrics on each function pod
# Add to your Prometheus config:
cat >> /etc/prometheus/prometheus.yml << 'EOF'
- job_name: 'nuclio-functions'
kubernetes_sd_configs:
- role: pod
namespaces:
names: ['nuclio']
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_nuclio_io_function_name]
action: keep
regex: .+
- source_labels: [__address__]
target_label: __address__
regex: '([^:]+):.*'
replacement: '${1}:8090'
EOF
Troubleshooting
Function deployment fails with image build error:
# Check build logs
nuctl get function my-function -n nuclio -o json | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(d['status'].get('message',''))"
kubectl logs -n nuclio -l nuclio.io/app=builder -f
GPU function not using GPU:
# Verify GPU is requested and available
kubectl get pods -n nuclio -l nuclio.io/function-name=ml-inference -o yaml | grep -A5 resources
# Inside the function pod
kubectl exec -n nuclio <pod-name> -- nvidia-smi
kubectl exec -n nuclio <pod-name> -- python3 -c "import torch; print(torch.cuda.is_available())"
Kafka trigger not consuming messages:
# Check trigger configuration
nuctl get function stream-processor -n nuclio -o json | \
python3 -c "import json,sys; d=json.load(sys.stdin); print(json.dumps(d['spec']['triggers'], indent=2))"
# Verify Kafka connectivity from the function pod
kubectl exec -n nuclio <pod> -- nc -zv kafka 9092
Function scaling not working:
# Check HPA
kubectl get hpa -n nuclio
kubectl describe hpa -n nuclio nuclio-data-processor
# Ensure metrics server is installed
kubectl top pods -n nuclio
Conclusion
Nuclio's strength lies in its high-performance architecture optimized for real-time data processing and AI/ML inference—native GPU support, ultra-low latency through container pre-warming, and direct integration with streaming platforms like Kafka make it the right choice when standard serverless latency is unacceptable. Deploy via the dashboard or nuctl CLI, define Kafka and HTTP triggers in function YAML specifications, and use the init_context function to load ML models once at startup rather than on every invocation to eliminate model loading overhead.


