Skip to content

Crossplane Concepts

Before making any decision about Helm's role, you need to understand how Crossplane's resource model actually works. This page explains every layer — from the lowest-level Managed Resource to the highest-level Claim — with diagrams showing how they connect.


The Four Layers

Crossplane has four distinct resource types. They form a stack, but you do not have to use all four. The decision about which layers to use is the entire point of this project.


Layer 1: Managed Resources (MRs)

A Managed Resource is a 1:1 representation of a cloud resource in your Kubernetes cluster. It is the lowest-level building block and corresponds directly to an API call in the cloud provider.

What it is

  • A Kubernetes Custom Resource installed by a Crossplane provider
  • Maps to exactly one cloud resource (one Azure VNet, one Storage Account, etc.)
  • Crossplane's controller continuously reconciles the MR's spec with the real cloud state
  • If someone changes the resource in Azure portal, Crossplane detects the drift and corrects it

Real example

yaml
apiVersion: network.azure.upbound.io/v1beta1
kind: VirtualNetwork
metadata:
  name: myapp-dev-vnet
spec:
  forProvider:
    location: eastus
    resourceGroupNameRef:
      name: myapp-dev-rg
    addressSpace:
      - "10.0.0.0/16"
  providerConfigRef:
    name: default

Key fields

FieldPurpose
apiVersionIdentifies the provider and API group (e.g., network.azure.upbound.io/v1beta1)
kindThe specific Azure resource type (VirtualNetwork, Subnet, Account, etc.)
spec.forProviderThe actual Azure resource configuration — maps to Azure Resource Manager fields
spec.providerConfigRefWhich set of Azure credentials to use
*Ref / *Selector fieldsReferences to other MRs — Crossplane resolves these at runtime

How references work

MRs reference each other using *Ref (by name) or *Selector (by label). Crossplane resolves these references and injects the actual Azure resource IDs at runtime.

This is critical: Crossplane handles the wiring, not Helm. Helm only needs to produce consistent metadata.name values. The actual Azure resource ID resolution happens in the Crossplane controller.

Lifecycle


Layer 2: Compositions

A Composition is a mapping template that tells Crossplane how to turn a high-level request (an XR) into a set of low-level Managed Resources.

What it is

  • A Kubernetes resource of kind Composition
  • Contains a list of resources: — each one is a Managed Resource template
  • Uses patches: to inject values from the XR into each MR template
  • Installed once by the platform team, consumed by many XRs

What it looks like

yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: azure-network
  labels:
    provider: azure
spec:
  compositeTypeRef:
    apiVersion: platform.example.org/v1alpha1
    kind: XNetwork               # This Composition serves XNetwork XRs
  resources:
    - name: vnet
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: VirtualNetwork
        spec:
          forProvider:
            location: ""         # Patched from XR
            addressSpace: []     # Patched from XR
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.location
          toFieldPath: spec.forProvider.location
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.cidr
          toFieldPath: spec.forProvider.addressSpace[0]

    - name: subnet-app
      base:
        apiVersion: network.azure.upbound.io/v1beta1
        kind: Subnet
        spec:
          forProvider:
            addressPrefixes: []
      patches:
        - type: FromCompositeFieldPath
          fromFieldPath: spec.parameters.appSubnetCidr
          toFieldPath: spec.forProvider.addressPrefixes[0]

The patching model

Compositions use patches to move data between the XR (high-level) and MRs (low-level):

Patch types

Patch TypeDirectionUse Case
FromCompositeFieldPathXR → MRPush XR values into MR specs
ToCompositeFieldPathMR → XRPull MR status back into XR (e.g., connection details)
CombineFromCompositeXR → MRCombine multiple XR fields into one MR field
CombineToCompositeMR → XRCombine multiple MR fields into one XR field

Pipeline Mode (Modern Alternative)

Crossplane v1.14+ introduced pipeline-mode Compositions that use functions instead of patch-and-transform. This is what Upbound's reference platforms use.

yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: azure-network-pipeline
spec:
  compositeTypeRef:
    apiVersion: platform.example.org/v1alpha1
    kind: XNetwork
  mode: Pipeline
  pipeline:
    - step: render
      functionRef:
        name: function-kcl
      input:
        apiVersion: krm.kcl.dev/v1alpha1
        kind: KCLRun
        spec:
          source: |
            # KCL code that generates MRs

WARNING

Pipeline mode is more powerful but adds complexity. Stick with patch-and-transform when you have fewer than 10 resources in a Composition.


Layer 3: Composite Resource Definitions (XRDs) and Composite Resources (XRs)

XRD — the schema

A CompositeResourceDefinition (XRD) defines a new custom API type in your cluster. It creates both an XR kind (cluster-scoped) and optionally a Claim kind (namespace-scoped).

yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xnetworks.platform.example.org
spec:
  group: platform.example.org
  names:
    kind: XNetwork           # The cluster-scoped XR type
    plural: xnetworks
  claimNames:
    kind: Network            # The namespace-scoped Claim type
    plural: networks
  versions:
    - name: v1alpha1
      served: true
      referenceable: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                parameters:
                  type: object
                  properties:
                    location:
                      type: string
                    cidr:
                      type: string
                    appSubnetCidr:
                      type: string
                  required:
                    - location
                    - cidr

What the XRD creates

When you apply an XRD, Crossplane registers two new CRDs in your cluster:

XR — an instance

An XR (Composite Resource) is a concrete instance of the type defined by an XRD. It is cluster-scoped and triggers a Composition.

yaml
apiVersion: platform.example.org/v1alpha1
kind: XNetwork
metadata:
  name: prod-network
spec:
  parameters:
    location: westeurope
    cidr: "10.30.0.0/16"
    appSubnetCidr: "10.30.1.0/24"
  compositionRef:
    name: azure-network      # Which Composition to use

When this XR is created, Crossplane:

  1. Finds the Composition named azure-network (or selects one via labels)
  2. Renders all the MR templates in that Composition
  3. Applies patches to inject the XR's spec.parameters into each MR
  4. Creates the MRs in the cluster
  5. Crossplane's provider controllers reconcile those MRs against Azure

Layer 4: Claims

A Claim is a namespace-scoped request for a Composite Resource. It is the interface that application teams use — they never see MRs or Compositions.

yaml
apiVersion: platform.example.org/v1alpha1
kind: Network                # This is the Claim kind (from XRD.spec.claimNames)
metadata:
  name: my-network
  namespace: team-alpha      # Claims live in namespaces
spec:
  parameters:
    location: eastus
    cidr: "10.10.0.0/16"
    appSubnetCidr: "10.10.1.0/24"

Claim vs XR

AspectClaimXR
ScopeNamespaceCluster
Created byApplication teamsPlatform teams (or by Claims)
VisibilityOnly sees own namespaceSees all resources cluster-wide
NameNetwork (from claimNames)XNetwork (from names)
Use caseMulti-tenant, RBAC-controlledSingle-tenant, admin access

The full flow


Which Layers Does This Project Use?

Layer 1 only — Managed Resources.

Helm replaces Layers 2-4. Instead of XRDs + Compositions + Claims, Helm's values.yaml is your parameterization layer and templates/ render the MRs directly.

This means:

  • No XRDs to write or maintain
  • No Compositions to debug
  • No Claim/XR indirection
  • Full visibility into every Azure resource
  • helm template shows you exactly what will be applied

The trade-off is documented in When to Abstract — there are concrete conditions under which you should graduate to Compositions.


Glossary

TermFull NameWhat It Is
MRManaged Resource1:1 map to a cloud resource. Installed by providers.
XRDCompositeResourceDefinitionSchema that defines a new custom API type. Creates XR + Claim CRDs.
XRComposite ResourceCluster-scoped instance of an XRD. Triggers a Composition.
ClaimClaimNamespace-scoped request for an XR. Consumer-facing interface.
CompositionCompositionTemplate mapping XR fields to MR specs via patches.
ProviderProviderCrossplane package that installs MR CRDs (e.g., provider-azure-network).
ProviderConfigProviderConfigCredentials configuration for a provider.
forProviderThe spec block containing cloud-specific configuration.
*RefReferenceCrossplane-native cross-resource reference resolved at runtime.
*SelectorSelectorLabel-based cross-resource reference resolved at runtime.

Released under the MIT License.