Ecosystem

6 min read

How does Orkestra compare to ArgoCD?

ArgoCD does manage drift. That’s a fair starting point.

The real question is what you do when you need an operator — when drift correction of static manifests is not enough, when you need conditional resources, live state reactions, external API calls, cross-operator dependencies.

At that point you drop into Go. And every team that does this builds the same machinery, from scratch, for every operator: informers, workqueues, leader election, worker pools, health endpoints, Prometheus metrics, retry logic, finalizers, status management, safe panic recovery, multi-version CRD handling, admission and deletion protection.

That machinery is not the reason the operator exists. It is the cost of entry.

Orkestra says: the machinery is the runtime’s job. You focus on the reason the operator exists — your custom logic.

Helm + ArgoCDOrkestra
Drift correctionYes — reconciles declared stateYes — reconcile: true on any resource
Custom CR logicNoYes — when:, external:, status:, hooks
Live state reactionsNoYes — reconciler re-runs on every change event
External API callsNoYes — external: block, no client code
Admission controlNoYes — validation and mutation webhooks
Multi-version CRDsNoYes — declarative conversion, no webhook code
Per-operator autoscalingNoYes — workers, queue depth, resync period
Operator distributionHelm chartOCI Katalog

Helm + ArgoCD is the right tool for managing static platform resources. Orkestra is the runtime for teams writing operators — so they write the part that matters and stop rebuilding the machinery every time.


How does Orkestra compare to Kubebuilder and Operator SDK?

Both Kubebuilder and Operator SDK are scaffolding frameworks. They generate the controller skeleton — informer setup, event handlers, reconcile loop stub — and reduce the boilerplate you write. You fill in the logic.

You still own the machinery. Queue depth, worker count, leader election lease, health endpoints, Prometheus metrics, retry logic, panic recovery — all of it is yours to configure, test, and maintain. Kubebuilder scaffolds it. You own it.

Orkestra is a runtime. You do not write controllers. The machinery is the runtime’s job.

Kubebuilder / Operator SDKOrkestra
LanguageGoYAML (Go hooks optional)
Controller codeRequired — you fill in the reconcilerNot required — runtime executes your Katalog
Informer / queue / workersYours to configureRuntime-managed, per-CRD
Admission webhooksWrite and deploy separatelyDeclared in Katalog, served by Gateway
MetricsInstrument yourselfBuilt-in per-CRD — queue depth, error rate, worker utilisation
Operator distributionBinary / Docker imageOCI Katalog
TestingUnit tests + envtestork simulate (in-memory) + ork e2e (real cluster)

The escape hatch: when the declarative layer genuinely is not enough — writing a row into PostgreSQL, calling a non-HTTP API — typed hooks let you drop back to Go without giving up the declarative layer. You write the part that requires code. The runtime handles the rest.


How does Orkestra compare to kro?

kro (Kubernetes Resource Orchestrator) was announced in 2024 by Google, Microsoft, and AWS. It allows declaring ResourceGraphDefinitions that compose Kubernetes resources declaratively. The core insight — operator behavior should be a declaration — is the same insight Orkestra is built on.

The differences are significant:

kroOrkestra
Per-CRD isolationNo — shared reconcile contextYes — dedicated informer, queue, workers
Multi-version CRDsNoYes — declarative conversion paths
Registry/distributionNoYes — OCI artifacts, Artifact Hub
Admission webhooksNoYes — validation and mutation
ObservabilityNoYes — per-CRD health endpoints, Prometheus, Control Center
Hooks for external logicNoYes — typed and dynamic Go hooks

kro is a composability layer. Orkestra is a runtime. The fact that three major cloud providers independently arrived at the same insight validates the direction — Orkestra extends it into a complete operator runtime.


Can Orkestra manage third-party CRDs?

Yes — any CRD that Kubernetes accepts, Orkestra can watch and reconcile. No fork, no reverse engineering, no changes to the CRD definition needed.

spec:
  crds:
    prometheus:
      apiTypes:
        group: monitoring.coreos.com
        version: v1
        kind: Prometheus
        plural: prometheuses
      operatorBox:
        onCreate:
          # governance, companion resources, defaults

This is how governance patterns work — you apply Orkestra’s validation and mutation model to CRDs you did not write and cannot modify.

For the full wrapping pattern — internal CRD → ecosystem resource, admission enforcement, status propagation, and e2e testing against the real tool — see the Ecosystem Composition Guide.


What is the path to Kubernetes core?

See Declarative Operators: A New Model for Kubernetes Extensibility for the full argument.

The short version: Orkestra is building toward CNCF Sandbox, then a Kubernetes Enhancement Proposal, then alpha/beta/GA integration into kube-controller-manager. The prerequisite is production adoption at multiple organisations, with metrics. The timeline depends on that adoption curve.

The Katalog and Komposer becoming native Kubernetes kinds — kubectl get katalogs — is the end state. At that point, every cluster ships with a meta-controller that understands declarative operator definitions. Platform teams write Katalogs. Kubernetes manages them.

I already have a controller-runtime operator. Where do I start?

Pull the migration pack and look at 04-constructor-migration:

ork init --pack from-controller-runtime
cd from-controller-runtime/04-constructor-migration

Your Reconcile method stays completely unchanged — same signature, same body. Two lines in a constructor wire it into Orkestra:

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, and metrics.

Or run ork migrate to have the constructor injected automatically — see below.

If you want to understand the full range of options first, the Migration Guide walks through each mode from zero-Go declarative to full constructor.


What does ork migrate do?

ork migrate takes your existing controller-runtime reconciler file and produces a ready-to-run Orkestra operator. By default (--mode toclient) it leaves your Reconcile method completely untouched — no signature change, no body change. It removes SetupWithManager and injects the constructor:

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

It also writes a katalog.yaml stub, simulate.yaml, e2e.yaml, go.mod, Makefile, and Dockerfile alongside the rewritten file. Search for TODO(ork migrate) in the output to see what needs your attention.

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

For a full rewrite to native Orkestra style (new Reconcile signature, struct, and call sites), use --mode native.

ork migrate reference · Migration Guide


I want to try Orkestra but I don’t have a cluster. What do I need?

Docker. That is all.

Two ways to get started:

# Create the cluster first, then start the runtime
ork create cluster
ork run

# Or in one command — creates the cluster and starts the runtime together
ork run --dev

ork create cluster provisions a local kind cluster and writes the kubeconfig. ork run starts the Orkestra runtime against it. ork run --dev does both in a single step — the fastest path from nothing to a running Orkestra operator.

No cloud provider account. No Minikube. No existing Kubernetes setup.


Further reading