Crossplane Compositions Explained: Kubernetes Platform APIs

Updated on
9 min read

Platform teams often need to offer the same cloud resources to many application teams without asking every developer to learn each provider’s APIs. Crossplane Compositions address that problem by defining Kubernetes APIs for infrastructure and connecting each request to controllers that create and manage the underlying resources. This explainer covers how those APIs, composition functions, and providers work together, and where Crossplane fits alongside tools such as Terraform and Kubernetes Operators.

Why Crossplane Compositions Are Being Talked About

Kubernetes has become a common foundation for internal platforms, but its built-in resources describe workloads and cluster behavior—not every database, network, bucket, or cloud service an organization needs. Teams can expose those capabilities through custom APIs, then let controllers reconcile requests instead of giving every workload direct access to infrastructure credentials.

Crossplane is a cloud-native framework for building control planes on Kubernetes. Its composition model lets platform engineers present a smaller, stable interface to application teams while retaining control over implementation choices. The Crossplane project describes this goal as creating cloud-native control planes; the underlying technology is useful when an organization needs reusable service APIs rather than a single one-off deployment.

What Is a Crossplane Composition?

A Crossplane Composition is a reusable template and function pipeline that tells Crossplane how to turn a request for a higher-level resource into one or more lower-level resources. A team might define a Database API with fields for engine, size, and backup policy. A developer submits one Database object, and Crossplane can create a provider-managed database, networking resources, and related Kubernetes objects.

The request is a composite resource (XR). A composite resource definition (XRD) declares the API’s schema, scope, and versions. A Composition targets a kind of XR and describes its implementation. The official Crossplane composition documentation explains these resources and the function pipeline in detail.

An XR is a Kubernetes custom resource, but it is not the same thing as a cloud resource. It is the platform-facing request and status surface. The Composition determines which resources should exist, while providers and other controllers do the work of creating and observing them.

The Problem Compositions Solve

Without a shared platform API, each product team may write its own Terraform modules, provider-specific scripts, or Kubernetes manifests. That can duplicate policy, credentials, naming rules, and operational knowledge. A small change—such as enforcing encryption or changing a default network—then has to propagate through many independent implementations.

Crossplane lets platform engineers encode a supported path once and expose it through the Kubernetes API. Consumers request an outcome in terms relevant to them, while the platform team can change implementation details behind that contract. The interface can include safe defaults and validation, and RBAC can control who is allowed to create or update requests.

This abstraction has a cost. The platform team now owns the API lifecycle, composition logic, packages, provider configuration, and failure handling. Crossplane does not remove infrastructure complexity; it centralizes and automates the parts an organization chooses to standardize.

How Crossplane Compositions Work

The normal path starts when a user applies an XR. Kubernetes validates it against the schema generated from the XRD and stores it in the API server. Crossplane observes the resource and selects a compatible Composition. For a pipeline-mode Composition, Crossplane calls its configured functions in order, passing observed state, previously desired state, function input, and relevant context.

Each function returns desired composed resources. Those can include Kubernetes objects and provider-managed resources. Crossplane compares the desired set with what exists and applies changes; the controllers responsible for each resource then reconcile their own state. A provider controller, for example, translates a managed-resource object into cloud API operations and reports the observed result. Crossplane propagates useful connection details or status back to the XR when the composition is configured to do so.

The loop is asynchronous. Applying an XR means the request was accepted, not that a database is ready. The provider may need credentials, quota, network capacity, and time to create the external service. An XR’s conditions and composed resources are the signals to inspect when a request is progressing or failing.

Concern Crossplane Terraform Kubernetes Operator
Main interface Kubernetes APIs and composite resources Configuration and module inputs Application-specific custom resources
Typical control loop Controllers continuously reconcile desired resources Plan and apply operations; automation can schedule repeated runs A controller reconciles application state
Scope of abstraction Platform services across providers and Kubernetes resources Infrastructure described by configured providers The lifecycle of a particular application or service
User interaction Submit or update an XR through Kubernetes tooling Run a pipeline or command that plans and applies changes Create or update the Operator’s custom resource
Good fit Kubernetes-native self-service APIs and shared platform guardrails Infrastructure workflows centered on plans, state, and approvals Encoding operational knowledge for an application

These tools can coexist. Terraform may provision the Kubernetes cluster or resources outside the Crossplane control plane. An Operator can manage a database running inside the cluster, while Crossplane provisions cloud infrastructure the database depends on. Crossplane is not a replacement for every IaC workflow or every Operator.

Components and Key Concepts

  • XRDs define the schema and API versions for a family of composite resources. Schema validation protects the API boundary, but teams still need to plan compatibility and deprecation.
  • XRs are instances of that API. A namespaced XR can give a team or environment a clear ownership boundary; the chosen scope should match the organization’s tenancy model.
  • Compositions connect an XR kind to implementation logic. A Composition can be revised as the platform evolves, while teams need deliberate rollout rules so existing requests do not change unexpectedly.
  • Composition functions transform observed state and inputs into desired composed resources. A pipeline can use different functions for rendering, patching, or custom logic. The official Crossplane composition quickstart demonstrates a YAML-based function and a small application API.
  • Providers and managed resources connect Kubernetes objects to external services. A provider package contains controllers and schemas for a provider’s APIs; a managed resource represents a specific external object and its desired configuration.
  • Claims and connection details are optional API and data-sharing patterns. Claims can provide a namespaced request interface in supported setups, while connection details can expose credentials or endpoints. Both require careful RBAC and secret-handling decisions.
  • Package configuration describes installed providers, functions, and configurations. These packages are part of the control plane’s supply chain and need versioning, access controls, and upgrade procedures.

The control-plane contract is shaped by established Kubernetes API design conventions. The Kubernetes community’s API conventions describe patterns such as separating desired state in spec from observed state in status. Kubernetes custom resources add API types, but a custom resource by itself does not create a controller or implement useful behavior.

Real-World Uses

Self-service databases: A platform can accept a database size, region, and backup policy, then compose a provider-managed database with network rules and monitoring configuration. Developers use a stable request API rather than maintaining provider-specific resource graphs.

Environment provisioning: An XR can represent a development or test environment composed of a namespace, policies, service dependencies, and managed cloud resources. Deleting such an environment still needs explicit safeguards for persistent data and shared dependencies.

Platform APIs across providers: A platform can expose a consistent interface while using different implementations for different infrastructure providers. This does not make the providers identical; unsupported features, latency, cost, and failure modes remain provider-specific.

Guardrailed infrastructure changes: Teams can let consumers choose from approved options while keeping credentials and provider permissions in the control plane. Composition logic can encode defaults, but RBAC, admission controls, and provider permissions remain important security boundaries.

Getting Started: Install and Apply a Composition

Start with a Kubernetes cluster and a supported Helm installation. The official Crossplane installation guide documents prerequisites and chart options. These commands install the stable chart into its own namespace:

helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane \
  --namespace crossplane-system \
  --create-namespace \
  crossplane-stable/crossplane
kubectl get pods -n crossplane-system

After Crossplane is ready, the quickstart provides a namespaced App API, a patch-and-transform function, a Composition that creates a Deployment and Service, and a sample App request. Apply the resources in order:

kubectl apply -f https://docs.crossplane.io/latest/manifests/get-started/composition/xrd.yaml
kubectl wait --for=condition=Established xrd/apps.example.crossplane.io --timeout=120s
kubectl apply -f https://docs.crossplane.io/latest/manifests/get-started/composition/fn-patch-and-transform.yaml
kubectl get functions
kubectl apply -f https://docs.crossplane.io/latest/manifests/get-started/composition/composition-yaml.yaml
kubectl apply -f https://docs.crossplane.io/latest/manifests/get-started/composition/app.yaml

The function is installed as a package, so check that it becomes healthy before applying the sample request. Then inspect the request and the resources it composes:

kubectl get xrd,compositions,functions
kubectl get app my-app -n default
kubectl get deployments,services -n default \
  -l example.crossplane.io/app=my-app
kubectl describe app my-app -n default

If the XR is not ready, inspect its conditions and events, then check whether the function and Composition are healthy and selected. For cloud-backed managed resources, also verify provider package health, provider credentials, IAM permissions, quotas, and the external resource’s own status. Avoid copying the quickstart’s example API directly into production; define fields, ownership boundaries, deletion behavior, and permissions for the platform’s real consumers.

Common Misconceptions

  • “A Composition is a cloud resource.” It is an implementation template. The XR is a Kubernetes request, and a provider controller is responsible for the external object.
  • “Applying an XR means provisioning has finished.” Kubernetes accepts the request first. Crossplane functions and providers reconcile asynchronously, so readiness and failure conditions matter.
  • “Crossplane eliminates Terraform or Operators.” It offers a Kubernetes-native control-plane model. Existing Terraform workflows and application Operators can remain useful at different layers.
  • “A single Composition works everywhere.” Composition logic can be reused, but provider capabilities, credentials, regions, quotas, and policies still differ.

Changelog

  • Initial publication.
TBO Editorial

About the Author

TBO Editorial writes about the latest updates about products and services related to Technology, Business, Finance & Lifestyle. Do get in touch if you want to share any useful article with our community.