Skip to main content
This is a self-hosting guide. The hosted product at https://www.orcapods.ai needs none of this. Sign in and go.

Architecture on Kubernetes

Key points:
  • Conductors: Deployment + HPA (stateless, scale freely)
  • Runners: StatefulSet + headless Service (stable pod DNS = stable RUNNER_BASE_URL)
  • Sidecars: additional containers inside each runner pod
  • Ingress: nginx with proxy_buffering off for SSE

Conductor Deployment


Runner StatefulSet

Runners must have stable DNS names so conductors can route sessions to them. MCP_BASE_URL is the address a runner advertises to its own sidecars for MCP callbacks, and it defaults to RUNNER_BASE_URL when unset. In a multi-replica StatefulSet, template it per pod the same way as RUNNER_BASE_URL: pinning it to a single replica’s hostname across all pods misroutes every other replica’s sidecar tool calls.
With this StatefulSet and headless service, pods get stable DNS names:
  • <runner-0>.<runner-service>.<cluster-domain>:7070
  • <runner-1>.<runner-service>.<cluster-domain>:7070
  • <runner-2>.<runner-service>.<cluster-domain>:7070
Set these in RUNNER_URLS on the conductor.

Secrets


VirtualFS Strict Mount Configuration

When deploying the standalone VirtualFS service (orca/vfs) to Kubernetes, the strict mount model requires explicit backend configuration. Do NOT use --profile dev in production: the dev profile uses in-process RAM and cannot persist data across pod restarts. Required environment variables for the prod profile: If these are missing or the bucket is unreachable at pod startup, the affected mounts surface as unavailable in GET /vfs/mounts. The server still passes /healthz: liveness checks are independent of mount status. Use the VirtualFS smoke script (scripts/vfs-smoke.sh) in a post-deploy readiness check to assert all expected mounts are ready before traffic is sent.

Ingress with SSE Support

Without proxy-buffering: "false", Server-Sent Events will not stream correctly. nginx-ingress will buffer the entire response.

Updating Runner Count

When you scale the StatefulSet, update the conductor’s RUNNER_URLS to include the new pod DNS names. The safest approach:
  1. Scale the StatefulSet: kubectl scale statefulset runner --replicas=4 -n orca
  2. Wait for the new pod to be ready: kubectl rollout status statefulset runner -n orca
  3. Update the conductor Deployment env to include <runner-3>.<runner-service>.<cluster-domain>:7070
  4. Roll out the conductor: kubectl rollout restart deployment conductor -n orca
New sessions will round-robin to include the new runner. Existing sessions remain pinned to their original runner.

Namespace and RBAC


Monitoring Integration

Both conductor and runner expose /metrics in Prometheus text format, gated behind a bearer token: set METRICS_AUTH_TOKEN on the conductor Deployment and the runner StatefulSet, or every scrape gets a 401 Unauthorized. Create a ServiceMonitor if you’re using the Prometheus Operator, pointing bearerTokenSecret at that same token:
Last modified on September 6, 2026