Skip to content
Orkestra

Orkestra

Kubernetes operators without the infrastructure.

Reconciliation as a runtime service.
Security as a runtime service.
Intent Delivery as a runtime service.

Release Artifact Hub Go Kubernetes License

Quick Start · Docs · Discussions · Early Access Slack


Every Kubernetes operator carries three kinds of infrastructure no one wanted to build:

  • Reconciliation infrastructure — informers, workqueues, worker pools, leader election, retries, backoff, finalizers, status patching, panic recovery
  • Security infrastructure — admission webhooks, validation rules, mutation rules, RBAC generation, TLS management
  • Intent delivery infrastructure — CR construction, caller interfaces, field routing, value translation, schema evolution

None of this is the reason the operator exists. All of it is the cost of entry.

Orkestra absorbs all three. You declare behavior — or keep your existing Reconcile function — and the runtime handles the rest.


If you already have a controller-runtime operator

Two lines. Your Reconcile method is completely untouched.

func NewWebAppReconciler(kube kubeclient.Interface) domain.Reconciler {
    return domain.ReconcilerFrom(&WebAppReconciler{
        Client: kubeclient.ToClient(kube),
    })
}

Remove SetupWithManager, Scheme, and main.go. Orkestra provides the informer, workqueue, worker pool, leader election, panic recovery, metrics, retries, health endpoints, and admission webhooks. Or run ork migrate to have the constructor injected automatically:

ork migrate ./controller/webapp_controller.go -o ./my-operator

Migration Guide · ork migrate reference


If you are starting from scratch

No Go required. Declare what the operator should do:

apiVersion: orkestra.orkspace.io/v1
kind: Katalog
metadata:
  name: website-operator
spec:
  crds:
    website:
      crdFile: ./crd.yaml
      crFiles: [./cr.yaml]
      operatorBox:
        onCreate:
          deployments:
            - name: "{{ .metadata.name }}"
              image: "{{ .spec.image }}"
              replicas: "{{ .spec.replicas }}"
              reconcile: true
          services:
            - name: "{{ .metadata.name }}-svc"
              port: 80
              targetPort: "{{ .spec.port }}"
              reconcile: true
ork run

Orkestra reads the Katalog, installs the CRD, starts the operator, creates the Deployment and Service, sets owner references, writes status, emits events, corrects drift, and exposes health, metrics, and a control center.

Not a single line of Go.


What every CRD gets

Every CRD declared in a Katalog becomes a complete, isolated operator. Nothing to configure.

Informer Watches your exact GVK. In-memory cache. Zero API calls on read.
Workqueue Per-CRD. Rate-limited. Deduplicated. Isolated from every other CRD.
Worker pool Configurable concurrency. A panic in one CRD does not affect any other.
Drift correction reconcile: true — desired state is enforced on every cycle.
Owner references Child resources deleted when the CR is deleted. No onDelete logic needed.
Finalizers CRs protected from dirty deletion automatically.
Events Every reconcile is a traceable Kubernetes event.
Leader election One active instance. Followers hold warm caches. Failover in under 15s.
Status Ready condition + your own status fields written after every reconcile.
Health API /katalog/{crd}/health, /katalog/{crd}/cr, /metrics — per CRD.
Prometheus metrics Reconcile totals, queue depth, error rate — labeled by GVK.
Admission webhooks Validation and mutation declared in the Katalog. No webhook server to write or deploy.
RBAC ork generate rbac derives ClusterRoles from the Katalog. No manual authoring.
Deletion protection Orkestra and everything it manages cannot be accidentally kubectl delete.
Control Center Realtime visibility per CRD, per Katalog, across instances. Auto-generated operator docs — overview, reconcile mode, child resources, kubectl reference, access control.
Developer portal serve.enabled: true on any CRD surfaces a self-service form in the Control Center. Callers submit intent in their vocabulary — no kubectl, no YAML, no Kubernetes knowledge required.

Getting started

Install

# Install (macOS)
brew install orkspace/tap/ork orkspace/tap/orkcc

# Install (Linux)
curl -sSL https://get.orkestra.sh | bash

Windows Download ork_windows_amd64.zip and orkcc_windows_amd64.zip from the latest release.
Extract the archives and add the folder containing ork.exe and orkcc.exe to your PATH.

Initialize and run

ork init
ork run

No cluster? Add --dev to create a temporary kind cluster. Requires Docker.

ork init scaffolds a katalog.yaml, crd.yaml, and cr.yaml in the current directory.

Learning to Orkestrate — the guided path from first operator to full platform. Every capability has a runnable example.


Control Center

ork control

→ localhost:8081 · username:password → orkestra

Control Center — multi-Runtime view

Control Center — per-Runtime panel

Control Center — auto-generated operator docs

Six Runtimes. 75 CRDs. One Control Center.

Live deployment: cc.orkestra.sh


Numbers

Traditional (75 operators) Orkestra
Processes 75 6 runtimes + 1 control center
Memory 3.75 GB – 15 GB ~79 MB per runtime (measured)
CRDs under management 75 75
First operator 3–6 weeks Under 1 hour
Lines of Go 400+ per operator 0
Adding a new CRD Days to weeks Minutes

79 MB is a live measurement from a 10-CRD runtime (process_resident_memory_bytes from the /metrics endpoint — raw scrape). The reduction works because Orkestra pays the cost of client-go, leader election, and health servers once per runtime. Per-CRD cost is a goroutine pool and an in-memory cache — the same isolation model as kube-controller-manager. A panic in one CRD is caught by safeReconcile; the others keep running.


What Orkestra is not

Not an operator framework — an operator runtime. A framework gives you libraries and conventions. Orkestra gives you a runtime: the reconciliation loop, security layer, and delivery surface are the runtime's job. You write the behavior.

Not a replacement for Go. Hooks and constructors exist for exactly this reason. ~90% of operators are declarative; ~10% need code. Orkestra handles the 90% and gives the 10% a clean seam — the same informer, queue, health, and metrics infrastructure, with a single function to implement.

Not GitOps. Katalogs define long-lived API contracts resolved at startup. Treat Katalog changes like any other runtime change — deploy through a pipeline.

Not a product — a primitive layer. Notes, autoscaler, serve mode, Katalogs — none of these are products. They are primitives ready for composition.


Documentation

Migration Guide Bring an existing controller-runtime operator into Orkestra — zero changes to your reconciler
Why Orkestra What Orkestra is, how it works, and why it's different
Foundations The decisions that shaped the design — and why they hold
Trust and Failure Model What happens when things go wrong
Getting Started First operator in under an hour
Learning to Orkestrate Every capability, as a runnable example
Katalog Reference Complete field reference
Orkestra Registry OCI distribution for operators
Security How Orkestra is secure by default

Community

Issues · Discussions · Contributing


Apache 2.0 — see LICENSE