Publications

The Orkestra Provider Model

**Extending declarative operators to external infrastructure.**

3 min read

Extending declarative operators to external infrastructure.


The problem with external resources

Kubernetes operators manage Kubernetes resources. The reconcile loop reads a CR, creates Deployments and Services, writes status. This is the model controller-runtime was designed for and the model Orkestra’s declarative layer covers completely.

Real operators manage more than Kubernetes resources. A DatabaseCluster CR creates an RDS instance and a Route 53 record. A MessageQueue CR provisions an SQS queue and attaches an IAM policy. A MongoUser CR creates a database user in Atlas.

The provider model is the third option: external resources declared in the Katalog, executed by a registered provider library, composable with Kubernetes resource declarations, publishable to the OrkestraRegistry.


What a provider is

A provider is a Go library that handles a named block in the Katalog’s onCreate, onReconcile, or onDelete sections. AWS ships a provider that handles aws: blocks. MongoDB ships a provider that handles database: blocks with driver: mongo.

The provider receives:

  • The resolved CR object — all spec fields, metadata, status accessible as map[string]interface{}
  • The declarations from its YAML block — already template-resolved by Orkestra’s resolver before the provider is called
  • A context with cancellation, logger, and request ID
  • The Kubernetes client — for reading Secrets, ConfigMaps, and other cluster resources the provider may need

The provider returns an error or nil. Orkestra handles retry, backoff, status patching, and event emission.


The Katalog syntax

spec:
  crds:
    - name: application-stack
      operatorBox:
        default: true
        onCreate:
          # ── Kubernetes resources (Orkestra core) ────────────────────────
          deployments:
            - name: "{{ .metadata.name }}"
              image: "{{ .spec.image }}"
              replicas: "{{ .spec.replicas }}"

          # ── External resources (provider libraries) ─────────────────────
          aws:
            - s3:
                bucket: "{{ .metadata.name }}-{{ .metadata.namespace }}-assets"
                region: "{{ .spec.region }}"

The Katalog author writes YAML. The provider author writes Go. The operator user writes neither — they apply a CR.


What providers must guarantee

Idempotency. Reconcile is called on every cycle — every resync, every watch event. A provider that creates an RDS instance must check whether it exists before calling CreateDBInstance.

Declarative intent, not imperative sequence. The provider receives declarations of desired state. The correct question is always “does the current external state match the declared desired state?”

Safe deletion. Delete is called once during finalizer execution. If the external resource does not exist, Delete should return nil — not an error.

No Kubernetes writes. Providers read Secrets for credentials and ConfigMaps for configuration. They do not create, update, or delete Kubernetes resources.


Conclusion

The provider model is the natural endpoint of Orkestra’s architecture. The declarative layer handles Kubernetes resources. Providers handle external resources. Notes handle data transformation. The boundary between them is clean and permanent.

When AWS ships github.com/aws/orkestra-provider-aws, every Orkestra operator that registers it gains declarative RDS, S3, Route 53, and IAM — without writing a line of AWS SDK code.

This is the vision: one runtime, many providers, operators as pure declarations of intent.