Skip to content

Banner image Banner image

Crossplane 2.2: What's New (and Why It Matters)

Here's a scenario that'll feel familiar if you've been writing Crossplane composition functions for a while. You've got a multi-step pipeline, something's failing, and you're staring at the Composite Resource conditions trying to figure out which function in the chain produced the wrong output. You can see that it failed. You can't see what was sent to the function or what came back. So you add debug logging, redeploy, reproduce the failure, squint at the logs, and eventually piece it together. It's not broken, exactly. It's just slower than it needs to be.

Crossplane 2.2 fixes that with the Pipeline Inspector. And honestly that's the headline — the rest of the release is the kind of solid incremental work that makes a platform more reliable without asking you to change much. Composition functions got smarter about version-awareness, a meaningful bug fix landed for function selectors, and the MRD controller got quieter in busy clusters. Worth knowing what changed before you upgrade.


Pipeline Inspector: finally, real function debugging (alpha)

The most useful new thing in 2.2 for anyone writing composition functions is the Pipeline Inspector. It's alpha, disabled by default, and you have to opt in explicitly — but it solves a real problem.

Before the inspector, debugging a failing composition function meant staring at conditions on the Composite Resource and trying to reconstruct what went wrong from partial state. You couldn't easily see what request was sent to a function or what response came back.

The inspector changes that. When enabled, it forwards every function request and response to a gRPC endpoint you configure. Wire it up to a local collector or your existing observability stack, and you get a full trace of what each function in your pipeline received and returned. For complex compositions with multiple function steps, that's a fundamentally different debugging experience.

To enable it:

apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
  name: pipeline-inspector
spec:
  deploymentTemplate:
    spec:
      template:
        spec:
          containers:
            - name: crossplane
              args:
                - --enable-pipeline-inspector
                - --pipeline-inspector-grpc-endpoint=your-collector:9999

Alpha means the interface can change. Don't build critical production workflows around the inspector endpoint format yet, but absolutely use it in dev and staging — it's genuinely useful right now.

Enable in dev and staging today

Even in alpha, the Pipeline Inspector gives you function request/response traces that make composition debugging dramatically faster. Enable it in non-production environments now. The interface may change before GA, but the debugging value is immediate — complex multi-function pipelines that used to require adding logging and redeploying can be traced in real time.


RequiredSchemas and Capabilities: smarter function contracts

Two related additions that matter if you're writing custom composition functions.

RequiredSchemas lets a function declare which Kubernetes resource schemas it needs. Previously, functions had to either make assumptions about available types or handle missing schemas defensively. Now a function can populate RunFunctionResponse.requiredSchemas with the group/version/kind it needs, and Crossplane will provide those schemas in subsequent requests.

Capabilities is the other side of the same problem — functions now receive a Capabilities field in the request that tells them what version of Crossplane they're running against. This lets function authors write version-aware logic without parsing environment variables or making separate API calls. If you're maintaining functions that run across multiple Crossplane versions, this is the clean way to handle compatibility.

Apply this: adopt Capabilities before writing version conditionals

If you're maintaining composition functions that need to behave differently across Crossplane versions, use the new Capabilities field rather than environment variable parsing or API calls. It's the supported, clean path — and it means your version-conditional logic is explicit in the function code rather than buried in deployment configs.


Composition functions: select all resources of a kind

A small but genuinely useful fix: composition functions can now use a selector with no match field to mean "all resources of that kind". Previously this was either broken or required a workaround. Now it works as you'd expect.

This matters for compositions that need to enumerate all existing instances of a type — for status aggregation, for cleanup logic, for functions that need to reason about the full set of composed resources rather than a specific subset.

Apply this: remove selector workarounds

If you've been working around the missing "select all" behaviour with empty match patterns or custom logic, clean those up after upgrading to 2.2. The idiomatic pattern (selector with no match field) now works correctly — keeping the workarounds in place makes the composition harder to read and creates a maintenance burden that no longer has a purpose.


Reliability: server-side apply for MRDs

The MRD (Managed Resource Definition) controller now uses server-side apply when updating CRDs. This is a reliability improvement rather than a behaviour change — server-side apply handles field ownership more cleanly and is less likely to produce unexpected diffs when other controllers have also modified the CRD.

Practically: if you've seen intermittent CRD update conflicts in busy clusters, this should reduce them. Not a migration concern, just a quieter control plane.


ImageConfig: dependency package runtime configuration

ImageConfig resources can now configure the DeploymentRuntimeConfig for packages installed as dependencies, not just top-level packages. If you're using ImageConfig to control things like pull policies, resource requests, or node selectors for your Crossplane packages, dependency packages now respect the same configuration.

This closes a gap where your direct package installs had consistent runtime behaviour but their dependencies did not. The configuration is inherited, not duplicated — update the ImageConfig prefix rule and it applies to everything matching, including transitive dependencies.

One ImageConfig prefix rule now covers the full dependency tree

With 2.2, a single ImageConfig rule matching your registry prefix applies to both direct and transitive dependency packages. If you've been duplicating configuration to cover dependencies separately, simplify to the prefix-based approach after upgrading — fewer rules to maintain, same coverage.


Quick takeaways

  • Pipeline Inspector is alpha but genuinely useful now — enable it in dev and staging environments to get real function request/response traces for debugging
  • RequiredSchemas and Capabilities clean up version-aware function authoring — worth adopting if you're maintaining functions that run across multiple Crossplane versions
  • "Select all resources of a kind" now works correctly in composition function selectors — fix your workarounds
  • MRD controller uses server-side apply — quieter CRD updates, fewer conflicts in busy clusters
  • ImageConfig covers dependencies — runtime configuration now applies consistently across direct and transitive packages

Crossplane 2.2 is a solid maintenance release with one genuinely new capability worth enabling. Upgrade path is standard — the 2.x release cycle is stable and the changes here are backwards-compatible.


Frequently asked questions

Is the Pipeline Inspector safe to enable in production?

It's alpha, so the interface can change and there's no stability guarantee on the gRPC endpoint format. Enable it in dev and staging environments — it's genuinely useful for debugging — but don't build critical production tooling around the endpoint format yet. The functionality itself is stable enough for investigation work; it's the API contract that's still in flux.

What's the performance impact of enabling the Pipeline Inspector?

Minimal for most clusters. The inspector forwards function request/response payloads to a gRPC endpoint; the overhead is proportional to the size and frequency of your composition function invocations. For clusters with high-volume composition pipelines, benchmark before enabling broadly. For typical platform engineering workloads, the overhead is negligible.

Do RequiredSchemas and Capabilities require changes to existing functions?

No, they're additive. Existing functions continue to work exactly as before — you only need to update a function if you want to take advantage of the new capabilities. The main reason to adopt RequiredSchemas is if your function makes assumptions about available types that occasionally break in multi-version clusters. The main reason to adopt Capabilities is if you're already writing version-conditional logic via workarounds.

Does the MRD server-side apply change require any migration?

No. It's an implementation detail of the MRD controller — the behaviour from a user perspective is unchanged, and existing MRDs don't require any modification. If you've been seeing intermittent CRD update conflicts in busy clusters, you should notice they become less frequent after upgrading.

We're on Crossplane 2.0 — can we skip to 2.2 directly?

Yes. The 2.x release series is designed for standard sequential upgrades, but 2.2 doesn't remove any APIs or introduce breaking changes relative to 2.0 or 2.1. Check the release notes for any deprecated features you might be using, but the upgrade path is a standard Helm chart bump — no data migration or cluster restart required.


What you get

  • Pipeline Inspector — real function request/response traces for debugging composition pipelines, available now in dev/staging
  • Version-aware composition functions — RequiredSchemas and Capabilities let functions declare their dependencies and adapt to the Crossplane version they're running on
  • "Select all resources of a kind" in composition function selectors — works correctly now, fix your workarounds
  • Quieter MRD controller — server-side apply reduces intermittent CRD update conflicts in busy clusters
  • Consistent ImageConfig — dependency packages now inherit runtime configuration the same way direct packages do

Further reading