Composite Resource Definitions

This document is for an older version of Crossplane.

This document applies to Crossplane version v1.17 and not to the latest release v1.18.

Composite resource definitions (XRDs) define the schema for a custom API.
Users create composite resources (XRs) and Claims (XCs) using the API schema defined by an XRD.

Note

Read the composite resources page for more information about composite resources.

Read the Claims page for more information about Claims.

Crossplane has four core components that users commonly mix up:

  • Compositions - A template to define how to create resources.
  • Composite Resource Definition (XRD) - This page. A custom API specification.
  • Composite Resource (XR) - Created by using the custom API defined in a Composite Resource Definition. XRs use the Composition template to create new managed resources.
  • Claims (XRC) - Like a Composite Resource, but with namespace scoping.

Crossplane XRDs are like Kubernetes custom resource definitions. XRDs require fewer fields and add options related to Crossplane, like Claims and connection secrets.

Creating a CompositeResourceDefinition

Creating a CompositeResourceDefinition consists of:

Optionally, CompositeResourceDefinitions also support:

Composite resource definitions (XRDs) create new API endpoints inside a Kubernetes cluster.

Creating a new API requires defining an API group, name and version.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata: 
 4  name: xmydatabases.example.org
 5spec:
 6  group: example.org
 7  names:
 8    kind: XMyDatabase
 9    plural: xmydatabases
10  versions:
11  - name: v1alpha1
12  # Removed for brevity

After applying an XRD, Crossplane creates a new Kubernetes custom resource definition matching the defined API.

For example, the XRD xmydatabases.example.org creates a custom resource definition xmydatabases.example.org.

1kubectl api-resources
2NAME                              SHORTNAMES   APIVERSION          NAMESPACED   KIND
3xmydatabases.example.org                       v1alpha1            false        xmydatabases
4# Removed for brevity
Warning
You can’t change the XRD group or names.
You must delete and recreate the XRD to change the group or names.

XRD groups

Groups define a collection of related API endpoints. The group can be any value, but common convention is to map to a fully qualified domain name.

Many XRDs may use the same group to create a logical collection of APIs.

For example a database group may have a relational and nosql kinds.

Tip
Group names are cluster scoped. Choose group names that don’t conflict with Providers.
Avoid Provider names in the group.

XRD names

The names field defines how to refer to this specific XRD.
The required name fields are:

  • kind - the kind value to use when calling this API. The kind is UpperCamelCased. Crossplane recommends starting XRD kinds with an X to show it’s a custom Crossplane API definition.
  • plural - the plural name used for the API URL. The plural name must be lowercase.
Important

The XRD metadata.name must be plural name, . (dot character), group.

For example, xmydatabases.example.org matches the plural name xmydatabases, . group name, example.org.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata: 
 4  name: xmydatabases.example.org
 5spec:
 6  group: example.org
 7  names:
 8    kind: XMyDatabase
 9    plural: xmydatabases
10    # Removed for brevity

XRD versions

The XRD version is like the API versioning used by Kubernetes. The version shows how mature or stable the API is and increments when changing, adding or removing fields in the API.

Crossplane doesn’t require specific versions or a specific version naming convention, but following Kubernetes API versioning guidelines is strongly recommended.

  • v1alpha1 - A new API that may change at any time.
  • v1beta1 - An existing API that’s considered stable. Breaking changes are strongly discouraged.
  • v1 - A stable API that doesn’t have breaking changes.

Define a schema

The schema defines the names of the parameters, the data types of the parameters and which parameters are required or optional.

Note
All schemas follow the Kubernetes custom resource definition OpenAPIv3 structural schema.

Each version of the API has a unique schema.

All XRD schemas validate against the openAPIV3Schema. The schema is an OpenAPI object with the properties of a spec object.

Inside the spec.properties is the custom API definition.

In this example, the key region is a string.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  group: custom-api.example.org
 7  names:
 8    kind: xDatabase
 9    plural: xdatabases
10  versions:
11  - name: v1alpha1
12    schema:
13      openAPIV3Schema:
14        type: object
15        properties:
16          spec:
17            type: object
18            properties:
19              region:
20                type: string
21    # Removed for brevity

A composite resource using this API references the group/version and kind. The spec has the region key with a string value.

1apiVersion: custom-api.example.org/v1alpha1
2kind: xDatabase
3metadata:
4  name: my-composite-resource
5spec: 
6  region: "US"
Tip

The custom API defined inside the spec.properties is an OpenAPIv3 specification. The data models page of the Swagger documentation provides a list of examples using data types and input restrictions.

The Kubernetes documentation lists the set of special restrictions on what your OpenAPIv3 custom API can use.

Important
Changing or expanding the XRD schema requires restarting the Crossplane pod to take effect.
Required fields

By default all fields in a schema are optional. Define a parameter as required with the required attribute.

In this example the XRD requires region and size but name is optional.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  group: custom-api.example.org
 7  names:
 8    kind: xDatabase
 9    plural: xdatabases
10  versions:
11  - name: v1alpha1
12    schema:
13      openAPIV3Schema:
14        type: object
15        properties:
16          spec:
17            type: object
18            properties:
19              region:
20                type: string 
21              size:
22                type: string  
23              name:
24                type: string  
25            required: 
26              - region 
27              - size
28    # Removed for brevity

According to the OpenAPIv3 specification, the required field is per-object. If a schema contains multiple objects the schema may need multiple required fields.

This XRD defines two objects:

  1. the top-level spec object
  2. a second location object

The spec object requires the size and location but name is optional.

Inside the required location object, country is required and zone is optional.

 1# Removed for brevity
 2- name: v1alpha1
 3    schema:
 4      openAPIV3Schema:
 5        type: object
 6        properties:
 7          spec:
 8            type: object
 9            properties:
10              size:
11                type: string  
12              name:
13                type: string 
14              location:
15                type: object
16                properties:
17                  country: 
18                    type: string 
19                  zone:
20                    type: string
21                required:
22                  - country
23            required:  
24              - size
25              - location

The Swagger “Describing Parameters” documentation has more examples.

Crossplane reserved fields

Crossplane doesn’t allow the following fields in a schema:

  • spec.resourceRef
  • spec.resourceRefs
  • spec.claimRef
  • spec.writeConnectionSecretToRef
  • status.conditions
  • status.connectionDetails

Crossplane ignores any fields matching the reserved fields.

Serve and reference a schema

To use a schema it must be served: true and referenceable: true.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  group: custom-api.example.org
 7  names:
 8    kind: xDatabase
 9    plural: xdatabases
10  versions:
11  - name: v1alpha1
12    served: true
13    referenceable: true
14    schema:
15      openAPIV3Schema:
16        type: object
17        properties:
18          spec:
19            type: object
20            properties:
21              region:
22                type: string            

Composite resources can use any schema version set as served: true.
Kubernetes rejects any composite resource using a schema version set as served: false.

Tip
Setting a schema version as served:false causes errors for users using an older schema. This can be an effective way to identify and upgrade users before deleting the older schema version.

The referenceable: true field indicates which version of the schema Compositions use. Only one version can be referenceable.

Note
Changing which version is referenceable:true requires updating the compositeTypeRef.apiVersion of any Compositions referencing that XRD.

Multiple schema versions

Warning

Crossplane supports defining multiple versions, but the schema of each version can’t change any existing fields, also called “making a breaking change.”

Breaking schema changes between versions requires the use of conversion webhooks.

New versions may define new optional parameters, but new required fields are a “breaking change.”

Crossplane XRDs use Kubernetes custom resource definitions for versioning. Read the Kubernetes documentation on versions in CustomResourceDefinitions for more background on versions and breaking changes.

Crossplane recommends implementing breaking schema changes as brand new XRDs.

For XRDs, to create a new version of an API add a new name in the versions list.

For example, this XRD version v1alpha1 only has the field region.

A second version, v1 expands the API to have both region and size.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  group: custom-api.example.org
 7  names:
 8    kind: xDatabase
 9    plural: xdatabases
10  versions:
11  - name: v1alpha1
12    schema:
13      openAPIV3Schema:
14        type: object
15        properties:
16          spec:
17            type: object
18            properties:
19              region:
20                type: string  
21  - name: v1
22    schema:
23      openAPIV3Schema:
24        type: object
25        properties:
26          spec:
27            type: object
28            properties:
29              region:
30                type: string 
31              size:
32                type: string            
Important
Changing or expanding the XRD schema requires restarting the Crossplane pod to take effect.

Enable Claims

Optionally, XRDs can allow Claims to use the XRD API.

Note
Read the Claims page for more information about Claims.

XRDs offer Claims with a claimNames object.

The claimNames defines a kind and plural like the XRD names object.
Also like XRD names, use UpperCamelCase for the kind and lowercase for the plural.

The Claim kind and plural must be unique. They can’t match any other Claim or other XRD kind.

Tip
Common Crossplane convention is to use claimNames that match the XRD names, but without the beginning “x.”
 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  group: custom-api.example.org
 7  names:
 8    kind: xDatabase
 9    plural: xdatabases
10  claimNames:
11    kind: Database
12    plural: databases
13  versions:
14  # Removed for brevity
Important
You can’t change the claimNames after they’re defined. You must delete and recreate the XRD to change the claimNames.

Manage connection secrets

When a composite resource creates managed resources, Crossplane provides any connection secrets to the composite resource or Claim. This requires the creators of composite resources and Claims to know the secrets provided by a managed resource. In other cases, Crossplane administrators may not want to expose some or all the generated connection secrets.

XRDs can define a list of connectionSecretKeys to limit what’s provided to a composite resource or Claim.

Crossplane only provides the keys listed in the connectionSecretKeys to the composite resource or Claim using this XRD. Any other connection secrets aren’t passed to the composite resource or Claim.

Important

The keys listed in the connectionSecretKeys must match the key names listed in the Composition’s connectionDetails.

An XRD ignores any keys listed that aren’t created by a managed resource.

For more information read the Composition documentation.

For example, an XRD passes the keys username, password and address.

Composite resources or Claims save these in the secret defined by their writeConnectionSecretToRef field.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  group: custom-api.example.org
 7  names:
 8    kind: xDatabase
 9    plural: xdatabases
10  connectionSecretKeys:
11    - username
12    - password
13    - address
14  versions:
15  # Removed for brevity
Warning
You can’t change the connectionSecretKeys of an XRD. You must delete and recreate the XRD to change the connectionSecretKeys.

For more information on connection secrets read the Connection Secrets knowledge base article.

Set composite resource defaults

XRDs can set default parameters for composite resources and Claims.

defaultCompositeDeletePolicy

The defaultCompositeDeletePolicy defines the default value for the claim’s compositeDeletePolicy property if the user doesn’t specify a value when creating the claim. The claim controller uses the compositeDeletePolicy property to specify the propagation policy when deleting the associated composite. The compositeDeletePolicy doesn’t apply to standalone composites that don’t have associated claims.

Using a defaultCompositeDeletePolicy: Background policy causes the CRD for the claim to have the default value Background for the compositeDeletePolicy property. When a deleted claim has the compositeDeletePolicy property set to Background the claim controller deletes the composite resource using the propagation policy background and returns, relying on Kubernetes to delete the remaining child objects, like managed resources, nested composites and secrets.

Using defaultCompositeDeletePolicy: Foreground causes the CRD for the claim to have the compositeDeletePolicy default value Foreground. When a deleted claim has the compositeDeletePolicy property set to Foreground the controller deletes the associated composite using the propagation policy foreground. This causes Kubernetes to use foreground cascading deletion which deletes all child resources before deleting the parent resource. The claim controller waits for the composite deletion to finish before returning.

When creating a claim the user can override the defaultCompositeDeletePolicy by including the spec.compositeDeletePolicy property with either the Background or Foreground value.

The default value is defaultCompositeDeletePolicy: Background.

Set defaultCompositeDeletePolicy: Foreground to change the XRD deletion policy.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  defaultCompositeDeletePolicy: Foreground
 7  group: custom-api.example.org
 8  names:
 9  # Removed for brevity
10  versions:
11  # Removed for brevity

defaultCompositionRef

It’s possible for multiple Compositions to reference the same XRD. If more than one Composition references the same XRD, the composite resource or Claim must select which Composition to use.

An XRD can define the default Composition to use with the defaultCompositionRef value.

Set a defaultCompositionRef to set the default Composition.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  defaultCompositionRef: 
 7    name: myComposition
 8  group: custom-api.example.org
 9  names:
10  # Removed for brevity
11  versions:
12  # Removed for brevity

defaultCompositionUpdatePolicy

Changes to a Composition generate a new Composition revision. By default all composite resources and Claims use the updated Composition revision.

Set the XRD defaultCompositionUpdatePolicy to Manual to prevent composite resources and Claims from automatically using the new revision.

The default value is defaultCompositionUpdatePolicy: Automatic.

Set defaultCompositionUpdatePolicy: Manual to set the default Composition update policy for composite resources and Claims using this XRD.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  defaultCompositionUpdatePolicy: Manual
 7  group: custom-api.example.org
 8  names:
 9  # Removed for brevity
10  versions:
11  # Removed for brevity

enforcedCompositionRef

To require all composite resources or Claims to use a specific Composition use the enforcedCompositionRef setting in the XRD.

For example, to require all composite resources and Claims using this XRD to use the Composition myComposition set enforcedCompositionRef.name: myComposition.

 1apiVersion: apiextensions.crossplane.io/v1
 2kind: CompositeResourceDefinition
 3metadata:
 4  name: xdatabases.custom-api.example.org
 5spec:
 6  enforcedCompositionRef: 
 7    name: myComposition
 8  group: custom-api.example.org
 9  names:
10  # Removed for brevity
11  versions:
12  # Removed for brevity

Verify a CompositeResourceDefinition

Verify an XRD with kubectl get compositeresourcedefinition or the short form, kubectl get xrd.

1kubectl get xrd                                
2NAME                                ESTABLISHED   OFFERED   AGE
3xdatabases.custom-api.example.org   True          True      22m

The ESTABLISHED field indicates Crossplane installed the Kubernetes custom resource definition for this XRD.

The OFFERED field indicates this XRD offers a Claim and Crossplane installed the Kubernetes custom resource definitions for the Claim.

XRD conditions

Crossplane uses a standard set of Conditions for XRDs.
View the conditions of a XRD under their Status with kubectl describe xrd.

 1kubectl describe xrd
 2Name:         xpostgresqlinstances.database.starter.org
 3API Version:  apiextensions.crossplane.io/v1
 4Kind:         CompositeResourceDefinition
 5# Removed for brevity
 6Status:
 7  Conditions:
 8    Reason:                WatchingCompositeResource
 9    Status:                True
10    Type:                  Established
11    Reason:                WatchingCompositeResourceClaim
12    Status:                True
13    Type:                  Offered
14# Removed for brevity

WatchingCompositeResource

Reason: WatchingCompositeResource indicates Crossplane defined the new Kubernetes custom resource definitions related to the composite resource and is watching for the creation of new composite resources.

1Type: Established
2Status: True
3Reason: WatchingCompositeResource

TerminatingCompositeResource

Reason: TerminatingCompositeResource indicates Crossplane is deleting the custom resource definitions related to the composite resource and is terminating the composite resource controller.

1Type: Established
2Status: False
3Reason: TerminatingCompositeResource

WatchingCompositeResourceClaim

Reason: WatchingCompositeResourceClaim indicates Crossplane defined the new Kubernetes custom resource definitions related to the offered Claims and is watching for the creation of new Claims.

1Type: Offered
2Status: True
3Reason: WatchingCompositeResourceClaim

TerminatingCompositeResourceClaim

Reason: TerminatingCompositeResourceClaim indicates Crossplane is deleting the custom resource definitions related to the offered Claims and is terminating the Claims controller.

1Type: Offered
2Status: False
3Reason: TerminatingCompositeResourceClaim