Back to Devoured - June 08, 2026
DEVOURED
Is your control plane ready for Crossplane v2?

Is your control plane ready for Crossplane v2?

DevOps Crossplane
Crossplane v1.20.9 adds a read-only CLI command to identify breaking changes before you upgrade your control plane to v2.
What: The new `crossplane beta upgrade check` command scans v1.x control planes for deprecated features like native patch-and-transform compositions, ControllerConfigs, and external secret stores, providing specific fixes and documentation links for identified blockers.
Why it matters: This tool aims to lower the barrier for major version upgrades by replacing manual, error-prone audits with automated, actionable path-finding for cluster configuration.
Takeaway: Install the v1.20.9 Crossplane CLI and run `crossplane beta upgrade check` against your clusters to get a precise list of required migration steps before moving to v2.
Deep dive
  • Scans all namespaces and cluster-scoped resources for v2-incompatible configurations.
  • Flags deprecated 'native patch-and-transform' compositions that must be moved to function pipelines.
  • Detects usage of ControllerConfig, which is replaced by DeploymentRuntimeConfig in v2.
  • Identifies dependencies on external secret stores that are being removed.
  • Checks for unqualified package references that need explicit registry hostnames.
  • Provides non-zero exit codes to facilitate automation in CI/CD pipelines.
  • Offers JSON output for structured report integration.
Decoder
  • Crossplane: An open-source Kubernetes add-on that transforms clusters into control planes to manage cloud services and infrastructure via custom resources.
  • Composition: A set of logic used to bundle multiple resources into a single user-defined Kubernetes object.
  • XR (Composite Resource): An abstraction that enables users to define their own infrastructure APIs in Kubernetes.
  • ControllerConfig: A v1-only resource for customizing the deployment of provider controllers, now replaced by DeploymentRuntimeConfig.
Original article

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 check is 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 ControllerConfig type is removed, replaced by DeploymentRuntimeConfig. The check finds both ControllerConfigs themselves 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

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-resources skips the managed-resource scan entirely. The command still inspects StoreConfig resources, the Crossplane Deployment, 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 (default 10) 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

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.

Explore all 68 articles in today's digest

Fresh dev news, AI-digested daily. Never miss a trend at devoured.fyi