# OCM: a hub and spoke model for managing many Kubernetes clusters

> Open Cluster Management is an Apache-2.0 CNCF sandbox project whose core is a hub cluster, a klusterlet agent on each managed cluster, and three APIs: cluster inventory registration, ManifestWork for pulling work out to the clusters, and Placement for deciding which clusters get it.

**open-cluster-management-io/ocm** — Core components in the OCM project. Report here if you found any issues in OCM.

- Repository: https://github.com/open-cluster-management-io/ocm
- Website: https://open-cluster-management.io
- Stars: 1,112 · Forks: 181
- Language: Go
- License: Apache-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/open-cluster-management-io-ocm

## Nobody runs just one cluster

Open Cluster Management is a Cloud Native Computing Foundation sandbox project focused on multicluster and multicloud scenarios for Kubernetes applications. Its stated purpose is to make running, managing and using heterogeneous multicluster environments simpler.

The premise in the README is short and direct: no one runs just one cluster, and making multicluster management as easy as possible encourages community growth across all projects. The core goal is stated as multicluster everything.

The differentiation argument has four parts and they are worth separating, because one of them is weaker than the others. Vendor neutrality comes from using APIs that are not tied to any cloud provider or proprietary platform. Standards-based means the project provides a reference implementation of the APIs put forward by SIG-Multicluster, plus extended capabilities on top of them. Extensibility comes from the add-on structure, which lets a project gain multicluster support with minimal code changes.

The fourth is the plug-and-play architecture, and it is the one that does the most work. By standardising on a single PlacementDecision API, any scheduler can publish its choices and any consumer can subscribe to them, which is the mechanism behind the interoperability claim. One API in the middle, producers on one side, consumers on the other.

The licence is Apache-2.0, the primary language is Go, and the repository is not archived with the last push on 2026-10-15. The release tags are v1.3.0 on 2026-05-09, v1.3.1 on 2026-05-19 and v1.4.0 on 2026-10-07.

## Hub, spoke, and the klusterlet

The architecture is a hub-spoke model, and the README is explicit about what that buys.

The hub cluster centralizes control of all managed clusters. An agent called the klusterlet resides on each managed cluster to manage registration to the hub and to run instructions from the hub. The model can survive failure and recovery of components without interrupting workloads, which is the property that matters most when the thing you are running is a live broadcast or a customer-facing service.

The design principles listed are Kubernetes principles: open declarative APIs, code built with DevOps and automation, a containerised vendor-neutral deployment, and a declarative management style aligned with GitOps.

That last one is the most consequential, and it is what explains the pull-based work distribution described later. GitOps alignment means the hub states what should be true and the cluster reaches out to find out, rather than the hub pushing and the cluster accepting. The consequence for the hub is that it never holds the credentials needed to reach into a managed cluster.

The components are published as operators. The README carries Artifact Hub badges for the cluster-manager and klusterlet community operators, which is how an operator-based install on OpenShift or Kubernetes works. In the Makefile, the image names follow the same pattern with a `quay.io/open-cluster-management` registry and a `latest` tag by default, and there is a separate image for the work agent alongside the registration operator.

## Cluster inventory: the double opt-in handshake

Registration of multiple clusters to a hub cluster places them for management, and this is the part with the most interesting security design.

OCM implements a secure double opt-in handshaking protocol that requires explicit consent from both hub cluster administrators and managed cluster administrators before the connection is established. Neither side can enrol a cluster on its own, which closes off the obvious attack of a hub pulling in clusters it should not control.

The mechanics are worth understanding. The registration process creates an mTLS connection between the registration-agent on the managed cluster, which is part of the klusterlet, and the registration-controller on the hub, which is part of the Cluster Manager. Once registered, each managed cluster is assigned a dedicated namespace on the hub, for isolation and security.

That per-cluster namespace is the isolation boundary for everything else. The registration-controller continuously monitors cluster health and manages cluster lifecycle operations, including certificate rotation and permission management. Certificate rotation in particular is the operation you want handled for you, because a hub holding long-lived credentials for dozens of clusters is a hub with a large blast radius when one of those clusters is compromised.

The `sigs.k8s.io/cluster-inventory-api` dependency in the module list, at version 0.2.0, points at this API being standardised outside the project, which is consistent with the standards-based claim.

## ManifestWork pulls resources out to the clusters

Work distribution is the ManifestWork API, which enables resources to be applied to managed clusters from a hub cluster.

A ManifestWork acts as a wrapper containing Kubernetes resource manifests that need to be distributed and applied to specific managed clusters. The API supports update strategies, conflict resolution, resource ordering and status feedback, which together cover the questions any distribution mechanism has to answer: what happens when the hub changes its mind, what happens when two controllers fight over the same object, in what order do things get applied, and how does the hub learn what happened.

The direction of travel is the interesting design decision. The work-agent on each managed cluster actively pulls ManifestWork resources from its dedicated namespace on the hub and applies them locally. The README gives the reason: this pull-based approach ensures scalability and eliminates the need to store managed cluster credentials on the hub.

That is a security property, not just a scaling one. A push model requires the hub to hold a credential or to establish an inbound connection to every spoke, and both of those scale badly and both widen the attack surface. With pull, the spoke needs only read access to its own namespace, and a cluster that goes away needs no cleanup on the hub beyond deleting a namespace.

The cost of the model is that a disconnected cluster does not get its updates, and the hub has no channel to reach into a cluster that has lost its connection. That is a deliberate trade, and it is the one to think about when a spoke goes offline.

## Placement decides which clusters get the work

Content placement is the third API, and it is the scheduling layer.

The Placement API is described as a sophisticated scheduler for multicluster environments that operates on a hub-spoke model and is deeply integrated with the Work API. Administrators use vendor-neutral selectors to dynamically choose clusters based on labels, resource capacity or custom criteria, and the PlacementDecision resource provides a list of selected clusters that can be consumed by any scheduler or controller.

That last clause is the plug-and-play claim in practice. PlacementDecision is the interchange point. A scheduler that knows how to place workloads somewhere produces a PlacementDecision, and anything downstream that knows how to consume a list of chosen clusters can act on it. Neither side has to know about the other.

The choice of criteria is deliberately open, since it includes custom criteria and not only built-in ones. Capacity-aware placement is included, which matters for a fleet with heterogeneous cluster sizes, and label-based selection is the basic case that covers most multi-region or multi-tenant splits.

The API set is deliberately small, then: inventory for registration, ManifestWork for distribution, Placement for selection. The project's value proposition is that these three are enough to build on, and the add-on framework is the extension point for everything else, with `open-cluster-management.io/addon-framework` at v1.4.0 in the module list.

## Building the Go components and the operator packaging

The repository is a Go monorepo with an operator-oriented build, and the module list is long enough to show the scope.

The go.mod requires Go 1.26.0 and pulls in the Kubernetes libraries at v0.36.4 across api, apimachinery, apiserver, client-go, component-base, kube-aggregator and kubectl. The controller runtime is `sigs.k8s.io/controller-runtime` at 0.24.1. The OCM pieces themselves are separate modules, with `open-cluster-management.io/api`, `open-cluster-management.io/sdk-go` and `open-cluster-management.io/addon-framework` all at v1.4.0, matching the v1.4.0 tag of this repository. Cloudevents and cel-go are there, and the AWS SDK is present for the EKS-specific integrations.

The Makefile is the OpenShift build-machinery style. It includes golang.mk plus the deps, images and yaml-patch targets from the vendored `github.com/openshift/build-machinery-go`, so the build is a fork of the OpenShift operator build system rather than a hand-rolled one. It pulls in four separate test makefiles, for integration tests, e2e tests, OLM tests and kind images, which tells you the test strategy spans unit, integration, end to end and operator lifecycle.

The operator toolchain is pinned in the same file. operator-sdk is at v1.32.0, Helm at v3.14.0, and the operator SDK and Helm architectures are switched for darwin, so the build runs on a developer Mac as well as on Linux.

Two variables are worth reading closely. `RELEASED_CSV_VERSION` is set to 0.14.0, the last released operator version, and `CSV_VERSION` is set to 9.9.9, the placeholder used to generate the latest ClusterServiceVersion manifests. That is the pattern for an operator that has to generate manifests for a version that does not exist yet.

Unit tests run with the race detector and a coverage profile, and the package pattern is `./pkg/...`.

## Conclusion

OCM fits an operator with several clusters across clouds or on-premises who wants one place to register them, push resources out and decide placement without adopting a cloud provider's fleet management. It does not fit a team with one cluster, and the hub itself becomes a piece of infrastructure you must run and back up. Before deploying, read the cluster inventory documentation for the double opt-in registration handshake, decide whether you want the pull-based ManifestWork model, and read development.md and the troubleshooting directory before your first hub installation.

## FAQ

### What is Open Cluster Management?

It is a CNCF sandbox project focused on multicluster and multicloud scenarios for Kubernetes applications, with the goal of making running, managing and using heterogeneous multicluster environments simpler. Its core goal is described as multicluster everything, and it is Apache-2.0 licensed.

### What is the klusterlet in OCM?

The klusterlet is the agent that resides on each managed cluster. It manages registration to the hub and runs instructions from the hub. The registration process creates an mTLS connection between its registration-agent and the registration-controller on the hub.

### How does OCM distribute resources to managed clusters?

Through the ManifestWork API. The work-agent on each managed cluster actively pulls ManifestWork resources from its dedicated namespace on the hub and applies them locally, a pull-based approach that scales and means managed cluster credentials are not stored on the hub.

### How does a cluster get registered with an OCM hub?

OCM uses a double opt-in handshake that requires explicit consent from both hub and managed cluster administrators. Once registered, each managed cluster is assigned a dedicated namespace on the hub for isolation and security.

### What is the Placement API used for in OCM?

It is the scheduling layer for content placement, letting administrators select clusters with vendor-neutral selectors based on labels, resource capacity or custom criteria. The resulting PlacementDecision lists the chosen clusters and can be consumed by any scheduler or controller.

## Sources

- [License: Apache-2.0](https://github.com/open-cluster-management-io/ocm/blob/main/LICENSE)
- [open-cluster-management-io/ocm on GitHub](https://github.com/open-cluster-management-io/ocm)
- [Project website](https://open-cluster-management.io)
- [README](https://github.com/open-cluster-management-io/ocm/blob/main/README.md)
- [Releases](https://github.com/open-cluster-management-io/ocm/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/open-cluster-management-io-ocm
