Kubernetes Controllers

The OCM controllers reconcile OCM component versions into a Kubernetes cluster. They form a chain of four custom resources, each depending on the previous one becoming Ready:

  • Repository validates that an OCM repository is reachable.
  • Component resolves and verifies a component version from that repository.
  • Resource fetches a specific resource from the component version.
  • Deployer downloads the resource content and applies it to the cluster.

Architecture

The OCM controllers act as a bridge between an OCM repository and a Kubernetes cluster. Rather than pulling manifests from a Git repository or a plain OCI image, they consume structured OCM component versions — complete with provenance, signatures, and access metadata — and translate them into running workloads.

This separation means that the same component version can be deployed to multiple clusters, across air-gapped environments, or with different credential configurations, without changing what was published. The controllers handle resolution, verification, and delivery. The component author controls what gets shipped and how it is signed.

Show architecture diagram
Artifact Storage
Artifact Storage
GitOps Sources
GitOps Sources
Cluster Administrator
Cluster Administrator
Kubernetes Cluster
Kubernetes Cluster


















3rd Party Deployers
3rd Party Deployers...
GitOps 
Deployer
GitOps...
API Server
















OCM Controller
OCM Controller...
Repository ControllerComponent ControllerResource ControllerDeployerControllerRComponent Descriptor Resolution And Verification Service
Component Descriptor Cache (In-Memory)
Component Descriptor Cache (In-Memory)
OCM Repositories
OCM Repositories
OCI RegistryRRFluxKROArgoCDR
Poll 
Descriptors
Poll...
OCI RegistryHelmRepository
 
Verify And 
Fetch
Resources
...
RRR
Health
Check
Health...
RR
Watch /
CRUD
API Objects
Watch /...
API Objects
API Objects
Repository
Repository
Resource
Resource
RBAC
RBAC
Deployment
Deployment
RR
Watch /
CRUD
API Objects
Watch /...
Push API 
Objects To 
GitOps
Push API...
Component
Component
Deployer
Deployer
Watch /
CRUD
API Objects
Watch /...
Poll API Objects
Poll API O...
Text is not SVG - cannot display

The Reconciliation Chain

Each custom resource in the chain depends on the previous one being Ready. A child object declares a reference to its parent by name, and will not proceed until the parent has been successfully reconciled. This gives each step a clear responsibility and a clear failure surface.

  flowchart LR
    classDef crd fill:#e8f4fd,stroke:#2c7be5,color:#1a1a2e

    Repository["Repository"]
    Component["Component"]
    Resource["Resource"]
    Deployer["Deployer\n(cluster-scoped)"]

    Repository -->|referenced by| Component
    Component  -->|referenced by| Resource
    Resource   -->|referenced by| Deployer

    class Repository,Component,Resource,Deployer crd

Repository

A Repository validates that a given OCM repository is reachable and healthy. It is the entry point for the entire chain — without a Ready repository, nothing downstream can proceed. You configure it with the registry base URL and type, plus any credentials needed to reach it.

API reference

Component

A Component tracks a specific OCM component within a repository. You give it a component name and a semver constraint, and it continuously resolves the highest matching version. Once resolved, the controller verifies the component descriptor and optionally checks cryptographic signatures. The resolved version and digest are published in its status for downstream objects to consume.

You can control whether the controller is allowed to move to a lower version if the constraint is relaxed (downgradePolicy), and narrow the candidate set further with a regex filter on version strings.

API reference

Resource

A Resource selects a specific artifact from within a resolved component version. You identify the artifact by name (and optionally by a path through nested component references). Once the parent Component is Ready, the controller fetches the resource descriptor — access information, digest, type, labels — and stores it in its status.

You can attach CEL expressions via additionalStatusFields to extract values from the descriptor and surface them in status.additional. This is useful when downstream tools like Kro need to wire specific values — such as an image reference or chart version — into their own resources without parsing the full descriptor themselves.

API reference

Deployer

A Deployer is a cluster-scoped object that watches a Resource and, once it is Ready, downloads the resource blob and applies the contained Kubernetes manifests to the cluster using server-side apply. It manages the full lifecycle of what it deploys: creating resources on first apply, updating them when the component version changes, and pruning resources that are no longer part of the manifest set.

See Kubernetes Deployer for a full description of its apply semantics, drift detection, and caching behavior.

API reference

Asynchronous Component Resolution

Component version resolution happens in a background worker pool. When a controller needs a component version, it submits a request and receives a sentinel error (ErrResolutionInProgress). The controller returns early without blocking. Once the worker finishes, it broadcasts an event that re-triggers reconciliation for all waiting objects.

Requests for the same component version are deduplicated across multiple subscribers.

Configuration Propagation

OCM configuration such as credentials and resolvers flows through the reconciliation chain. Each object can declare its own config references and inherit configs from its parent:

spec:
  ocmConfig:
    - kind: Secret
      name: registry-credentials
      policy: Propagate

Propagate makes the config available to child objects in the chain. DoNotPropagate scopes it to that object only. Supported sources are Kubernetes Secrets, ConfigMaps, and OCMConfiguration objects.

Additional Status Fields

The Resource object supports additionalStatusFields, a map of field names to CEL expressions evaluated against the resource descriptor:

spec:
  additionalStatusFields:
    registry: "resource.access.globalAccess.imageReference.split('/')[0]"

Results are stored under status.additional.<fieldName> and can be consumed by downstream tools like Kro to wire values between resources in a ResourceGraphDefinition.

Installation

See Install the OCM Controllers for a step-by-step guide including prerequisites and verification.

Deployer tools

While the OCM controllers technically can be used standalone, it requires kro and a deployer, e.g. Flux, to deploy an OCM resource into a Kubernetes cluster. The OCM controllers deployment, however, does not contain kro or any deployer. Please refer to the respective installation guides for these tools: