Production Setup

January 15, 2026 · View on GitHub

Note: For testing, skip this! Just run nexrl -m self-hosted -c config.yaml --run-nexrl


When You Need This

✅ Multi-user cluster ✅ Custom Docker images ✅ Persistent shared storage ✅ Team deployment ✅ Shared inference router (optional)

Otherwise use defaults or environment variables (../README.md)


Setup Options

Option A: Basic Setup (5 Steps)

For single-user or testing environments.

Option B: Full Setup with Router (8 Steps)

For multi-user production with shared inference routing.


Basic Setup (6 Steps)

1. Namespace

kubectl apply -f 01-namespace.yaml

2. Job RBAC (Required)

This creates a service account with permissions to create Volcano jobs:

kubectl apply -f 09-nexrl-job-rbac.yaml

3. Admin Config

Edit 02-admin-config.yaml:

storage_path: "/your/nfs/path"     # ← Change!
worker_image: "your-reg.com/img"    # ← Change!
controller_image: "your-reg.com/img" # ← Change!

Apply:

kubectl apply -f 02-admin-config.yaml

4. User Secret

cp 03-user-config-template.yaml 03-user-config.yaml
vim 03-user-config.yaml  # Change YOUR_USER_ID and YOUR_WANDB_KEY
kubectl apply -f 03-user-config.yaml

5. Local Config (Optional)

mkdir -p ~/.nexrl
echo "user_id: alice" > ~/.nexrl/config.yaml

6. Volcano Queue

kubectl apply -f 04-volcano-queue.yaml

Full Setup with Router (9 Steps)

If you want a shared inference router for all jobs:

7. Redis Secret (for Router)

Edit 05-redis-secret-template.yaml:

stringData:
  REDIS_HOST: "your-redis-host"    # ← Change!
  REDIS_PORT: "6379"               # ← Change if needed
  REDIS_PASSWORD: "your-password"  # ← Change!

Apply:

kubectl apply -f 05-redis-secret-template.yaml

8. Router RBAC

kubectl apply -f 06-sglang-router-rbac.yaml

9. Rollout Router & ConfigMap

kubectl apply -f 07-rollout-router.yaml
kubectl apply -f 08-routers-configmap.yaml

What does this do?

  • Creates a shared SGLang router that load-balances across all inference instances
  • Router performs service discovery and health checking
  • All jobs share the same router URL: http://rollout-router-svc.nexrl.svc.cluster.local:12345

When to use?

  • ✅ Multi-user environments with shared inference
  • ✅ Production deployments requiring load balancing
  • ✅ When you have Redis available

When to skip?

  • ❌ Single-user testing
  • ❌ No Redis available
  • ❌ Prefer per-job isolated routing

If you skip router setup, NexRL will automatically create a dynamic router per job.


Verify

Basic Setup

kubectl get namespace nexrl
kubectl get configmap nexrl-admin-settings -n nexrl
kubectl get secret nexrl-wandb-alice -n nexrl

Full Setup (with Router)

kubectl get namespace nexrl
kubectl get configmap nexrl-admin-settings -n nexrl
kubectl get secret nexrl-wandb-alice -n nexrl
kubectl get secret nexrl-redis-secret -n nexrl
kubectl get deployment rollout-router -n nexrl
kubectl get service rollout-router-svc -n nexrl

Router Behavior

With Pre-deployed Router (kubectl apply -f cli/setup/)

  • All jobs share the same router at rollout-router-svc
  • Router performs service discovery and load balancing
  • INFERENCE_BASE_URL = http://rollout-router-svc.nexrl.svc.cluster.local:12345

Without Pre-deployed Router (default)

  • Each job gets its own dynamic router
  • Router lifecycle tied to the job
  • INFERENCE_BASE_URL = http://<router-pod-ip>:12345

Multi-User

Admin (once - Basic):

kubectl apply -f 01-namespace.yaml 09-nexrl-job-rbac.yaml 02-admin-config.yaml 04-volcano-queue.yaml

Admin (once - With Router):

kubectl apply -f 01-namespace.yaml 09-nexrl-job-rbac.yaml 02-admin-config.yaml 04-volcano-queue.yaml \
               05-redis-secret-template.yaml 06-sglang-router-rbac.yaml \
               07-rollout-router.yaml 08-routers-configmap.yaml

Each user:

cp 03-user-config-template.yaml user-alice.yaml
vim user-alice.yaml
kubectl apply -f user-alice.yaml

Update

# Update images
kubectl edit configmap nexrl-admin-settings -n nexrl

# Update user secret
kubectl delete secret nexrl-wandb-alice -n nexrl
kubectl apply -f 03-user-config.yaml

Advanced

Private Registry

kubectl create secret docker-registry regcred \
  --docker-server=reg.com --docker-username=u --docker-password=p -n nexrl

NFS Storage

storage_type: "nfs"
nfs_server: "server.com"
nfs_path: "/exports/nexrl"

PVC Storage

storage_type: "pvc"
storage_pvc_name: "nexrl-storage"

Troubleshooting

# Check ConfigMap
kubectl get configmap -n nexrl

# Check Secret
kubectl get secret -n nexrl | grep wandb

# Test storage
kubectl run test --rm -it --image=busybox -n nexrl -- ls /storage

Cleanup

kubectl delete namespace nexrl

Main CLI Docs: ../README.md