Deployment

Kubernetes

Deploying Spectron on Kubernetes for production workloads.

Spectron is designed for Kubernetes. The application tier stores no durable state in-process – memory lives in SurrealDB – so you can run multiple replicas behind a standard Service and scale with a HorizontalPodAutoscaler. SurrealDB is deployed separately as a StatefulSet or managed service.

Create a Kubernetes Secret for API keys before deploying any other resources. Never embed secrets directly in manifest files.

apiVersion: v1
kind: Secret
metadata:
name: spectron-secrets
namespace: spectron
type: Opaque
stringData:
OPENAI_API_KEY: "sk-..."
SPECTRON_SURREALDB_PASS: "changeme"

Apply it:

kubectl apply -f secret.yaml

In production, use an external secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault) with an operator such as the External Secrets Operator to populate the Secret from your secrets store.

Deploy SurrealDB as a StatefulSet so that storage is tied to the pod identity. Set workingDir: /data to match the volume mount and SURREAL_PATH: rocksdb://surrealdb so database files land in /data/surrealdb on the persistent volume. RocksDB creates a directory there — not a single database file.

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: surrealdb
namespace: spectron
spec:
serviceName: surrealdb
replicas: 1
selector:
matchLabels:
app: surrealdb
template:
metadata:
labels:
app: surrealdb
spec:
containers:
- name: surrealdb
image: surrealdb/surrealdb:latest
workingDir: /data
args:
- start
- --log
- info
- --user
- root
- --pass
- $(SURREALDB_PASS)
env:
- name: SURREALDB_PASS
valueFrom:
secretKeyRef:
name: spectron-secrets
key: SPECTRON_SURREALDB_PASS
- name: SURREAL_PATH
value: rocksdb://surrealdb
ports:
- containerPort: 8000
volumeMounts:
- name: data
mountPath: /data
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 5
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 50Gi
---
apiVersion: v1
kind: Service
metadata:
name: surrealdb
namespace: spectron
spec:
selector:
app: surrealdb
ports:
- port: 8000
targetPort: 8000
clusterIP: None # headless service for StatefulSet

If SurrealDB fails with Failed to create RocksDB directory or a read-only filesystem error, check that workingDir matches mountPath and that the path slashes are correct — see Docker storage paths.

Spectron uses a Deployment with RollingUpdate because replicas do not hold durable state locally.

apiVersion: apps/v1
kind: Deployment
metadata:
name: spectron
namespace: spectron
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: spectron
template:
metadata:
labels:
app: spectron
spec:
containers:
- name: spectron
image: ghcr.io/surrealdb/spectron:latest
ports:
- containerPort: 9090
env:
- name: SPECTRON_SURREALDB_URL
value: "ws://surrealdb.spectron.svc.cluster.local:8000"
- name: SPECTRON_OBJECT_STORE_URL
value: "s3://my-spectron-bucket/prod?region=eu-west-1"
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: spectron-secrets
key: OPENAI_API_KEY
livenessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 10
periodSeconds: 15
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 9090
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 2
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1000m"
memory: "1Gi"
---
apiVersion: v1
kind: Service
metadata:
name: spectron
namespace: spectron
spec:
selector:
app: spectron
ports:
- port: 80
targetPort: 9090
type: ClusterIP

Expose Spectron externally via an Ingress or LoadBalancer depending on your cluster setup. Ensure TLS termination at the ingress layer.

Spectron scales well on CPU and memory. Configure an HPA to handle traffic spikes:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: spectron
namespace: spectron
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: spectron
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

All resources above use the spectron namespace. Create it before applying the manifests:

kubectl create namespace spectron
kubectl apply -f secret.yaml
kubectl apply -f surrealdb.yaml
kubectl apply -f spectron.yaml
kubectl apply -f hpa.yaml

Wait for the Spectron pods to reach Running state:

kubectl rollout status deployment/spectron -n spectron

Run the spectron init command inside one of the running pods to create the admin management key:

kubectl exec -n spectron deploy/spectron -- spectron init --admin-key

Copy the printed secret. It is shown only once.

Update the image tag in your Deployment manifest and apply it. The rolling update strategy ensures zero-downtime upgrades. Schema migrations run automatically when each new pod starts.

# Update the image tag (replace 0.2.0 with the target version)
kubectl set image deployment/spectron spectron=ghcr.io/surrealdb/spectron:0.2.0 -n spectron
kubectl rollout status deployment/spectron -n spectron

Was this page helpful?