Skip to main content

Quickstart

Get OpenControlPlane running on your local machine in under 10 minutes. By the end, you'll have a platform that hands out managed ControlPlanes with the capability for teams to request Flux.

note

ocpctl is the CLI for managing OpenControlPlane environments locally and in production. It is under active development. Some commands and flags may change.

What You'll Build

OpenControlPlane creates three clusters that work together:

ClusterWho uses itPurpose
🟢 PlatformPlatform operatorsRuns platform services, cluster providers, and service providers
🔵 OnboardingEnd users (teams)API surface where teams create ControlPlanes
🟣 ControlPlaneEnd users (teams)One per team, isolated workspace with requested services

The separation ensures end users never touch infrastructure. They interact only with the Onboarding cluster to request resources, and their services appear on their own ControlPlane cluster.


Prerequisites

  • Docker running (8 GB RAM allocated to it)
  • Go installed
  • kubectl CLI installed
  • kind CLI installed
  • flux CLI installed
  • ~10 minutes

Install ocpctl

go install github.com/openmcp-project/ocpctl@v0.2.0

Or download a pre-built binary from the releases page.


Step 1: Start the platform

ocpctl env apply local

This takes a few minutes. It creates a local Kind-based environment with the full OpenControlPlane stack: openmcp-operator, cluster-provider-kind, plus an onboarding cluster and pre-installed services that you can consume.

Error

We might see that Platform Service Gateway (ps-gateway-5db88d9474-6sxsp) has an ERROR.

...
Error: applying resources: applying Unstructured//gateway: no matches for kind "GatewayServiceConfig" in version "gateway.openmcp.cloud/v1alpha1"

Please wait for a couple of seconds and then try execute ocpctl env apply local again. This will restart the Pod. All Pods above should be running eventually.

Verify the platform is running:

Apply to Platform Cluster
kubectl config use-context kind-local-platform
kubectl get pods -n openmcp-system

You should see these pods in Running state:

NAME READY STATUS RESTARTS AGE
cp-kind-5cf448bb88-sx2vf 1/1 Running 0 2m30s
cp-kind-init-xfjb8 0/1 Completed 0 2m49s
openmcp-operator-5b7f788ddb-5r8br 1/1 Running 0 3m14s
ps-gateway-5db88d9474-jkgg8 1/1 Running 4 (81s ago) 2m5s
ps-gateway-init-j556q 0/1 Completed 0 2m48s
ps-helmdeployer-644d7454fc-nrlv9 1/1 Running 0 2m48s
ps-helmdeployer-init-vq5ks 0/1 Completed 0 2m51s
ps-managedcontrolplane-7958959559-vsrtr 1/1 Running 0 2m8s
ps-managedcontrolplane-init-2lpkt 0/1 Completed 0 2m51s
sp-crossplane-84f8bbfb58-265pf 1/1 Running 0 2m8s
sp-crossplane-init-97c57 0/1 Completed 0 2m49s
sp-flux-844b667b9c-jbfqp 1/1 Running 0 2m
sp-flux-init-9w45m 0/1 Completed 0 2m49s
sp-kro-ffbdcf787-tst4z 1/1 Running 0 96s
sp-kro-init-sfcjb 0/1 Completed 0 2m47s
sp-ocm-756946b9dd-4djgn 1/1 Running 0 113s
sp-ocm-init-sh8x8 0/1 Completed 0 2m49s

In this output we can see that openmcp-operator and multiple other services like cluster-provider-kind (cp-kind) and service providers such as Crossplane, Flux, Kro and OCM are running.

Configure allowed Flux versions

To enable end users to request Flux for a ControlPlane, as Platform Owner, we need to make sure to configure allowed versions of Flux. We can configure them via a ProviderConfig:

Apply to Platform Cluster
flux install
kubectl apply -f - <<EOF
apiVersion: flux.services.open-control-plane.io/v1alpha1
kind: ProviderConfig
metadata:
name: flux
spec:
versions:
- version: "2.8.3"
chartVersion: "2.18.2"
chartUrl: "oci://ghcr.io/fluxcd-community/charts/flux2"
EOF

This controls exactly which versions teams can request in Step 3. Add more entries to the versions list to offer additional versions.


Step 2: Create a ControlPlane

Now switch to the end-user perspective. A team wants their own ControlPlane.

First, export the onboarding cluster's kubeconfig so kubectl can reach it:

kind export kubeconfig --name local-onboarding

See the ControlPlane reference for the full API.

Apply to Onboarding API
kubectl config use-context kind-local-onboarding
kubectl apply -f - <<EOF
apiVersion: core.open-control-plane.io/v2alpha1
kind: ControlPlane
metadata:
name: my-controlplane
namespace: default
spec:
iam: {}
EOF

Wait for it to become ready:

kubectl config use-context kind-local-onboarding
kubectl get controlplane my-controlplane -w

Once provisioning completes, you will see:

NAME PHASE
my-controlplane Ready

The platform has provisioned an isolated ControlPlane cluster. Behind the scenes, OpenControlPlane asked cluster-provider-kind to create a new Kind cluster for this ControlPlane. The cluster is assigned a generated name of the form mcp-<hash>.<random> — for example mcp-ad2klitc.f52190f9. The hash is derived from the environment name; the suffix is random per provisioning run. You will need this name in Step 3.


Step 3: Request Flux as a service

The team wants Flux installed on their ControlPlane:

Apply to Onboarding API
kubectl config use-context kind-local-onboarding
kubectl apply -f - <<EOF
apiVersion: flux.services.open-control-plane.io/v1alpha1
kind: Flux
metadata:
name: my-controlplane
namespace: default
spec:
version: 2.8.3
EOF

ServiceProvider Flux on the platform cluster detects this request and installs Flux into the ControlPlane cluster automatically.

Connect to the ControlPlane cluster

The ControlPlane cluster runs as its own Kind cluster with a generated name. Find it:

kind get clusters
local-onboarding
local-platform
mcp-ad2klitc.f52190f9 <- your ControlPlane cluster

Export its kubeconfig and switch context:

CONTROLPLANE_CLUSTER=$(kind get clusters | grep '^mcp-')
kind export kubeconfig --name "$CONTROLPLANE_CLUSTER"
kubectl config use-context "kind-$CONTROLPLANE_CLUSTER"

Verify Flux is running

Flux installation can take a few minutes while the ControlPlane cluster finishes bootstrapping. Wait for all pods to reach Running:

Apply to ControlPlane Cluster
kubectl get pods -n flux-system
NAME READY STATUS RESTARTS AGE
helm-controller-8564d95f86-6kxlg 1/1 Running 0 2m8s
image-automation-controller-5c484478c6-jj29p 1/1 Running 0 2m8s
image-reflector-controller-5875745f59-b9cp4 1/1 Running 0 2m8s
kustomize-controller-7587bc49f9-m47nv 1/1 Running 0 2m8s
notification-controller-d7d89cdb9-sht7p 1/1 Running 0 2m8s
source-controller-7f6f4dd77d-vmxvv 1/1 Running 0 2m8s

The team now has a fully functional control plane with Flux, provisioned through a simple API request.


Next Steps

Add more services

Beyond Flux, we can offer Crossplane, External Secrets Operator, Velero, and more to end users. Each service is a ServiceProvider deployed on the platform cluster.

Our CLI tool ocpctl already pre-installs a lot of these Service Providers. We can look them up via:

Apply to Platform Cluster
kubectl config use-context kind-local-platform
kubectl get serviceproviders

The output looks like this:

NAME PHASE
crossplane Ready
flux Ready
kro Ready
ocm Ready

But we can also apply a new ServiceProvider to our platform to offer e.g. External Secrets Operator to end users:

Apply to Platform Cluster
kubectl config use-context kind-local-platform
kubectl apply -f - <<EOF
apiVersion: openmcp.cloud/v1alpha1
kind: ServiceProvider
metadata:
name: externalsecretsoperator
namespace: openmcp-system
spec:
image: ghcr.io/openmcp-project/images/service-provider-external-secrets:v1.0.0
EOF

We can look up the status of the installation by executing:

kubectl config use-context kind-local-platform
kubectl get serviceproviders

The output looks like this:

NAME PHASE
crossplane Ready
externalsecretsoperator Progressing
flux Ready
kro Ready
ocm Ready

Next, we need to configure these ServiceProviders via their ProviderConfig API to rule which versions end users can install.

note

More coming soon

Managed team access

Learn how Projects and Workspaces let you organize teams and ControlPlanes.

note

More coming soon

Configure an Identity Provider

Learn how to set up an IdP to authenticate users against a local OpenControlPlane environment.

note

More coming soon

Deploy on real infrastructure

Follow the Production Setup guide to run OpenControlPlane on Gardener.


Clean up

ocpctl env delete local

Removes all Kind clusters and resources created by ocpctl env apply local.