Infrastructure as Code has been around for a while, but it’s often a bottleneck for developers. They have to file tickets, wait for SREs to provision resources, and then hope they got the configuration right. Crossplane, and specifically its concept of XRDs (Composed Resources), offers a way to democratize infrastructure provisioning by letting developers define and manage their own resources directly.
Imagine you’re building a web application and you need a PostgreSQL database. Normally, you’d open a ticket: "I need a PostgreSQL instance with these specs." An SRE would then use Terraform, Pulumi, or manual CLI commands to create it, apply security rules, and hand you back the connection string. This process is slow and error-prone, especially when you need multiple databases or frequent changes.
Crossplane XRCs flip this model. Instead of waiting for an SRE, you, the developer, can define a CompositeResourceDefinition (XRD) that describes a kind of infrastructure you want. For example, you might define a CompositePostgreSQLInstance XRD. This XRD isn’t a real database; it’s a blueprint.
Here’s what that blueprint might look like in YAML:
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: compositedatabaseinstances.database.example.com
spec:
group: database.example.com
names:
kind: CompositeDatabaseInstance
plural: compositedatabaseinstances
versions:
- name: v1
served: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
description: "Size of the database in GB"
instanceClass:
type: string
description: "Instance type for the database"
compositionSelector:
matchLabels:
provider: aws # Or gcp, azure, etc.
tier: production
required:
- parameters
This CompositeResourceDefinition (XRD) tells Crossplane about a new custom resource called CompositeDatabaseInstance. It specifies that this resource has a spec with parameters like storageGB and instanceClass, and crucially, it uses a compositionSelector to find the actual how-to for provisioning this resource.
The "how-to" is defined in a Composition. A Composition is a Crossplane resource that tells Crossplane how to provision underlying infrastructure when a CompositeResource (like our CompositeDatabaseInstance) is created. It maps the developer-friendly parameters from the CompositeResource to the specific resources of a cloud provider.
Here’s a Composition that fulfills our CompositeDatabaseInstance XRD, targeting AWS RDS:
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: rds-postgres-production
labels:
provider: aws
tier: production
spec:
compositeTypeRef:
kind: CompositeDatabaseInstance
apiVersion: database.example.com/v1
resources:
- name: rdsinstance
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
region: us-east-1
skipFinalizer: false
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: spec.parameters.storageGB
toFieldPath: spec.allocatedStorage
- fromFieldPath: spec.parameters.instanceClass
toFieldPath: spec.dbInstanceClass
- fromFieldPath: spec.parameters.storageGB
toFieldPath: spec.maxAllocatedStorage # Example of mapping
This Composition says: "When someone creates a CompositeDatabaseInstance and it matches my labels (e.g., provider: aws, tier: production), create an AWS RDS Instance. Map the spec.parameters.storageGB from the CompositeDatabaseInstance to the spec.allocatedStorage of the RDS Instance, and spec.parameters.instanceClass to spec.dbInstanceClass."
Now, the developer can create an instance of their CompositeDatabaseInstance custom resource:
apiVersion: database.example.com/v1
kind: CompositeDatabaseInstance
metadata:
name: my-app-db
spec:
parameters:
storageGB: 100
instanceClass: db.t3.medium
When Crossplane sees this CompositeDatabaseInstance, it looks for a Composition that matches its spec.compositionSelector. It finds rds-postgres-production, and then uses the resources and patches defined within it to create an actual AWS RDS Instance. The connection details for this RDS instance will be automatically populated into a Kubernetes Secret, usually named something like rdsinstance-my-app-db, which the developer can then use in their application.
The magic here is that the developer never had to touch AWS CLI, Terraform, or know the exact RDS Instance API. They’re working with a higher-level abstraction that they (or their platform team) defined. The Composition acts as the bridge between the developer’s desired state and the cloud provider’s reality.
What most people miss is that the CompositeResourceDefinition (XRD) and Composition are themselves Kubernetes Custom Resources. Crossplane is just extending the Kubernetes API. This means you can use standard Kubernetes tools like kubectl to manage your infrastructure definitions. You can version control your XRDs and Compositions in Git, apply them using kubectl apply -f, and treat your infrastructure blueprints like any other application code. This also means you can build sophisticated policies and workflows around them using Kubernetes admission controllers or GitOps tools.
Once your CompositeDatabaseInstance is created and the underlying RDS instance is provisioned, the next logical step is to integrate it directly with your application deployment.