Is your control plane ready for Crossplane v2?
TL;DR
- The vast majority of v1.x control planes can upgrade to Crossplane v2 right away with no changes. Claims, composite resources (XRs), Compositions, and cluster-scoped managed resources all keep working.
- A small set of v1 features were removed or changed in v2. If your control plane uses one, you'll want to find that out before you upgrade.
crossplane beta upgrade checkis a new, read-only CLI command that scans a live v1.x control plane and reports exactly what (if anything) would break, which resource is responsible, and how to fix it.- It ships in the v1.20 CLI, so install the latest v1.20 CLI and run it against your cluster before you upgrade.
Ready to upgrade?
When we designed Crossplane v2, backward compatibility was a first-class goal: the vast majority of v1.x control planes can upgrade without changing a thing. Your claims, composite resources (XRs), compositions, and cluster-scoped managed resources all keep working in v2.
But "the vast majority" isn't "everyone." Crossplane v2 does remove or change the behavior of a small set of v1 features, and if your control plane uses any of them, you'll want to catch it before you upgrade. Until now, that meant reading the backward compatibility notes and then spelunking through every composition, package, and resource in your cluster for something that's going away - tedious and easy to get wrong on a control plane of any real size. Understandably, that uncertainty has kept some folks from upgrading to v2.
crossplane beta upgrade check is now available to give you a definitive answer. It's a read-only command that connects to a live v1.x control plane and exhaustively scans it for anything v2 removes or changes in a breaking way. Point it at your cluster before you upgrade and it takes you straight to the resources that need attention, with the exact fix for each.
What it checks
The command covers every breaking change called out in the v2 backward compatibility notes. For each one, it reports the specific resources responsible so you can act on them directly:
- Native patch-and-transform Compositions. Composition Functions are how you compose resources in Crossplane v2. Native patch-and-transform (P&T) Composition, where resources and patches are embedded directly in the Composition, is removed. This is the change most likely to affect you, so any Composition still using it needs to move to a function pipeline.
- ControllerConfig usage. The
ControllerConfigtype is removed, replaced byDeploymentRuntimeConfig. The check finds bothControllerConfigsthemselves and the Providers or Functions that still reference one. - External secret stores. This alpha feature is removed in v2. The check finds where it's enabled and where your Compositions and resources still publish connection details through it.
- Unqualified package sources. Crossplane v2 drops the implicit default registry, so every package reference (Providers, Configurations, Functions, and their dependencies) must be fully qualified with its registry hostname.
- Composite resource connection details. This one is informational. Legacy XRs and Claims keep aggregating connection details in v2, so the upgrade itself needs no action here. The check highlights resources you'd only need to revisit if you later migrate them to v2-style namespaced XRs, which do not support connection details at the XR level.
The command is also careful about false positives. Crossplane's controllers and the API server inject defaults onto every cluster, and the check knows to look past those and flag only the features you actually opted into. A finding means real usage you'll need to address.
Let's see it in action
Running the command is as simple as pointing it at a cluster. By default it uses your current kubeconfig context and sweeps the entire control plane: all of your Crossplane configuration, cluster-scoped resources, and every namespace:
crossplane beta upgrade check
On a control plane that's already clean, you get the answer you're hoping for and a zero exit code:
[✓] 0 issues, 0 informational, 0 incomplete checks.
There we go - ready to upgrade. On a control plane that still leans on some v1-only features, the report tells you precisely what stands in the way. Here's a representative output from a control plane that is still using native patch-and-transform and external secret stores:
[✗] 4 issues, 0 informational, 0 incomplete checks.
[✗] Native patch-and-transform Compositions - 3 issues
│
│ Crossplane v2 removes native patch-and-transform (P&T) Composition. Compositions must use mode: Pipeline with Composition Functions.
│ Fix: Migrate to Composition Functions (spec.mode: Pipeline with spec.pipeline steps). Run "crossplane beta convert pipeline-composition" to convert existing Compositions.
│ Docs: https://docs.crossplane.io/latest/guides/upgrade-to-crossplane-v2/#native-patch-and-transform-composition
│ https://docs.crossplane.io/v1.20/cli/command-reference/#beta-convert
│
│ NAME FIELD
│ composition.apiextensions.crossplane.io/nativepnt-composition .spec.mode
│ composition.apiextensions.crossplane.io/nativepnt-composition .spec.patchSets
│ composition.apiextensions.crossplane.io/nativepnt-composition .spec.resources
└──
[✓] ControllerConfig usage
[✗] External secret stores - 1 issue
│
│ Crossplane v2 removes support for external secret stores. Publish connection details as Kubernetes Secrets composed by your Compositions, or adopt External Secrets Operator if
│ you need an external store.
│ Fix: Disable --enable-external-secret-stores on the Crossplane Deployment, replace StoreConfig-based publishing with composed Kubernetes Secrets (or adopt External Secrets
│ Operator), then delete StoreConfig resources. No automated converter exists.
│ Docs: https://docs.crossplane.io/latest/guides/upgrade-to-crossplane-v2/#external-secret-stores
│ https://docs.crossplane.io/latest/guides/connection-details-composition
│ https://github.com/external-secrets/external-secrets
│
│ NAMESPACE NAME FIELD
│ crossplane-system deployment.apps/crossplane .spec.template.spec.containers[0].args
└──
[✓] Composite resource connection details
[✓] Unqualified package sources
crossplane: error: blockers found
Each finding is self-contained. The top line summarizes the breaking change in plain language, the Fix: line tells you what to do about it - often naming the exact crossplane beta convert command that will migrate the resource for you - and the Docs: line links straight to the relevant section of the upgrade guide. Below that, a table lists every resource and field responsible, so there's no guesswork about which of your Compositions needs attention.
The command exits non-zero when it finds blockers and zero when it doesn't, and -o json emits the same findings as structured data:
crossplane beta upgrade check -o json
The exit code and JSON output make the check easy to automate anywhere it has access to your cluster: a readiness gate in a CD or promotion pipeline, or a scheduled job watching a fleet of control planes. Most often, though, it's simply something you run by hand once, right before you upgrade.
Performance Tuning
Scanning every managed resource for external secret stores usage is the most expensive part of the run on control planes with many provider CRDs, and these flags let you make a trade off for execution time versus the load the command puts on your API server:
--skip-managed-resourcesskips the managed-resource scan entirely. The command still inspectsStoreConfigresources, the CrossplaneDeployment, and composite resources for external secret stores usage; it just doesn't scan managed resources. This gives the biggest reduction in run time, at the cost of not catching external secret stores usage on managed resources.--concurrency(default10) bounds how many resources the command processes in parallel. Lower it, for example--concurrency 2, to put less load on a busy production control plane you don't want to overload; raise it to finish faster at the cost of more load on the API server.
How to get it
Because this tool is only useful before you upgrade, it ships exclusively in the v1.20 Crossplane CLI - a v2 control plane has nothing left to check, and the v1-only types these checks rely on don't even exist there. We made a deliberate exception to v1.20's critical-fixes-only maintenance policy to ship this in the v1.20.9 patch release, precisely so the whole community can check their control planes before they make the jump.
If you're running a v1.x control plane, you likely already have the CLI on hand. You just need a build that includes upgrade check, which means the latest v1.20 patch release. Install it with:
curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | XP_VERSION=v1.20.9 sh
You can also download the binary directly from releases.crossplane.io, or see Download other CLI versions in the docs for more options. Then confirm you're ready to roll:
crossplane beta upgrade check --help
When you're ready to dig into the changes themselves, the Crossplane v2 upgrade guide and the backward compatibility notes walk through each breaking change and how to migrate.
Upgrade with confidence
Most of you will run crossplane beta upgrade check, see a clean report, and upgrade to v2 the same day - which is exactly the outcome all that backward compatibility work was for. For everyone else, it trades guesswork for a precise list of what to change before you go. Either way, you upgrade deliberately, knowing exactly where your control plane stands.
This check is just a first step. It tells you what needs to change, and for some breaking changes it can already point you at a crossplane beta convert command that does the rewrite for you, but it stops short of migrating your control plane end to end. Smoothing that path is where the community should head next.
To lead that effort, we've started a new special interest group (SIG) for v2 migration. Drop into #sig-v2-migration to help shape where we invest in tooling, share best practices, and learn from others making the same move - and to tell us how the upgrade check is working for you, including any case it misses or flags incorrectly.
We love to hear from the community, as they are exactly what makes this project great. Whether you are a developer, user, or just interested in what we're up to, feel free to join us via one of the following methods: