This document is for an older version of Crossplane.

This document applies to Crossplane version v1.11 and not to the latest release v1.13.

A managed resource (MR) represents an external service in a Provider. When users create a new managed resource, the Provider reacts by creating an external resource inside the Provider’s environment. Every external service managed by Crossplane maps to a managed resource.

Note
Crossplane calls the object inside Kubernetes a managed resource and the external object inside the Provider an external resource.

Examples of managed resources include:

Tip
You can create individual managed resources, but Crossplane recommends using Compositions and Claims to create managed resources.

Managed resource fields

The Provider defines the group, kind and version of a managed resource. The Provider also define the available settings of a managed resource.

Group, kind and version

Each managed resource is a unique API endpoint with their own group, kind and version.

For example the Upbound AWS Provider defines the Instance kind from the group ec2.aws.upbound.io

1apiVersion: ec2.aws.upbound.io/v1beta1
2kind: Instance

deletionPolicy

A managed resource’s deletionPolicy tells the Provider what to do after deleting the managed resource. If the deletionPolicy is delete the Provider deletes the external resource as well. If the deletionPolicy is orphan the Provider deletes the managed resource but doesn’t delete the external resource.

Options

  • deletionPolicy: Delete - Default - Delete the external resource when deleting the managed resource.
  • deletionPolicy: Orphan - Leave the external resource when deleting the managed resource.

forProvider

The spec.forProvider of a managed resource maps to the parameters of the external resource.

For example, when creating an AWS EC2 instance, the Provider supports defining the AWS region and the VM size, called the instanceType.

Note

The Provider defines the settings and their valid values. Providers also define required and optional values in the forProvider definition.

Refer to the documentation of your specific Provider for details.

1apiVersion: ec2.aws.upbound.io/v1beta1
2kind: Instance
3# Removed for brevity
4spec:
5  forProvider:
6    region: us-west-1
7    instanceType: t2.micro
Important
Crossplane considers the forProvider field of a managed resource the “source of truth” for external resources. Crossplane overrides any changes made to an external resource outside of Crossplane. If a user makes a change inside a Provider’s web console, Crossplane reverts that change back to what’s configured in the forProvider setting.

Providers add any settings not manually set to the forProvider field of the created managed resource object. Use kubectl describe <managed_resource> to view the applied values.

Referencing other resources

Some fields in a managed resource may depend on values from other managed resources. For example a VM may need the name of a virtual network to use.

Managed resources can reference other managed resources by external name, name reference or selector.

Matching by external name

When matching a resource by name Crossplane looks for the name of the external resource in the Provider.

For example, a AWS VPC object named my-test-vpc has the external name vpc-01353cfe93950a8ff.

1kubectl get vpc
2NAME            READY   SYNCED   EXTERNAL-NAME           AGE
3my-test-vpc     True    True     vpc-01353cfe93950a8ff   49m

To match the VPC by name, use the external name. For example, creating a Subnet managed resource attached to this VPC.

1apiVersion: ec2.aws.upbound.io/v1beta1
2kind: Subnet
3spec:
4  forProvider:
5    # Removed for brevity
6    vpcId: vpc-01353cfe93950a8ff
Matching by name reference

To match a resource based on the name of the managed resource and not the external resource name inside the Provider, use a nameRef.

For example, a AWS VPC object named my-test-vpc has the external name vpc-01353cfe93950a8ff.

1kubectl get vpc
2NAME            READY   SYNCED   EXTERNAL-NAME           AGE
3my-test-vpc     True    True     vpc-01353cfe93950a8ff   49m

To match the VPC by name reference, use the managed resource name. For example, creating a Subnet managed resource attached to this VPC.

1apiVersion: ec2.aws.upbound.io/v1beta1
2kind: Subnet
3spec:
4  forProvider:
5    # Removed for brevity
6    vpcIdRef: 
7      name: my-test-vpc
Matching by selector

Matching by selector is the most flexible matching method.

Note
The Composition section covers the matchControllerRef selector.

Use matchLabels to match the labels applied to a resource. For example, this Subnet resource only matches VPC resources with the label my-label: label-value.

1apiVersion: ec2.aws.upbound.io/v1beta1
2kind: Subnet
3spec:
4  forProvider:
5    # Removed for brevity
6    vpcIdSelector: 
7      matchLabels:
8        my-label: label-value

Immutable fields

Some providers don’t support changing the fields of some managed resources after creation. For example, you can’t change the region of an Amazon AWS RDSInstance. These fields are immutable fields. Amazon requires you delete and recreate the resource.

Crossplane allows you to edit the immutable field of a managed resource, but doesn’t apply the change. Crossplane never deletes a resource based on a forProvider change.

Note

Crossplane behaves differently than other tools like Terraform. Terraform deletes and recreates a resource to change an immutable field. Crossplane only deletes an external resource if their corresponding managed resource object is deleted from Kubernetes and the deletionPolicy is delete.

managementPolicy

Important

The managed resource managementPolicy option is an alpha feature.

Enable the managementPolicy in a provider with --enable-management-policies in a ControllerConfig.

A managementPolicy determines if Crossplane can make changes to managed resources. The ObserveOnly policy imports existing external resources not originally created by Crossplane.
This allows new managed resources to reference the ObserveOnly resource, for example, a shared database or network. The ObserveOnly policy can also place existing resources under the control of Crossplane.

Tip
Read the Import Existing Resources guide for more information on using the managementPolicy to import existing resources.

Options

  • managementPolicy: FullControl - Default - Crossplane can create, change and delete the managed resource.
  • managementPolicy: ObserveOnly - Crossplane only imports the details of the external resource, but doesn’t make any changes to the managed resource.

providerConfigRef

The providerConfigRef on a managed resource tells the Provider which ProviderConfig to use when creating the managed resource.

Use a ProviderConfig to define the authentication method to use when communicating to the Provider.

Important
If providerConfigRef isn’t applied, Providers use the ProviderConfig named default.

For example, a managed resource references a ProviderConfig named user-keys.

This matches the name of a ProviderConfig.

1apiVersion: ec2.aws.upbound.io/v1beta1
2kind: Instance
3spec:
4  forProvider:
5    # Removed for brevity
6  providerConfigRef: user-keys
1apiVersion: aws.crossplane.io/v1beta1
2kind: ProviderConfig
3metadata:
4  name: user-keys
5# Removed for brevity
Tip
Each managed resource can reference different ProviderConfigs. This allows different managed resources to authenticate with different credentials to the same Provider.

providerRef

Crossplane deprecated the providerRef field in crossplane-runtime v0.10.0. Managed resources using providerRefmust use providerConfigRef.

writeConnectionSecretToRef

When a Provider creates a managed resource it may generate resource-specific details, like usernames, passwords or connection details like an IP address.

Crossplane stores these details in a Kubernetes Secret object specified by the writeConnectionSecretToRef values.

For example, when creating an AWS RDS database instance with the Crossplane community AWS provider generates an endpoint, password, port and username data. The Provider saves these variables in the Kubernetes secret rds-secret, referenced by the writeConnectionSecretToRef field.

1apiVersion: database.aws.crossplane.io/v1beta1
2kind: RDSInstance
3metadata:
4  name: my-rds-instance
5spec:
6  forProvider:
7  # Removed for brevity
8  writeConnectionSecretToRef:
9    name: rds-secret

Viewing the Secret object shows the saved fields.

1kubectl describe secret rds-secret
2Name:         rds-secret
3# Removed for brevity
4Data
5====
6port:      4 bytes
7username:  10 bytes
8endpoint:  54 bytes
9password:  27 bytes
Important
The Provider determines the data written to the Secret object. Refer to the specific Provider documentation for the generated Secret data.

publishConnectionDetailsTo

The publishConnectionDetailsTo field expands on writeConnectionSecretToRef supporting storing managed resource information as a Kubernetes Secret object or in an external secrets store like HashiCorp Vault.

Using publishConnectionDetailsTo requires enabling Crossplane External Secrets Stores (ESS). Enable ESS inside a Provider with a ControllerConfig and in Crossplane with the --enable-external-secret-stores argument.

Note
Not all Providers support publishConnectionDetailsTo. Check your Provider documentation for details.

Publish secrets to Kubernetes

To publish the data generated by a managed resource as a Kubernetes Secret object provide a publishConnectionDetailsTo.name

1apiVersion: rds.aws.upbound.io/v1beta1
2kind: Instance
3spec:
4  forProvider:
5  # Removed for brevity
6  publishConnectionDetailsTo:
7    name: rds-kubernetes-secret

Crossplane can apply labels and annotations to the Kubernetes secret as well using publishConnectionDetailsTo.metadata.

 1apiVersion: rds.aws.upbound.io/v1beta1
 2kind: Instance
 3spec:
 4  forProvider:
 5  # Removed for brevity
 6  publishConnectionDetailsTo:
 7    name: rds-kubernetes-secret
 8    metadata:
 9      labels:
10        label-tag: label-value
11      annotations:
12        annotation-tag: annotation-value

Publish secrets to an external secrets store

Publishing secrets data to an external secret store like HashiCorp Vault relies on a publishConnectionDetailsTo.configRef.

The configRef.name references a StoreConfig object.

1apiVersion: rds.aws.upbound.io/v1beta1
2kind: Instance
3spec:
4  forProvider:
5  # Removed for brevity
6  publishConnectionDetailsTo:
7    name: rds-kubernetes-secret
8    configRef: 
9      name: my-vault-storeconfig
1apiVersion: secrets.crossplane.io/v1alpha1
2kind: StoreConfig
3metadata:
4  name: my-vault-storeconfig
5# Removed for brevity
Tip
Read the Vault as an External Secrets Store guide for details on using StoreConfig objects.

Annotations

Crossplane applies a standard set of Kubernetes annotations to managed resources.

AnnotationDefinition
crossplane.io/external-nameThe name of the managed resource inside the Provider.
crossplane.io/external-create-pendingThe timestamp of when Crossplane began creating the managed resource.
crossplane.io/external-create-succeededThe timestamp of when the Provider successfully created the managed resource.
crossplane.io/external-create-failedThe timestamp of when the Provider failed to create the managed resource.
crossplane.io/pausedIndicates Crossplane isn’t reconciling this resource. Read the Pause Annotation for more details.
crossplane.io/composition-resource-nameFor managed resource created by a Composition, this is the Composition’s resources.name value.

Naming external resources

By default Providers give external resources the same name as the Kubernetes object.

For example, a managed resource named my-rds-instance has the name my-rds-instance as an external resource inside the Provider’s environment.

1apiVersion: database.aws.crossplane.io/v1beta1
2kind: RDSInstance
3metadata:
4  name: my-rds-instance
1kubectl get rdsinstance
2NAME                 READY   SYNCED   EXTERNAL-NAME        AGE
3my-rds-instance      True    True     my-rds-instance      11m

Managed resource created with a crossplane.io/external-name annotation already provided use the annotation value as the external resource name.

For example, the Provider creates managed resource named my-rds-instance but uses the name my-custom-name for the external resource inside AWS.

1apiVersion: database.aws.crossplane.io/v1beta1
2kind: RDSInstance
3metadata:
4  name: my-rds-instance  
5  annotations: 
6    crossplane.io/external-name: my-custom-namee
1kubectl get rdsinstance
2NAME                 READY   SYNCED   EXTERNAL-NAME        AGE
3my-rds-instance      True    True     my-custom-name       11m

Creation annotations

Providers create new managed resources with the crossplane.io/external-create-pending annotation.

The Provider applies the crossplane.io/external-create-succeeded or crossplane.io/external-create-failed annotation after making the external API call and receiving a response.

Note

If a Provider restarts before creating the succeed or fail annotations the Provider can’t reconcile the manged resource.

Read Crossplane issue #3037 for more details

Paused

Manually applying the crossplane.io/paused annotation causes the Provider to stop reconciling the managed resource.

Pausing a resource is useful when modifying Providers or preventing race-conditions when editing Kubernetes objects.

Apply a crossplane.io/paused: "true" annotation to a managed resource to pause reconciliation.

Note
Only the value "true" pauses reconciliation.
 1apiVersion: ec2.aws.upbound.io/v1beta1
 2kind: Instance
 3metadata:
 4  name: my-rds-instance
 5  annotations:
 6    crossplane.io/paused: "true"
 7spec:
 8  forProvider:
 9    region: us-west-1
10    instanceType: t2.micro

Remove the annotation to resume reconciliation.

Finalizers

Crossplane applies a Finalizer on managed resources to control their deletion.

Note
Kubernetes can’t delete objects with Finalizers.

When Crossplane deletes a managed resource the Provider begins deleting the external resource, but the managed resource remains until the external resource is fully deleted.

When the external resource is fully deleted Crossplane removes the Finalizer and deletes the managed resource object.

Conditions

Crossplane has a standard set of Conditions for a managed resource. View the Conditions of a managed resource with kubectl describe <managed_resource>

Note
Providers may define their own custom Conditions.

Available

Reason: Available indicates the Provider created the managed resource and it’s ready for use.

1Conditions:
2  Type:                  Ready
3  Status:                True
4  Reason:                Available

Creating

Reason: Creating indicates the Provider is attempting to create the managed resource.

1Conditions:
2  Type:                  Ready
3  Status:                False
4  Reason:                Creating

Deleting

Reason: Deleting indicates the Provider is attempting to delete the managed resource.

1Conditions:
2  Type:                  Ready
3  Status:                False
4  Reason:                Deleting

ReconcilePaused

Reason: ReconcilePaused indicates the managed resource has a Pause annotation

1Conditions:
2  Type:                  Synced
3  Status:                False
4  Reason:                ReconcilePaused

ReconcileError

Reason: ReconcileError indicates Crossplane encountered an error while reconciling the managed resource. The Message: value of the Condition helps identify the Crossplane error.

1Conditions:
2  Type:                  Synced
3  Status:                False
4  Reason:                ReconcileError

ReconcileSuccess

Reason: ReconcileSuccess indicates the Provider created and is monitoring the managed resource.

1Conditions:
2  Type:                  Synced
3  Status:                True
4  Reason:                ReconcileSuccess

Unavailable

Reason: Unavailable indicates Crossplane expects the managed resource to be available, but the Provider reports the resource is unhealthy.

1Conditions:
2  Type:                  Ready
3  Status:                False
4  Reason:                Unavailable

Unknown

Reason: Unknown indicates the Provider has an unexpected error with the managed resource. The conditions.message provides more information on what went wrong.

1Conditions:
2  Type:                  Unknown
3  Status:                False
4  Reason:                Unknown

Upjet Provider conditions

Upjet, the open source tool to generate Crossplane Providers, also has a set of standard Conditions.

AsyncOperation

Some resources may take more than a minute to create. Upjet based providers can complete their Kubernetes command before creating the managed resource by using an asynchronous operation.

Finished

The Reason: Finished indicates the asynchronous operation completed successfully.

1Conditions:
2  Type:                  AsyncOperation
3  Status:                True
4  Reason:                Finished
Ongoing

Reason: Ongoing indicates the managed resource operation is still in progress.

1Conditions:
2  Type:                  AsyncOperation
3  Status:                True
4  Reason:                Ongoing

LastAsyncOperation

The Upjet Type: LastAsyncOperation captures the previous asynchronous operation status as either Success or a failure Reason.

ApplyFailure

Reason: ApplyFailure indicates the Provider failed to apply a setting to the managed resource. The conditions.message provides more information on what went wrong.

1Conditions:
2  Type:                  LastAsyncOperation
3  Status:                False
4  Reason:                ApplyFailure
DestroyFailure

Reason: DestroyFailure indicates the Provider failed to delete the managed resource. The conditions.message provides more information on what went wrong.

1Conditions:
2  Type:                  LastAsyncOperation
3  Status:                False
4  Reason:                DestroyFailure
Success

Reason: Success indicates the Provider successfully created the managed resource asynchronously.

1Conditions:
2  Type:                  LastAsyncOperation
3  Status:                True
4  Reason:                Success