How do you create and use Crossplane Compositions with patches for dynamic configuration?
Quick Answer
Crossplane Compositions define a template of managed resources that are created when a user submits a Composite Resource claim, and patches dynamically map values from the claim into the underlying infrastructure resources, enabling self-service provisioning with guardrails.
Detailed Answer
Crossplane Compositions are the central abstraction that transforms a Kubernetes cluster into a universal control plane for infrastructure. A Composition defines which managed resources should be created and how values from a user-facing Composite Resource (XR) or Claim (XRC) flow into those resources through patches. When a platform team at a company creates a Composition for the payments-api database, they are encoding organizational best practices such as encryption at rest, backup windows, and network isolation into a reusable blueprint that application developers consume without needing cloud console access.
The architecture involves three core components working together. First, the CompositeResourceDefinition (XRD) defines the schema of the custom API that application teams interact with. This is analogous to creating a custom Kubernetes resource type, such as XPostgreSQLInstance, with fields like storageGB, region, and environment. Second, the Composition maps that XRD to a specific set of managed resources. For example, the payments-api team might request an XPostgreSQLInstance, and the Composition creates an RDS instance, a subnet group, a security group, and a parameter group in AWS. Third, patches are the glue that transfers values between the composite resource and the composed resources. The FromCompositeFieldPath patch type copies a field from the XR spec into a managed resource spec, while ToCompositeFieldPath copies status values back up to the XR for consumers to read, such as the database endpoint or connection secret.
Patches support powerful transformations that make dynamic configuration possible. The transform block can apply string formatting using the fmt type, converting a simple environment name like staging into a full resource name like payments-api-db-staging. Math transforms can multiply a user-requested storage value by a factor for different environments. Map transforms convert enumerated values, for instance mapping small to db.t3.micro and large to db.r5.2xlarge for the order-processing-service database. Convert transforms handle type coercion between strings and integers. The combine transform merges multiple fields, such as joining region and environment into a unique identifier for the inventory-sync database subnet group. Each patch also supports a policy block with fromFieldPath set to Required or Optional, controlling whether a missing source field should block provisioning or use a default.
In production environments, Compositions typically create five to fifteen managed resources per claim. The checkout-service database Composition at a typical e-commerce company might provision an RDS instance, a KMS key for encryption, an IAM role for enhanced monitoring, a CloudWatch alarm for CPU utilization, a subnet group spanning three availability zones, and a security group with ingress rules scoped to the application namespace CIDR. Each of these resources receives values from the claim through patches, and the connection details such as host, port, username, and password are propagated back through connectionDetails blocks in the Composition, ultimately stored as a Kubernetes Secret in the claiming namespace where the application pod mounts them.
A critical best practice is versioning Compositions using the revision system. When the platform team updates a Composition, existing composite resources remain on their original revision unless the updatePolicy on the XRD is set to Automatic. This prevents breaking changes from cascading across all environments simultaneously. The user-auth-service team can test the new Composition revision in their dev environment before the platform team rolls it to staging and production. Teams should also use readinessChecks in the Composition to define when a composed resource is considered ready, such as checking that the RDS instance status field equals available, which gates the overall composite resource readiness and prevents applications from attempting to connect to infrastructure that is still provisioning.