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. Pending per-Context schema migrations are applied asynchronously by the scheduler and workers — see Migrations and upgrades.

# 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?