Skip to main content
The unified Runlayer operator reconciles two custom resources in one controller:
CRDPurpose
RunlayerInstanceTenant platform stack (backend, frontend, worker, migrations, optional components)
MCPServerHosted MCP server Deployments (Runlayer Deploy)
Use this path when you want multiple isolated Runlayer tenants on a shared EKS cluster. For single-tenant installs, the legacy Helm + Kubernetes (anysource-chart) path remains supported until you cut over.
Do not install the unified operator on a cluster that already runs runlayer-deploy-operator or anysource-chart. Both reconcile MCPServer CRs. Cut over one cluster at a time — see Migration.

Prerequisites

  • Kubernetes 1.24+ (EKS recommended)
  • Helm 3.8+
  • External platform dependencies provisioned per tenant: RDS/Aurora, Redis, IAM roles, ingress/TLS, Secrets
  • Cluster admin access to install CRDs and a cluster-scoped ClusterRole

Install the operator

helm upgrade --install runlayer-operator oci://412677576004.dkr.ecr.us-east-1.amazonaws.com/runlayer-helm-charts/runlayer-operator \
  --version 0.1.1 \
  --namespace runlayer-system --create-namespace \
  -f values-runlayer-operator.yaml
Or install from the monorepo chart directory during development:
helm upgrade --install runlayer-operator infra/aws-helm/runlayer-operator \
  --namespace runlayer-system --create-namespace \
  -f infra/aws-helm/runlayer-operator/values.example.yaml
The chart ships CRDs under crds/ on first install. Helm does not upgrade CRDs on subsequent releases — apply CRD updates explicitly before upgrading when the schema changes:
kubectl apply -f infra/aws-helm/runlayer-operator/crds/platform.runlayer.com_runlayerinstances.yaml
kubectl apply -f infra/aws-helm/runlayer-operator/crds/deploy.runlayer.com_mcpservers.yaml
Monorepo contributors regenerate chart CRDs from the operator with cd runlayer-operator && make sync-helm-crds.

Configure the operator

Copy and customize values:
cp infra/aws-helm/runlayer-operator/values.example.yaml values-runlayer-operator.yaml
Common settings:
Values keyPurpose
image.repository / image.tagOperator container image
telemetryProxy.*Cluster-wide default MCP telemetry proxy sidecar (overridable per tenant on RunlayerInstance.spec.deploy.telemetryProxy)
mcpWorkloads.dedicatedNodes.*Fallback MCP node scheduling when MCPServer.spec.infrastructure.scheduling is unset
otel.*Operator OpenTelemetry traces
metrics.*Controller-runtime metrics + optional Prometheus ServiceMonitor
See the chart README and CHART-DOCS.md for the full values reference.

Create a tenant

  1. Provision external resources for the tenant (database, Redis, WorkOS credentials, TLS cert Secret, optional S3/IAM).
  2. Create platform-namespace Secrets in the tenant platform namespace (default runlayer-<customerId>) — the operator never reads Secret payloads; it only references names/keys.
SecretRequired keysReferenced in CR
runlayer-dbusername, passworddatabase.credentials.*From
runlayer-redispassword or REDIS_URLredis.credentials.passwordFrom or urlFrom
runlayer-authAUTH_CLIENT_ID, AUTH_API_KEYauth.clientIdFrom, auth.apiKeyFrom
runlayer-appSECRET_KEY, MASTER_SALT (+ optional keys)appSecretRef.name
See the RunlayerInstance secrets reference for optional component Secrets and env-var mapping.
  1. Apply a RunlayerInstance in runlayer-system:
apiVersion: platform.runlayer.com/v1alpha1
kind: RunlayerInstance
metadata:
  name: acme
  namespace: runlayer-system
spec:
  customerId: acme
  domain: acme.example.com
  environment: production
  version: "1.0.0"
  images:
    backend: <ecr>/runlayer-backend:1.0.0
    frontend: <ecr>/runlayer-frontend:1.0.0
    worker: <ecr>/runlayer-worker:1.0.0
  database:
    host: acme-db.cluster-xxx.us-east-1.rds.amazonaws.com
    credentials:
      usernameFrom: { name: runlayer-db, key: username }
      passwordFrom: { name: runlayer-db, key: password }
  redis:
    host: acme-redis.xxx.cache.amazonaws.com
    credentials:
      passwordFrom: { name: runlayer-redis, key: password }
  auth:
    clientIdFrom: { name: runlayer-auth, key: AUTH_CLIENT_ID }
    apiKeyFrom: { name: runlayer-auth, key: AUTH_API_KEY }
  appSecretRef:
    name: runlayer-app
  deploy:
    enabled: true
  components:
    backend: { enabled: true, replicas: 2 }
    frontend: { enabled: true, replicas: 2 }
    worker: { enabled: true, replicas: 1 }
  1. Wait for status.phase: Ready on the RunlayerInstance.
  2. Create MCP env Secrets in the tenant MCP namespace, then create MCPServer CRs (runlayer-<customerId>-mcps by default) or enable backend-managed deploy (RUNLAYER_DEPLOY=K8S, ENG-3531).
CRD references:

Namespace layout

NamespaceContents
runlayer-systemOperator Deployment, RunlayerInstance CRs
runlayer-<customerId>Platform workloads for one tenant
runlayer-<customerId>-mcpsMCP Deployments and MCPServer CRs for that tenant

Migration from legacy charts

Per-cluster cutover (high level):
  1. Provision unified-path prerequisites if missing.
  2. Install runlayer-operator on a greenfield cluster or during a maintenance window.
  3. Create RunlayerInstance; verify platform Ready.
  4. Migrate MCP workloads to MCPServer CRs in the tenant MCP namespace.
  5. Switch DNS/traffic to the unified platform ingress.
  6. Uninstall legacy runlayer-deploy-operator and anysource-chart on that cluster only.
Detailed plan: gradual migration plan.

Legacy Helm (single tenant)

anysource-chart for traditional single-tenant installs

EKS + Terraform

Provision EKS, RDS, and Redis before Helm