Replace content/master with a copy of content/v2.0-preview

Signed-off-by: Nic Cope <nicc@rk0n.org>
This commit is contained in:
Nic Cope 2025-08-05 15:53:30 -07:00
parent 431e87a035
commit fe508db0b1
72 changed files with 3797 additions and 17073 deletions

View File

@ -1,51 +1,39 @@
---
title: "Overview"
title: "Welcome"
weight: -1
cascade:
version: "master"
---
{{< img src="/media/banner.png" alt="Crossplane Popsicle Truck" size="large" >}}
Welcome to the Crossplane documentation. Crossplane is a control plane framework
for platform engineering.
<br />
# Using the documentation
Crossplane is an open source Kubernetes extension that transforms your Kubernetes
cluster into a **universal control plane**.
Crossplane organizes its documentation into the following sections:
Crossplane lets you manage anything, anywhere, all through standard Kubernetes
APIs. Crossplane can even let you
[order a pizza](https://blog.crossplane.io/providers-101-ordering-pizza-with-kubernetes-and-crossplane/)
directly from Kubernetes. If it has an API, Crossplane can connect to it.
* [What's Crossplane?]({{<ref "whats-crossplane">}}) introduces Crossplane
and explains why you should use it.
With Crossplane, platform teams can create new abstractions and custom
APIs with the full power of Kubernetes policies, namespaces, role based access
controls and more. Crossplane brings all your non-Kubernetes resources under
one roof.
* [What's New in v2?]({{<ref "whats-new">}}) highlights what's changed in
Crossplane v2.
Custom APIs, created by platform teams, allow security and compliance
enforcement across resources or clouds, without exposing any complexity to the
developers. A single API call can create multiple resources, in multiple clouds
and use Kubernetes as the control plane for everything.
* [Get Started]({{<ref "get-started">}}) explains how to install Crossplane and
create a control plane.
{{< hint "tip" >}}
**What's a control plane?**
<!-- vale Google.WordList = NO -->
Control planes create and manage the lifecycle of resources. Control planes
constantly _check_ that the intended resources exist, _report_ when the intended
state doesn't match reality and _act_ to make things right.
* [Composition]({{<ref "composition">}}) covers the key concepts of composition.
Crossplane extends the Kubernetes control plane to be a **universal control
plane** to check, report and act on any resource, anywhere.
<!-- vale Google.WordList = YES -->
{{< /hint >}}
* [Managed Resources]({{<ref "managed-resources">}}) covers the key concepts of
managed resources.
* [Packages]({{<ref "packages">}}) covers the key concepts of the Crossplane
package manager.
# Get started
* [Install Crossplane]({{<ref "software/install">}}) in your Kubernetes cluster
* Learn more about how Crossplane works in the
[Crossplane introduction]({{<ref "getting-started/introduction" >}})
* Join the [Crossplane Slack](https://slack.crossplane.io/) and start a
conversation with a community of over 7,000 operators.
* [Guides]({{<ref "guides">}}) guide you through common use cases, like
monitoring Crossplane or extending it by writing a composition function.
* [CLI Reference]({{<ref "cli">}}) documents the `crossplane` command-line
interface that you can use to configure a Crossplane control plane.
Crossplane is a [Cloud Native Compute Foundation](https://www.cncf.io/) project.
* [API Reference]({{<ref "api">}}) documents the APIs that you can use to
configure a Crossplane control plane.

View File

@ -8,6 +8,3 @@ cascade:
The Crossplane API describes the types and parameters for the core Crossplane
components.
For details on the components read the [Concepts]({{<ref "../concepts/">}})
section.

View File

@ -116,6 +116,10 @@ spec:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
- message: Plural name must be lowercase
rule: self.plural == self.plural.lowerAscii()
- message: Singular name must be lowercase
rule: '!has(self.singular) || self.singular == self.singular.lowerAscii()'
connectionSecretKeys:
description: |-
ConnectionSecretKeys is the list of keys that will be exposed to the end
@ -228,6 +232,10 @@ spec:
required:
- strategy
type: object
x-kubernetes-validations:
- message: Webhook configuration is required when conversion strategy
is Webhook
rule: self.strategy == 'Webhook' && has(self.webhook)
defaultCompositeDeletePolicy:
default: Background
description: |-
@ -355,6 +363,26 @@ spec:
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
- message: Plural name must be lowercase
rule: self.plural == self.plural.lowerAscii()
- message: Singular name must be lowercase
rule: '!has(self.singular) || self.singular == self.singular.lowerAscii()'
scope:
default: LegacyCluster
description: |-
Scope of the defined composite resource. Namespaced composite resources
are scoped to a single namespace. Cluster scoped composite resource exist
outside the scope of any namespace. Neither can be claimed. Legacy
cluster scoped composite resources are cluster scoped resources that can
be claimed.
enum:
- LegacyCluster
- Namespaced
- Cluster
type: string
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
versions:
description: |-
Versions is the list of all API versions of the defined composite
@ -474,6 +502,9 @@ spec:
- names
- versions
type: object
x-kubernetes-validations:
- message: Only LegacyCluster composite resources can offer claims
rule: self.scope == 'LegacyCluster' || !has(self.claimNames)
status:
description: CompositeResourceDefinitionStatus shows the observed state
of the definition.
@ -569,6 +600,581 @@ spec:
type: object
type: object
served: true
# v1 is actually the storage version, its set to false only here in the docs so v2alpha1 will be displayed
storage: false
subresources:
status: {}
- additionalPrinterColumns:
- jsonPath: .status.conditions[?(@.type=='Established')].status
name: ESTABLISHED
type: string
- jsonPath: .status.conditions[?(@.type=='Offered')].status
name: OFFERED
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v2alpha1
schema:
openAPIV3Schema:
description: |-
A CompositeResourceDefinition defines the schema for a new custom Kubernetes
API.
Read the Crossplane documentation for
[more information about CustomResourceDefinitions](https://docs.crossplane.io/latest/concepts/composite-resource-definitions).
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: CompositeResourceDefinitionSpec specifies the desired state
of the definition.
properties:
claimNames:
description: |-
ClaimNames specifies the names of an optional composite resource claim.
When claim names are specified Crossplane will create a namespaced
'composite resource claim' CRD that corresponds to the defined composite
resource. This composite resource claim acts as a namespaced proxy for
the composite resource; creating, updating, or deleting the claim will
create, update, or delete a corresponding composite resource. You may add
claim names to an existing CompositeResourceDefinition, but they cannot
be changed or removed once they have been set.
Deprecated: Claims aren't supported in apiextensions.crossplane.io/v2.
properties:
categories:
description: |-
categories is a list of grouped resources this custom resource belongs to (e.g. 'all').
This is published in API discovery documents, and used by clients to support invocations like
`kubectl get all`.
items:
type: string
type: array
x-kubernetes-list-type: atomic
kind:
description: |-
kind is the serialized kind of the resource. It is normally CamelCase and singular.
Custom resource instances will use this value as the `kind` attribute in API calls.
type: string
listKind:
description: listKind is the serialized kind of the list for this
resource. Defaults to "`kind`List".
type: string
plural:
description: |-
plural is the plural name of the resource to serve.
The custom resources are served under `/apis/<group>/<version>/.../<plural>`.
Must match the name of the CustomResourceDefinition (in the form `<names.plural>.<group>`).
Must be all lowercase.
type: string
shortNames:
description: |-
shortNames are short names for the resource, exposed in API discovery documents,
and used by clients to support invocations like `kubectl get <shortname>`.
It must be all lowercase.
items:
type: string
type: array
x-kubernetes-list-type: atomic
singular:
description: singular is the singular name of the resource. It
must be all lowercase. Defaults to lowercased `kind`.
type: string
required:
- kind
- plural
type: object
connectionSecretKeys:
description: |-
ConnectionSecretKeys is the list of keys that will be exposed to the end
user of the defined kind.
If the list is empty, all keys will be published.
items:
type: string
type: array
conversion:
description: Conversion defines all conversion settings for the defined
Composite resource.
properties:
strategy:
description: |-
strategy specifies how custom resources are converted between versions. Allowed values are:
- `"None"`: The converter only change the apiVersion and would not touch any other field in the custom resource.
- `"Webhook"`: API Server will call to an external webhook to do the conversion. Additional information
is needed for this option. This requires spec.preserveUnknownFields to be false, and spec.conversion.webhook to be set.
type: string
webhook:
description: webhook describes how to call the conversion webhook.
Required when `strategy` is set to `"Webhook"`.
properties:
clientConfig:
description: clientConfig is the instructions for how to call
the webhook if strategy is `Webhook`.
properties:
caBundle:
description: |-
caBundle is a PEM encoded CA bundle which will be used to validate the webhook's server certificate.
If unspecified, system trust roots on the apiserver are used.
format: byte
type: string
service:
description: |-
service is a reference to the service for this webhook. Either
service or url must be specified.
If the webhook is running within the cluster, then you should use `service`.
properties:
name:
description: |-
name is the name of the service.
Required
type: string
namespace:
description: |-
namespace is the namespace of the service.
Required
type: string
path:
description: path is an optional URL path at which
the webhook will be contacted.
type: string
port:
description: |-
port is an optional service port at which the webhook will be contacted.
`port` should be a valid port number (1-65535, inclusive).
Defaults to 443 for backward compatibility.
format: int32
type: integer
required:
- name
- namespace
type: object
url:
description: |-
url gives the location of the webhook, in standard URL form
(`scheme://host:port/path`). Exactly one of `url` or `service`
must be specified.
The `host` should not refer to a service running in the cluster; use
the `service` field instead. The host might be resolved via external
DNS in some apiservers (e.g., `kube-apiserver` cannot resolve
in-cluster DNS as that would be a layering violation). `host` may
also be an IP address.
Please note that using `localhost` or `127.0.0.1` as a `host` is
risky unless you take great care to run this webhook on all hosts
which run an apiserver which might need to make calls to this
webhook. Such installs are likely to be non-portable, i.e., not easy
to turn up in a new cluster.
The scheme must be "https"; the URL must begin with "https://".
A path is optional, and if present may be any string permissible in
a URL. You may use the path to pass an arbitrary string to the
webhook, for example, a cluster identifier.
Attempting to use a user or basic auth e.g. "user:password@" is not
allowed. Fragments ("#...") and query parameters ("?...") are not
allowed, either.
type: string
type: object
conversionReviewVersions:
description: |-
conversionReviewVersions is an ordered list of preferred `ConversionReview`
versions the Webhook expects. The API server will use the first version in
the list which it supports. If none of the versions specified in this list
are supported by API server, conversion will fail for the custom resource.
If a persisted Webhook configuration specifies allowed versions and does not
include any versions known to the API Server, calls to the webhook will fail.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- conversionReviewVersions
type: object
required:
- strategy
type: object
defaultCompositeDeletePolicy:
description: |-
DefaultCompositeDeletePolicy is the policy used when deleting the Composite
that is associated with the Claim if no policy has been specified.
Deprecated: Claims aren't supported in apiextensions.crossplane.io/v2.
enum:
- Background
- Foreground
type: string
defaultCompositionRef:
description: |-
DefaultCompositionRef refers to the Composition resource that will be used
in case no composition selector is given.
properties:
name:
description: Name of the Composition.
type: string
required:
- name
type: object
defaultCompositionUpdatePolicy:
default: Automatic
description: |-
DefaultCompositionUpdatePolicy is the policy used when updating composites after a new
Composition Revision has been created if no policy has been specified on the composite.
enum:
- Automatic
- Manual
type: string
enforcedCompositionRef:
description: |-
EnforcedCompositionRef refers to the Composition resource that will be used
by all composite instances whose schema is defined by this definition.
properties:
name:
description: Name of the Composition.
type: string
required:
- name
type: object
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
group:
description: |-
Group specifies the API group of the defined composite resource.
Composite resources are served under `/apis/<group>/...`. Must match the
name of the XRD (in the form `<names.plural>.<group>`).
type: string
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
metadata:
description: Metadata specifies the desired metadata for the defined
composite resource and claim CRD's.
properties:
annotations:
additionalProperties:
type: string
description: |-
Annotations is an unstructured key value map stored with a resource that may be
set by external tools to store and retrieve arbitrary metadata. They are not
queryable and should be preserved when modifying objects.
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations
type: object
labels:
additionalProperties:
type: string
description: |-
Map of string keys and values that can be used to organize and categorize
(scope and select) objects. May match selectors of replication controllers
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels
and services.
These labels are added to the composite resource and claim CRD's in addition
to any labels defined by `CompositionResourceDefinition` `metadata.labels`.
type: object
type: object
names:
description: |-
Names specifies the resource and kind names of the defined composite
resource.
properties:
categories:
description: |-
categories is a list of grouped resources this custom resource belongs to (e.g. 'all').
This is published in API discovery documents, and used by clients to support invocations like
`kubectl get all`.
items:
type: string
type: array
x-kubernetes-list-type: atomic
kind:
description: |-
kind is the serialized kind of the resource. It is normally CamelCase and singular.
Custom resource instances will use this value as the `kind` attribute in API calls.
type: string
listKind:
description: listKind is the serialized kind of the list for this
resource. Defaults to "`kind`List".
type: string
plural:
description: |-
plural is the plural name of the resource to serve.
The custom resources are served under `/apis/<group>/<version>/.../<plural>`.
Must match the name of the CustomResourceDefinition (in the form `<names.plural>.<group>`).
Must be all lowercase.
type: string
shortNames:
description: |-
shortNames are short names for the resource, exposed in API discovery documents,
and used by clients to support invocations like `kubectl get <shortname>`.
It must be all lowercase.
items:
type: string
type: array
x-kubernetes-list-type: atomic
singular:
description: singular is the singular name of the resource. It
must be all lowercase. Defaults to lowercased `kind`.
type: string
required:
- kind
- plural
type: object
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
- message: Plural name must be lowercase
rule: self.plural == self.plural.lowerAscii()
- message: Singular name must be lowercase
rule: '!has(self.singular) || self.singular == self.singular.lowerAscii()'
scope:
default: Namespaced
description: |-
Scope of the defined composite resource. Namespaced composite resources
are scoped to a single namespace. Cluster scoped composite resource exist
outside the scope of any namespace.
enum:
- Namespaced
- Cluster
type: string
x-kubernetes-validations:
- message: Value is immutable
rule: self == oldSelf
versions:
description: |-
Versions is the list of all API versions of the defined composite
resource. Version names are used to compute the order in which served
versions are listed in API discovery. If the version string is
"kube-like", it will sort above non "kube-like" version strings, which
are ordered lexicographically. "Kube-like" versions start with a "v",
then are followed by a number (the major version), then optionally the
string "alpha" or "beta" and another number (the minor version). These
are sorted first by GA > beta > alpha (where GA is a version with no
suffix such as beta or alpha), and then by comparing major version, then
minor version. An example sorted list of versions: v10, v2, v1, v11beta2,
v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
items:
description: CompositeResourceDefinitionVersion describes a version
of an XR.
properties:
additionalPrinterColumns:
description: |-
AdditionalPrinterColumns specifies additional columns returned in Table
output. If no columns are specified, a single column displaying the age
of the custom resource is used. See the following link for details:
https://kubernetes.io/docs/reference/using-api/api-concepts/#receiving-resources-as-tables
items:
description: CustomResourceColumnDefinition specifies a column
for server side printing.
properties:
description:
description: description is a human readable description
of this column.
type: string
format:
description: |-
format is an optional OpenAPI type definition for this column. The 'name' format is applied
to the primary identifier column to assist in clients identifying column is the resource name.
See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for details.
type: string
jsonPath:
description: |-
jsonPath is a simple JSON path (i.e. with array notation) which is evaluated against
each custom resource to produce the value for this column.
type: string
name:
description: name is a human readable name for the column.
type: string
priority:
description: |-
priority is an integer defining the relative importance of this column compared to others. Lower
numbers are considered higher priority. Columns that may be omitted in limited space scenarios
should be given a priority greater than 0.
format: int32
type: integer
type:
description: |-
type is an OpenAPI type definition for this column.
See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for details.
type: string
required:
- jsonPath
- name
- type
type: object
type: array
deprecated:
description: |-
The deprecated field specifies that this version is deprecated and should
not be used.
type: boolean
deprecationWarning:
description: |-
DeprecationWarning specifies the message that should be shown to the user
when using this version.
maxLength: 256
type: string
name:
description: |-
Name of this version, e.g. “v1”, “v2beta1”, etc. Composite resources are
served under this version at `/apis/<group>/<version>/...` if `served` is
true.
type: string
referenceable:
description: |-
Referenceable specifies that this version may be referenced by a
Composition in order to configure which resources an XR may be composed
of. Exactly one version must be marked as referenceable; all Compositions
must target only the referenceable version. The referenceable version
must be served. It's mapped to the CRD's `spec.versions[*].storage` field.
type: boolean
schema:
description: |-
Schema describes the schema used for validation, pruning, and defaulting
of this version of the defined composite resource. Fields required by all
composite resources will be injected into this schema automatically, and
will override equivalently named fields in this schema. Omitting this
schema results in a schema that contains only the fields required by all
composite resources.
properties:
openAPIV3Schema:
description: |-
OpenAPIV3Schema is the OpenAPI v3 schema to use for validation and
pruning.
type: object
x-kubernetes-preserve-unknown-fields: true
type: object
served:
description: Served specifies that this version should be served
via REST APIs.
type: boolean
required:
- name
- referenceable
- served
type: object
type: array
required:
- group
- names
- versions
type: object
x-kubernetes-validations:
- message: Claims aren't supported in apiextensions.crossplane.io/v2
rule: '!has(self.claimNames)'
status:
description: CompositeResourceDefinitionStatus shows the observed state
of the definition.
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: |-
LastTransitionTime is the last time this condition transitioned from one
status to another.
format: date-time
type: string
message:
description: |-
A Message containing details about this condition's last transition from
one status to another, if any.
type: string
observedGeneration:
description: |-
ObservedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
type: integer
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: |-
Type of this condition. At most one of each condition type may apply to
a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
controllers:
description: |-
Controllers represents the status of the controllers that power this
composite resource definition.
properties:
compositeResourceClaimType:
description: |-
The CompositeResourceClaimTypeRef is the type of composite resource claim
that Crossplane is currently reconciling for this definition. Its version
will eventually become consistent with the definition's referenceable
version. Note that clients may interact with any served type; this is
simply the type that Crossplane interacts with.
properties:
apiVersion:
description: APIVersion of the type.
type: string
kind:
description: Kind of the type.
type: string
required:
- apiVersion
- kind
type: object
compositeResourceType:
description: |-
The CompositeResourceTypeRef is the type of composite resource that
Crossplane is currently reconciling for this definition. Its version will
eventually become consistent with the definition's referenceable version.
Note that clients may interact with any served type; this is simply the
type that Crossplane interacts with.
properties:
apiVersion:
description: APIVersion of the type.
type: string
kind:
description: Kind of the type.
type: string
required:
- apiVersion
- kind
type: object
type: object
type: object
type: object
served: true
# v2alpha1 is not actually the storage version, but its set to true here in the docs so v2alpha1 will be displayed
storage: true
subresources:
status: {}

View File

@ -77,395 +77,16 @@ spec:
- message: Value is immutable
rule: self == oldSelf
mode:
default: Resources
default: Pipeline
description: |-
Mode controls what type or "mode" of Composition will be used.
"Pipeline" indicates that a Composition specifies a pipeline of
Composition Functions, each of which is responsible for producing
composed resources that Crossplane should create or update.
"Resources" indicates that a Composition uses what is commonly referred
to as "Patch & Transform" or P&T composition. This mode of Composition
uses an array of resources, each a template for a composed resource.
All Compositions should use Pipeline mode. Resources mode is deprecated.
Resources mode won't be removed in Crossplane 1.x, and will remain the
default to avoid breaking legacy Compositions. However, it's no longer
accepting new features, and only accepting security related bug fixes.
enum:
- Resources
- Pipeline
type: string
patchSets:
description: |-
PatchSets define a named set of patches that may be included by any
resource in this Composition. PatchSets cannot themselves refer to other
PatchSets.
PatchSets are only used by the "Resources" mode of Composition. They
are ignored by other modes.
Deprecated: Use Composition Functions instead.
items:
description: |-
A PatchSet is a set of patches that can be reused from all resources within
a Composition.
properties:
name:
description: Name of this PatchSet.
type: string
patches:
description: Patches will be applied as an overlay to the base
resource.
items:
description: |-
Patch objects are applied between composite and composed resources. Their
behaviour depends on the Type selected. The default Type,
FromCompositeFieldPath, copies a value from the composite resource to
the composed resource, applying any defined transformers.
properties:
combine:
description: |-
Combine is the patch configuration for a CombineFromComposite or
CombineToComposite patch.
properties:
strategy:
description: |-
Strategy defines the strategy to use to combine the input variable values.
Currently only string is supported.
enum:
- string
type: string
string:
description: |-
String declares that input variables should be combined into a single
string, using the relevant settings for formatting purposes.
properties:
fmt:
description: |-
Format the input using a Go format string. See
https://golang.org/pkg/fmt/ for details.
type: string
required:
- fmt
type: object
variables:
description: |-
Variables are the list of variables whose values will be retrieved and
combined.
items:
description: |-
A CombineVariable defines the source of a value that is combined with
others to form and patch an output value. Currently, this only supports
retrieving values from a field path.
properties:
fromFieldPath:
description: |-
FromFieldPath is the path of the field on the source whose value is
to be used as input.
type: string
required:
- fromFieldPath
type: object
minItems: 1
type: array
required:
- strategy
- variables
type: object
fromFieldPath:
description: |-
FromFieldPath is the path of the field on the resource whose value is
to be used as input. Required when type is FromCompositeFieldPath or
ToCompositeFieldPath.
type: string
patchSetName:
description: PatchSetName to include patches from. Required
when type is PatchSet.
type: string
policy:
description: Policy configures the specifics of patching
behaviour.
properties:
fromFieldPath:
description: |-
FromFieldPath specifies how to patch from a field path. The default is
'Optional', which means the patch will be a no-op if the specified
fromFieldPath does not exist. Use 'Required' if the patch should fail if
the specified path does not exist.
enum:
- Optional
- Required
type: string
mergeOptions:
description: MergeOptions Specifies merge options
on a field path.
properties:
appendSlice:
description: Specifies that already existing elements
in a merged slice should be preserved
type: boolean
keepMapValues:
description: Specifies that already existing values
in a merged map should be preserved
type: boolean
type: object
type: object
toFieldPath:
description: |-
ToFieldPath is the path of the field on the resource whose value will
be changed with the result of transforms. Leave empty if you'd like to
propagate to the same path as fromFieldPath.
type: string
transforms:
description: |-
Transforms are the list of functions that are used as a FIFO pipe for the
input to be transformed.
items:
description: |-
Transform is a unit of process whose input is transformed into an output with
the supplied configuration.
properties:
convert:
description: Convert is used to cast the input into
the given output type.
properties:
format:
description: |-
The expected input format.
* `quantity` - parses the input as a K8s [`resource.Quantity`](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity).
Only used during `string -> float64` conversions.
* `json` - parses the input as a JSON string.
Only used during `string -> object` or `string -> list` conversions.
If this property is null, the default conversion is applied.
enum:
- none
- quantity
- json
type: string
toType:
description: ToType is the type of the output
of this transform.
enum:
- string
- int
- int64
- bool
- float64
- object
- array
type: string
required:
- toType
type: object
map:
additionalProperties:
x-kubernetes-preserve-unknown-fields: true
description: Map uses the input as a key in the
given map and returns the value.
type: object
match:
description: Match is a more complex version of
Map that matches a list of patterns.
properties:
fallbackTo:
default: Value
description: Determines to what value the transform
should fallback if no pattern matches.
enum:
- Value
- Input
type: string
fallbackValue:
description: |-
The fallback value that should be returned by the transform if now pattern
matches.
x-kubernetes-preserve-unknown-fields: true
patterns:
description: |-
The patterns that should be tested against the input string.
Patterns are tested in order. The value of the first match is used as
result of this transform.
items:
description: |-
MatchTransformPattern is a transform that returns the value that matches a
pattern.
properties:
literal:
description: |-
Literal exactly matches the input string (case sensitive).
Is required if `type` is `literal`.
type: string
regexp:
description: |-
Regexp to match against the input string.
Is required if `type` is `regexp`.
type: string
result:
description: The value that is used as
result of the transform if the pattern
matches.
x-kubernetes-preserve-unknown-fields: true
type:
default: literal
description: |-
Type specifies how the pattern matches the input.
* `literal` - the pattern value has to exactly match (case sensitive) the
input string. This is the default.
* `regexp` - the pattern treated as a regular expression against
which the input string is tested. Crossplane will throw an error if the
key is not a valid regexp.
enum:
- literal
- regexp
type: string
required:
- result
- type
type: object
type: array
type: object
math:
description: |-
Math is used to transform the input via mathematical operations such as
multiplication.
properties:
clampMax:
description: ClampMax makes sure that the value
is not bigger than the given value.
format: int64
type: integer
clampMin:
description: ClampMin makes sure that the value
is not smaller than the given value.
format: int64
type: integer
multiply:
description: Multiply the value.
format: int64
type: integer
type:
default: Multiply
description: Type of the math transform to be
run.
enum:
- Multiply
- ClampMin
- ClampMax
type: string
type: object
string:
description: |-
String is used to transform the input into a string or a different kind
of string. Note that the input does not necessarily need to be a string.
properties:
convert:
description: |-
Optional conversion method to be specified.
`ToUpper` and `ToLower` change the letter case of the input string.
`ToBase64` and `FromBase64` perform a base64 conversion based on the input string.
`ToJson` converts any input value into its raw JSON representation.
`ToSha1`, `ToSha256` and `ToSha512` generate a hash value based on the input
converted to JSON.
`ToAdler32` generate a addler32 hash based on the input string.
enum:
- ToUpper
- ToLower
- ToBase64
- FromBase64
- ToJson
- ToSha1
- ToSha256
- ToSha512
- ToAdler32
type: string
fmt:
description: |-
Format the input using a Go format string. See
https://golang.org/pkg/fmt/ for details.
type: string
join:
description: Join defines parameters to join
a slice of values to a string.
properties:
separator:
description: |-
Separator defines the character that should separate the values from each
other in the joined string.
type: string
required:
- separator
type: object
regexp:
description: Extract a match from the input
using a regular expression.
properties:
group:
description: Group number to match. 0 (the
default) matches the entire expression.
type: integer
match:
description: |-
Match string. May optionally include submatches, aka capture groups.
See https://pkg.go.dev/regexp/ for details.
type: string
required:
- match
type: object
trim:
description: Trim the prefix or suffix from
the input
type: string
type:
default: Format
description: Type of the string transform to
be run.
enum:
- Format
- Convert
- TrimPrefix
- TrimSuffix
- Regexp
- Join
type: string
type: object
type:
description: Type of the transform to be run.
enum:
- map
- match
- math
- string
- convert
type: string
required:
- type
type: object
type: array
type:
default: FromCompositeFieldPath
description: |-
Type sets the patching behaviour to be used. Each patch type may require
its own fields to be set on the Patch object.
enum:
- FromCompositeFieldPath
- PatchSet
- ToCompositeFieldPath
- CombineFromComposite
- CombineToComposite
type: string
type: object
type: array
required:
- name
- patches
type: object
type: array
pipeline:
description: |-
Pipeline is a list of composition function steps that will be used when a
@ -513,6 +134,9 @@ spec:
- name
- source
type: object
x-kubernetes-validations:
- message: the Secret source requires a secretRef
rule: self.source == 'Secret' && has(self.secretRef)
type: array
x-kubernetes-list-map-keys:
- name
@ -543,532 +167,24 @@ spec:
- functionRef
- step
type: object
maxItems: 99
minItems: 1
type: array
x-kubernetes-list-map-keys:
- step
x-kubernetes-list-type: map
publishConnectionDetailsWithStoreConfigRef:
default:
name: default
description: |-
PublishConnectionDetailsWithStoreConfig specifies the secret store config
with which the connection details of composite resources dynamically
provisioned using this composition will be published.
THIS IS AN ALPHA FIELD. Do not use it in production. It is not honored
unless the relevant Crossplane feature flag is enabled, and may be
changed or removed without notice.
properties:
name:
description: Name of the referenced StoreConfig.
type: string
required:
- name
type: object
resources:
description: |-
Resources is a list of resource templates that will be used when a
composite resource referring to this composition is created.
Resources are only used by the "Resources" mode of Composition. They are
ignored by other modes.
Deprecated: Use Composition Functions instead.
items:
description: |-
ComposedTemplate is used to provide information about how the composed resource
should be processed.
properties:
base:
description: Base is the target resource that the patches will
be applied on.
type: object
x-kubernetes-embedded-resource: true
x-kubernetes-preserve-unknown-fields: true
connectionDetails:
description: |-
ConnectionDetails lists the propagation secret keys from this target
resource to the composition instance connection secret.
items:
description: |-
ConnectionDetail includes the information about the propagation of the connection
information from one secret to another.
properties:
fromConnectionSecretKey:
description: |-
FromConnectionSecretKey is the key that will be used to fetch the value
from the composed resource's connection secret.
type: string
fromFieldPath:
description: |-
FromFieldPath is the path of the field on the composed resource whose
value to be used as input. Name must be specified if the type is
FromFieldPath.
type: string
name:
description: |-
Name of the connection secret key that will be propagated to the
connection secret of the composition instance. Leave empty if you'd like
to use the same key name.
type: string
type:
description: |-
Type sets the connection detail fetching behaviour to be used. Each
connection detail type may require its own fields to be set on the
ConnectionDetail object. If the type is omitted Crossplane will attempt
to infer it based on which other fields were specified. If multiple
fields are specified the order of precedence is:
1. FromValue
2. FromConnectionSecretKey
3. FromFieldPath
enum:
- FromConnectionSecretKey
- FromFieldPath
- FromValue
type: string
value:
description: |-
Value that will be propagated to the connection secret of the composite
resource. May be set to inject a fixed, non-sensitive connection secret
value, for example a well-known port.
type: string
type: object
type: array
name:
description: |-
A Name uniquely identifies this entry within its Composition's resources
array. Names are optional but *strongly* recommended. When all entries in
the resources array are named entries may added, deleted, and reordered
as long as their names do not change. When entries are not named the
length and order of the resources array should be treated as immutable.
Either all or no entries must be named.
type: string
patches:
description: Patches will be applied as overlay to the base
resource.
items:
description: |-
Patch objects are applied between composite and composed resources. Their
behaviour depends on the Type selected. The default Type,
FromCompositeFieldPath, copies a value from the composite resource to
the composed resource, applying any defined transformers.
properties:
combine:
description: |-
Combine is the patch configuration for a CombineFromComposite or
CombineToComposite patch.
properties:
strategy:
description: |-
Strategy defines the strategy to use to combine the input variable values.
Currently only string is supported.
enum:
- string
type: string
string:
description: |-
String declares that input variables should be combined into a single
string, using the relevant settings for formatting purposes.
properties:
fmt:
description: |-
Format the input using a Go format string. See
https://golang.org/pkg/fmt/ for details.
type: string
required:
- fmt
type: object
variables:
description: |-
Variables are the list of variables whose values will be retrieved and
combined.
items:
description: |-
A CombineVariable defines the source of a value that is combined with
others to form and patch an output value. Currently, this only supports
retrieving values from a field path.
properties:
fromFieldPath:
description: |-
FromFieldPath is the path of the field on the source whose value is
to be used as input.
type: string
required:
- fromFieldPath
type: object
minItems: 1
type: array
required:
- strategy
- variables
type: object
fromFieldPath:
description: |-
FromFieldPath is the path of the field on the resource whose value is
to be used as input. Required when type is FromCompositeFieldPath or
ToCompositeFieldPath.
type: string
patchSetName:
description: PatchSetName to include patches from. Required
when type is PatchSet.
type: string
policy:
description: Policy configures the specifics of patching
behaviour.
properties:
fromFieldPath:
description: |-
FromFieldPath specifies how to patch from a field path. The default is
'Optional', which means the patch will be a no-op if the specified
fromFieldPath does not exist. Use 'Required' if the patch should fail if
the specified path does not exist.
enum:
- Optional
- Required
type: string
mergeOptions:
description: MergeOptions Specifies merge options
on a field path.
properties:
appendSlice:
description: Specifies that already existing elements
in a merged slice should be preserved
type: boolean
keepMapValues:
description: Specifies that already existing values
in a merged map should be preserved
type: boolean
type: object
type: object
toFieldPath:
description: |-
ToFieldPath is the path of the field on the resource whose value will
be changed with the result of transforms. Leave empty if you'd like to
propagate to the same path as fromFieldPath.
type: string
transforms:
description: |-
Transforms are the list of functions that are used as a FIFO pipe for the
input to be transformed.
items:
description: |-
Transform is a unit of process whose input is transformed into an output with
the supplied configuration.
properties:
convert:
description: Convert is used to cast the input into
the given output type.
properties:
format:
description: |-
The expected input format.
* `quantity` - parses the input as a K8s [`resource.Quantity`](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity).
Only used during `string -> float64` conversions.
* `json` - parses the input as a JSON string.
Only used during `string -> object` or `string -> list` conversions.
If this property is null, the default conversion is applied.
enum:
- none
- quantity
- json
type: string
toType:
description: ToType is the type of the output
of this transform.
enum:
- string
- int
- int64
- bool
- float64
- object
- array
type: string
required:
- toType
type: object
map:
additionalProperties:
x-kubernetes-preserve-unknown-fields: true
description: Map uses the input as a key in the
given map and returns the value.
type: object
match:
description: Match is a more complex version of
Map that matches a list of patterns.
properties:
fallbackTo:
default: Value
description: Determines to what value the transform
should fallback if no pattern matches.
enum:
- Value
- Input
type: string
fallbackValue:
description: |-
The fallback value that should be returned by the transform if now pattern
matches.
x-kubernetes-preserve-unknown-fields: true
patterns:
description: |-
The patterns that should be tested against the input string.
Patterns are tested in order. The value of the first match is used as
result of this transform.
items:
description: |-
MatchTransformPattern is a transform that returns the value that matches a
pattern.
properties:
literal:
description: |-
Literal exactly matches the input string (case sensitive).
Is required if `type` is `literal`.
type: string
regexp:
description: |-
Regexp to match against the input string.
Is required if `type` is `regexp`.
type: string
result:
description: The value that is used as
result of the transform if the pattern
matches.
x-kubernetes-preserve-unknown-fields: true
type:
default: literal
description: |-
Type specifies how the pattern matches the input.
* `literal` - the pattern value has to exactly match (case sensitive) the
input string. This is the default.
* `regexp` - the pattern treated as a regular expression against
which the input string is tested. Crossplane will throw an error if the
key is not a valid regexp.
enum:
- literal
- regexp
type: string
required:
- result
- type
type: object
type: array
type: object
math:
description: |-
Math is used to transform the input via mathematical operations such as
multiplication.
properties:
clampMax:
description: ClampMax makes sure that the value
is not bigger than the given value.
format: int64
type: integer
clampMin:
description: ClampMin makes sure that the value
is not smaller than the given value.
format: int64
type: integer
multiply:
description: Multiply the value.
format: int64
type: integer
type:
default: Multiply
description: Type of the math transform to be
run.
enum:
- Multiply
- ClampMin
- ClampMax
type: string
type: object
string:
description: |-
String is used to transform the input into a string or a different kind
of string. Note that the input does not necessarily need to be a string.
properties:
convert:
description: |-
Optional conversion method to be specified.
`ToUpper` and `ToLower` change the letter case of the input string.
`ToBase64` and `FromBase64` perform a base64 conversion based on the input string.
`ToJson` converts any input value into its raw JSON representation.
`ToSha1`, `ToSha256` and `ToSha512` generate a hash value based on the input
converted to JSON.
`ToAdler32` generate a addler32 hash based on the input string.
enum:
- ToUpper
- ToLower
- ToBase64
- FromBase64
- ToJson
- ToSha1
- ToSha256
- ToSha512
- ToAdler32
type: string
fmt:
description: |-
Format the input using a Go format string. See
https://golang.org/pkg/fmt/ for details.
type: string
join:
description: Join defines parameters to join
a slice of values to a string.
properties:
separator:
description: |-
Separator defines the character that should separate the values from each
other in the joined string.
type: string
required:
- separator
type: object
regexp:
description: Extract a match from the input
using a regular expression.
properties:
group:
description: Group number to match. 0 (the
default) matches the entire expression.
type: integer
match:
description: |-
Match string. May optionally include submatches, aka capture groups.
See https://pkg.go.dev/regexp/ for details.
type: string
required:
- match
type: object
trim:
description: Trim the prefix or suffix from
the input
type: string
type:
default: Format
description: Type of the string transform to
be run.
enum:
- Format
- Convert
- TrimPrefix
- TrimSuffix
- Regexp
- Join
type: string
type: object
type:
description: Type of the transform to be run.
enum:
- map
- match
- math
- string
- convert
type: string
required:
- type
type: object
type: array
type:
default: FromCompositeFieldPath
description: |-
Type sets the patching behaviour to be used. Each patch type may require
its own fields to be set on the Patch object.
enum:
- FromCompositeFieldPath
- PatchSet
- ToCompositeFieldPath
- CombineFromComposite
- CombineToComposite
type: string
type: object
type: array
readinessChecks:
default:
- matchCondition:
status: "True"
type: Ready
type: MatchCondition
description: |-
ReadinessChecks allows users to define custom readiness checks. All checks
have to return true in order for resource to be considered ready. The
default readiness check is to have the "Ready" condition to be "True".
items:
description: |-
ReadinessCheck is used to indicate how to tell whether a resource is ready
for consumption.
properties:
fieldPath:
description: FieldPath shows the path of the field whose
value will be used.
type: string
matchCondition:
description: MatchCondition specifies the condition you'd
like to match if you're using "MatchCondition" type.
properties:
status:
default: "True"
description: Status is the status of the condition
you'd like to match.
type: string
type:
default: Ready
description: Type indicates the type of condition
you'd like to use.
type: string
required:
- status
- type
type: object
matchInteger:
description: MatchInt is the value you'd like to match
if you're using "MatchInt" type.
format: int64
type: integer
matchString:
description: MatchString is the value you'd like to match
if you're using "MatchString" type.
type: string
type:
description: Type indicates the type of probe you'd like
to use.
enum:
- MatchString
- MatchInteger
- NonEmpty
- MatchCondition
- MatchTrue
- MatchFalse
- None
type: string
required:
- type
type: object
type: array
required:
- base
type: object
type: array
writeConnectionSecretsToNamespace:
description: |-
WriteConnectionSecretsToNamespace specifies the namespace in which the
connection secrets of composite resource dynamically provisioned using
this composition will be created.
This field is planned to be replaced in a future release in favor of
PublishConnectionDetailsWithStoreConfigRef. Currently, both could be
set independently and connection details would be published to both
without affecting each other as long as related fields at MR level
specified.
type: string
required:
- compositeTypeRef
type: object
x-kubernetes-validations:
- message: an array of pipeline steps is required in Pipeline mode
rule: self.mode == 'Pipeline' && has(self.pipeline)
type: object
served: true
storage: true

View File

@ -58,7 +58,7 @@ spec:
type: object
type: object
served: true
storage: false
storage: true
subresources: {}
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
@ -100,5 +100,5 @@ spec:
type: object
type: object
served: true
storage: true
storage: false
subresources: {}

View File

@ -26,6 +26,9 @@ spec:
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
deprecated: true
deprecationWarning: apiextensions.crossplane.io Usage is deprecated; migrate to
protection.crossplane.io Usage or ClusterUsage
name: v1alpha1
schema:
openAPIV3Schema:
@ -36,7 +39,9 @@ spec:
resources with dependent resources.
Read the Crossplane documentation for
[more information about Compositions](https://docs.crossplane.io/latest/concepts/usages).
[more information about Usages](https://docs.crossplane.io/latest/concepts/usages).
Deprecated: Use protection.crossplane.io Usage or ClusterUsage.
properties:
apiVersion:
description: |-
@ -223,6 +228,9 @@ spec:
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
deprecated: true
deprecationWarning: apiextensions.crossplane.io Usage is deprecated; migrate to
protection.crossplane.io Usage or ClusterUsage
name: v1beta1
schema:
openAPIV3Schema:
@ -233,7 +241,9 @@ spec:
resources with dependent resources.
Read the Crossplane documentation for
[more information about Compositions](https://docs.crossplane.io/latest/concepts/usages).
[more information about Usages](https://docs.crossplane.io/latest/concepts/usages).
Deprecated: Use protection.crossplane.io Usage or ClusterUsage.
properties:
apiVersion:
description: |-

View File

@ -146,27 +146,6 @@ spec:
description: PackageRevisionStatus represents the observed state of a
PackageRevision.
properties:
appliedImageConfigRefs:
description: |-
AppliedImageConfigRefs records any image configs that were applied in
reconciling this revision, and what they were used for.
items:
description: |-
ImageConfigRef is a reference to an image config that indicates how the
referenced image config was used by the package manager.
properties:
name:
description: Name is the name of the image config.
type: string
reason:
description: Reason indicates what the image config was used
for.
type: string
required:
- name
- reason
type: object
type: array
conditions:
description: Conditions of the resource.
items:
@ -302,12 +281,6 @@ spec:
- verbs
type: object
type: array
resolvedImage:
description: |-
ResolvedPackage is the name of the package that was installed. It may be
different from spec.image if the package path was rewritten using an
image config.
type: string
type: object
type: object
served: true

View File

@ -138,27 +138,6 @@ spec:
status:
description: ConfigurationStatus represents the observed state of a Configuration.
properties:
appliedImageConfigRefs:
description: |-
AppliedImageConfigRefs records any image configs that were applied in
reconciling this package, and what they were used for.
items:
description: |-
ImageConfigRef is a reference to an image config that indicates how the
referenced image config was used by the package manager.
properties:
name:
description: Name is the name of the image config.
type: string
reason:
description: Reason indicates what the image config was used
for.
type: string
required:
- name
- reason
type: object
type: array
conditions:
description: Conditions of the resource.
items:
@ -220,12 +199,6 @@ spec:
reflect the most up to date revision, whether it has been activated or
not.
type: string
resolvedPackage:
description: |-
ResolvedPackage is the name of the package that was used for version
resolution. It may be different from spec.package if the package path was
rewritten using an image config.
type: string
type: object
type: object
served: true

View File

@ -189,27 +189,6 @@ spec:
description: FunctionRevisionStatus represents the observed state of a
FunctionRevision.
properties:
appliedImageConfigRefs:
description: |-
AppliedImageConfigRefs records any image configs that were applied in
reconciling this revision, and what they were used for.
items:
description: |-
ImageConfigRef is a reference to an image config that indicates how the
referenced image config was used by the package manager.
properties:
name:
description: Name is the name of the image config.
type: string
reason:
description: Reason indicates what the image config was used
for.
type: string
required:
- name
- reason
type: object
type: array
conditions:
description: Conditions of the resource.
items:
@ -350,12 +329,6 @@ spec:
- verbs
type: object
type: array
resolvedImage:
description: |-
ResolvedPackage is the name of the package that was installed. It may be
different from spec.image if the package path was rewritten using an
image config.
type: string
type: object
type: object
served: true
@ -534,27 +507,6 @@ spec:
description: FunctionRevisionStatus represents the observed state of a
FunctionRevision.
properties:
appliedImageConfigRefs:
description: |-
AppliedImageConfigRefs records any image configs that were applied in
reconciling this revision, and what they were used for.
items:
description: |-
ImageConfigRef is a reference to an image config that indicates how the
referenced image config was used by the package manager.
properties:
name:
description: Name is the name of the image config.
type: string
reason:
description: Reason indicates what the image config was used
for.
type: string
required:
- name
- reason
type: object
type: array
conditions:
description: Conditions of the resource.
items:
@ -695,12 +647,6 @@ spec:
- verbs
type: object
type: array
resolvedImage:
description: |-
ResolvedPackage is the name of the package that was installed. It may be
different from spec.image if the package path was rewritten using an
image config.
type: string
type: object
type: object
served: true

View File

@ -168,27 +168,6 @@ spec:
status:
description: FunctionStatus represents the observed state of a Function.
properties:
appliedImageConfigRefs:
description: |-
AppliedImageConfigRefs records any image configs that were applied in
reconciling this package, and what they were used for.
items:
description: |-
ImageConfigRef is a reference to an image config that indicates how the
referenced image config was used by the package manager.
properties:
name:
description: Name is the name of the image config.
type: string
reason:
description: Reason indicates what the image config was used
for.
type: string
required:
- name
- reason
type: object
type: array
conditions:
description: Conditions of the resource.
items:
@ -250,12 +229,6 @@ spec:
reflect the most up to date revision, whether it has been activated or
not.
type: string
resolvedPackage:
description: |-
ResolvedPackage is the name of the package that was used for version
resolution. It may be different from spec.package if the package path was
rewritten using an image config.
type: string
type: object
type: object
served: true
@ -413,27 +386,6 @@ spec:
status:
description: FunctionStatus represents the observed state of a Function.
properties:
appliedImageConfigRefs:
description: |-
AppliedImageConfigRefs records any image configs that were applied in
reconciling this package, and what they were used for.
items:
description: |-
ImageConfigRef is a reference to an image config that indicates how the
referenced image config was used by the package manager.
properties:
name:
description: Name is the name of the image config.
type: string
reason:
description: Reason indicates what the image config was used
for.
type: string
required:
- name
- reason
type: object
type: array
conditions:
description: Conditions of the resource.
items:
@ -495,12 +447,6 @@ spec:
reflect the most up to date revision, whether it has been activated or
not.
type: string
resolvedPackage:
description: |-
ResolvedPackage is the name of the package that was used for version
resolution. It may be different from spec.package if the package path was
rewritten using an image config.
type: string
type: object
type: object
served: true

View File

@ -47,19 +47,13 @@ spec:
description: ImageConfigSpec contains the configuration for matching images.
properties:
matchImages:
description: |-
MatchImages is a list of image matching rules. This ImageConfig will
match an image if any one of these rules is satisfied. In the case where
multiple ImageConfigs match an image for a given purpose the one with the
most specific match will be used. If multiple rules of equal specificity
match an arbitrary one will be selected.
description: MatchImages is a list of image matching rules that should
be satisfied.
items:
description: ImageMatch defines a rule for matching image.
properties:
prefix:
description: |-
Prefix is the prefix that should be matched. When multiple prefix rules
match an image path, the longest one takes precedence.
description: Prefix is the prefix that should be matched.
type: string
type:
default: Prefix
@ -101,19 +95,6 @@ spec:
- pullSecretRef
type: object
type: object
rewriteImage:
description: RewriteImage defines how a matched image's path should
be rewritten.
properties:
prefix:
description: |-
Prefix is the prefix that will replace the portion of the image's path
matched by the prefix in the ImageMatch. If multiple prefixes matched,
the longest one will be replaced.
type: string
required:
- prefix
type: object
verification:
description: Verification contains the configuration for verifying
the image.

View File

@ -189,27 +189,6 @@ spec:
description: PackageRevisionStatus represents the observed state of a
PackageRevision.
properties:
appliedImageConfigRefs:
description: |-
AppliedImageConfigRefs records any image configs that were applied in
reconciling this revision, and what they were used for.
items:
description: |-
ImageConfigRef is a reference to an image config that indicates how the
referenced image config was used by the package manager.
properties:
name:
description: Name is the name of the image config.
type: string
reason:
description: Reason indicates what the image config was used
for.
type: string
required:
- name
- reason
type: object
type: array
conditions:
description: Conditions of the resource.
items:
@ -345,12 +324,6 @@ spec:
- verbs
type: object
type: array
resolvedImage:
description: |-
ResolvedPackage is the name of the package that was installed. It may be
different from spec.image if the package path was rewritten using an
image config.
type: string
type: object
type: object
served: true

View File

@ -170,27 +170,6 @@ spec:
status:
description: ProviderStatus represents the observed state of a Provider.
properties:
appliedImageConfigRefs:
description: |-
AppliedImageConfigRefs records any image configs that were applied in
reconciling this package, and what they were used for.
items:
description: |-
ImageConfigRef is a reference to an image config that indicates how the
referenced image config was used by the package manager.
properties:
name:
description: Name is the name of the image config.
type: string
reason:
description: Reason indicates what the image config was used
for.
type: string
required:
- name
- reason
type: object
type: array
conditions:
description: Conditions of the resource.
items:
@ -252,12 +231,6 @@ spec:
reflect the most up to date revision, whether it has been activated or
not.
type: string
resolvedPackage:
description: |-
ResolvedPackage is the name of the package that was used for version
resolution. It may be different from spec.package if the package path was
rewritten using an image config.
type: string
type: object
type: object
served: true

View File

@ -0,0 +1,216 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.5
name: clusterusages.protection.crossplane.io
spec:
group: protection.crossplane.io
names:
categories:
- crossplane
kind: ClusterUsage
listKind: ClusterUsageList
plural: clusterusages
singular: clusterusage
scope: Cluster
versions:
- additionalPrinterColumns:
- jsonPath: .metadata.annotations.crossplane\.io/usage-details
name: DETAILS
type: string
- jsonPath: .status.conditions[?(@.type=='Ready')].status
name: READY
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: |-
A ClusterUsage defines a deletion blocking relationship between two
resources.
Usages prevent accidental deletion of a single resource or deletion of
resources with dependent resources.
Read the Crossplane documentation for
[more information about usages](https://docs.crossplane.io/latest/concepts/usages).
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: ClusterUsageSpec defines the desired state of a ClusterUsage.
properties:
by:
description: By is the resource that is "using the other resource".
properties:
apiVersion:
description: API version of the referent.
type: string
kind:
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
resourceRef:
description: Reference to the resource.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
resourceSelector:
description: |-
Selector to the resource.
This field will be ignored if ResourceRef is set.
properties:
matchControllerRef:
description: |-
MatchControllerRef ensures an object with the same controller reference
as the selecting object is selected.
type: boolean
matchLabels:
additionalProperties:
type: string
description: MatchLabels ensures an object with matching labels
is selected.
type: object
type: object
type: object
x-kubernetes-validations:
- message: either a resource reference or a resource selector should
be set.
rule: has(self.resourceRef) || has(self.resourceSelector)
of:
description: Of is the resource that is "being used".
properties:
apiVersion:
description: API version of the referent.
type: string
kind:
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
resourceRef:
description: Reference to the resource.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
resourceSelector:
description: |-
Selector to the resource.
This field will be ignored if ResourceRef is set.
properties:
matchControllerRef:
description: |-
MatchControllerRef ensures an object with the same controller reference
as the selecting object is selected.
type: boolean
matchLabels:
additionalProperties:
type: string
description: MatchLabels ensures an object with matching labels
is selected.
type: object
type: object
type: object
x-kubernetes-validations:
- message: either a resource reference or a resource selector should
be set.
rule: has(self.resourceRef) || has(self.resourceSelector)
reason:
description: Reason is the reason for blocking deletion of the resource.
type: string
replayDeletion:
description: ReplayDeletion will trigger a deletion on the used resource
during the deletion of the usage itself, if it was attempted to
be deleted at least once.
type: boolean
required:
- of
type: object
x-kubernetes-validations:
- message: either "spec.by" or "spec.reason" must be specified.
rule: has(self.by) || has(self.reason)
status:
description: UsageStatus defines the observed state of Usage.
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: |-
LastTransitionTime is the last time this condition transitioned from one
status to another.
format: date-time
type: string
message:
description: |-
A Message containing details about this condition's last transition from
one status to another, if any.
type: string
observedGeneration:
description: |-
ObservedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
type: integer
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: |-
Type of this condition. At most one of each condition type may apply to
a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -0,0 +1,223 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.5
name: usages.protection.crossplane.io
spec:
group: protection.crossplane.io
names:
categories:
- crossplane
kind: Usage
listKind: UsageList
plural: usages
singular: usage
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .metadata.annotations.crossplane\.io/usage-details
name: DETAILS
type: string
- jsonPath: .status.conditions[?(@.type=='Ready')].status
name: READY
type: string
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
name: v1beta1
schema:
openAPIV3Schema:
description: |-
A Usage defines a deletion blocking relationship between two resources.
Usages prevent accidental deletion of a single resource or deletion of
resources with dependent resources.
Read the Crossplane documentation for
[more information about Compositions](https://docs.crossplane.io/latest/concepts/usages).
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: UsageSpec defines the desired state of Usage.
properties:
by:
description: By is the resource that is "using the other resource".
properties:
apiVersion:
description: API version of the referent.
type: string
kind:
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
resourceRef:
description: Reference to the resource.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
resourceSelector:
description: |-
Selector to the resource.
This field will be ignored if ResourceRef is set.
properties:
matchControllerRef:
description: |-
MatchControllerRef ensures an object with the same controller reference
as the selecting object is selected.
type: boolean
matchLabels:
additionalProperties:
type: string
description: MatchLabels ensures an object with matching labels
is selected.
type: object
type: object
type: object
x-kubernetes-validations:
- message: either a resource reference or a resource selector should
be set.
rule: has(self.resourceRef) || has(self.resourceSelector)
of:
description: Of is the resource that is "being used".
properties:
apiVersion:
description: API version of the referent.
type: string
kind:
description: |-
Kind of the referent.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
resourceRef:
description: Reference to the resource.
properties:
name:
description: Name of the referent.
type: string
namespace:
description: Namespace of the referent.
type: string
required:
- name
type: object
resourceSelector:
description: |-
Selector to the resource.
This field will be ignored if ResourceRef is set.
properties:
matchControllerRef:
description: |-
MatchControllerRef ensures an object with the same controller reference
as the selecting object is selected.
type: boolean
matchLabels:
additionalProperties:
type: string
description: MatchLabels ensures an object with matching labels
is selected.
type: object
namespace:
description: |-
Namespace ensures an object in the supplied namespace is selected.
Omit namespace to only match resources in the Usage's namespace.
type: string
type: object
type: object
x-kubernetes-validations:
- message: either a resource reference or a resource selector should
be set.
rule: has(self.resourceRef) || has(self.resourceSelector)
reason:
description: Reason is the reason for blocking deletion of the resource.
type: string
replayDeletion:
description: ReplayDeletion will trigger a deletion on the used resource
during the deletion of the usage itself, if it was attempted to
be deleted at least once.
type: boolean
required:
- of
type: object
x-kubernetes-validations:
- message: either "spec.by" or "spec.reason" must be specified.
rule: has(self.by) || has(self.reason)
status:
description: UsageStatus defines the observed state of Usage.
properties:
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: |-
LastTransitionTime is the last time this condition transitioned from one
status to another.
format: date-time
type: string
message:
description: |-
A Message containing details about this condition's last transition from
one status to another, if any.
type: string
observedGeneration:
description: |-
ObservedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
type: integer
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True,
False, or Unknown?
type: string
type:
description: |-
Type of this condition. At most one of each condition type may apply to
a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}

View File

@ -1,172 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.5
name: storeconfigs.secrets.crossplane.io
spec:
group: secrets.crossplane.io
names:
categories:
- crossplane
- store
kind: StoreConfig
listKind: StoreConfigList
plural: storeconfigs
singular: storeconfig
scope: Cluster
versions:
- additionalPrinterColumns:
- jsonPath: .metadata.creationTimestamp
name: AGE
type: date
- jsonPath: .spec.type
name: TYPE
type: string
- jsonPath: .spec.defaultScope
name: DEFAULT-SCOPE
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: |-
A StoreConfig configures how Crossplane controllers should store connection
details in an external secret store.
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: A StoreConfigSpec defines the desired state of a StoreConfig.
properties:
defaultScope:
description: |-
DefaultScope used for scoping secrets for "cluster-scoped" resources.
If store type is "Kubernetes", this would mean the default namespace to
store connection secrets for cluster scoped resources.
In case of "Vault", this would be used as the default parent path.
Typically, should be set as Crossplane installation namespace.
type: string
kubernetes:
description: |-
Kubernetes configures a Kubernetes secret store.
If the "type" is "Kubernetes" but no config provided, in cluster config
will be used.
properties:
auth:
description: Credentials used to connect to the Kubernetes API.
properties:
env:
description: |-
Env is a reference to an environment variable that contains credentials
that must be used to connect to the provider.
properties:
name:
description: Name is the name of an environment variable.
type: string
required:
- name
type: object
fs:
description: |-
Fs is a reference to a filesystem location that contains credentials that
must be used to connect to the provider.
properties:
path:
description: Path is a filesystem path.
type: string
required:
- path
type: object
secretRef:
description: |-
A SecretRef is a reference to a secret key that contains the credentials
that must be used to connect to the provider.
properties:
key:
description: The key to select.
type: string
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- key
- name
- namespace
type: object
source:
description: Source of the credentials.
enum:
- None
- Secret
- Environment
- Filesystem
type: string
required:
- source
type: object
required:
- auth
type: object
plugin:
description: Plugin configures External secret store as a plugin.
properties:
configRef:
description: ConfigRef contains store config reference info.
properties:
apiVersion:
description: APIVersion of the referenced config.
type: string
kind:
description: Kind of the referenced config.
type: string
name:
description: Name of the referenced config.
type: string
required:
- apiVersion
- kind
- name
type: object
endpoint:
description: Endpoint is the endpoint of the gRPC server.
type: string
type: object
type:
default: Kubernetes
description: |-
Type configures which secret store to be used. Only the configuration
block for this store will be used and others will be ignored if provided.
Default is Kubernetes.
enum:
- Kubernetes
- Vault
- Plugin
type: string
required:
- defaultScope
type: object
required:
- spec
type: object
served: true
storage: true
subresources: {}

View File

@ -17,17 +17,17 @@ The Crossplane CLI includes:
The Crossplane CLI is a single standalone binary with no external dependencies.
{{<hint "note" >}}
Install the Crossplane CLI on a user's computer.
Install the Crossplane CLI on a user's computer.
Most Crossplane CLI commands are independent of Kubernetes and
Most Crossplane CLI commands are independent of Kubernetes and
don't require access to a Crossplane pod.
{{< /hint >}}
{{< /hint >}}
To download the latest version for your CPU architecture with the Crossplane
install script.
```shell
curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | sh
curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | XP_CHANNEL=preview sh
```
[The script](https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh)
@ -35,13 +35,13 @@ detects your CPU architecture and downloads the latest stable release.
{{<expand "Manually install the Crossplane CLI" >}}
If you don't want to run shell script you can manually download a binary from
the Crossplane releases repository at
If you don't want to run shell script you can manually download a binary from
the Crossplane releases repository at
https://releases.crossplane.io/stable/current/bin
{{<hint "important" >}}
<!-- vale write-good.Passive = NO -->
The CLI is named `crank` in the release repository. Download this file.
The CLI is named `crank` in the release repository. Download this file.
<!-- vale write-good.Passive = YES -->
The `crossplane` binary is the Kubernetes Crossplane pod image.
@ -53,29 +53,12 @@ Move the binary to a location in your `$PATH`, for example `/usr/local/bin`.
### Download other CLI versions
Download different Crossplane CLI versions or different release branches with
the `XP_CHANNEL` and `XP_VERSION` environmental variables.
the `XP_CHANNEL` and `XP_VERSION` environmental variables.
By default the CLI installs from the `XP_CHANNEL` named `stable` and the
By default the CLI installs from the `XP_CHANNEL` named `stable` and the
`XP_VERSION` of `current`, matching the most recent stable release.
For example, to install CLI version `v1.14.0` add `XP_VERSION=v1.14.0` to the
download script curl command:
For example, to install CLI version `v1.14.0` add `XP_VERSION=v1.14.0` to the
download script curl command:
`curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | XP_VERSION=v1.14.0 sh`
## Installing shell autocompletions
The Crossplane CLI supports shell autocompletions for `bash`, `zsh` and `fish`.
You can install the autocompletions with the `completions` command by adding it to
your shell's configuration file.
```shell
source <(crossplane completions)
```
{{<hint "note" >}}
The `completions` command generates the autocompletions for your default shell.
It's not possible to generate autocompletions for a different shell, if you want to
install the autocompletions for a different shell, you have to configure the Crossplane
CLI as the completer manually.
{{< /hint >}}
`curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/main/install.sh" | XP_VERSION=v1.14.0 sh`

View File

@ -38,8 +38,8 @@ Server Version: v1.17.0
## render
The `crossplane render` command previews the output of a
[composite resource]({{<ref "../concepts/composite-resources">}}) after applying
any [composition functions]({{<ref "../concepts/compositions">}}).
[composite resource]({{<ref "../composition/composite-resources">}}) after applying
any [composition functions]({{<ref "../composition/compositions">}}).
{{< hint "important" >}}
The `crossplane render` command requires you to use composition functions.
@ -178,7 +178,7 @@ built-in support in [function-go-templating](https://github.com/crossplane-contr
## xpkg
The `crossplane xpkg` commands create, install and update Crossplane
[packages]({{<ref "../concepts/packages">}}) as well as enable authentication
[packages]({{<ref "../packages/configurations">}}) as well as enable authentication
and publishing of Crossplane packages to a Crossplane package registry.
### xpkg build
@ -193,9 +193,9 @@ The CLI applies the required annotations and values to meet the
[Crossplane XPKG specification](https://github.com/crossplane/crossplane/blob/main/contributing/specifications/xpkg.md).
The `crossplane` CLI supports building
[configuration]({{< ref "../concepts/packages" >}}),
[function]({{<ref "../concepts/compositions">}}) and
[provider]({{<ref "../concepts/providers" >}}) package types.
[configuration]({{< ref "../packages/configurations" >}}),
[function]({{<ref "../composition/compositions">}}) and
[provider]({{<ref "../packages/providers" >}}) package types.
#### Flags
@ -270,9 +270,9 @@ with the command
The `<name>` input isn't used. Crossplane reserves the `<name>` for future releases.
The `<template>` value may be one of four well known templates:
* `configuration-template` - A template to build a Crossplane [Configuration]({{<ref "../concepts/packages">}}) from the [crossplane/configuration-template](https://github.com/crossplane/configuration-template) repository.
* `function-template-go` - A template to build Crossplane Go [composition functions]({{<ref "../concepts/compositions">}}) from the [crossplane/function-template-go](https://github.com/crossplane/function-template-go) repository.
* `function-template-python` - A template to build Crossplane Python [composition functions]({{<ref "../concepts/compositions">}}) from the [crossplane/function-template-python](https://github.com/crossplane/function-template-go) repository.
* `configuration-template` - A template to build a Crossplane [Configuration]({{<ref "../packages/configurations">}}) from the [crossplane/configuration-template](https://github.com/crossplane/configuration-template) repository.
* `function-template-go` - A template to build Crossplane Go [composition functions]({{<ref "../composition/compositions">}}) from the [crossplane/function-template-go](https://github.com/crossplane/function-template-go) repository.
* `function-template-python` - A template to build Crossplane Python [composition functions]({{<ref "../composition/compositions">}}) from the [crossplane/function-template-python](https://github.com/crossplane/function-template-go) repository.
* `provider-template` - A template to build a basic Crossplane provider from the [Crossplane/provider-template](https://github.com/crossplane/provider-template) repository.
* `provider-template-upjet` - A template for building [Upjet](https://github.com/crossplane/upjet) based Crossplane providers from existing Terraform providers. Copies from the [upbound/upjet-provider-template](https://github.com/upbound/upjet-provider-template) repository.
@ -352,7 +352,7 @@ returns an error if the `wait` time expires before the package is `HEALTHY`.
#### Require manual package activation
Set the package to require
[manual activation]({{<ref "../concepts/packages#revision-activation-policy" >}}),
[manual activation]({{<ref "../packages/configurations#revision-activation-policy" >}}),
preventing an automatic upgrade of a package with `--manual-activation`
#### Authenticate to a private registry
@ -372,7 +372,7 @@ cache.
Store more inactive copies of a package with `--revision-history-limit`.
Read more about
[package revisions]({{< ref "../concepts/packages#configuration-revisions" >}})
[package revisions]({{< ref "../packages/configurations#configuration-revisions" >}})
in the package documentation.
### xpkg login
@ -514,11 +514,10 @@ As Crossplane evolves, its APIs and resources may change. To help with the
migration to the new APIs and resources, the `crossplane beta convert` command
converts a Crossplane resource to a new version or kind.
Use the `crossplane beta convert` command to convert an existing
[ControllerConfig]({{<ref "../concepts/providers#controller-configuration">}})
to a [DeploymentRuntimeConfig]({{<ref "../concepts/providers#runtime-configuration">}})
Use the `crossplane beta convert` command to convert a
ControllerConfig to a [DeploymentRuntimeConfig]({{<ref "../packages/providers#runtime-configuration">}})
or a legacy Composition using `mode: Resources` to a
[Composition pipeline function]({{< ref "../concepts/compositions" >}}).
[Composition pipeline function]({{< ref "../composition/compositions" >}}).
Provide the `crossplane beta convert` command the conversion type, the input
file and optionally, an output file. By default the command writes the output to
@ -595,19 +594,19 @@ running the `top` command may produce an error, for example,
### beta trace
Use the `crossplane beta trace` command to display a visual relationship of
Crossplane objects. The `trace` command supports claims, compositions,
Crossplane objects. The `trace` command supports XRs, compositions,
functions, managed resources or packages.
The command requires a resource type and a resource name.
`crossplane beta trace <resource kind> <resource name>`
For example to view a resource named `my-claim` of type `example.crossplane.io`:
`crossplane beta trace example.crossplane.io my-claim`
For example to view a resource named `my-xr` of type `example.crossplane.io`:
`crossplane beta trace example.crossplane.io my-xr`
The command also accepts Kubernetes CLI style `<kind>/<name>` input.
For example,
`crossplane beta trace example.crossplane.io/my-claim`
`crossplane beta trace example.crossplane.io/my-xr`
By default the `crossplane beta trace` command uses the Kubernetes
configuration defined in `~/.kube/config`.
@ -635,46 +634,6 @@ variable `KUBECONFIG`.
By default `crossplane beta trace` prints directly to the terminal, limiting the
"Ready" condition and "Status" messages to 64 characters.
The following an example output a "cluster" claim from the AWS reference
platform, which includes multiple Compositions and composed resources:
```shell {copy-lines="1"}
crossplane beta trace cluster.aws.platformref.upbound.io platform-ref-aws
NAME VERSION INSTALLED HEALTHY STATE STATUS
Configuration/platform-ref-aws v0.9.0 True True - HealthyPackageRevision
├─ ConfigurationRevision/platform-ref-aws-9ad7b5db2899 v0.9.0 - True Active HealthyPackageRevision
├─ Configuration/upbound-configuration-aws-network v0.7.0 True True - HealthyPackageRevision
│ ├─ ConfigurationRevision/upbound-configuration-aws-network-97be9100cfe1 v0.7.0 - True Active HealthyPackageRevision
│ ├─ Provider/upbound-provider-aws-ec2 v0.47.0 True True - HealthyPackageRevision
│ │ ├─ ProviderRevision/upbound-provider-aws-ec2-cfeb0cd0f1d2 v0.47.0 - True Active HealthyPackageRevision
│ │ └─ Provider/upbound-provider-family-aws v1.0.0 True True - HealthyPackageRevision
│ │ └─ ProviderRevision/upbound-provider-family-aws-48b3b5ccf964 v1.0.0 - True Active HealthyPackageRevision
│ └─ Function/upbound-function-patch-and-transform v0.2.1 True True - HealthyPackageRevision
│ └─ FunctionRevision/upbound-function-patch-and-transform-a2f88f8d8715 v0.2.1 - True Active HealthyPackageRevision
├─ Configuration/upbound-configuration-aws-database v0.5.0 True True - HealthyPackageRevision
│ ├─ ConfigurationRevision/upbound-configuration-aws-database-3112f0a765c5 v0.5.0 - True Active HealthyPackageRevision
│ └─ Provider/upbound-provider-aws-rds v0.47.0 True True - HealthyPackageRevision
│ └─ ProviderRevision/upbound-provider-aws-rds-58f96aa9fc4b v0.47.0 - True Active HealthyPackageRevision
├─ Configuration/upbound-configuration-aws-eks v0.5.0 True True - HealthyPackageRevision
│ ├─ ConfigurationRevision/upbound-configuration-aws-eks-83c9d65f4a47 v0.5.0 - True Active HealthyPackageRevision
│ ├─ Provider/crossplane-contrib-provider-helm v0.16.0 True True - HealthyPackageRevision
│ │ └─ ProviderRevision/crossplane-contrib-provider-helm-b4cc4c2c8db3 v0.16.0 - True Active HealthyPackageRevision
│ ├─ Provider/crossplane-contrib-provider-kubernetes v0.10.0 True True - HealthyPackageRevision
│ │ └─ ProviderRevision/crossplane-contrib-provider-kubernetes-63506a3443e0 v0.10.0 - True Active HealthyPackageRevision
│ ├─ Provider/upbound-provider-aws-eks v0.47.0 True True - HealthyPackageRevision
│ │ └─ ProviderRevision/upbound-provider-aws-eks-641a096d79d8 v0.47.0 - True Active HealthyPackageRevision
│ └─ Provider/upbound-provider-aws-iam v0.47.0 True True - HealthyPackageRevision
│ └─ ProviderRevision/upbound-provider-aws-iam-438eac423037 v0.47.0 - True Active HealthyPackageRevision
├─ Configuration/upbound-configuration-app v0.2.0 True True - HealthyPackageRevision
│ └─ ConfigurationRevision/upbound-configuration-app-5d95726dba8c v0.2.0 - True Active HealthyPackageRevision
├─ Configuration/upbound-configuration-observability-oss v0.2.0 True True - HealthyPackageRevision
│ ├─ ConfigurationRevision/upbound-configuration-observability-oss-a51529457ad7 v0.2.0 - True Active HealthyPackageRevision
│ └─ Provider/grafana-provider-grafana v0.8.0 True True - HealthyPackageRevision
│ └─ ProviderRevision/grafana-provider-grafana-ac529c8ce1c6 v0.8.0 - True Active HealthyPackageRevision
└─ Configuration/upbound-configuration-gitops-flux v0.2.0 True True - HealthyPackageRevision
└─ ConfigurationRevision/upbound-configuration-gitops-flux-2e80ec62738d v0.2.0 - True Active HealthyPackageRevision
```
#### Wide outputs
Print the entire "Ready" or "Status" message if they're longer than
64 characters with `--output=wide`.
@ -684,7 +643,7 @@ For example, the output truncates the "Status" message that's too long.
```shell {copy-lines="1"
crossplane trace cluster.aws.platformref.upbound.io platform-ref-aws
NAME SYNCED READY STATUS
Cluster/platform-ref-aws (default) True False Waiting: ...resource claim is waiting for composite resource to become Ready
Cluster/platform-ref-aws (default) True False Unready resources: cluster
```
Use `--output=wide` to see the full message.
@ -692,7 +651,7 @@ Use `--output=wide` to see the full message.
```shell {copy-lines="1"
crossplane trace cluster.aws.platformref.upbound.io platform-ref-aws --output=wide
NAME SYNCED READY STATUS
Cluster/platform-ref-aws (default) True False Waiting: Composite resource claim is waiting for composite resource to become Ready
Cluster/platform-ref-aws (default) True False Unready resources: cluster
```
#### Graphviz dot file output
@ -870,7 +829,7 @@ Configuration/platform-ref-aws v0.9.0 True
### beta validate
The `crossplane beta validate` command validates
[compositions]({{<ref "../concepts/compositions">}}) against provider or XRD
[compositions]({{<ref "../composition/compositions">}}) against provider or XRD
schemas using the Kubernetes API server's validation library
with extra validation such as checking for unknown fields,
a common source of difficult to debug issues in Crossplane.
@ -902,7 +861,6 @@ A Kubernetes cluster running Crossplane isn't required.
| | `--cache-dir=".crossplane/cache"` | Specify the absolute path to the cache directory to store downloaded schemas. |
| | `--clean-cache` | Clean the cache directory before downloading package schemas. |
| | `--skip-success-results` | Skip printing success results. |
| | `--error-on-missing-schemas` | Return a non zero exit code if any schemas are missing. |
| | `--verbose` | Print verbose logging statements. |
{{< /table >}}

View File

@ -0,0 +1,5 @@
---
title: Composition
weight: 51
description: Understand Crossplane's core components
---

View File

@ -1,40 +1,34 @@
---
title: Composite Resource Definitions
weight: 40
weight: 20
description: "Composite Resource Definitions or XRDs define custom API schemas"
---
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`.
Users create composite resources (`XRs`) using the API schema defined by an
XRD.
{{< hint "note" >}}
{{<hint "note">}}
Read the [composite resources]({{<ref "./composite-resources">}}) page for more
information about composite resources.
Read the [Claims]({{<ref "./claims">}}) page for more
information about Claims.
{{</hint >}}
{{</hint>}}
{{<expand "Confused about Compositions, XRDs, XRs and Claims?" >}}
Crossplane has four core components that users commonly mix up:
{{<expand "What are XRs, XRDs and Compositions?" >}}
A [composite resource]({{<ref "./composite-resources">}}) or XR is a custom API.
* [Compositions]({{<ref "./compositions" >}}) - A template to define how to create resources.
* Composite Resource Definition (`XRD`) - This page. A custom API specification.
* [Composite Resource]({{<ref "./composite-resources">}}) (`XR`) - Created by
using the custom API defined in a Composite Resource Definition. XRs use the
Composition template to create new managed resources.
* [Claims]({{<ref "./claims" >}}) (`XRC`) - Like a Composite Resource, but
with namespace scoping.
You use two Crossplane types to create a new custom API:
* A Composite Resource Definition (XRD) - This page. Defines the XR's schema.
* A [Composition]({{<ref "./compositions" >}}) - Configures how the XR creates
other resources.
{{</expand >}}
Crossplane XRDs are like
[Kubernetes custom resource definitions](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/).
XRDs require fewer fields and add options related to Crossplane, like Claims and
connection secrets.
XRDs require fewer fields and add options related to Crossplane, like connection
secrets.
## Creating a CompositeResourceDefinition
@ -44,8 +38,6 @@ Creating a CompositeResourceDefinition consists of:
* [Defining a custom API schema and version](#xrd-versions).
Optionally, CompositeResourceDefinitions also support:
* [Offering a Claim](#enable-claims).
* [Defining connection secrets](#manage-connection-secrets).
* [Setting composite resource defaults](#set-composite-resource-defaults).
Composite resource definitions (`XRDs`) create new API endpoints inside a
@ -60,12 +52,12 @@ Creating a new API requires defining an API
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xmydatabases.example.org
name: mydatabases.example.org
spec:
group: example.org
names:
kind: XMyDatabase
plural: xmydatabases
plural: mydatabases
versions:
- name: v1alpha1
# Removed for brevity
@ -75,14 +67,14 @@ After applying an XRD, Crossplane creates a new Kubernetes custom resource
definition matching the defined API.
For example, the XRD
{{<hover label="xrd1" line="4">}}xmydatabases.example.org{{</hover >}}
{{<hover label="xrd1" line="4">}}mydatabases.example.org{{</hover >}}
creates a custom resource definition
{{<hover label="kubeapi" line="2">}}xmydatabases.example.org{{</hover >}}.
{{<hover label="kubeapi" line="2">}}mydatabases.example.org{{</hover >}}.
```shell {label="kubeapi",copy-lines="3"}
kubectl api-resources
NAME SHORTNAMES APIVERSION NAMESPACED KIND
xmydatabases.example.org v1alpha1 false xmydatabases
mydatabases.example.org v1alpha1 true mydatabases
# Removed for brevity
```
@ -106,12 +98,6 @@ Many XRDs may use the same `group` to create a logical collection of APIs.
<!-- vale write-good.Weasel = YES -->
For example a `database` group may have a `relational` and `nosql` kinds.
{{<hint "tip" >}}
Group names are cluster scoped. Choose group names that don't conflict with
Providers.
Avoid Provider names in the group.
{{< /hint >}}
### XRD names
The `names` field defines how to refer to this specific XRD.
@ -131,9 +117,9 @@ The XRD
{{<hover label="xrdName" line="6">}}group{{</hover>}}.
For example, {{<hover label="xrdName"
line="4">}}xmydatabases.example.org{{</hover>}} matches the {{<hover
line="4">}}mydatabases.example.org{{</hover>}} matches the {{<hover
label="xrdName" line="9">}}plural{{</hover>}} name
{{<hover label="xrdName" line="9">}}xmydatabases{{</hover>}}, `.`
{{<hover label="xrdName" line="9">}}mydatabases{{</hover>}}, `.`
{{<hover label="xrdName" line="6">}}group{{</hover>}} name,
{{<hover label="xrdName" line="6">}}example.org{{</hover>}}.
@ -141,12 +127,12 @@ label="xrdName" line="9">}}plural{{</hover>}} name
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xmydatabases.example.org
name: mydatabases.example.org
spec:
group: example.org
names:
kind: XMyDatabase
plural: xmydatabases
plural: mydatabases
# Removed for brevity
```
{{</hint >}}
@ -258,7 +244,7 @@ on what your OpenAPIv3 custom API can use.
{{<hint "important" >}}
Changing or expanding the XRD schema requires restarting the [Crossplane pod]({{<ref "./pods#crossplane-pod">}}) to take effect.
Changing or expanding the XRD schema requires restarting the [Crossplane pod]({{<ref "../guides/pods#crossplane-pod">}}) to take effect.
{{< /hint >}}
##### Required fields
@ -356,12 +342,9 @@ 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`
* Any field under the object `spec.crossplane`
* Any field under the object `status.crossplane`
* `status.conditions`
* `status.connectionDetails`
Crossplane ignores any fields matching the reserved fields.
@ -413,7 +396,7 @@ field indicates which version of the schema Compositions use. Only one
version can be `referenceable`.
{{< hint "note" >}}
Changing which version is `referenceable:true` requires [updating the `compositeTypeRef.apiVersion`]({{<ref "./compositions#enable-composite-resources" >}})
Changing which version is `referenceable:true` requires [updating the `compositeTypeRef.apiVersion`]({{<ref "./compositions#match-composite-resources" >}})
of any Compositions referencing that XRD.
{{< /hint >}}
@ -492,190 +475,18 @@ spec:
{{<hint "important" >}}
Changing or expanding the XRD schema requires restarting the [Crossplane pod]({{<ref "./pods#crossplane-pod">}}) to take effect.
Changing or expanding the XRD schema requires restarting the [Crossplane pod]({{<ref "../guides/pods#crossplane-pod">}}) to take effect.
{{< /hint >}}
### Enable Claims
Optionally, XRDs can allow Claims to use the XRD API.
{{<hint "note" >}}
Read the [Claims]({{<ref "./claims">}}) page for more
information about Claims.
{{</hint >}}
XRDs offer Claims with a
{{<hover label="claim" line="10">}}claimNames{{</hover >}} object.
The {{<hover label="claim" line="10">}}claimNames{{</hover >}} defines a
{{<hover label="claim" line="11">}}kind{{</hover >}} and
{{<hover label="claim" line="12">}}plural{{</hover >}} like the XRD
{{<hover label="claim" line="7">}}names{{</hover >}} object.
Also like XRD
{{<hover label="claim" line="7">}}names{{</hover >}}, use UpperCamelCase
for the
{{<hover label="claim" line="11">}}kind{{</hover >}} and lowercase for the
{{<hover label="claim" line="12">}}plural{{</hover >}}.
The Claim
{{<hover label="claim" line="11">}}kind{{</hover >}} and
{{<hover label="claim" line="12">}}plural{{</hover >}} must be unique. They
can't match any other Claim or other XRD
{{<hover label="claim" line="8">}}kind{{</hover >}}.
{{<hint "tip" >}}
Common Crossplane convention is to use
{{<hover label="claim" line="10">}}claimNames{{</hover >}} that match the XRD
{{<hover label="claim" line="7">}}names{{</hover >}}, but without the beginning
"x."
{{</hint >}}
```yaml {label="claim",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xdatabases.custom-api.example.org
spec:
group: custom-api.example.org
names:
kind: xDatabase
plural: xdatabases
claimNames:
kind: Database
plural: databases
versions:
# Removed for brevity
```
{{<hint "important" >}}
You can't change the
{{<hover label="claim" line="10">}}claimNames{{</hover >}}
after they're defined. You must delete and
recreate the XRD to change the
{{<hover label="claim" line="10">}}claimNames{{</hover >}}.
{{</hint >}}
### Manage connection secrets
When a composite resource creates managed resources, Crossplane provides any
[connection secrets]({{<ref "./managed-resources#writeconnectionsecrettoref">}})
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
{{<hover label="key" line="10">}}connectionSecretKeys{{</hover>}}
to limit what's provided to a composite resource or Claim.
Crossplane only provides the keys listed in the
{{<hover label="key" line="10">}}connectionSecretKeys{{</hover>}}
to the composite resource or Claim using this XRD. Any other connection
secrets aren't passed to the composite resource or Claim.
{{<hint "important" >}}
The keys listed in the
{{<hover label="key" line="10">}}connectionSecretKeys{{</hover>}} 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]({{<ref "./compositions#store-connection-details">}}).
{{< /hint >}}
For example, an XRD passes the keys
{{<hover label="key" line="11">}}username{{</hover>}},
{{<hover label="key" line="12">}}password{{</hover>}} and
{{<hover label="key" line="13">}}address{{</hover>}}.
Composite resources or Claims save these in the secret defined by their
`writeConnectionSecretToRef` field.
```yaml {label="key",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xdatabases.custom-api.example.org
spec:
group: custom-api.example.org
names:
kind: xDatabase
plural: xdatabases
connectionSecretKeys:
- username
- password
- address
versions:
# Removed for brevity
```
{{<hint "warning">}}
You can't change the `connectionSecretKeys` of an XRD. You must delete and
recreate the XRD to change the `connectionSecretKeys`.
{{</hint >}}
For more information on connection secrets read the
[Connection Secrets knowledge base article]({{<ref "connection-details">}}).
### Set composite resource defaults
XRDs can set default parameters for composite resources and Claims.
<!-- vale off -->
#### defaultCompositeDeletePolicy
<!-- vale on -->
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
{{<hover label="delete" line="6">}}defaultCompositeDeletePolicy: Foreground{{</hover>}}
to change the XRD deletion policy.
```yaml {label="delete",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xdatabases.custom-api.example.org
spec:
defaultCompositeDeletePolicy: Foreground
group: custom-api.example.org
names:
# Removed for brevity
versions:
# Removed for brevity
```
XRDs can set default parameters for composite resources.
<!-- vale off -->
#### defaultCompositionRef
<!-- vale on -->
It's possible for multiple [Compositions]({{<ref "./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.
the composite resource must select which Composition to use.
An XRD can define the default Composition to use with the
`defaultCompositionRef` value.
@ -704,16 +515,16 @@ spec:
<!-- vale on -->
Changes to a Composition generate a new Composition revision. By default all
composite resources and Claims use the updated Composition revision.
composite resources use the updated Composition revision.
Set the XRD `defaultCompositionUpdatePolicy` to `Manual` to prevent composite
resources and Claims from automatically using the new revision.
resources from automatically using the new revision.
The default value is `defaultCompositionUpdatePolicy: Automatic`.
Set {{<hover label="compRev" line="6">}}defaultCompositionUpdatePolicy: Manual{{</hover>}}
to set the default Composition update policy for composite resources and Claims
using this XRD.
to set the default Composition update policy for composite resources and using
this XRD.
```yaml {label="compRev",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
@ -732,11 +543,11 @@ spec:
<!-- vale off -->
#### enforcedCompositionRef
<!-- vale on -->
To require all composite resources or Claims to use a specific Composition use
the `enforcedCompositionRef` setting in the XRD.
To require all composite resources 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
For example, to require all composite resources using this XRD to use the
Composition
{{<hover label="enforceComp" line="6">}}myComposition{{</hover>}}
set
{{<hover label="enforceComp" line="6">}}enforcedCompositionRef.name: myComposition{{</hover>}}.
@ -770,9 +581,6 @@ xdatabases.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
@ -789,9 +597,6 @@ Status:
Reason: WatchingCompositeResource
Status: True
Type: Established
Reason: WatchingCompositeResourceClaim
Status: True
Type: Offered
# Removed for brevity
```
@ -820,29 +625,3 @@ Type: Established
Status: False
Reason: TerminatingCompositeResource
```
<!-- vale off -->
#### WatchingCompositeResourceClaim
<!-- vale on -->
`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.
```yaml
Type: Offered
Status: True
Reason: WatchingCompositeResourceClaim
```
<!-- vale off -->
#### TerminatingCompositeResourceClaim
<!-- vale on -->
`Reason: TerminatingCompositeResourceClaim` indicates Crossplane is deleting the
custom resource definitions related to the offered Claims and is
terminating the Claims controller.
```yaml
Type: Offered
Status: False
Reason: TerminatingCompositeResourceClaim
```

View File

@ -0,0 +1,349 @@
---
title: Composite Resources
weight: 10
description: "Composite resources, an XR or XRs, represent a collection of related cloud resources."
---
A composite resource, or XR, represents a set of Kubernetes resources as a
single Kubernetes object. Crossplane creates composite resources when users
access a custom API, defined in the CompositeResourceDefinition.
{{<hint "tip" >}}
Composite resources are a _composite_ of Kubernetes resources.
A _Composition_ defines how to _compose_ the resources together.
{{< /hint >}}
{{<expand "What are XRs, XRDs and Compositions?" >}}
A composite resource or XR (this page) is a custom API.
You use two Crossplane types to create a new custom API:
* A [Composite Resource Definition]({{<ref "./composite-resource-definitions">}})
(XRD) - Defines the XR's schema.
* A [Composition]({{<ref "./compositions" >}}) - Configures how the XR creates
other resources.
{{</expand >}}
## Create composite resources
Creating composite resources requires a
[Composition]({{<ref "./compositions">}}) and a
[CompositeResourceDefinition]({{<ref "./composite-resource-definitions">}})
(XRD).
The Composition defines the set of resources to create. The XRD defines the
custom API users call to request the set of resources.
```mermaid
flowchart TD
user(["User"])
xr("Composite Resource (XR)")
xrd("Composite Resource Definition (XRD)")
comp("Composition")
cda("Composed Resource A")
cdb("Composed Resource B")
cdc("Composed Resource C")
xrd -.defines.-> xr
comp configure-xr@-.configures.-> xr
user --creates--> xr
xr compose-a@--composes-->cda
xr compose-b@--composes-->cdb
xr compose-c@--composes-->cdc
configure-xr@{animate: true}
compose-a@{animate: true}
compose-b@{animate: true}
compose-c@{animate: true}
```
XRDs define the API used to create a composite resource. For example,
this {{<hover label="xrd1" line="2">}}CompositeResourceDefinition{{</hover>}}
creates a custom API endpoint
{{<hover label="xrd1" line="4">}}mydatabases.example.org{{</hover>}}.
```yaml {label="xrd1",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: mydatabases.example.org
spec:
group: example.org
names:
kind: MyDatabase
plural: mydatabases
# Removed for brevity
```
When a user calls the custom API,
{{<hover label="xrd1" line="4">}}mydatabases.example.org{{</hover>}},
Crossplane chooses the Composition to use based on the Composition's
{{<hover label="typeref" line="6">}}compositeTypeRef{{</hover>}}
```yaml {label="typeref",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: my-composition
spec:
compositeTypeRef:
apiVersion: example.org/v1alpha1
kind: MyDatabase
# Removed for brevity
```
The Composition
{{<hover label="typeref" line="6">}}compositeTypeRef{{</hover>}} matches the
XRD {{<hover label="xrd1" line="6">}}group{{</hover>}} and
{{<hover label="xrd1" line="9">}}kind{{</hover>}}.
Crossplane creates the resources defined in the matching Composition and
represents them as a single `composite` resource.
```shell{copy-lines="1"}
kubectl get composite
NAME SYNCED READY COMPOSITION AGE
my-composite-resource True True my-composition 4s
```
### Composition selection
Select a specific Composition for a composite resource to use with
{{<hover label="compref" line="7">}}compositionRef{{</hover>}}
{{<hint "important">}}
The selected Composition must allow the composite resource to use it with a
`compositeTypeRef`. Read more about the `compositeTypeRef` field in the
[Enable Composite Resources]({{<ref "./compositions#match-composite-resources">}})
section of the Composition documentation.
{{< /hint >}}
```yaml {label="compref",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: MyDatabase
metadata:
namespace: default
name: my-composite-resource
spec:
crossplane:
compositionRef:
name: my-other-composition
# Removed for brevity
```
A composite resource can also select a Composition based on labels instead of
the exact name with a
{{<hover label="complabel" line="7">}}compositionSelector{{</hover>}}.
Inside the {{<hover label="complabel" line="7">}}matchLabels{{</hover>}} section
provide one or more Composition labels to match.
```yaml {label="complabel",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: MyDatabase
metadata:
namespace: default
name: my-composite-resource
spec:
crossplane:
compositionSelector:
matchLabels:
environment: production
# Removed for brevity
```
### Composition revision policy
Crossplane tracks changes to Compositions as
[Composition revisions]({{<ref "composition-revisions">}}) .
A composite resource can use
a {{<hover label="comprev" line="7">}}compositionUpdatePolicy{{</hover>}} to
manually or automatically reference newer Composition revisions.
The default
{{<hover label="comprev" line="7">}}compositionUpdatePolicy{{</hover>}} is
"Automatic." Composite resources automatically use the latest Composition
revision.
Change the policy to
{{<hover label="comprev" line="7">}}Manual{{</hover>}} to prevent composite
resources from automatically upgrading.
```yaml {label="comprev",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: MyDatabase
metadata:
namespace: default
name: my-composite-resource
spec:
crossplane:
compositionUpdatePolicy: Manual
# Removed for brevity
```
### Composition revision selection
Crossplane records changes to Compositions as
[Composition revisions]({{<ref "composition-revisions">}}).
A composite resource can
select a specific Composition revision.
Use {{<hover label="comprevref" line="7">}}compositionRevisionRef{{</hover>}} to
select a specific Composition revision by name.
For example, to select a specific Composition revision use the name of the
desired Composition revision.
```yaml {label="comprevref",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: MyDatabase
metadata:
namespace: default
name: my-composite-resource
spec:
crossplane:
compositionUpdatePolicy: Manual
compositionRevisionRef:
name: my-composition-b5aa1eb
# Removed for brevity
```
{{<hint "note" >}}
Find the Composition revision name from
{{<hover label="getcomprev" line="1">}}kubectl get compositionrevision{{</hover>}}
```shell {label="getcomprev",copy-lines="1"}
kubectl get compositionrevision
NAME REVISION XR-KIND XR-APIVERSION AGE
my-composition-5c976ad 1 mydatabases example.org/v1alpha1 65m
my-composition-b5aa1eb 2 mydatabases example.org/v1alpha1 64m
```
{{< /hint >}}
A Composite resource can also select Composition revisions based on labels
instead of the exact name with a
{{<hover label="comprevsel" line="7">}}compositionRevisionSelector{{</hover>}}.
Inside the {{<hover label="comprevsel" line="7">}}matchLabels{{</hover>}}
section provide one or more Composition revision labels to match.
```yaml {label="comprevsel",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: MyDatabase
metadata:
namespace: default
name: my-composite-resource
spec:
crossplane:
compositionRevisionSelector:
matchLabels:
channel: dev
# Removed for brevity
```
### Pausing composite resources
<!-- vale Google.WordList = NO -->
Crossplane supports pausing composite resources. A paused composite resource
doesn't check or make changes on its external resources.
<!-- vale Google.WordList = YES -->
To pause a composite resource apply the
{{<hover label="pause" line="4">}}crossplane.io/paused{{</hover>}} annotation.
```yaml {label="pause",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: MyDatabase
metadata:
namespace: default
name: my-composite-resource
annotations:
crossplane.io/paused: "true"
spec:
# Removed for brevity
```
## Verify composite resources
Use
{{<hover label="getcomposite" line="1">}}kubectl get composite{{</hover>}}
to view all the composite resources Crossplane created.
```shell{copy-lines="1",label="getcomposite"}
kubectl get composite
NAME SYNCED READY COMPOSITION AGE
my-composite-resource True True my-composition 4s
```
Use `kubectl get` for the specific custom API endpoint to view
only those resources.
```shell {copy-lines="1"}
kubectl get mydatabases
NAME SYNCED READY COMPOSITION AGE
my-composite-resource True True my-composition 12m
```
Use
{{<hover label="desccomposite" line="1">}}kubectl describe composite{{</hover>}}
to view the linked
{{<hover label="desccomposite" line="16">}}Composition Ref{{</hover>}},
and unique resources created in the
{{<hover label="desccomposite" line="22">}}Resource Refs{{</hover>}}.
```yaml {copy-lines="1",label="desccomposite"}
kubectl describe composite my-composite-resource
Name: my-composite-resource
Namespace: default
API Version: example.org/v1alpha1
Kind: MyDatabase
Spec:
Composition Ref:
Name: my-composition
Composition Revision Ref:
Name: my-composition-cf2d3a7
Composition Update Policy: Automatic
Resource Refs:
API Version: s3.aws.m.upbound.io/v1beta1
Kind: Bucket
Name: my-composite-resource-fmrks
API Version: dynamodb.aws.m.upbound.io/v1beta1
Kind: Table
Name: my-composite-resource-wnr9t
# Removed for brevity
```
### Composite resource conditions
A composite resource has two status conditions: Synced and Ready.
Crossplane sets the Synced status condition to True when it's able to
successfully reconcile the composite resource. If Crossplane can't reconcile the
composite resource it'll report an error in the Synced condition.
Crossplane sets the Ready status condition to True when the composite resource's
composition function pipeline reports that all of its composed resources are
ready. If a composed resource isn't ready Crossplane will report it in the
Ready condition.
## Composite resource labels
Crossplane adds labels to composed resources to show their relationship to
other Crossplane components.
Crossplane adds the
{{<hover label="complabel" line="4">}} crossplane.io/composite{{</hover>}} label
to all composed resources. The label matches the name of the composite.
Crossplane applies the composite label to anyresource created by a composite,
creating a reference between the resource and owning composite resource.
```shell {label="complabel",copy-lines="1"}
kubectl describe mydatabase.example.org/my-database-x9rx9
Name: my-database2-x9rx9
Namespace: default
Labels: crossplane.io/composite=my-database-x9rx9
```

View File

@ -10,8 +10,8 @@ familiarity with Crossplane, and particularly with
A `Composition` configures how Crossplane should reconcile a Composite Resource
(XR). Put otherwise, when you create an XR the selected `Composition` determines
what managed resources Crossplane will create in response. Let's say for example
that you define a `PlatformDB` XR, which represents your organisation's common
what resources Crossplane will create in response. Let's say for example that
you define a `PlatformDB` XR, which represents your organisation's common
database configuration of an Azure MySQL Server and a few firewall rules. The
`Composition` contains the 'base' configuration for the MySQL server and the
firewall rules that are extended by the configuration for the `PlatformDB`.
@ -42,9 +42,9 @@ some XRs to previous `Composition` settings without rolling back all XRs.
When Composition Revisions are enabled three things happen:
1. Crossplane creates a `CompositionRevision` for each `Composition` update.
1. Composite Resources gain a `spec.compositionRevisionRef` field that specifies
1. Composite Resources gain a `spec.crossplane.compositionRevisionRef` field that specifies
which `CompositionRevision` they use.
1. Composite Resources gain a `spec.compositionUpdatePolicy` field that
1. Composite Resources gain a `spec.crossplane.compositionUpdatePolicy` field that
specifies how they should be updated to new Composition Revisions.
Each time you edit a `Composition` Crossplane will automatically create a
@ -91,15 +91,13 @@ kind: PlatformDB
metadata:
name: example
spec:
parameters:
storageGB: 20
# The Manual policy specifies that you don't want this XR to update to the
# latest CompositionRevision automatically.
compositionUpdatePolicy: Manual
compositionRef:
name: example
writeConnectionSecretToRef:
name: db-conn
storageGB: 20
crossplane:
# The Manual policy specifies that you don't want this XR to update to the
# latest CompositionRevision automatically.
compositionUpdatePolicy: Manual
compositionRef:
name: example
```
Crossplane sets an XR's `compositionRevisionRef` automatically at creation time
@ -113,16 +111,14 @@ kind: PlatformDB
metadata:
name: example
spec:
parameters:
storageGB: 20
compositionUpdatePolicy: Manual
compositionRef:
name: example
# Update the referenced CompositionRevision if and when you are ready.
compositionRevisionRef:
name: example-18pdg
writeConnectionSecretToRef:
name: db-conn
storageGB: 20
crossplane:
compositionUpdatePolicy: Manual
compositionRef:
name: example
# Update the referenced CompositionRevision if and when you are ready.
compositionRevisionRef:
name: example-18pdg
```
## Complete example
@ -133,21 +129,6 @@ resource and continues with creating multiple XRs to observe different upgrade p
assign different CompositionRevisions to the created composite resources each time the composition is updated.
### Preparation
##### Install Crossplane
Install Crossplane v1.11.0 or later and wait until the Crossplane pods are running.
```shell
kubectl create namespace crossplane-system
helm repo add crossplane-master https://charts.crossplane.io/master/
helm repo update
helm install crossplane --namespace crossplane-system crossplane-master/crossplane --devel --version 1.11.0-rc.0.108.g0521c32e
kubectl get pods -n crossplane-system
```
Expected Output:
```shell
NAME READY STATUS RESTARTS AGE
crossplane-7f75ddcc46-f4d2z 1/1 Running 0 9s
crossplane-rbac-manager-78bd597746-sdv6w 1/1 Running 0 9s
```
#### Deploy Composition and XRD Examples
Apply the example Composition.
@ -160,7 +141,6 @@ metadata:
channel: dev
name: myvpcs.aws.example.upbound.io
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: aws.example.upbound.io/v1alpha1
kind: MyVPC
@ -175,7 +155,7 @@ spec:
resources:
- name: my-vpc
base:
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: VPC
spec:
forProvider:
@ -241,6 +221,7 @@ Create an XR without a `compositionUpdatePolicy` defined. The update policy is `
apiVersion: aws.example.upbound.io/v1alpha1
kind: MyVPC
metadata:
namespace: default
name: vpc-auto
spec:
id: vpc-auto
@ -256,12 +237,14 @@ Create a Composite Resource with `compositionUpdatePolicy: Manual` and `composit
apiVersion: aws.example.upbound.io/v1alpha1
kind: MyVPC
metadata:
namespace: default
name: vpc-man
spec:
id: vpc-man
compositionUpdatePolicy: Manual
compositionRevisionRef:
name: myvpcs.aws.example.upbound.io-ad265bc
crossplane:
compositionUpdatePolicy: Manual
compositionRevisionRef:
name: myvpcs.aws.example.upbound.io-ad265bc
```
Expected Output:
@ -275,12 +258,14 @@ Create an XR with a `compositionRevisionSelector` of `channel: dev`:
apiVersion: aws.example.upbound.io/v1alpha1
kind: MyVPC
metadata:
namespace: default
name: vpc-dev
spec:
id: vpc-dev
compositionRevisionSelector:
matchLabels:
channel: dev
crossplane:
compositionRevisionSelector:
matchLabels:
channel: dev
```
Expected Output:
```shell
@ -292,12 +277,14 @@ Create an XR with a `compositionRevisionSelector` of `channel: staging`:
apiVersion: aws.example.upbound.io/v1alpha1
kind: MyVPC
metadata:
namespace: default
name: vpc-staging
spec:
id: vpc-staging
compositionRevisionSelector:
matchLabels:
channel: staging
crossplane:
compositionRevisionSelector:
matchLabels:
channel: staging
```
Expected Output:
@ -308,7 +295,7 @@ myvpc.aws.example.upbound.io/vpc-staging created
Verify the Composite Resource with the label `channel: staging` doesn't have a `REVISION`.
All other XRs have a `REVISION` matching the created Composition Revision.
```shell
kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.compositionRevisionRef.name,POLICY:.spec.compositionUpdatePolicy,MATCHLABEL:.spec.compositionRevisionSelector.matchLabels"
kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.crossplane.compositionRevisionRef.name,POLICY:.spec.crossplane.compositionUpdatePolicy,MATCHLABEL:.spec.crossplane.compositionRevisionSelector.matchLabels"
```
Expected Output:
```shell
@ -352,7 +339,7 @@ Verify that Crossplane assigns the Composite Resources `vpc-auto` and `vpc-stagi
XRs `vpc-man` and `vpc-dev` are still assigned to the original `revision:1`:
```shell
kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.compositionRevisionRef.name,POLICY:.spec.compositionUpdatePolicy,MATCHLABEL:.spec.compositionRevisionSelector.matchLabels"
kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.crossplane.compositionRevisionRef.name,POLICY:.spec.crossplane.compositionUpdatePolicy,MATCHLABEL:.spec.crossplane.compositionRevisionSelector.matchLabels"
```
Expected Output:
```shell
@ -380,7 +367,6 @@ metadata:
channel: dev
name: myvpcs.aws.example.upbound.io
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: aws.example.upbound.io/v1alpha1
kind: MyVPC
@ -395,7 +381,7 @@ spec:
resources:
- name: my-vpc
base:
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: VPC
spec:
forProvider:
@ -431,7 +417,7 @@ Verify Crossplane assigns the Composite Resources `vpc-auto` and `vpc-dev` to Co
`vpc-staging` is assigned to `revision:2`, and `vpc-man` is still assigned to the original `revision:1`:
```shell
kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.compositionRevisionRef.name,POLICY:.spec.compositionUpdatePolicy,MATCHLABEL:.spec.compositionRevisionSelector.matchLabels"
kubectl get composite -o="custom-columns=NAME:.metadata.name,SYNCED:.status.conditions[0].status,REVISION:.spec.crossplane.compositionRevisionRef.name,POLICY:.spec.crossplane.compositionUpdatePolicy,MATCHLABEL:.spec.crossplane.compositionRevisionSelector.matchLabels"
```
Expected Output:
```shell
@ -449,7 +435,7 @@ vpc-staging True myvpcs.aws.example.upbound.io-727b3c8 Automatic map[c
{{< /hint >}}
[composition type]: {{<ref "../../master/concepts/compositions" >}}
[Compositions]: {{<ref "../../master/concepts/compositions" >}}
[composition type]: {{<ref "compositions">}}
[Compositions]: {{<ref "compositions">}}
[canary]: https://martinfowler.com/bliki/CanaryRelease.html
[install guide]: {{<ref "../../master/software/install" >}}
[install guide]: {{<ref "../get-started/install">}}

View File

@ -5,14 +5,14 @@ aliases:
- composition
- composition-functions
- /knowledge-base/guides/composition-functions
description: "Compositions are a template for creating Crossplane resources"
description: "Compositions are a template for creating composite resources"
---
Compositions are a template for creating multiple managed resources as a single
object.
Compositions are a template for creating multiple Kubernetes resources as a
single _composite_ resource.
A Composition _composes_ individual managed resources together into a larger,
reusable, solution.
A Composition _composes_ individual resources together into a larger, reusable,
solution.
An example Composition may combine a virtual machine, storage resources and
networking policies. A Composition template links all these individual
@ -44,7 +44,7 @@ spec:
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -52,17 +52,14 @@ spec:
```
{{<expand "Confused about Compositions, XRDs, XRs and Claims?" >}}
Crossplane has four core components that users commonly mix up:
{{<expand "What are XRs, XRDs and Compositions?" >}}
A [composite resource]({{<ref "./composite-resources">}}) or XR is a custom API.
* Compositions - This page. A template to define how to create resources.
* [Composite Resource Definition]({{<ref "./composite-resource-definitions">}})
(`XRD`) - A custom API specification.
* [Composite Resource]({{<ref "./composite-resources">}}) (`XR`) - Created by
using the custom API defined in a Composite Resource Definition. XRs use the
Composition template to create new managed resources.
* [Claims]({{<ref "./claims" >}}) (`XRC`) - Like a Composite Resource, but
with namespace scoping.
You use two Crossplane types to create a new custom API:
* A [Composite Resource Definition]({{<ref "./composite-resource-definitions">}})
(XRD) - Defines the XR's schema.
* A Composition - This page. Configures how the XR creates other resources.
{{</expand >}}
## Create a Composition
@ -70,7 +67,7 @@ Crossplane has four core components that users commonly mix up:
Creating a Composition consists of:
* [Using composition functions](#use-a-function-in-a-composition) to define the
resources to create.
* [Enabling composite resources](#enable-composite-resources) to use the
* [Enabling composite resources](#match-composite-resources) to use the
Composition template.
A Composition is a pipeline of composition functions.
@ -81,40 +78,18 @@ to determine what resources it should create when you create a composite
resource (XR).
{{<hint "tip" >}}
The Crossplane community has built lots of functions that let you template
Crossplane resources using
[CUE](https://github.com/crossplane-contrib/function-cue),
[KCL](https://github.com/crossplane-contrib/function-kcl),
Crossplane has functions that let you template composed resources using YAML
[patch and transforms]({{<ref "../guides/function-patch-and-transform">}}).
Helm-like
[Go templates](https://github.com/crossplane-contrib/function-go-templating) or
legacy Crossplane
[Patch and Transforms]({{<ref "../guides/function-patch-and-transform">}}).
[YAML templates](https://github.com/crossplane-contrib/function-go-templating),
[CUE](https://github.com/crossplane-contrib/function-cue),
[KCL](https://github.com/crossplane-contrib/function-kcl), or
[Python](https://github.com/crossplane-contrib/function-python).
You can also [write your own function](#write-a-composition-function) using Go
or Python.
{{< /hint >}}
{{<hint "important" >}}
Crossplane has two modes of composition:
* `mode: Pipeline`
* `mode: Resources`
Use the `Pipeline` mode to use composition functions.
<!-- vale write-good.Passive = NO -->
The `Resources` mode is deprecated, and you shouldn't use it. Crossplane
supports Compositions that use the `Resources` mode for backward compatibility,
but the feature is no longer maintained. Crossplane doesn't accept new
`Resources` features, and only accepts security bug fixes.
<!-- vale write-good.Passive = YES -->
See the [CLI documentation]({{<ref "../cli/command-reference#beta-convert">}})
to learn how to use the `crossplane beta convert` command to convert a legacy
`Resources` Composition to the `Pipeline` mode.
{{< /hint >}}
### Install a composition function
Installing a Function creates a function pod. Crossplane sends requests to this
@ -139,7 +114,7 @@ spec:
{{< hint "tip" >}}
Functions are Crossplane Packages. Read more about Packages in the
[Packages documentation]({{<ref "packages" >}}).
[Packages documentation]({{<ref "../packages/functions" >}}).
{{< /hint >}}
By default, the Function pod installs in the same namespace as Crossplane
@ -168,8 +143,8 @@ you create a composite resource. The Function also tells Crossplane what to do
with these resources when you update or delete a composite resource.
When Crossplane calls a Function it sends it the current state of the composite
resource. It also sends it the current state of any managed resources the
composite resource owns.
resource. It also sends it the current state of any resources the composite
resource owns.
Crossplane knows what Function to call when a composite resource changes by
looking at the Composition the composite resource uses.
@ -186,14 +161,6 @@ Each {{<hover label="single" line="8">}}step{{</hover>}} uses a
{{<hover label="single" line="9">}}functionRef{{</hover>}} to reference the
{{<hover label="single" line="10">}}name{{</hover>}} of the Function to call.
{{<hint "important" >}}
Compositions using {{<hover label="single" line="6">}}mode: Pipeline{{</hover>}}
can't specify resource templates with a `resources` field.
Use function "Patch and Transform" to create resource templates.
{{< /hint >}}
Some Functions also allow you to specify an
{{<hover label="single" line="11">}}input{{</hover>}}.
The function defines the
@ -223,7 +190,7 @@ spec:
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -261,7 +228,7 @@ spec:
export:
target: Resources
value: |
apiVersion: "s3.aws.upbound.io/v1beta1"
apiVersion: "s3.aws.m.upbound.io/v1beta1"
kind: "Bucket"
spec: forProvider: region: "us-east-2"
- step: automatically-detect-readiness
@ -270,11 +237,10 @@ spec:
```
### Enable composite resources
### Match composite resources
A Composition is only a template defining how to create managed
resources. A Composition limits which Composite Resources can use this
template.
A Composition is only a template defining how to create composed resources. A
Composition limits which kind of composite resource (XR) can use this template.
A Composition's {{<hover label="typeref" line="6">}}compositeTypeRef{{</hover>}}
defines which Composite Resource type can use this Composition.
@ -303,132 +269,63 @@ spec:
# Removed for brevity
```
### Store connection details
### Grant access to composed resources
Some managed resources generate unique details like usernames, passwords, IP
addresses, ports or other connection details.
Crossplane uses its [service account](https://kubernetes.io/docs/concepts/security/service-accounts/)
to create the composed resources that a function pipeline returns.
When resources inside a Composition create connection details Crossplane creates
a Kubernetes secret object for each managed resource generating connection
details.
Crossplane's service account has access to create, update, and delete any
resource installed by a [provider]({{<ref "../packages/providers">}}), or
defined by an XRD. This includes all
[MRs]({{<ref "../managed-resources/managed-resources">}}) and
[XRs]({{<ref "composite-resources">}}). It also has access to some types of
Kubernetes resources that it needs to function - for example it can create
deployments.
{{<hint "note">}}
This section discusses creating Kubernetes secrets.
Crossplane also supports using external secret stores like
[HashiCorp Vault](https://www.vaultproject.io/).
You must grant Crossplane access to compose any other kind of resource. You do
this by creating an [RBAC ClusterRole](https://kubernetes.io/docs/reference/access-authn-authz/rbac/).
Read the [external secrets store guide]({{<ref "../guides/vault-as-secret-store">}}) for more information on using Crossplane
with an external secret store.
{{</hint >}}
<!-- vale write-good.TooWordy = NO -->
<!-- TooWordy thinks "aggregate" is too wordy, but it's the name of the concept. -->
The ClusterRole must aggregate to Crossplane's primary ClusterRole using
[ClusterRole aggregation](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles).
<!-- vale write-good.TooWordy = YES -->
#### Composite resource combined secret
Here's a ClusterRole that grants Crossplane access to manage
[CloudNativePG](https://cloudnative-pg.io) PostgreSQL clusters.
Crossplane can combine all the secrets generated by the resources inside a
Composition into a single Kubernetes secret and optionally copy the secret
object for claims.
Set the value of `writeConnectionSecretsToNamespace` to the namespace where
Crossplane should store the combined secret object.
```yaml {copy-lines="none",label="writeConn"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
writeConnectionSecretsToNamespace: my-namespace
resources:
# Removed for brevity
```
#### Composed resource secrets
Inside the `spec` of each resource producing connection details, define the
`writeConnectionSecretToRef`, with a `namespace` and `name` of the secret object
for the resource.
If a `writeConnectionSecretToRef` isn't defined, Crossplane doesn't write any
keys to the secret.
```yaml {label="writeConnRes"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1
```
Crossplane saves a secret with the `name` in the `namespace` provided.
```shell {label="viewComposedSec"}
kubectl get secrets -n docs
NAME TYPE DATA AGE
key1 connection.crossplane.io/v1alpha1 4 4m30s
```
{{<hint "tip" >}}
Remember to create a unique name for each secret.
{{< /hint >}}
#### External secret stores
Crossplane
[External Secret Stores]({{<ref "../guides/vault-as-secret-store" >}})
write secrets and connection details to external secret stores like HashiCorp
Vault.
{{<hint "important" >}}
External Secret Stores are an alpha feature.
They're not recommended for production use. Crossplane disables External Secret
Stores by default.
{{< /hint >}}
Use `publishConnectionDetailsWithStoreConfigRef` in place of
`writeConnectionSecretsToNamespace` to define the `StoreConfig` to save
connection details to.
For example, using a `StoreConfig` with the `name` "vault," use
`publishConnectionDetailsWithStoreConfigRef.name` matching the
`StoreConfig.name`, in this example, "vault."
```yaml {label="gcp-storeconfig",copy-lines="none"}
apiVersion: gcp.crossplane.io/v1alpha1
kind: StoreConfig
``` yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: vault
# Removed for brevity.
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
spec:
publishConnectionDetailsWithStoreConfigRef:
name: vault
# Removed for brevity
name: cnpg:aggregate-to-crossplane
labels:
rbac.crossplane.io/aggregate-to-crossplane: "true"
rules:
- apiGroups:
- postgresql.cnpg.io
resources:
- clusters
verbs:
- "*"
```
For more details read the
[External Secret Stores]({{<ref "../guides/vault-as-secret-store" >}})
integration guide.
<!-- vale write-good.TooWordy = NO -->
<!-- TooWordy thinks "aggregate" is too wordy, but it's the name of the concept. -->
The `rbac.crossplane.io/aggregate-to-crossplane: "true"` label is critical. It
configures the role to aggregate to Crossplane's primary cluster role.
<!-- vale write-good.TooWordy = YES -->
{{<hint "note" >}}
The [RBAC manager]({{<ref "../guides/pods#rbac-manager-pod">}}) automatically
grants Crossplane access to MRs and XRs. The RBAC manager uses
[escalate access](https://kubernetes.io/docs/concepts/security/rbac-good-practices/#escalate-verb)
to grant Crossplane access that the RBAC manager doesn't have.
The RBAC manager is an optional Crossplane component that's enabled by default.
**If you disable the RBAC manager, you must manually grant Crossplane access to
_any_ kind of resource you wish to compose - including XRs and MRs.**
{{< /hint >}}
## Test a composition
@ -436,11 +333,6 @@ You can preview the output of any composition using the Crossplane CLI. You
don't need a Crossplane control plane to do this. The Crossplane CLI uses Docker
Engine to run functions.
{{<hint "important">}}
The `crossplane render` command only supports composition functions. It doesn't
support `mode: Resources` Compositions.
{{< /hint >}}
{{<hint "tip">}}
See the [Crossplane CLI docs]({{<ref "../cli">}}) to
learn how to install and use the Crossplane CLI.
@ -464,11 +356,11 @@ created.
```yaml
---
apiVersion: example.crossplane.io/v1
kind: XBucket
kind: Bucket
metadata:
name: example-render
---
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
metadata:
annotations:
@ -480,7 +372,7 @@ metadata:
- apiVersion: example.crossplane.io/v1
blockOwnerDeletion: true
controller: true
kind: XBucket
kind: Bucket
name: example-render
uid: ""
spec:
@ -497,7 +389,7 @@ The `xr.yaml` file contains the composite resource to render:
```yaml
apiVersion: example.crossplane.io/v1
kind: XBucket
kind: Bucket
metadata:
name: example-render
spec:
@ -515,7 +407,7 @@ metadata:
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1
kind: XBucket
kind: Bucket
mode: Pipeline
pipeline:
- step: patch-and-transform
@ -527,7 +419,7 @@ spec:
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
patches:
- type: FromCompositeFieldPath
@ -599,11 +491,6 @@ the container, and `Orphan`, to leave it running.
`Development` runtime this annotation tells the CLI to connect to a Function
running at the specified target. It uses
[gRPC target syntax](https://github.com/grpc/grpc/blob/v1.59.1/doc/naming.md).
* `render.crossplane.io/runtime-docker-env` - When using the `Docker` runtime this
annotation specifies the environment variables that will be used for the
container. This is helpful to e.g. control KCL registry access to use a different
registry. The annotations value is a comma separated string of key=value pairs
e.g. "key1=value1,key2=value2".
## Verify a Composition
@ -635,106 +522,6 @@ composite`.
Composition.
{{< /hint >}}
## Composition validation
When creating a Composition, Crossplane automatically validates its integrity,
checking that the Composition is well formed, for example:
If using `mode: Resources`:
* The `resources` field isn't empty.
* All resources either use a `name` or don't. Compositions can't use both named
and unnamed resources.
* No duplicate resource names.
* Patch sets must have names.
* Patches that require a `fromFieldPath` value provide it.
* Patches that require a `toFieldPath` value provide it.
* Patches that require a `combine` field provide it.
* Readiness checks using `matchString` aren't empty.
* Readiness checks using `matchInteger` isn't `0`.
* Readiness checks requiring a `fieldPath` value provide it.
If using `mode: Pipeline` (Composition Functions):
* The `pipeline` field isn't empty.
* No duplicate step names.
### Composition schema aware validation
Crossplane also performs schema aware
validation of Compositions. Schema validation checks that `patches`,
`readinessChecks` and `connectionDetails` are valid according to the resource
schemas. For example, checking that the source and destination fields of a patch
are valid according to the source and destination resource schema.
{{<hint "note" >}}
Composition schema aware validation is a beta feature. Crossplane enables
beta features by default.
Disable schema aware validation by setting the
`--enable-composition-webhook-schema-validation=false` flag on the Crossplane
pod.
The [Crossplane Pods]({{<ref "./pods#edit-the-deployment">}}) page has
more information on enabling Crossplane flags.
{{< /hint >}}
#### Schema aware validation modes
Crossplane always rejects Compositions in case of integrity errors.
Set the schema aware validation mode to configure how Crossplane handles both
missing resource schemas and schema aware validation errors.
{{<hint "note" >}}
If a resource schema is missing, Crossplane skips schema aware validation
but still returns an error for integrity errors and a warning or an error
for the missing schemas.
{{< /hint >}}
The following modes are available:
{{< table "table table-sm table-striped" >}}
| Mode | Missing Schema | Schema Aware Error | Integrity Error |
| -------- | -------------- |--------------------|-----------------|
| `warn` | Warning | Warning | Error |
| `loose` | Warning | Error | Error |
| `strict` | Error | Error | Error |
{{< /table >}}
Change the validation mode for a Composition with the
{{<hover label="mode" line="5">}}crossplane.io/composition-schema-aware-validation-mode{{</hover>}}
annotation.
If not specified, the default mode is `warn`.
For example, to enable `loose` mode checking set the annotation value to
{{<hover label="mode" line="5">}}loose{{</hover>}}.
```yaml {copy-lines="none",label="mode"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
annotations:
crossplane.io/composition-schema-aware-validation-mode: loose
# Removed for brevity
spec:
# Removed for brevity
```
{{<hint "important" >}}
Validation modes also apply to Compositions defined by Configuration packages.
Depending on the mode configured in the Composition, schema aware validation
issues may result in warnings or the rejection of the Composition.
View the Crossplane logs for validation warnings.
Crossplane sets a Configuration as unhealthy if there are validation errors.
View the Configuration details with `kubectl describe configuration` to see the
specific errors.
{{< /hint >}}
## Write a composition function
Composition functions let you replace complicated Compositions with code written
@ -816,8 +603,8 @@ which composed resources it should create or update.
If the function needs __extra resources__ to determine the desired state it can
request any cluster-scoped resource Crossplane already has access to, either by
by name or labels through the returned RunFunctionResponse. Crossplane then
calls the function again including the requested __extra resources__ and the
name or labels through the returned RunFunctionResponse. Crossplane then calls
the function again including the requested __extra resources__ and the
__context__ returned by the Function itself alongside the same __input__,
__observed__ and __desired state__ of the previous RunFunctionRequest. Functions
can iteratively request __extra resources__ if needed, but to avoid endlessly
@ -827,13 +614,8 @@ stable, so the Function returns the same exact request two times in a row.
Crossplane errors if stability isn't reached after 5 iterations.
{{<hint "tip">}}
<!-- vale write-good.Weasel = NO -->
<!-- Disable Weasel to say "usually", which is correct in this context. -->
A _composed_ resource is a resource created by a composite resource. Composed
resources are usually Crossplane managed resources (MRs), but they can be any
kind of Crossplane resource. For example a composite resource could also create
a ProviderConfig, or another kind of composite resource.
<!-- vale write-good.Weasel = YES -->
resources can be any kind of Kubernetes resource.
{{</hint>}}
### Observed state
@ -843,7 +625,7 @@ sends it to the composition function as part of the observed state.
```yaml
apiVersion: example.crossplane.io/v1
kind: XBucket
kind: Bucket
metadata:
name: example-render
spec:
@ -923,7 +705,7 @@ For example, if all a function wants is to make sure an S3 bucket in region
resources.
```yaml
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -955,7 +737,7 @@ metadata:
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1
kind: XBucket
kind: Bucket
mode: Pipeline
pipeline:
- step: patch-and-transform
@ -967,7 +749,7 @@ spec:
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
patches:
- type: FromCompositeFieldPath
@ -987,8 +769,3 @@ that isn't desired state. Functions can use context for this. Any function can
write to the pipeline context. Crossplane passes the context to all following
functions. When Crossplane has called all functions it discards the pipeline
context.
Crossplane can write context too. If you enable the alpha
[composition environment]({{<ref "environment-configs">}}) feature Crossplane
writes the environment to the top-level context field
`apiextensions.crossplane.io/environment`.

View File

@ -1,10 +1,10 @@
---
title: Environment Configurations
title: Environment Configs
weight: 75
state: beta
alphaVersion: "1.11"
betaVersion: "1.18"
description: "Environment Configurations or EnvironmentConfigs are an in-memory datastore used in Compositions"
description: "Environment Configs or EnvironmentConfigs are an in-memory datastore used in Compositions"
---
<!--
@ -472,7 +472,7 @@ spec:
resources:
- name: vpc
base:
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: VPC
spec:
forProvider:

View File

@ -1,73 +0,0 @@
---
title: Concepts
weight: 50
description: Understand Crossplane's core components
---
Crossplane extends Kubernetes allowing it to create and manage
resources external to the Kubernetes cluster. Crossplane enables platform
engineers to create custom APIs and abstractions combining both native
Kubernetes resources and cloud resources under a single control plane.
With custom APIs, the platform users, like developers, don't need to know
any details about the underlying resources or requirements.
The platform users only need to know the details exposed by the platform, like
`big` or `small` or `US` or `EU`. Platform users don't need to know any details
about the underlying provider like instance type or region names.
Crossplane uses multiple core components to manage the various elements of
building and managing external resources through Kubernetes.
* [**The Crossplane pods**]({{<ref "./pods">}}) include the core Crossplane pod and
Crossplane RBAC manager pod. Together these pods manage all Crossplane
components and resources.
* [**Providers**]({{<ref "./providers">}}) connect Kubernetes to any external
provider, like AWS, Azure or GCP. Providers translate Kubernetes native
manifests and API calls into external API calls. Providers are responsible for
creating, deleting and managing the lifecycle of their resources.
* [**Managed resources**]({{<ref "./managed-resources">}}) are Kubernetes objects
representing things the Provider created outside of Kubernetes. Creating a
managed resource in Kubernetes requires a Provider to create a resource.
Deleting a managed resource requires a Provider to delete the associated
external resource.
* [**Compositions**]({{<ref "./compositions">}}) are a template of managed
resources. Compositions describe more complex deployments, combining multiple
managed resources and any resource customizations, like the size of a database
or the cloud provider region.
* [**Composite Resource Definitions**]({{<ref "./composite-resource-definitions">}})
represent a custom API, created by platform engineers and consumed by
developers or end users. Composite resource definitions use an OpenAPIv3
schema to further extend Kubernetes with custom API endpoints, revisions and
more.
* [**Composite Resources**]({{<ref "./composite-resources">}}) represent all the
objects created by a user calling the custom API. Every time a user access the
custom API Crossplane creates a single Composite Resource and links all
the related managed resources to it.
* [**Claims**]({{<ref "./claims">}}) are like Composite Resources, but exist
in a Kubernetes namespace. Every Claim links to a single cluster scoped
Composite Resource. Platform users create Claims in their unique namespace,
isolating their resources from other teams in other namespaces.
* [**EnvironmentConfigs**]({{<ref "./environment-configs">}}) are an in-memory
data store, like a Kubernetes ConfigMap. EnvironmentConfigs are useful for
custom resource mapping or storing and retrieving data across Claims and
Composite Resources.
* [**Usages**]({{<ref "./usages">}}) defining critical resources or custom
dependency mappings. Usages can prevent Crossplane from deleting or can
ensure that a parent resource waits for Crossplane to delete all child
resources first.
* [**Packages**]({{<ref "./packages">}}) are a convenient way to package up an
entire custom platform and define any other Crossplane related requirements.
Packages define how to install Providers, custom APIs or composition functions.
* [**ImageConfigs**]({{<ref "./image-configs">}}) are for centralized control
of the configuration of Crossplane package images.

View File

@ -1,207 +0,0 @@
---
title: Claims
weight: 60
description: "Claims are a way to consume Crossplane resources with namespace scoping"
---
Claims represents a set of managed resources as a single
Kubernetes object, inside a namespace.
Users create claims when they access the
custom API, defined in the CompositeResourceDefinition.
{{< hint "tip" >}}
Claims are like [composite resources]({{<ref "./composite-resources">}}). The
difference between Claims and composite resources is Crossplane can create
Claims in a namespace, while composite resources are cluster scoped.
{{< /hint >}}
{{<expand "Confused about Compositions, XRDs, XRs and Claims?" >}}
Crossplane has four core components that users commonly mix up:
* [Compositions]({{<ref "./compositions">}}) - A template to define how to create resources.
* [Composite Resource Definition]({{<ref "./composite-resource-definitions">}})
(`XRD`) - A custom API specification.
* [Composite Resources]({{<ref "./composite-resources">}}) (`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`) - This page. Like a Composite Resource, but
with namespace scoping.
{{</expand >}}
## Creating a Claim
Creating a Claim requires a
[Composition]({{<ref "./compositions">}}) and a
[CompositeResourceDefinition]({{<ref "./composite-resource-definitions">}})
(`XRD`) already installed.
{{<hint "note" >}}
The XRD must
[enable Claims]({{<ref "./composite-resource-definitions#enable-claims">}}).
{{< /hint >}}
The Composition defines the set of resources to create.
The XRD defines the custom API users call to request the set of resources.
![Diagram of the relationship of Crossplane components](/media/composition-how-it-works.svg)
For example,
this {{<hover label="xrd1" line="2">}}CompositeResourceDefinition{{</hover>}}
creates a composite resource API endpoint
{{<hover label="xrd1" line="4">}}xmydatabases.example.org{{</hover>}} and
enables a Claim API endpoint
{{<hover label="xrd1" line="11">}}database.example.org{{</hover>}}
```yaml {label="xrd1",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xmydatabases.example.org
spec:
group: example.org
names:
kind: XMyDatabase
plural: xmydatabases
claimNames:
kind: Database
plural: databases
# Removed for brevity
```
The Claim uses the XRD's
{{<hover label="xrd1" line="11">}}kind{{</hover>}} API endpoint to request
resources.
The Claim's {{<hover label="xrd1" line="1">}}apiVersion{{</hover>}} matches
the XRD {{<hover label="xrd1" line="6">}}group{{</hover>}} and the
{{<hover label="claim1" line="2">}}kind{{</hover>}} matches the XRD
{{<hover label="xrd1" line="11">}}claimNames.kind{{</hover>}}
```yaml {label="claim1",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: database
metadata:
name: my-claimed-database
spec:
# Removed for brevity
```
When a user creates a Claim in a namespace Crossplane also creates a composite
resource.
Use {{<hover label="claimcomp" line="1">}}kubectl describe{{</hover>}} on the
Claim to view the related composite resource.
The {{<hover label="claimcomp" line="6">}}Resource Ref{{</hover>}} is the
composite resource Crossplane created for this Claim.
```shell {label="claimcomp",copy-lines="1"}
kubectl describe database.example.org/my-claimed-database
Name: my-claimed-database
API Version: example.org/v1alpha1
Kind: database
Spec:
Resource Ref:
API Version: example.org/v1alpha1
Kind: XMyDatabase
Name: my-claimed-database-rr4ll
# Removed for brevity.
```
Use {{<hover label="getcomp" line="1">}}kubectl describe{{</hover>}} on the
composite resource to view the
{{<hover label="getcomp" line="6">}}Claim Ref{{</hover>}} linking the
composite resource to the original Claim.
```shell {label="getcomp",copy-lines="1"}
kubectl describe xmydatabase.example.org/my-claimed-database-rr4ll
Name: my-claimed-database-rr4ll
API Version: example.org/v1alpha1
Kind: XMyDatabase
Spec:
Claim Ref:
API Version: example.org/v1alpha1
Kind: database
Name: my-claimed-database
Namespace: default
```
{{<hint "note" >}}
Crossplane supports directly creating composite resources. Claims allow
namespace scoping and isolation for users consuming the custom APIs.
If you don't use namespaces in your Kubernetes deployment Claims aren't necessary.
{{< /hint >}}
### Claiming existing composite resources
By default, creating a Claim creates a new composite resource. Claims can also
link to existing composite resources.
A use case for claiming existing composite resources may be slow to provision
resources. Composite resources can be pre-provisioned and a Claim can
use those resources without waiting for their creation.
Set the Claim's {{<hover label="resourceref" line="6">}}resourceRef{{</hover>}}
and match the pre-existing composite resource
{{<hover label="resourceref" line="9">}}name{{</hover>}}.
```yaml {label="resourceref",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: database
metadata:
name: my-claimed-database
spec:
resourceRef:
apiVersion: example.org/v1alpha1
kind: XMyDatabase
name: my-pre-created-xr
```
If a Claim specifies a
{{<hover label="resourceref" line="6">}}resourceRef{{</hover>}} that doesn't
exist, Crossplane doesn't create a composite resource.
{{<hint "note" >}}
All Claims have a
{{<hover label="resourceref" line="6">}}resourceRef{{</hover>}}. Manually
defining the
{{<hover label="resourceref" line="6">}}resourceRef{{</hover>}}
isn't required. Crossplane fills in the
{{<hover label="resourceref" line="6">}}resourceRef{{</hover>}}
with the information from the composite resource created for the Claim.
{{< /hint >}}
## Claim connection secrets
If a Claim expects connection secrets the Claim must define a
{{<hover label="claimSec" line="6">}}writeConnectionSecretToRef{{</hover>}}
object.
The
{{<hover label="claimSec" line="6">}}writeConnectionSecretToRef{{</hover>}}
object defines the name of the Kubernetes secret object where Crossplane saves
the connection details.
{{<hint "note" >}}
The Crossplane creates the secret object in the same namespace as the Claim.
{{< /hint >}}
For example, to a new secret object named
{{<hover label="claimSec" line="7">}}my-claim-secret{{</hover>}} use
{{<hover label="claimSec" line="6">}}writeConnectionSecretToRef{{</hover>}} with
the
{{<hover label="claimSec" line="7">}}name: my-claim-secret{{</hover>}}.
```yaml {label="claimSec"}
apiVersion: example.org/v1alpha1
kind: database
metadata:
name: my-claimed-database
spec:
writeConnectionSecretToRef:
name: my-claim-secret
```
For more information on connection secrets read the [Connection Secrets knowledge base article]({{<ref "connection-details">}}).

View File

@ -1,482 +0,0 @@
---
title: Composite Resources
weight: 50
description: "Composite resources, an XR or XRs, represent a collection of related cloud resources."
---
A composite resource represents a set of managed resources as a single
Kubernetes object. Crossplane creates composite resources when users access a
custom API, defined in the CompositeResourceDefinition.
{{<hint "tip" >}}
Composite resources are a _composite_ of managed resources.
A _Composition_ defines how to _compose_ the managed resources together.
{{< /hint >}}
{{<expand "Confused about Compositions, XRDs, XRs and Claims?" >}}
Crossplane has four core components that users commonly mix up:
* [Compositions]({{<ref "./compositions">}}) - A template to define how to create resources.
* [Composite Resource Definition]({{<ref "./composite-resource-definitions">}})
(`XRD`) - A custom API specification.
* Composite Resource (`XR`) - This page. Created by
using the custom API defined in a Composite Resource Definition. XRs use the
Composition template to create new managed resources.
* [Claims]({{<ref "./claims" >}}) (`XRC`) - Like a Composite Resource, but
with namespace scoping.
{{</expand >}}
## Creating composite resources
Creating composite resources requires a
[Composition]({{<ref "./compositions">}}) and a
[CompositeResourceDefinition]({{<ref "./composite-resource-definitions">}})
(`XRD`).
The Composition defines the set of resources to create.
The XRD defines the custom API users call to request the set of resources.
![Diagram of the relationship of Crossplane components](/media/composition-how-it-works.svg)
XRDs define the API used to create a composite resource.
For example,
this {{<hover label="xrd1" line="2">}}CompositeResourceDefinition{{</hover>}}
creates a custom API endpoint
{{<hover label="xrd1" line="4">}}xmydatabases.example.org{{</hover>}}.
```yaml {label="xrd1",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xmydatabases.example.org
spec:
group: example.org
names:
kind: xMyDatabase
plural: xmydatabases
# Removed for brevity
```
When a user calls the custom API,
{{<hover label="xrd1" line="4">}}xmydatabases.example.org{{</hover>}},
Crossplane chooses the Composition to use based on the Composition's
{{<hover label="typeref" line="6">}}compositeTypeRef{{</hover>}}
```yaml {label="typeref",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: my-composition
spec:
compositeTypeRef:
apiVersion: example.org/v1alpha1
kind: xMyDatabase
# Removed for brevity
```
The Composition
{{<hover label="typeref" line="6">}}compositeTypeRef{{</hover>}} matches the
XRD {{<hover label="xrd1" line="6">}}group{{</hover>}} and
{{<hover label="xrd1" line="9">}}kind{{</hover>}}.
Crossplane creates the resources defined in the matching Composition and
represents them as a single `composite` resource.
```shell{copy-lines="1"}
kubectl get composite
NAME SYNCED READY COMPOSITION AGE
my-composite-resource True True my-composition 4s
```
### Naming external resources
By default, managed resources created by a composite resource have the name of
the composite resource, followed by a random suffix.
<!-- vale Google.FirstPerson = NO -->
<!-- vale Crossplane.Spelling = NO -->
For example, a composite resource named "my-composite-resource" creates external
resources named "my-composite-resource-fqvkw."
<!-- vale Google.FirstPerson = YES -->
<!-- vale Crossplane.Spelling = YES -->
Resource names can be deterministic by applying an
{{<hover label="annotation" line="5">}}annotation{{</hover>}} to the composite
resource.
```yaml {label="annotation",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
annotations:
crossplane.io/external-name: my-custom-name
# Removed for brevity
```
Inside the Composition, use a
{{<hover label="comp" line="10">}}patch{{</hover>}}
to apply the external-name to the resources.
The {{<hover label="comp" line="11">}}fromFieldPath{{</hover>}} patch copies the
{{<hover label="comp" line="11">}}metadata.annotations{{</hover>}} field from
the composite resource to the
{{<hover label="comp" line="12">}}metadata.annotations{{</hover>}} inside the
managed resource.
{{<hint "note" >}}
If a managed resource has the `crossplane.io/external-name` annotation
Crossplane uses the annotation value to name the external resource.
{{</hint >}}
```yaml {label="comp",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: my-composition
spec:
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: database
base:
# Removed for brevity
patches:
- fromFieldPath: metadata.annotations
toFieldPath: metadata.annotations
```
For more information on using `function-patch-and-transform` to patch
resources refer to the
[Function Patch and Transform]({{<ref "../guides/function-patch-and-transform">}})
documentation.
### Composition selection
Select a specific Composition for a composite resource to use with
{{<hover label="compref" line="6">}}compositionRef{{</hover>}}
{{<hint "important">}}
The selected Composition must allow the composite resource to use it with a
`compositeTypeRef`. Read more about the `compositeTypeRef` field in the
[Enable Composite Resources]({{<ref "./compositions#enable-composite-resources">}})
section of the Composition documentation.
{{< /hint >}}
```yaml {label="compref",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
spec:
compositionRef:
name: my-other-composition
# Removed for brevity
```
A composite resource can also select a Composition based on labels instead of
the exact name with a
{{<hover label="complabel" line="6">}}compositionSelector{{</hover>}}.
Inside the {{<hover label="complabel" line="7">}}matchLabels{{</hover>}} section
provide one or more Composition labels to match.
```yaml {label="complabel",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
spec:
compositionSelector:
matchLabels:
environment: production
# Removed for brevity
```
### Composition revision policy
Crossplane tracks changes to Compositions as
[Composition revisions]({{<ref "composition-revisions">}}) .
A composite resource can use
a {{<hover label="comprev" line="6">}}compositionUpdatePolicy{{</hover>}} to
manually or automatically reference newer Composition revisions.
The default
{{<hover label="comprev" line="6">}}compositionUpdatePolicy{{</hover>}} is
"Automatic." Composite resources automatically use the latest Composition
revision.
Change the policy to
{{<hover label="comprev" line="6">}}Manual{{</hover>}} to prevent composite
resources from automatically upgrading.
```yaml {label="comprev",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
spec:
compositionUpdatePolicy: Manual
# Removed for brevity
```
### Composition revision selection
Crossplane records changes to Compositions as
[Composition revisions]({{<ref "composition-revisions">}}).
A composite resource can
select a specific Composition revision.
Use {{<hover label="comprevref" line="6">}}compositionRevisionRef{{</hover>}} to
select a specific Composition revision by name.
For example, to select a specific Composition revision use the name of the
desired Composition revision.
```yaml {label="comprevref",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
spec:
compositionUpdatePolicy: Manual
compositionRevisionRef:
name: my-composition-b5aa1eb
# Removed for brevity
```
{{<hint "note" >}}
Find the Composition revision name from
{{<hover label="getcomprev" line="1">}}kubectl get compositionrevision{{</hover>}}
```shell {label="getcomprev",copy-lines="1"}
kubectl get compositionrevision
NAME REVISION XR-KIND XR-APIVERSION AGE
my-composition-5c976ad 1 xmydatabases example.org/v1alpha1 65m
my-composition-b5aa1eb 2 xmydatabases example.org/v1alpha1 64m
```
{{< /hint >}}
A Composite resource can also select Composition revisions based on labels
instead of the exact name with a
{{<hover label="comprevsel" line="6">}}compositionRevisionSelector{{</hover>}}.
Inside the {{<hover label="comprevsel" line="7">}}matchLabels{{</hover>}}
section provide one or more Composition revision labels to match.
```yaml {label="comprevsel",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
spec:
compositionRevisionSelector:
matchLabels:
channel: dev
# Removed for brevity
```
### Manage connection secrets
When a composite resource creates resources, Crossplane provides any
[connection secrets]({{<ref "./managed-resources#writeconnectionsecrettoref">}})
to the composite resource.
{{<hint "important" >}}
A resource may only access connection secrets allowed by the XRD. By
default XRDs provide access to all connection secrets generated by managed
resources.
Read more about [managing connection secrets]({{<ref "./composite-resource-definitions#manage-connection-secrets">}})
in the XRD documentation.
{{< /hint >}}
Use
{{<hover label="writesecret" line="6">}}writeConnectionSecretToRef{{</hover>}}
to specify where the composite resource writes their connection secrets to.
For example, this composite resource saves the connection secrets in a
Kubernetes secret object named
{{<hover label="writesecret" line="7">}}my-secret{{</hover>}} in the namespace
{{<hover label="writesecret" line="8">}}crossplane-system{{</hover>}}.
```yaml {label="writesecret",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
spec:
writeConnectionSecretToRef:
name: my-secret
namespace: crossplane-system
# Removed for brevity
```
Composite resources can write connection secrets to an
[external secret store]({{<ref "../guides/vault-as-secret-store">}}),
like HashiCorp Vault.
{{<hint "important" >}}
External secret stores are an alpha feature. Alpha features aren't enabled by
default.
{{< /hint >}}
Use the {{<hover label="publishsecret"
line="6">}}publishConnectionDetailsTo{{</hover>}} field to save connection
secrets to an external secrets store.
```yaml {label="publishsecret",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
spec:
publishConnectionDetailsTo:
name: my-external-secret-store
# Removed for brevity
```
Read the [External Secrets Store]({{<ref "../guides/vault-as-secret-store">}}) documentation for more information on using
external secret stores.
For more information on connection secrets read the [Connection Secrets knowledge base article]({{<ref "connection-details">}}).
### Pausing composite resources
<!-- vale Google.WordList = NO -->
Crossplane supports pausing composite resources. A paused composite resource
doesn't check or make changes on its external resources.
<!-- vale Google.WordList = YES -->
To pause a composite resource apply the
{{<hover label="pause" line="4">}}crossplane.io/paused{{</hover>}} annotation.
```yaml {label="pause",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: xMyDatabase
metadata:
name: my-composite-resource
annotations:
crossplane.io/paused: "true"
spec:
# Removed for brevity
```
## Verify composite resources
Use
{{<hover label="getcomposite" line="1">}}kubectl get composite{{</hover>}}
to view all the composite resources Crossplane created.
```shell{copy-lines="1",label="getcomposite"}
kubectl get composite
NAME SYNCED READY COMPOSITION AGE
my-composite-resource True True my-composition 4s
```
Use `kubectl get` for the specific custom API endpoint to view
only those resources.
```shell {copy-lines="1"}
kubectl get xMyDatabase.example.org
NAME SYNCED READY COMPOSITION AGE
my-composite-resource True True my-composition 12m
```
Use
{{<hover label="desccomposite" line="1">}}kubectl describe composite{{</hover>}}
to view the linked
{{<hover label="desccomposite" line="16">}}Composition Ref{{</hover>}},
and unique managed resources created in the
{{<hover label="desccomposite" line="22">}}Resource Refs{{</hover>}}.
```yaml {copy-lines="1",label="desccomposite"}
kubectl describe composite my-composite-resource
Name: my-composite-resource
API Version: example.org/v1alpha1
Kind: xMyDatabase
Spec:
Composition Ref:
Name: my-composition
Composition Revision Ref:
Name: my-composition-cf2d3a7
Composition Update Policy: Automatic
Resource Refs:
API Version: s3.aws.upbound.io/v1beta1
Kind: Bucket
Name: my-composite-resource-fmrks
API Version: dynamodb.aws.upbound.io/v1beta1
Kind: Table
Name: my-composite-resource-wnr9t
# Removed for brevity
```
### Composite resource conditions
The conditions of composite resources match the conditions of their managed
resources.
Read the
[conditions section]({{<ref "./managed-resources#conditions">}}) of the
managed resources documentation for details.
## Composite resource labels
Crossplane adds labels to composite resources to show their relationship to
other Crossplane components.
### Composite label
Crossplane adds the
{{<hover label="complabel" line="4">}} crossplane.io/composite{{</hover>}} label
to all composite resources. The label matches the name of the composite.
Crossplane applies the composite label to any managed resource created by a
composite, creating a reference between the managed resource and owning
composite resource.
```shell {label="claimname",copy-lines="1"}
kubectl describe xmydatabase.example.org/my-claimed-database-x9rx9
Name: my-claimed-database2-x9rx9
Namespace:
Labels: crossplane.io/composite=my-claimed-database-x9rx9
```
### Claim name label
Crossplane adds the
{{<hover label="claimname" line="4">}}crossplane.io/claim-name{{</hover>}}
label to composite resources created from a Claim. The label indicates the name
of the Claim linked to this composite resource.
```shell {label="claimname",copy-lines="1"}
kubectl describe xmydatabase.example.org/my-claimed-database-x9rx9
Name: my-claimed-database2-x9rx9
Namespace:
Labels: crossplane.io/claim-name=my-claimed-database
```
Composite resources created directly, without using a Claim, don't have a
{{<hover label="claimname" line="4">}}crossplane.io/claim-name{{</hover>}}
label.
### Claim namespace label
Crossplane adds the
{{<hover label="claimname" line="4">}}crossplane.io/claim-namespace{{</hover>}}
label to composite resources created from a Claim. The label indicates the
namespace of the Claim linked to this composite resource.
```shell {label="claimname",copy-lines="1"}
kubectl describe xmydatabase.example.org/my-claimed-database-x9rx9
Name: my-claimed-database2-x9rx9
Namespace:
Labels: crossplane.io/claim-namespace=default
```
Composite resources created directly, without using a Claim, don't have a
{{<hover label="claimname" line="4">}}crossplane.io/claim-namespace{{</hover>}}
label.

View File

@ -1,674 +0,0 @@
---
title: Connection Details
weight: 110
description: "How to create and manage connection details across Crossplane managed resources, composite resources, Compositions and Claims"
---
Using connection details in Crossplane requires the following components:
* Defining the `writeConnectionSecretToRef.name` in a [Claim]({{<ref "/master/concepts/claims#claim-connection-secrets">}}).
* Defining the `writeConnectionSecretsToNamespace` value in the [Composition]({{<ref "/master/concepts/compositions#composite-resource-combined-secret">}}).
* Define the `writeConnectionSecretToRef` name and namespace for each resource in the
[Composition]({{<ref "/master/concepts/compositions#composed-resource-secrets">}}).
* Define the list of secret keys produced by each composed resource with in the
[Composition]({{<ref "/master/concepts/compositions">}}).
* Optionally, define the `connectionSecretKeys` in a
[CompositeResourceDefinition]({{<ref "/master/concepts/composite-resource-definitions#manage-connection-secrets">}}).
{{<hint "note">}}
This guide discusses creating Kubernetes secrets.
Crossplane also supports using external secret stores like [HashiCorp Vault](https://www.vaultproject.io/).
Read the [external secrets store guide]({{<ref "../guides/vault-as-secret-store">}}) for more information on using Crossplane
with an external secret store.
{{</hint >}}
## Background
When a [Provider]({{<ref "/master/concepts/providers">}}) creates a managed
resource, the resource may generate resource-specific details. These details can include
usernames, passwords or connection details like an IP address.
Crossplane refers to this information as the _connection details_ or
_connection secrets_.
The Provider
defines what information to present as a _connection
detail_ from a managed resource.
<!-- vale gitlab.SentenceLength = NO -->
<!-- wordy because of type names -->
When a managed resource is part of a
[Composition]({{<ref "/master/concepts/compositions">}}), the Composition,
[Composite Resource Definition]({{<ref "/master/concepts/composite-resource-definitions">}})
and optionally, the
[Claim]({{<ref "/master/concepts/claims">}}) define what details are visible
and where they're stored.
<!-- vale gitlab.SentenceLength = YES -->
{{<hint "note">}}
All the following examples use the same set of Compositions,
CompositeResourceDefinitions and Claims.
All examples rely on
[provider-aws-iam](https://github.com/crossplane-contrib/provider-upjet-aws)
to create resources.
{{<expand "Reference Composition" >}}
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xsecrettest.example.org
spec:
writeConnectionSecretsToNamespace: other-namespace
compositeTypeRef:
apiVersion: example.org/v1alpha1
kind: XSecretTest
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
userSelector:
matchControllerRef: true
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: password
type: FromConnectionSecretKey
fromConnectionSecretKey: password
- name: key
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.secret
- name: smtp
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.ses_smtp_password_v4
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
type: Format
fmt: "%s-secret1"
- name: user
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: User
spec:
forProvider: {}
- name: user2
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: User
metadata:
labels:
docs.crossplane.io: user
spec:
forProvider: {}
- name: key2
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
userSelector:
matchLabels:
docs.crossplane.io: user
writeConnectionSecretToRef:
namespace: docs
name: key2
connectionDetails:
- name: key2-user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: key2-password
type: FromConnectionSecretKey
fromConnectionSecretKey: password
- name: key2-secret
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.secret
- name: key2-smtp
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.ses_smtp_password_v4
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
type: Format
fmt: "%s-secret2"
```
{{</expand >}}
{{<expand "Reference CompositeResourceDefinition" >}}
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xsecrettests.example.org
spec:
group: example.org
connectionSecretKeys:
- username
- password
- attribute.secret
- attribute.ses_smtp_password_v4
- key2-user
- key2-pass
- key2-secret
- key2-smtp
names:
kind: XSecretTest
plural: xsecrettests
claimNames:
kind: SecretTest
plural: secrettests
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
```
{{</ expand >}}
{{<expand "Reference Claim" >}}
```yaml
apiVersion: example.org/v1alpha1
kind: SecretTest
metadata:
name: test-secrets
namespace: default
spec:
writeConnectionSecretToRef:
name: my-access-key-secret
```
{{</expand >}}
{{</hint >}}
## Connection secrets in a managed resource
<!-- vale gitlab.Substitutions = NO -->
<!-- vale gitlab.SentenceLength = NO -->
<!-- under 25 words -->
When a managed resource creates connection secrets, Crossplane can write the
secrets to a
[Kubernetes secret]({{<ref "/master/concepts/managed-resources#publish-secrets-to-kubernetes">}})
or an
[external secret store]({{<ref "/master/concepts/managed-resources#publish-secrets-to-an-external-secrets-store">}}).
<!-- vale gitlab.SentenceLength = YES -->
<!-- vale gitlab.Substitutions = YES -->
Creating an individual managed resource shows the connection secrets the
resource creates.
{{<hint "note" >}}
Read the [managed resources]({{<ref "/master/concepts/managed-resources">}})
documentation for more information on configuring resources and storing
connection secrets for individual resources.
{{< /hint >}}
For example, create an
{{<hover label="mr" line="2">}}AccessKey{{</hover>}} resource and save the
connection secrets in a Kubernetes secret named
{{<hover label="mr" line="12">}}my-accesskey-secret{{</hover>}}
in the
{{<hover label="mr" line="11">}}default{{</hover>}} namespace.
```yaml {label="mr"}
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
metadata:
name: test-accesskey
spec:
forProvider:
userSelector:
matchLabels:
docs.crossplane.io: user
writeConnectionSecretToRef:
namespace: default
name: my-accesskey-secret
```
View the Kubernetes secret to see the connection details from the managed
resource.
This includes an
{{<hover label="mrSecret" line="11">}}attribute.secret{{</hover>}},
{{<hover label="mrSecret" line="12">}}attribute.ses_smtp_password_v4{{</hover>}},
{{<hover label="mrSecret" line="13">}}password{{</hover>}} and
{{<hover label="mrSecret" line="14">}}username{{</hover>}}
```yaml {label="mrSecret",copy-lines="1"}
kubectl describe secret my-accesskey-secret
Name: my-accesskey-secret
Namespace: default
Labels: <none>
Annotations: <none>
Type: connection.crossplane.io/v1alpha1
Data
====
attribute.secret: 40 bytes
attribute.ses_smtp_password_v4: 44 bytes
password: 40 bytes
username: 20 bytes
```
Compositions and CompositeResourceDefinitions require the exact names of the
secrets generated by a resource.
## Connection secrets in Compositions
Resources in a Composition that create connection details still create a
secret object containing their connection details.
Crossplane also generates
another secret object for each composite resource,
containing the secrets from all the defined resources.
For example, a Composition defines two
{{<hover label="comp1" line="9">}}AccessKey{{</hover>}}
objects.
Each {{<hover label="comp1" line="9">}}AccessKey{{</hover>}} writes a
connection secrets to the {{<hover label="comp1" line="15">}}name{{</hover>}}
inside the {{<hover label="comp1" line="14">}}namespace{{</hover>}} defined by
the resource
{{<hover label="comp1" line="13">}}writeConnectionSecretToRef{{</hover>}}.
Crossplane also creates a secret object for the entire Composition
saved in the namespace defined by
{{<hover label="comp1" line="4">}}writeConnectionSecretsToNamespace{{</hover>}}
with a Crossplane generated name.
```yaml {label="comp1",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key1
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1-secret
- name: key2
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key2-secret
# Removed for brevity
```
After applying a Claim, view the Kubernetes secrets to see three secret objects
created.
The secret
{{<hover label="compGetSec" line="3">}}key1-secret{{</hover>}} is from the resource
{{<hover label="comp1" line="6">}}key1{{</hover>}},
{{<hover label="compGetSec" line="4">}}key2-secret{{</hover>}} is from the resource
{{<hover label="comp1" line="16">}}key2{{</hover>}}.
Crossplane creates another secret in the namespace
{{<hover label="compGetSec" line="5">}}other-namespace{{</hover>}} with the
secrets from resource in the Composition.
```shell {label="compGetSec",copy-lines="1"}
kubectl get secrets -A
NAMESPACE NAME TYPE DATA AGE
docs key1-secret connection.crossplane.io/v1alpha1 4 4s
docs key2-secret connection.crossplane.io/v1alpha1 4 4s
other-namespace 70975471-c44f-4f6d-bde6-6bbdc9de1eb8 connection.crossplane.io/v1alpha1 0 6s
```
Although Crossplane creates a secret object, by default, Crossplane doesn't add
any data to the object.
```yaml {copy-lines="none"}
kubectl describe secret 70975471-c44f-4f6d-bde6-6bbdc9de1eb8 -n other-namespace
Name: 70975471-c44f-4f6d-bde6-6bbdc9de1eb8
Namespace: other-namespace
Type: connection.crossplane.io/v1alpha1
Data
====
```
The Composition must list the connection secrets to store for each resource.
Use the
{{<hover label="comp2" line="16">}}connectionDetails{{</hover>}} object under
each resource and define the secret keys the resource creates.
{{<hint "warning">}}
You can't change the
{{<hover label="comp2" line="16">}}connectionDetails{{</hover>}}
of a Composition.
You must delete and
recreate the Composition to change the
{{<hover label="comp2" line="16">}}connectionDetails{{</hover>}}.
{{</hint >}}
```yaml {label="comp2",copy-lines="16-20"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
apiVersion: iam.aws.upbound.io/v1beta1
kind: AccessKey
spec:
forProvider:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: password
type: FromConnectionSecretKey
fromConnectionSecretKey: password
- name: key
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.secret
- name: smtp
type: FromConnectionSecretKey
fromConnectionSecretKey: attribute.ses_smtp_password_v4
# Removed for brevity
```
After applying a Claim the composite resource secret object contains the list of
keys listed in the
{{<hover label="comp2" line="16">}}connectionDetails{{</hover>}}.
```shell {copy-lines="1"}
kubectl describe secret -n other-namespace
Name: b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a
Namespace: other-namespace
Type: connection.crossplane.io/v1alpha1
Data
====
username: 20 bytes
attribute.secret: 40 bytes
attribute.ses_smtp_password_v4: 44 bytes
password: 40 bytes
```
{{<hint "important">}}
If a key isn't listed in the
{{<hover label="comp2" line="16">}}connectionDetails{{</hover>}}
it isn't stored in the secret object.
{{< /hint >}}
### Managing conflicting secret keys
If resources produce conflicting keys, create a unique name with a connection
details
{{<hover label="comp3" line="25">}}name{{</hover>}}.
```yaml {label="comp3",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
kind: AccessKey
spec:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: key2
base:
kind: AccessKey
spec:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key2
connectionDetails:
- name: key2-user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
```
The secret object contains both keys,
{{<hover label="comp3Sec" line="9">}}username{{</hover>}}
and
{{<hover label="comp3Sec" line="10">}}key2-user{{</hover>}}
```shell {label="comp3Sec",copy-lines="1"}
kubectl describe secret -n other-namespace
Name: b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a
Namespace: other-namespace
Type: connection.crossplane.io/v1alpha1
Data
====
username: 20 bytes
key2-user: 20 bytes
# Removed for brevity.
```
## Connection secrets in Composite Resource Definitions
The CompositeResourceDefinition (`XRD`), can restrict which secrets keys are
put in the combined secret and provided to a Claim.
By default an XRD writes all secret keys listed in the composed resource
`connectionDetails` to the combined secret object.
Limit the keys passed to the combined secret object and Claims with a
{{<hover label="xrd" line="4">}}connectionSecretKeys{{</hover>}} object.
Inside the {{<hover label="xrd" line="4">}}connectionSecretKeys{{</hover>}} list
the secret key names to create. Crossplane only adds the keys listed to the
combined secret.
{{<hint "warning">}}
When changing the {{<hover label="xrd" line="4">}}connectionSecretKeys{{</hover>}} of an XRD the change isn't immediately reflected.
You have two options to change the keys in the combined secret object.
- Delete and recreate the XRD. This only makes sense if the XRD isn't used as it leads to the deletion of XRs.
- Restart the XR reconciler, which can be done by restarting the Crossplane pod.
{{</hint >}}
For example, an XRD may restrict the secrets to only the
{{<hover label="xrd" line="5">}}username{{</hover>}},
{{<hover label="xrd" line="6">}}password{{</hover>}} and custom named
{{<hover label="xrd" line="7">}}key2-user{{</hover>}} keys.
```yaml {label="xrd",copy-lines="4-12"}
kind: CompositeResourceDefinition
spec:
# Removed for brevity.
connectionSecretKeys:
- username
- password
- key2-user
```
The secret from an individual resource contains all the resources detailed in
the Composition's `connectionDetails`.
```shell {label="xrdSec",copy-lines="1"}
kubectl describe secret key1 -n docs
Name: key1
Namespace: docs
Data
====
password: 40 bytes
username: 20 bytes
attribute.secret: 40 bytes
attribute.ses_smtp_password_v4: 44 bytes
```
The Claim's secret only contains the
keys allowed by the XRD
{{<hover label="xrd" line="4">}}connectionSecretKeys{{</hover>}}
fields.
```shell {label="xrdSec2",copy-lines="2"}
kubectl describe secret my-access-key-secret
Name: my-access-key-secret
Data
====
key2-user: 20 bytes
password: 40 bytes
username: 20 bytes
```
## Secret objects
Compositions create a secret object for each resource and an extra secret
containing all the secrets from all resources.
Crossplane saves the resource secret objects in the location defined by the
resource's
{{<hover label="comp4" line="11">}}writeConnectionSecretToRef{{</hover>}}.
Crossplane saves the combined secret with a Crossplane generated name in the
namespace defined in the Composition's
{{<hover label="comp4" line="4">}}writeConnectionSecretsToNamespace{{</hover>}}.
```yaml {label="comp4",copy-lines="none"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: key
base:
kind: AccessKey
spec:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key1
connectionDetails:
- name: user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
- name: key2
base:
kind: AccessKey
spec:
# Removed for brevity
writeConnectionSecretToRef:
namespace: docs
name: key2
connectionDetails:
- name: key2-user
type: FromConnectionSecretKey
fromConnectionSecretKey: username
```
If a Claim uses a secret, it's stored in the same namespace as the Claim with
the name defined in the Claim's
{{<hover label="claim3" line="7">}}writeConnectionSecretToRef{{</hover>}}.
```yaml {label="claim3",copy-lines="none"}
apiVersion: example.org/v1alpha1
kind: SecretTest
metadata:
name: test-secrets
namespace: default
spec:
writeConnectionSecretToRef:
name: my-access-key-secret
```
After applying the Claim Crossplane creates the following secrets:
* The Claim's secret, {{<hover label="allSec" line="3">}}my-access-key-secret{{</hover>}}
in the Claim's {{<hover label="claim3" line="5">}}namespace{{</hover>}}.
* The first resource's secret object, {{<hover label="allSec" line="4">}}key1{{</hover>}}.
* The second resource's secret object, {{<hover label="allSec" line="5">}}key2{{</hover>}}.
* The composite resource secret object in the
{{<hover label="allSec" line="6">}}other-namespace{{</hover>}} defined by the
Composition's `writeConnectionSecretsToNamespace`.
```shell {label="allSec",copy-lines="none"}
kubectl get secret -A
NAMESPACE NAME TYPE DATA AGE
default my-access-key-secret connection.crossplane.io/v1alpha1 8 29m
docs key1 connection.crossplane.io/v1alpha1 4 31m
docs key2 connection.crossplane.io/v1alpha1 4 31m
other-namespace b0dc71f8-2688-4ebc-818a-bbad6a2c4f9a connection.crossplane.io/v1alpha1 8 31m
```

View File

@ -1,105 +0,0 @@
---
title: Server-Side Apply
state: alpha
alphaVersion: "1.15"
weight: 300
---
Crossplane can use server-side apply to sync claims with composite resources
(XRs), and to sync composite resources with composed resources.
When Crossplane uses server-side apply, the Kubernetes API server helps sync
resources. Using server-side apply makes syncing more predictable and less
buggy.
{{<hint "tip">}}
Server-side apply is a Kubernetes feature. Read more about server-side apply in
the [Kubernetes documentation](https://kubernetes.io/docs/reference/using-api/server-side-apply/).
{{</hint>}}
## Use server-side apply to sync claims with composite resources
When you create a claim, Crossplane creates a corresponding composite resource.
Crossplane keeps the claim in sync with the composite resource. When you change
the claim, Crossplane reflects those changes on the composite resource.
Read the [claims documentation]({{<ref "./claims">}}) to learn more about claims
and how they relate to composite resources.
Crossplane can use server-side apply to keep the claim in sync with the
composite resource.
Use the `--enable-ssa-claims` feature flag to enable using server-side apply.
Read the [Install Crossplane documentation]({{<ref "../software/install#feature-flags">}})
to learn about feature flags.
If you see fields reappearing after you delete them from a claim's `spec`,
enable server-side apply to fix the problem. Enabling server-side apply also
fixes the problem where Crossplane doesn't delete labels and annotations from
the composite resource when you delete them from the claim.
{{<hint "important">}}
When you enable server-side apply, Crossplane is stricter about how it syncs
a claim with its counterpart composite resource:
- The claim's `metadata` syncs to the composite resource's `metadata`.
- The claim's `spec` syncs to the composite resource's `spec`.
- The composite resource's `status` syncs to the claim's `status`.
When you enable server-side apply Crossplane doesn't sync the composite resource's `metadata`
and `spec` back to the claim's `metadata` and `spec`. It also doesn't sync the
claim's `status` to the composite resource's `status`.
{{</hint>}}
## Use server-side apply to sync claims end-to-end
To get the full benefit of server-side apply, use the `--enable-ssa-claims`
feature flag together with composition functions.
When you use composition functions, Crossplane uses server side apply to sync
composite resources with composed resources. Read more about this in the
[composition functions documentation]({{<ref "./compositions#how-composition-functions-work">}}).
```mermaid
graph LR
A(Claim) -- claim server-side apply --> B(Composite Resource)
B -- function server-side apply --> C(Composed Resource)
B -- function server-side apply --> D(Composed Resource)
B -- function server-side apply --> E(Composed Resource)
```
When you use server-side apply end-to-end there is a clear, predictable
propagation of fields from claim to composed resources, and back:
* `metadata` and `spec` flow forwards, from claim to XR to composed resources.
* `status` flows backwards, from composed resources to XR to claim.
{{<hint "important">}}
When you use composition functions, Crossplane is stricter about how it syncs
composite resources (XRs) with composed resources:
- The XR's `metadata` syncs to the composed resource's `metadata`.
- The XR's `spec` syncs to the composed resource's `spec`.
- The composed resource's `status` syncs to the XR's `status`.
When you use composition functions Crossplane doesn't sync the composed resource's `metadata`
and `spec` back to the XR's `metadata` and `spec`.
{{</hint>}}
When Crossplane uses server-side apply end-to-end to sync claims with composed
resources, it deletes fields from a composed resource's `spec` when you
delete fields from the claim's `spec`.
When Crossplane uses server-side apply end-to-end it's also able to merge claim
fields into complex composed resource fields. Objects and arrays of objects are
examples of complex composed resource fields.
{{<hint "tip">}}
Crossplane can only merge complex fields for resources that use server-side
apply merge strategy OpenAPI extensions. Read about these extensions in the
Kubernetes [server-side apply documentation](https://kubernetes.io/docs/reference/using-api/server-side-apply/#merge-strategy).
If you find that Crossplane isn't merging managed resource fields, raise an
issue against the relevant provider. Ask the provider maintainer to add
server-side apply merge strategy extensions to the managed resource.
{{</hint>}}

View File

@ -0,0 +1,6 @@
---
title: Get Started
weight: 40
description: Get started with Crossplane.
---

View File

@ -0,0 +1,743 @@
---
title: Get Started With Composition
weight: 200
---
This guide shows how to create a new kind of custom resource named `App`. When a
user calls the custom resource API to create an `App`, Crossplane creates a
`Deployment` and a `Service`.
**Crossplane calls this _composition_.** The `App` is _composed of_ the
`Deployment` and the `Service`.
{{<hint "tip">}}
The guide shows how to configure composition using YAML, templated YAML, Python,
and KCL. You can pick your preferred language.
{{</hint>}}
An `App` custom resource looks like this:
```yaml
apiVersion: example.crossplane.io/v1
kind: App
metadata:
namespace: default
name: my-app
spec:
image: nginx
status:
replicas: 2 # Copied from the Deployment's status
address: 10.0.0.1 # Copied from the Service's status
```
**The `App` is the custom API Crossplane users use to configure an app.**
When users create an `App` Crossplane creates this `Deployment` and `Service`:
```yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: default
name: my-app-dhj3a
labels:
example.crossplane.io/app: my-app # Copied from the App's name
spec:
replicas: 2
selector:
matchLabels:
example.crossplane.io/app: my-app # Copied from the App's name
template:
metadata:
labels:
example.crossplane.io/app: my-app # Copied from the App's name
spec:
containers:
- name: app
image: nginx # Copied from the App's spec
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
namespace: default
name: my-app-03mda
labels:
example.crossplane.io/app: my-app # Copied from the App's name
spec:
selector:
example.crossplane.io/app: my-app # Copied from the App's name
ports:
- protocol: TCP
port: 8080
targetPort: 80
```
Crossplane builds on Kubernetes, so users can use `kubectl` or any other tool
from the Kubernetes ecosystem to work with apps.
{{<hint "tip">}}
Kubernetes custom resources are just JSON REST APIs, so users can use any tool
that supports REST APIs to work with apps.
{{</hint>}}
## Prerequisites
This guide requires:
* A Kubernetes cluster with at least 2 GB of RAM
* The Crossplane v2 preview [installed on the Kubernetes cluster]({{<ref "install">}})
## Create the custom resource
Follow these steps to create a new kind of custom resource using Crossplane:
1. [Define](#define-the-schema) the schema of the `App` custom resource
1. [Install](#install-the-function) the function you want to use to configure
how Crossplane composes apps
1. [Configure](#configure-the-composition) how Crossplane composes apps
After you complete these steps you can
[use the new `App` custom resource](#use-the-custom-resource).
### Define the schema
Crossplane calls a custom resource that's powered by composition a _composite
resource_, or XR.
{{<hint "note">}}
Kubernetes calls user-defined API resources _custom resources_.
Crossplane calls user-defined API resources that use composition _composite
resources_.
A composite resource is a kind of custom resource.
{{</hint>}}
Create this _composite resource definition_ (XRD) to define the schema of the
new `App` composite resource (XR).
```yaml
apiVersion: apiextensions.crossplane.io/v2
kind: CompositeResourceDefinition
metadata:
name: apps.example.crossplane.io
spec:
scope: Namespaced
group: example.crossplane.io
names:
kind: App
plural: apps
versions:
- name: v1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
image:
description: The app's OCI container image.
type: string
required:
- image
status:
type: object
properties:
replicas:
description: The number of available app replicas.
type: integer
address:
description: The app's IP address.
type: string
```
Save the XRD as `xrd.yaml` and apply it:
```shell
kubectl apply -f xrd.yaml
```
Check that Crossplane has established the XRD:
``` shell {copy-lines="1"}
kubectl get -f xrd.yaml
NAME ESTABLISHED OFFERED AGE
apps.example.crossplane.io True 21s
```
Now that Crossplane has established the XRD, Kubernetes is serving API requests
for the new `App` XR.
Crossplane now knows it's responsible for the new `App` XR, but it doesn't know
what to do when you create or update one. You tell Crossplane what to do by
[installing a function](#install-the-function) and
[configuring a composition](#configure-the-composition).
### Install the function
You can use different _composition functions_ to configure what Crossplane does
when someone creates or updates a composite resource (XR). Composition functions
are like configuration language plugins.
Pick what language to use to configure how Crossplane turns an `App` XR into a
`Deployment` and a `Service`.
{{< tabs >}}
{{< tab "YAML" >}}
YAML is a good choice for small, static compositions. It doesn't support loops
or conditionals.
Create this composition function to install YAML support:
```yaml
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: crossplane-contrib-function-patch-and-transform
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2
```
Save the function as `fn.yaml` and apply it:
```shell
kubectl apply -f fn.yaml
```
Check that Crossplane installed the function:
```shell {copy-lines="1"}
kubectl get -f fn.yaml
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-function-patch-and-transform True True xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2 10s
```
{{< /tab >}}
{{< tab "Templated YAML" >}}
Templated YAML is a good choice if you're used to writing
[Helm charts](https://helm.sh).
Create this composition function to install templated YAML support:
```yaml
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: crossplane-contrib-function-go-templating
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-go-templating:v0.9.2
```
Save the function as `fn.yaml` and apply it:
```shell
kubectl apply -f fn.yaml
```
Check that Crossplane installed the function:
```shell {copy-lines="1"}
kubectl get -f fn.yaml
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-function-go-templating True True xpkg.crossplane.io/crossplane-contrib/function-go-templating:v0.9.2 9s
```
{{< /tab >}}
{{< tab "Python" >}}
Python is a good choice for compositions with dynamic logic. You can use the
full [Python standard library](https://docs.python.org/3/library/index.html).
Create this composition function to install Python support:
```yaml
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: crossplane-contrib-function-python
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-python:v0.1.0
```
Save the function as `fn.yaml` and apply it:
```shell
kubectl apply -f fn.yaml
```
Check that Crossplane installed the function:
```shell {copy-lines="1"}
kubectl get -f fn.yaml
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-function-python True True xpkg.crossplane.io/crossplane-contrib/function-python:v0.1.0 12s
```
{{< /tab >}}
{{< tab "KCL" >}}
[KCL](https://kcl-lang.io) is a good choice for compositions with dynamic logic.
It's fast and sandboxed.
Create this composition function to install KCL support:
```yaml
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: crossplane-contrib-function-kcl
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-kcl:v0.11.2
```
Save the function as `fn.yaml` and apply it:
```shell
kubectl apply -f fn.yaml
```
Check that Crossplane installed the function:
```shell {copy-lines="1"}
kubectl get -f fn.yaml
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-function-kcl True True xpkg.crossplane.io/crossplane-contrib/function-kcl:v0.11.2 6s
```
{{< /tab >}}
{{</ tabs >}}
### Configure the composition
A composition tells Crossplane what functions to call when you create or
update a composite resource (XR).
Create a composition to tell Crossplane what to do when you create or update an
`App` XR.
{{< tabs >}}
{{< tab "YAML" >}}
Create this composition to use YAML to configure Crossplane:
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: app-yaml
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1
kind: App
mode: Pipeline
pipeline:
- step: create-deployment-and-service
functionRef:
name: crossplane-contrib-function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: deployment
base:
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 2
template:
spec:
containers:
- name: app
ports:
- containerPort: 80
patches:
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: metadata.labels[example.crossplane.io/app]
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: spec.selector.matchLabels[example.crossplane.io/app]
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: spec.template.metadata.labels[example.crossplane.io/app]
- type: FromCompositeFieldPath
fromFieldPath: spec.image
toFieldPath: spec.template.spec.containers[0].image
- type: ToCompositeFieldPath
fromFieldPath: status.availableReplicas
toFieldPath: status.replicas
readinessChecks:
- type: MatchCondition
matchCondition:
type: Available
status: "True"
- name: service
base:
apiVersion: v1
kind: Service
spec:
ports:
- protocol: TCP
port: 8080
targetPort: 80
patches:
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: metadata.labels[example.crossplane.io/app]
- type: FromCompositeFieldPath
fromFieldPath: metadata.name
toFieldPath: spec.selector[example.crossplane.io/app]
- type: ToCompositeFieldPath
fromFieldPath: spec.clusterIP
toFieldPath: status.address
readinessChecks:
- type: NonEmpty
fieldPath: spec.clusterIP
```
{{< /tab >}}
{{< tab "Templated YAML" >}}
Create this composition to use templated YAML to configure Crossplane:
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: app-templated-yaml
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1
kind: App
mode: Pipeline
pipeline:
- step: create-deployment-and-service
functionRef:
name: crossplane-contrib-function-go-templating
input:
apiVersion: gotemplating.fn.crossplane.io/v1beta1
kind: GoTemplate
source: Inline
inline:
template: |
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
gotemplating.fn.crossplane.io/composition-resource-name: deployment
{{ if eq (.observed.resources.deployment | getResourceCondition "Available").Status "True" }}
gotemplating.fn.crossplane.io/ready: "True"
{{ end }}
labels:
example.crossplane.io/app: {{ .observed.composite.resource.metadata.name }}
spec:
replicas: 2
selector:
matchLabels:
example.crossplane.io/app: {{ .observed.composite.resource.metadata.name }}
template:
metadata:
labels:
example.crossplane.io/app: {{ .observed.composite.resource.metadata.name }}
spec:
containers:
- name: app
image: {{ .observed.composite.resource.spec.image }}
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
annotations:
gotemplating.fn.crossplane.io/composition-resource-name: service
{{ if (get (getComposedResource . "service").spec "clusterIP") }}
gotemplating.fn.crossplane.io/ready: "True"
{{ end }}
labels:
example.crossplane.io/app: {{ .observed.composite.resource.metadata.name }}
spec:
selector:
example.crossplane.io/app: {{ .observed.composite.resource.metadata.name }}
ports:
- protocol: TCP
port: 8080
targetPort: 80
---
apiVersion: example.crossplane.io/v1
kind: App
status:
replicas: {{ get (getComposedResource . "deployment").status "availableReplicas" | default 0 }}
address: {{ get (getComposedResource . "service").spec "clusterIP" | default "" | quote }}
```
{{< /tab >}}
{{< tab "Python" >}}
Create this composition to use Python to configure Crossplane:
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: app-python
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1
kind: App
mode: Pipeline
pipeline:
- step: create-deployment-and-service
functionRef:
name: crossplane-contrib-function-python
input:
apiVersion: python.fn.crossplane.io/v1beta1
kind: Script
script: |
def compose(req, rsp):
observed_xr = req.observed.composite.resource
rsp.desired.resources["deployment"].resource.update({
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"labels": {"example.crossplane.io/app": observed_xr["metadata"]["name"]},
},
"spec": {
"replicas": 2,
"selector": {"matchLabels": {"example.crossplane.io/app": observed_xr["metadata"]["name"]}},
"template": {
"metadata": {
"labels": {"example.crossplane.io/app": observed_xr["metadata"]["name"]},
},
"spec": {
"containers": [{
"name": "app",
"image": observed_xr["spec"]["image"],
"ports": [{"containerPort": 80}]
}],
},
},
},
})
observed_deployment = req.observed.resources["deployment"].resource
if "status" in observed_deployment:
if "availableReplicas" in observed_deployment["status"]:
rsp.desired.composite.resource.get_or_create_struct("status")["replicas"] = observed_deployment["status"]["availableReplicas"]
if "conditions" in observed_deployment["status"]:
for condition in observed_deployment["status"]["conditions"]:
if condition["type"] == "Available" and condition["status"] == "True":
rsp.desired.resources["deployment"].ready = True
rsp.desired.resources["service"].resource.update({
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"labels": {"example.crossplane.io/app": observed_xr["metadata"]["name"]},
},
"spec": {
"selector": {"example.crossplane.io/app": observed_xr["metadata"]["name"]},
"ports": [{"protocol": "TCP", "port": 8080, "targetPort": 80}],
},
})
observed_service = req.observed.resources["service"].resource
if "spec" in observed_service and "clusterIP" in observed_service["spec"]:
rsp.desired.composite.resource.get_or_create_struct("status")["address"] = observed_service["spec"]["clusterIP"]
rsp.desired.resources["service"].ready = True
```
{{<hint "tip">}}
You can write your own function in Python.
It's a good idea to write your own function for larger configurations. When you
write your own function you can write multiple files of Python. You don't embed
the Python in YAML, so it's easier to use a Python IDE.
Read the [guide to writing a composition function in Python]({{<ref "../guides/write-a-composition-function-in-python">}}).
{{</hint>}}
{{< /tab >}}
{{< tab "KCL" >}}
Create this composition to use KCL to configure Crossplane:
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: app-kcl
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1
kind: App
mode: Pipeline
pipeline:
- step: create-deployment-and-service
functionRef:
name: crossplane-contrib-function-kcl
input:
apiVersion: krm.kcl.dev/v1alpha1
kind: KCLInput
spec:
source: |
observed_xr = option("params").oxr
_desired_deployment = {
apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
annotations = {
"krm.kcl.dev/composition-resource-name" = "deployment"
}
labels = {"example.crossplane.io/app" = observed_xr.metadata.name}
}
spec = {
replicas = 2
selector.matchLabels = {"example.crossplane.io/app" = observed_xr.metadata.name}
template = {
metadata.labels = {"example.crossplane.io/app" = observed_xr.metadata.name}
spec.containers = [{
name = "app"
image = observed_xr.spec.image
ports = [{containerPort = 80}]
}]
}
}
}
observed_deployment = option("params").ocds["deployment"]?.Resource
if any_true([c.type == "Available" and c.status == "True" for c in observed_deployment?.status?.conditions or []]):
_desired_deployment.metadata.annotations["krm.kcl.dev/ready"] = "True"
_desired_service = {
apiVersion = "v1"
kind = "Service"
metadata = {
annotations = {
"krm.kcl.dev/composition-resource-name" = "service"
}
labels = {"example.crossplane.io/app" = observed_xr.metadata.name}
}
spec = {
selector = {"example.crossplane.io/app" = observed_xr.metadata.name}
ports = [{protocol = "TCP", port = 8080, targetPort = 80}]
}
}
observed_service = option("params").ocds["service"]?.Resource
if observed_service?.spec?.clusterIP:
_desired_service.metadata.annotations["krm.kcl.dev/ready"] = "True"
_desired_xr = {
**option("params").dxr
status.address = observed_service?.spec?.clusterIP or ""
status.replicas = observed_deployment?.status?.availableReplicas or 0
}
items = [_desired_deployment, _desired_service, _desired_xr]
```
{{< /tab >}}
{{</ tabs >}}
Save the composition as `composition.yaml` and apply it:
```shell
kubectl apply -f composition.yaml
```
{{<hint "note">}}
A composition can include multiple functions.
Functions can change the results of earlier functions in the pipeline.
Crossplane uses the result returned by the last function.
{{</hint>}}
{{<hint "tip">}}
If you edit this composition to include a different kind of resource you might
need to grant Crossplane access to compose it. Read
[the composition documentation]({{<ref "../composition/compositions#grant-access-to-composed-resources">}})
to learn how to grant Crossplane access.
{{</hint>}}
## Use the custom resource
Crossplane now understands `App` custom resources.
Create an `App`:
```yaml
apiVersion: example.crossplane.io/v1
kind: App
metadata:
namespace: default
name: my-app
spec:
image: nginx
```
Save the `App` as `app.yaml` and apply it:
```shell
kubectl apply -f app.yaml
```
Check that the `App` is ready:
```shell {copy-lines="1"}
kubectl get -f app.yaml
NAME SYNCED READY COMPOSITION AGE
my-app True True app-yaml 56s
```
{{<hint "note">}}
The `COMPOSITION` column shows what composition the `App` is using.
You can create multiple compositions for each kind of XR.
[Read the XR page]({{<ref "../composition/composite-resources">}}) to learn how to
select which composition Crossplane uses.
{{</hint>}}
Check that Crossplane created a `Deployment` and a `Service`:
```shell {copy-lines="1"}
kubectl get deploy,service -l example.crossplane.io/app=my-app
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-app-2r2rk 2/2 2 2 11m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/my-app-xfkzg ClusterIP 10.96.148.56 <none> 8080/TCP 11m
```
{{<hint "tip">}}
Use `kubectl edit -f app.yaml` to edit the `App`'s image. Crossplane updates
the `Deployment`'s image to match.
{{</hint>}}
Delete the `App`.
```shell {copy-lines="1"}
kubectl delete -f app.yaml
```
When you delete the `App`, Crossplane deletes the `Deployment` and `Service`.
## Next steps
Managed resources (MRs) are ready-made Kubernetes custom resources.
Crossplane has an extensive library of managed resources you can use to manage
almost any cloud provider, or cloud native software.
[Get started with managed resources]({{<ref "get-started-with-managed-resources">}})
to learn more about them.
You can use MRs with composition. Try updating your `App` composition to include
an MR.

View File

@ -0,0 +1,239 @@
---
title: Get Started With Managed Resources
weight: 300
---
This guide shows how to install and use a new kind of custom resource called
`Bucket`. When a user calls the custom resource API to create a `Bucket`,
Crossplane creates a bucket in AWS S3.
**Crossplane calls this a _managed resource_**. A managed resource is a
ready-made custom resource that manages something outside of the control plane.
A `Bucket` managed resource looks like this:
```yaml
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
metadata:
namespace: default
name: crossplane-bucket-example
spec:
forProvider:
region: us-east-2
```
{{<hint "note">}}
Kubernetes calls third party API resources _custom resources_.
{{</hint>}}
## Prerequisites
This guide requires:
* A Kubernetes cluster with at least 2 GB of RAM
* The Crossplane v2 preview [installed on the Kubernetes cluster]({{<ref "install">}})
* An AWS account with permissions to create an S3 storage bucket
* AWS [access keys](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-creds)
{{<hint "note">}}
Only AWS managed resources support the Crossplane v2 preview.
<!-- vale gitlab.FutureTense = NO -->
Maintainers will update the managed resources for other systems including Azure,
GCP, Terraform, Helm, GitHub, etc to support Crossplane v2 soon.
<!-- vale gitlab.FutureTense = YES -->
{{</hint>}}
## Install support for the managed resource
Follow these steps to install support for the `Bucket` managed resource:
1. [Install](#install-the-provider) the provider
1. [Save](#save-the-providers-credentials) the provider's credentials as a secret
1. [Configure](#configure-the-provider) the provider to use the secret
After you complete these steps you can
[use the `Bucket` managed resource](#use-the-managed-resource).
### Install the provider
A Crossplane _provider_ installs support for a set of related managed resources.
The AWS S3 provider installs support for all the AWS S3 managed resources.
Create this provider to install the AWS S3 provider:
```yaml {label="provider",copy-lines="all"}
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: crossplane-contrib-provider-aws-s3
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v1.24.0-crossplane-v2-preview.0
```
Save this as `provider.yaml` and apply it:
```shell {label="kube-apply-provider",copy-lines="all"}
kubectl apply -f provider.yaml
```
Check that Crossplane installed the provider:
```shell {copy-lines="1",label="getProvider"}
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-family-aws True True xpkg.crossplane.io/crossplane-contrib/provider-family-aws:v1.24.0-crossplane-v2-preview.0 27s
crossplane-contrib-provider-aws-s3 True True xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v1.24.0-crossplane-v2-preview.0 31s
```
{{<hint "note">}}
The S3 provider installs a second provider, the
{{<hover label="getProvider" line="4">}}crossplane-contrib-provider-family-aws{{</hover >}}.
The family provider manages authentication to AWS across all AWS family
providers.
{{</hint>}}
Crossplane installed the AWS S3 provider. The provider needs credentials to
connect to AWS. Before you can use managed resources, you have to
[save the provider's credentials](#save-the-providers-credentials) and
[configure the provider to use them](#configure-the-provider).
### Save the provider's credentials
The provider needs credentials to create and manage AWS resources. Providers use
a Kubernetes _secret_ to connect the credentials to the provider.
Generate a secret from your AWS key-pair.
{{<hint "tip">}}
The [AWS documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-creds)
provides information on how to generate AWS Access keys.
{{</hint>}}
Create a file containing the AWS account `aws_access_key_id` and
`aws_secret_access_key`:
{{< editCode >}}
```ini {copy-lines="all"}
[default]
aws_access_key_id = $@<aws_access_key>$@
aws_secret_access_key = $@<aws_secret_key>$@
```
{{< /editCode >}}
Save the text file as `aws-credentials.ini`.
{{<hint "note">}}
The [Authentication](https://docs.upbound.io/providers/provider-aws/authentication/)
section of the AWS Provider documentation describes other authentication methods.
{{</hint>}}
Create a secret from the text file:
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret generic aws-secret \
--namespace=crossplane-system \
--from-file=creds=./aws-credentials.ini
```
{{<hint "important">}}
Crossplane providers don't have to store their credentials in a secret. They
can load their credentials from various sources.
{{</hint>}}
Next, [configure the provider](#configure-the-provider) to use the credentials.
### Configure the provider
A {{< hover label="providerconfig" line="2">}}provider configuration{{</ hover >}}
customizes the settings of the AWS Provider.
All providers need a configuration to tell them where to load credentials.
Create this provider configuration:
```yaml {label="providerconfig",copy-lines="all"}
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-secret
key: creds
```
Save the provider configuration as `providerconfig.yaml` and apply it:
```shell {label="kube-apply-providerconfig",copy-lines="all"}
kubectl apply -f providerconfig.yaml
```
This tells the provider to load credentials from
[the secret](#save-the-providers-credentials).
## Use the managed resource
{{<hint "note">}}
AWS S3 bucket names must be globally unique. This example uses `generateName` to
generate a random name. Any unique name is acceptable.
{{</hint>}}
```yaml {label="bucket"}
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
metadata:
namespace: default
generateName: crossplane-bucket-
spec:
forProvider:
region: us-east-2
```
Save the bucket to `bucket.yaml` and apply it:
```shell {label="kube-create-bucket",copy-lines="all"}
kubectl create -f bucket.yaml
```
Check that Crossplane created the bucket:
```shell {copy-lines="1"}
kubectl get buckets.s3.aws.m.upbound.io
NAME SYNCED READY EXTERNAL-NAME AGE
crossplane-bucket-7tfcj True True crossplane-bucket-7tfcj 3m4s
```
{{<hint "tip">}}
Crossplane created the bucket when the values `READY` and `SYNCED` are `True`.
{{</hint>}}
Delete the bucket:
```shell {copy-lines="1"}
kubectl delete buckets.s3.aws.m.upbound.io crossplane-bucket-7tfcj
bucket.s3.aws.m.upbound.io "crossplane-bucket-7tfcj" deleted
```
When you delete the bucket managed resource, Crossplane deletes the S3 bucket
from AWS.
{{<hint "important">}}
Make sure to delete the S3 bucket before uninstalling the provider or shutting
down your control plane. If those are no longer running, they can't clean up any
managed resources and you would need to do so manually.
{{</hint>}}
## Next steps
Crossplane allows you to compose **any kind of resource** into custom APIs for
your users, which includes managed resources. Enjoy the freedom that Crossplane
gives you to compose the diverse set of resources your applications need for
their unique environments, scenarios, and requirements.
Follow [Get Started with Composition]({{<ref "../get-started/get-started-with-composition">}})
to learn more about how composition works.

View File

@ -0,0 +1,110 @@
---
title: Install Crossplane
weight: 100
---
Crossplane installs into an existing Kubernetes cluster, creating the
Crossplane pod.
Installing Crossplane enables the installation of Crossplane _Provider_,
_Function_, and _Configuration_ resources.
{{< hint "tip" >}}
If you don't have a Kubernetes cluster create one locally with [Kind](https://kind.sigs.k8s.io/).
{{< /hint >}}
## Prerequisites
* An actively [supported Kubernetes version](https://kubernetes.io/releases/patch-releases/#support-period)
* [Helm](https://helm.sh/docs/intro/install/) version `v3.2.0` or later
## Install Crossplane
Install Crossplane using the _Helm chart_.
### Add the Crossplane Preview Helm repository
Add the Crossplane preview repository with the `helm repo add` command.
```shell
helm repo add crossplane-preview https://charts.crossplane.io/preview
```
Update the
local Helm chart cache with `helm repo update`.
```shell
helm repo update
```
### Install the Crossplane Preview Helm chart
Install the Crossplane Preview Helm chart with `helm install`.
{{< hint "tip" >}}
View the changes Crossplane makes to your cluster with the
`helm install --dry-run --debug` options. Helm shows what configurations it
applies without making changes to the Kubernetes cluster.
{{< /hint >}}
Crossplane creates and installs into the `crossplane-system` namespace.
```shell
helm install crossplane \
--namespace crossplane-system \
--create-namespace crossplane-preview/crossplane \
--version v2.0.0-preview.1
```
View the installed Crossplane pods with `kubectl get pods -n crossplane-system`.
```shell {copy-lines="1"}
kubectl get pods -n crossplane-system
NAME READY STATUS RESTARTS AGE
crossplane-6d67f8cd9d-g2gjw 1/1 Running 0 26m
crossplane-rbac-manager-86d9b5cf9f-2vc4s 1/1 Running 0 26m
```
## Installation options
### Customize the Crossplane Helm chart
Crossplane supports customizations at install time by configuring the Helm
chart.
Read [the Helm chart README](https://github.com/crossplane/crossplane/blob/v2/cluster/charts/crossplane/README.md#configuration)
to learn what customizations are available.
Read [the Helm documentation](https://helm.sh/docs/) to learn how to run Helm
with custom options using `--set` or `values.yaml`.
#### Feature flags
Crossplane introduces new features behind feature flags. By default alpha
features are off. Crossplane enables beta features by default. To enable a
feature flag, set the `args` value in the Helm chart. Available feature flags
can be directly found by running `crossplane core start --help`, or by looking
at the table below.
{{< expand "Feature flags" >}}
{{< table caption="Feature flags" >}}
| Status | Flag | Description |
| --- | --- | --- |
| Beta | `--enable-deployment-runtime-configs` | Enable support for DeploymentRuntimeConfigs. |
| Beta | `--enable-usages` | Enable support for Usages. |
| Alpha | `--enable-realtime-compositions` | Enable support for real time compositions. |
| Alpha | `--enable-dependency-version-upgrades ` | Enable automatic version upgrades of dependencies when updating packages. |
| Alpha | `--enable-signature-verification` | Enable support for package signature verification via ImageConfig API. |
{{< /table >}}
{{< /expand >}}
Set these flags either in the `values.yaml` file or at install time using the
`--set` flag, for example: `--set
args='{"--enable-composition-functions","--enable-composition-webhook-schema-validation"}'`.
#### Change the default package registry
Beginning with Crossplane version 1.20.0 Crossplane uses the [crossplane-contrib](https://github.com/orgs/crossplane-contrib/packages) GitHub Container Registry at `xpkg.crossplane.io` by default for downloading and
installing packages.
Change the default registry location during the Crossplane install with
`--set args='{"--registry=index.docker.io"}'`.

View File

@ -1,16 +0,0 @@
---
title: Getting Started
weight: 4
description: An introduction to Crossplane and Crossplane quickstart guides.
---
{{<img src="/media/banner.png" alt="Crossplane Popsicle Truck" size="large" >}}
## Hands-on
Want a hands-on example? Follow a Crossplane Quickstart for your cloud provider.
* [AWS quickstart]({{<ref "provider-aws" >}})
* [Azure quickstart]({{<ref "provider-azure" >}})
* [GCP quickstart]({{<ref "provider-gcp" >}})
## Install
Ready to get started? [Install Crossplane]({{<ref "../software/install" >}}) in a Kubernetes cluster.

File diff suppressed because it is too large Load Diff

View File

@ -1,492 +0,0 @@
---
title: Crossplane Introduction
weight: 2
---
Crossplane connects your Kubernetes cluster to external,
non-Kubernetes resources, and allows platform teams to build custom Kubernetes
APIs to consume those resources.
<!-- vale gitlab.SentenceLength = NO -->
Crossplane creates Kubernetes
[Custom Resource Definitions](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/)
(`CRDs`) to represent the external resources as native
[Kubernetes objects](https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/).
As native Kubernetes objects, you can use standard commands like `kubectl create`
and `kubectl describe`. The full
[Kubernetes API](https://kubernetes.io/docs/reference/using-api/) is available
for every Crossplane resource.
<!-- vale gitlab.SentenceLength = YES -->
Crossplane also acts as a
[Kubernetes Controller](https://kubernetes.io/docs/concepts/architecture/controller/)
to watch the state of the external resources and provide state enforcement. If
something modifies or deletes a resource outside of Kubernetes, Crossplane reverses
the change or recreates the deleted resource.
{{<img src="/media/crossplane-intro-diagram.png" alt="Diagram showing a user communicating to Kubernetes. Crossplane connected to Kubernetes and Crossplane communicating with AWS, Azure and GCP" align="center">}}
With Crossplane installed in a Kubernetes cluster, users only communicate with
Kubernetes. Crossplane manages the communication to external resources like AWS,
Azure or Google Cloud.
Crossplane also allows the creation of custom Kubernetes APIs. Platform teams can
combine external resources and simplify or customize the APIs presented to the
platform consumers.
## Crossplane components overview
This table provides a summary of Crossplane components and their roles.
{{< table "table table-hover table-sm">}}
| Component | Abbreviation | Scope | Summary |
| --- | --- | --- | ---- |
| [Provider]({{<ref "#providers">}}) | | cluster | Creates new Kubernetes Custom Resource Definitions for an external service. |
| [ProviderConfig]({{<ref "#provider-configurations">}}) | `PC` | cluster | Applies settings for a _Provider_. |
| [Managed Resource]({{<ref "#managed-resources">}}) | `MR` | cluster | A Provider resource created and managed by Crossplane inside the Kubernetes cluster. |
| [Composition]({{<ref "#compositions">}}) | | cluster | A template for creating multiple _managed resources_ at once. |
| [Composite Resources]({{<ref "#composite-resources" >}}) | `XR` | cluster | Uses a _Composition_ template to create multiple _managed resources_ as a single Kubernetes object. |
| [CompositeResourceDefinitions]({{<ref "#composite-resource-definitions" >}}) | `XRD` | cluster | Defines the API schema for _Composite Resources_ and _Claims_ |
| [Claims]({{<ref "#claims" >}}) | `XC` | namespace | Like a _Composite Resource_, but namespace scoped. |
{{< /table >}}
## The Crossplane Pod
When installed in a Kubernetes cluster Crossplane creates an initial set of
Custom Resource Definitions (`CRDs`) of the core Crossplane components.
{{< expand "View the initial Crossplane CRDs" >}}
After installing Crossplane use `kubectl get crds` to view the Crossplane
installed CRDs.
```shell
kubectl get crd
NAME
compositeresourcedefinitions.apiextensions.crossplane.io
compositionrevisions.apiextensions.crossplane.io
compositions.apiextensions.crossplane.io
configurationrevisions.pkg.crossplane.io
configurations.pkg.crossplane.io
controllerconfigs.pkg.crossplane.io
deploymentruntimeconfigs.pkg.crossplane.io
environmentconfigs.apiextensions.crossplane.io
functionrevisions.pkg.crossplane.io
functions.pkg.crossplane.io
locks.pkg.crossplane.io
providerrevisions.pkg.crossplane.io
providers.pkg.crossplane.io
storeconfigs.secrets.crossplane.io
usages.apiextensions.crossplane.io
```
{{< /expand >}}
The following sections describe the functions of some of these CRDs.
<!-- vale Google.Headings = NO -->
<!-- allow "Providers" -->
## Providers
<!-- vale Google.Headings = YES -->
A Crossplane _Provider_ creates a second set of CRDs that define how Crossplane
connects to a non-Kubernetes service. Each external service relies on its own
Provider. For example,
[AWS](https://github.com/crossplane-contrib/provider-upjet-aws),
[Azure](https://github.com/crossplane-contrib/provider-upjet-azure)
and [GCP](https://github.com/crossplane-contrib/provider-upjet-gcp)
are different providers for each cloud service.
{{< hint "tip" >}}
Most Providers are for cloud services but Crossplane can use a Provider to
connect to any service with an API.
{{< /hint >}}
For example, an AWS Provider defines Kubernetes CRDs for AWS resources like EC2
compute instances or S3 storage buckets.
The Provider defines the Kubernetes API definition for the external resource.
For example,
[provider-upjet-aws](https://github.com/crossplane-contrib/provider-upjet-aws)
defines a
[`bucket`](https://github.com/crossplane-contrib/provider-upjet-aws/blob/release-1.20/package/crds/s3.aws.upbound.io_buckets.yaml)
resource for creating and managing AWS S3 storage buckets.
In the `bucket` CRD is a
[`spec.forProvider.region`](https://github.com/crossplane-contrib/provider-upjet-aws/blob/release-1.20/package/crds/s3.aws.upbound.io_buckets.yaml#L91)
value that defines which AWS region to deploy the bucket in.
More providers are available in the [Crossplane Contrib repository](https://github.com/crossplane-contrib/).
Providers are cluster scoped and available to all cluster namespaces.
View all installed Providers with the command `kubectl get providers`.
## Provider configurations
Providers have _ProviderConfigs_. _ProviderConfigs_ configure settings
related to the Provider like authentication or global defaults for the
Provider.
The API endpoints for ProviderConfigs are unique to each Provider.
_ProviderConfigs_ are cluster scoped and available to all cluster namespaces.
View all installed ProviderConfigs with the command `kubectl get providerconfig`.
## Managed resources
A Provider's CRDs map to individual _resources_ inside the provider. When
Crossplane creates and monitors a resource it's a _Managed Resource_.
Using a Provider's CRD creates a unique _Managed Resource_. For example,
using the Provider AWS's `bucket` CRD, Crossplane creates a `bucket` _Managed Resource_
inside the Kubernetes cluster that's connected to an AWS S3 storage bucket.
The Crossplane controller provides state enforcement for _Managed Resources_.
Crossplane enforces the settings and existence of _Managed Resources_. This
"Controller Pattern" is like how the Kubernetes
[kube-controller-manager](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/)
enforces state for pods.
_Managed Resources_ are cluster scoped and available to all cluster namespaces.
Use `kubectl get managed` to view all _managed resources_.
{{<hint "warning" >}}
The `kubectl get managed` creates a lot of Kubernetes API queries.
Both the `kubectl` client and kube-apiserver throttle the API queries.
Depending on the size of the API server and number of managed resources, this
command may take minutes to return or may timeout.
For more information, read
[Kubernetes issue #111880](https://github.com/kubernetes/kubernetes/issues/111880)
and
[Crossplane issue #3459](https://github.com/crossplane/crossplane/issues/3459).
{{< /hint >}}
## Compositions
A _Composition_ is a template for a collection of _managed resource_. _Compositions_
allow platform teams to define a set of _managed resources_ as a
single object.
For example, a compute _managed resource_ may require the creation of a storage
resource and a virtual network as well. A single _Composition_ can define all three
resources in a single _Composition_ object.
Using _Compositions_ simplifies the deployment of infrastructure made up of
multiple _managed resources_. _Compositions_ also enforce standards and settings
across deployments.
Platform teams can define fixed or default settings for each _managed resource_ inside a
_Composition_ or define fields and settings that users may change.
Using the previous example, the platform team may set a compute resource size
and virtual network settings. But the platform team allows users to define the
storage resource size.
Creating a _Composition_ Crossplane doesn't create any managed
resources. The _Composition_ is only a template for a collection of _managed
resources_ and their settings. A _Composite Resource_ creates the specific resources.
{{< hint "note" >}}
The [_Composite Resources_]({{<ref "#composite-resources">}}) section discusses
_Composite Resources_.
{{< /hint >}}
_Compositions_ are cluster scoped and available to all cluster namespaces.
Use `kubectl get compositions` to view all _compositions_.
## Composite Resources
A _Composite Resource_ (`XR`) is a set of provisioned _managed resources_. A
_Composite Resource_ uses the template defined by a _Composition_ and applies
any user defined settings.
Multiple unique _Composite Resource_ objects can use the same _Composition_. For
example, a _Composition_ template can create a compute, storage and networking
set of _managed resources_. Crossplane uses the same _Composition_ template
every time a user requests this set of resources.
If a _Composition_ allows a user to define resource settings, users apply them
in a _Composite Resource_.
<!-- A _Composition_ defines which _Composite Resources_ can use the _Composition_
template with the _Composition_ `spec.compositeTypeRef` value. This defines the
{{<hover label="comp" line="7">}}apiVersion{{< /hover >}} and {{<hover
label="comp" line="8">}}kind{{< /hover >}} of _Composite Resources_ that can use the
_Composition_.
For example, in the _Composition_:
```yaml {label="comp"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: test.example.org
spec:
compositeTypeRef:
apiVersion: test.example.org/v1alpha1
kind: MyComputeResource
# Removed for brevity
```
A _Composite Resource_ that can use this template must match this
{{<hover label="comp" line="7">}}apiVersion{{< /hover >}} and {{<hover
label="comp" line="8">}}kind{{< /hover >}}.
```yaml {label="xr"}
apiVersion: test.example.org/v1alpha1
kind: MyComputeResource
metadata:
name: my-resource
spec:
storage: "large"
```
The _Composite Resource_ {{<hover label="xr" line="1">}}apiVersion{{< /hover >}}
matches the and _Composition_
{{<hover label="comp" line="7">}}apiVersion{{</hover >}} and the
_Composite Resource_ {{<hover label="xr" line="2">}}kind{{< /hover >}}
matches the _Composition_ {{<hover label="comp" line="8">}}kind{{< /hover >}}.
In this example, the _Composite Resource_ also sets the
{{<hover label="xr" line="7">}}storage{{< /hover >}} setting. The
_Composition_ uses this value when creating the associated _managed resources_
owned by this _Composite Resource_. -->
{{< hint "tip" >}}
_Compositions_ are templates for a set of _managed resources_.
_Composite Resources_ fill out the template and create _managed resources_.
Deleting a _Composite Resource_ deletes all the _managed resources_ it created.
{{< /hint >}}
_Composite Resources_ are cluster scoped and available to all cluster namespaces.
Use `kubectl get composite` to view all _Composite Resources_.
## Composite Resource Definitions
_Composite Resource Definitions_ (`XRDs`) create custom Kubernetes APIs used by
_Claims_ and _Composite Resources_.
{{< hint "note" >}}
The [_Claims_]({{<ref "#claims">}}) section discusses
_Claims_.
{{< /hint >}}
Platform teams define the custom APIs.
These APIs can define specific values
like storage space in gigabytes, generic settings like `small` or `large`,
deployment options like `cloud` or `onprem`. Crossplane doesn't limit the API definitions.
The _Composite Resource Definition's_ `kind` is from Crossplane.
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
```
The `spec` of a _Composite Resource Definition_ creates the `apiVersion`,
`kind` and `spec` of a _Composite Resource_.
{{< hint "tip" >}}
The _Composite Resource Definition_ defines the parameters for a _Composite
Resource_.
{{< /hint >}}
A _Composite Resource Definition_ has four main `spec` parameters:
* A {{<hover label="specGroup" line="3" >}}group{{< /hover >}}
to define the
{{< hover label="xr2" line="2" >}}apiVersion{{</hover >}}
in a _Composite Resource_ .
* The {{< hover label="specGroup" line="7" >}}versions.name{{</hover >}}
that defines the version used in a _Composite Resource_.
* A {{< hover label="specGroup" line="5" >}}names.kind{{</hover >}}
to define the _Composite Resource_
{{< hover label="xr2" line="3" >}}kind{{</hover>}}.
* A {{< hover label="specGroup" line="8" >}}versions.schema{{</hover>}} section
to define the _Composite Resource_ {{<hover label="xr2" line="6" >}}spec{{</hover >}}.
```yaml {label="specGroup"}
# Composite Resource Definition (XRD)
spec:
group: test.example.org
names:
kind: MyComputeResource
versions:
- name: v1alpha1
schema:
# Removed for brevity
```
A _Composite Resource_ based on this _Composite Resource Definition_ looks like this:
```yaml {label="xr2"}
# Composite Resource (XR)
apiVersion: test.example.org/v1alpha1
kind: MyComputeResource
metadata:
name: my-resource
spec:
storage: "large"
```
A _Composite Resource Definition_ {{< hover label="specGroup" line="8" >}}schema{{</hover >}} defines the _Composite Resource_
{{<hover label="xr2" line="6" >}}spec{{</hover >}} parameters.
These parameters are the new, custom APIs, that developers can use.
For example, creating a compute _managed resource_ requires knowledge of a
cloud provider's compute class names like AWS's `m6in.large` or GCP's
`e2-standard-2`.
A _Composite Resource Definition_ can limit the choices to `small` or `large`.
A _Composite Resource_ uses those options and the _Composition_ maps them
to specific cloud provider settings.
The following _Composite Resource Definition_ defines a {{<hover label="specVersions" line="17" >}}storage{{< /hover >}}
parameter. The storage is a
{{<hover label="specVersions" line="18">}}string{{< /hover >}}
and the OpenAPI
{{<hover label="specVersions" line="19" >}}oneOf{{< /hover >}} requires the
options to be either {{<hover label="specVersions" line="20" >}}small{{< /hover >}}
or {{<hover label="specVersions" line="21" >}}large{{< /hover >}}.
```yaml {label="specVersions"}
# Composite Resource Definition (XRD)
spec:
group: test.example.org
names:
kind: MyComputeResource
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
storage:
type: string
oneOf:
- pattern: '^small$'
- pattern: '^large$'
required:
- storage
```
A _Composite Resource Definition_ can define a wide variety of settings and options.
Creating a _Composite Resource Definition_ enables the creation of _Composite
Resources_ but can also create a _Claim_.
_Composite Resource Definitions_ with a `spec.claimNames` allow developers to
create _Claims_.
For example, the
{{< hover label="xrdClaim" line="6" >}}claimNames.kind{{</hover >}}
allows the creation of _Claims_ of `kind: computeClaim`.
```yaml {label="xrdClaim"}
# Composite Resource Definition (XRD)
spec:
group: test.example.org
names:
kind: MyComputeResource
claimNames:
kind: computeClaim
# Removed for brevity
```
## Claims
_Claims_ are the primary way developers interact with Crossplane.
_Claims_ access the custom APIs defined by the platform team in a _Composite
Resource Definition_.
_Claims_ look like _Composite Resources_, but they're namespace scoped,
while _Composite Resources_ are cluster scoped.
{{< hint "note" >}}
**Why does namespace scope matter?**
Having namespace scoped _Claims_ allows multiple teams, using unique namespaces,
to create the same types of resources, independent of each other. The compute
resources of team A are unique to the compute resources of team B.
Directly creating _Composite Resources_ requires cluster-wide permissions,
shared with all teams.
_Claims_ create the same set of resources, but on a namespace level.
{{< /hint >}}
The previous _Composite Resource Definition_ allows the creation of _Claims_
of the kind
{{<hover label="xrdClaim2" line="7" >}}computeClaim{{</hover>}}.
Claims use the same
{{< hover label="xrdClaim2" line="3" >}}apiVersion{{< /hover >}}
defined in _Composite Resource Definition_ and also used by
_Composite Resources_.
```yaml {label="xrdClaim2"}
# Composite Resource Definition (XRD)
spec:
group: test.example.org
names:
kind: MyComputeResource
claimNames:
kind: computeClaim
# Removed for brevity
```
In an example _Claim_ the
{{<hover label="claim" line="2">}}apiVersion{{< /hover >}}
matches the {{<hover label="xrdClaim2" line="3">}}group{{< /hover >}} in the
_Composite Resource Definition_.
The _Claim_ {{<hover label="claim" line="3">}}kind{{< /hover >}} matches the
_Composite Resource Definition_
{{<hover label="xrdClaim2" line="7">}}claimNames.kind{{< /hover >}}.
```yaml {label="claim"}
# Claim
apiVersion: test.example.org/v1alpha1
kind: computeClaim
metadata:
name: myClaim
namespace: devGroup
spec:
size: "large"
```
A _Claim_ can install in a {{<hover label="claim" line="6">}}namespace{{</hover >}}.
The _Composite Resource Definition_ defines the
{{<hover label="claim" line="7">}}spec{{< /hover >}} options the same way it
does for a _Composite Resource_
{{<hover label="xr-claim" line="6">}}spec{{< /hover >}}.
{{< hint "tip" >}}
_Composite Resources_ and _Claims_ are similar.
Only _Claims_ can be in
a {{<hover label="claim" line="6">}}namespace{{</hover >}}.
Also the _Composite Resource's_ {{<hover label="xr-claim"
line="3">}}kind{{</hover >}} may be different than the _Claim's_
{{<hover label="claim" line="3">}}kind{{< /hover >}}.
The _Composite Resource Definition_ defines the
{{<hover label="xrdClaim2" line="7">}}kind{{</hover >}} values.
{{< /hint >}}
```yaml {label="xr-claim"}
# Composite Resource (XR)
apiVersion: test.example.org/v1alpha1
kind: MyComputeResource
metadata:
name: my-resource
spec:
storage: "large"
```
_Claims_ are namespace scoped.
View all available Claims with the command `kubectl get claim`.
## Next steps
Build your own Crossplane platform using one of the quickstart guides.
* [Azure Quickstart]({{<ref "provider-azure" >}})
* [AWS Quickstart]({{<ref "provider-aws" >}})
* [GCP Quickstart]({{<ref "provider-gcp" >}})

View File

@ -1,599 +0,0 @@
---
title: AWS Quickstart Part 2
weight: 120
tocHidden: true
aliases:
- /master/getting-started/provider-aws-part-3
---
{{< hint "important" >}}
This guide is part 2 of a series.
[**Part 1**]({{<ref "provider-aws" >}}) covers
to installing Crossplane and connect your Kubernetes cluster to AWS.
{{< /hint >}}
This guide walks you through building and accessing a custom API with Crossplane.
## Prerequisites
* Complete [quickstart part 1]({{<ref "provider-aws" >}}) connecting Kubernetes
to AWS.
* an AWS account with permissions to create an AWS S3 storage bucket and a
DynamoDB instance
{{<expand "Skip part 1 and just get started" >}}
1. Add the Crossplane Helm repository and install Crossplane
```shell
helm repo add \
crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane \
crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace
```
2. When the Crossplane pods finish installing and are ready, apply the AWS Provider
```yaml {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v1.21.1
EOF
```
3. Create a file with your AWS keys
```ini
[default]
aws_access_key_id = <aws_access_key>
aws_secret_access_key = <aws_secret_key>
```
4. Create a Kubernetes secret from the AWS keys
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret \
generic aws-secret \
-n crossplane-system \
--from-file=creds=./aws-credentials.txt
```
5. Create a _ProviderConfig_
```yaml {label="providerconfig",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-secret
key: creds
EOF
```
{{</expand >}}
## Install the DynamoDB Provider
Part 1 only installed the AWS S3 Provider. This section deploys an S3 bucket
along with a DynamoDB Table.
Deploying a DynamoDB Table requires the DynamoDB Provider as well.
Add the new Provider to the cluster.
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-dynamodb
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-aws-dynamodb:v1.21.1
EOF
```
View the new DynamoDB provider with `kubectl get providers`.
```shell {copy-lines="1"}
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-family-aws True True xpkg.crossplane.io/crossplane-contrib/provider-family-aws:v1.21.1 15m
provider-aws-dynamodb True True xpkg.crossplane.io/crossplane-contrib/provider-aws-dynamodb:v1.21.1 22s
provider-aws-s3 True True xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v1.21.1 15m
```
## Create a custom API
<!-- vale alex.Condescending = NO -->
Crossplane allows you to build your own custom APIs for your users, abstracting
away details about the cloud provider and their resources. You can make your API
as complex or simple as you wish.
<!-- vale alex.Condescending = YES -->
The custom API is a Kubernetes object.
Here is an example custom API.
```yaml {label="exAPI"}
apiVersion: database.example.com/v1alpha1
kind: NoSQL
metadata:
name: my-nosql-database
spec:
location: "US"
```
Like any Kubernetes object the API has a
{{<hover label="exAPI" line="1">}}version{{</hover>}},
{{<hover label="exAPI" line="2">}}kind{{</hover>}} and
{{<hover label="exAPI" line="5">}}spec{{</hover>}}.
### Define a group and version
To create your own API start by defining an
[API group](https://kubernetes.io/docs/reference/using-api/#api-groups) and
[version](https://kubernetes.io/docs/reference/using-api/#api-versioning).
The _group_ can be any value, but common convention is to map to a fully
qualified domain name.
<!-- vale gitlab.SentenceLength = NO -->
The version shows how mature or stable the API is and increments when changing,
adding or removing fields in the API.
<!-- vale gitlab.SentenceLength = YES -->
Crossplane doesn't require specific versions or a specific version naming
convention, but following
[Kubernetes API versioning guidelines](https://kubernetes.io/docs/reference/using-api/#api-versioning)
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.
This guide uses the group
{{<hover label="version" line="1">}}database.example.com{{</hover>}}.
Because this is the first version of the API, this guide uses the version
{{<hover label="version" line="1">}}v1alpha1{{</hover>}}.
```yaml {label="version",copy-lines="none"}
apiVersion: database.example.com/v1alpha1
```
### Define a kind
The API group is a logical collection of related APIs. In a group are
individual kinds representing different resources.
For example a `database` group may have a `Relational` and `NoSQL` kinds.
The `kind` can be anything, but it must be
[UpperCamelCased](https://kubernetes.io/docs/contribute/style/style-guide/#use-upper-camel-case-for-api-objects).
This API's kind is
{{<hover label="kind" line="2">}}NoSQL{{</hover>}}
```yaml {label="kind",copy-lines="none"}
apiVersion: database.example.com/v1alpha1
kind: NoSQL
```
### Define a spec
The most important part of an API is the schema. The schema defines the inputs
accepted from users.
This API allows users to provide a
{{<hover label="spec" line="4">}}location{{</hover>}} of where to run their
cloud resources.
All other resource settings can't be configurable by the users. This allows
Crossplane to enforce any policies and standards without worrying about
user errors.
```yaml {label="spec",copy-lines="none"}
apiVersion: database.example.com/v1alpha1
kind: NoSQL
spec:
location: "US"
```
### Apply the API
Crossplane uses
{{<hover label="xrd" line="3">}}Composite Resource Definitions{{</hover>}}
(also called an `XRD`) to install your custom API in
Kubernetes.
The XRD {{<hover label="xrd" line="6">}}spec{{</hover>}} contains all the
information about the API including the
{{<hover label="xrd" line="7">}}group{{</hover>}},
{{<hover label="xrd" line="12">}}version{{</hover>}},
{{<hover label="xrd" line="9">}}kind{{</hover>}} and
{{<hover label="xrd" line="13">}}schema{{</hover>}}.
The XRD's {{<hover label="xrd" line="5">}}name{{</hover>}} must be the
combination of the {{<hover label="xrd" line="9">}}plural{{</hover>}} and
{{<hover label="xrd" line="7">}}group{{</hover>}}.
The {{<hover label="xrd" line="13">}}schema{{</hover>}} uses the
{{<hover label="xrd" line="14">}}OpenAPIv3{{</hover>}} specification to define
the API {{<hover label="xrd" line="17">}}spec{{</hover>}}.
The API defines a {{<hover label="xrd" line="20">}}location{{</hover>}} that
must be {{<hover label="xrd" line="22">}}oneOf{{</hover>}} either
{{<hover label="xrd" line="23">}}EU{{</hover>}} or
{{<hover label="xrd" line="24">}}US{{</hover>}}.
Apply this XRD to create the custom API in your Kubernetes cluster.
```yaml {label="xrd",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: nosqls.database.example.com
spec:
group: database.example.com
names:
kind: NoSQL
plural: nosqls
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
location:
type: string
oneOf:
- pattern: '^EU$'
- pattern: '^US$'
required:
- location
served: true
referenceable: true
claimNames:
kind: NoSQLClaim
plural: nosqlclaim
EOF
```
Adding the {{<hover label="xrd" line="29">}}claimNames{{</hover>}} allows users
to access this API either at the cluster level with the
{{<hover label="xrd" line="9">}}nosql{{</hover>}} endpoint or in a namespace
with the
{{<hover label="xrd" line="29">}}nosqlclaim{{</hover>}} endpoint.
The namespace scoped API is a Crossplane _Claim_.
{{<hint "tip" >}}
For more details on the fields and options of Composite Resource Definitions
read the
[XRD documentation]({{<ref "../concepts/composite-resource-definitions">}}).
{{< /hint >}}
View the installed XRD with `kubectl get xrd`.
```shell {copy-lines="1"}
kubectl get xrd
NAME ESTABLISHED OFFERED AGE
nosqls.database.example.com True True 2s
```
View the new custom API endpoints with `kubectl api-resources | grep nosql`
```shell {copy-lines="1",label="apiRes"}
kubectl api-resources | grep nosql
nosqlclaim database.example.com/v1alpha1 true NoSQLClaim
nosqls database.example.com/v1alpha1 false NoSQL
```
## Create a deployment template
When users access the custom API Crossplane takes their inputs and combines them
with a template describing what infrastructure to deploy. Crossplane calls this
template a _Composition_.
The {{<hover label="comp" line="3">}}Composition{{</hover>}} defines all the
cloud resources to deploy. Each entry in the template is a full resource
definition, defining all the resource settings and metadata like labels and
annotations.
This template creates an AWS
{{<hover label="comp" line="13">}}S3{{</hover>}}
{{<hover label="comp" line="14">}}Bucket{{</hover>}} and a
{{<hover label="comp" line="33">}}DynamoDB{{</hover>}}
{{<hover label="comp" line="34">}}Table{{</hover>}}.
This Composition takes the user's
{{<hover label="comp" line="21">}}location{{</hover>}} input and uses it as the
{{<hover label="comp" line="16">}}region{{</hover>}} used in the individual
resource.
{{<hint "important" >}}
This Composition uses an array of resource templates. You can patch each
template with data copied from the custom API. Crossplane calls this a _Patch
and Transform_ Composition.
You don't have to use Patch and Transform. Crossplane supports a variety of
alternatives, including Go Templating and CUE. You can also write a function in
Go or Python to template your resources.
Read the [Composition documentation]({{<ref "../concepts/compositions">}}) for
more information on configuring Compositions and all the available options.
{{< /hint >}}
Apply this Composition to your cluster.
```yaml {label="comp",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: dynamo-with-bucket
spec:
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: s3Bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
providerConfigRef:
name: default
patches:
- type: FromCompositeFieldPath
fromFieldPath: "spec.location"
toFieldPath: "spec.forProvider.region"
transforms:
- type: map
map:
EU: "eu-north-1"
US: "us-east-2"
- name: dynamoDB
base:
apiVersion: dynamodb.aws.upbound.io/v1beta1
kind: Table
spec:
forProvider:
region: "us-east-2"
writeCapacity: 1
readCapacity: 1
attribute:
- name: S3ID
type: S
hashKey: S3ID
patches:
- type: FromCompositeFieldPath
fromFieldPath: "spec.location"
toFieldPath: "spec.forProvider.region"
transforms:
- type: map
map:
EU: "eu-north-1"
US: "us-east-2"
compositeTypeRef:
apiVersion: database.example.com/v1alpha1
kind: NoSQL
EOF
```
The {{<hover label="comp" line="52">}}compositeTypeRef{{</hover >}} defines
which custom APIs can use this template to create resources.
A Composition uses a pipeline of _composition functions_ to define the cloud
resources to deploy. This template uses
{{<hover label="comp" line="10">}}function-patch-and-transform{{</hover>}}.
You must install the function before you can use it in a Composition.
Apply this Function to install `function-patch-and-transform`:
```yaml {label="install"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: function-patch-and-transform
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2
EOF
```
{{<hint "tip" >}}
Read the [Composition documentation]({{<ref "../concepts/compositions">}}) for
more information on configuring Compositions and all the available options.
Read the
[Patch and Transform function documentation]({{<ref "../guides/function-patch-and-transform">}})
for more information on how it uses patches to map user inputs to Composition
resource templates.
{{< /hint >}}
View the Composition with `kubectl get composition`
```shell {copy-lines="1"}
kubectl get composition
NAME XR-KIND XR-APIVERSION AGE
dynamo-with-bucket NoSQL database.example.com/v1alpha1 3s
```
## Access the custom API
With the custom API (XRD) installed and associated to a resource template
(Composition) users can access the API to create resources.
Create a {{<hover label="xr" line="2">}}NoSQL{{</hover>}} object to create the
cloud resources.
```yaml {copy-lines="all",label="xr"}
cat <<EOF | kubectl apply -f -
apiVersion: database.example.com/v1alpha1
kind: NoSQL
metadata:
name: my-nosql-database
spec:
location: "US"
EOF
```
View the resource with `kubectl get nosql`.
```shell {copy-lines="1"}
kubectl get nosql
NAME SYNCED READY COMPOSITION AGE
my-nosql-database True True dynamo-with-bucket 14s
```
This object is a Crossplane _composite resource_ (also called an `XR`).
It's a
single object representing the collection of resources created from the
Composition template.
View the individual resources with `kubectl get managed`
```shell {copy-lines="1"}
kubectl get managed
NAME READY SYNCED EXTERNAL-NAME AGE
table.dynamodb.aws.upbound.io/my-nosql-database-t5wtx True True my-nosql-database-t5wtx 33s
NAME READY SYNCED EXTERNAL-NAME AGE
bucket.s3.aws.upbound.io/my-nosql-database-xtzph True True my-nosql-database-xtzph 33s
```
Delete the resources with `kubectl delete nosql`.
```shell {copy-lines="1"}
kubectl delete nosql my-nosql-database
nosql.database.example.com "my-nosql-database" deleted
```
Verify Crossplane deleted the resources with `kubectl get managed`
{{<hint "note" >}}
It may take up to 5 minutes to delete the resources.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl get managed
No resources found
```
## Using the API with namespaces
Accessing the API `nosql` happens at the cluster scope.
Most organizations
isolate their users into namespaces.
A Crossplane _Claim_ is the custom API in a namespace.
Creating a _Claim_ is just like accessing the custom API endpoint, but with the
{{<hover label="claim" line="3">}}kind{{</hover>}}
from the custom API's `claimNames`.
Create a new namespace to test create a Claim in.
```shell
kubectl create namespace crossplane-test
```
Then create a Claim in the `crossplane-test` namespace.
```yaml {label="claim",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: database.example.com/v1alpha1
kind: NoSQLClaim
metadata:
name: my-nosql-database
namespace: crossplane-test
spec:
location: "US"
EOF
```
View the Claim with `kubectl get claim -n crossplane-test`.
```shell {copy-lines="1"}
kubectl get claim -n crossplane-test
NAME SYNCED READY CONNECTION-SECRET AGE
my-nosql-database True True 17s
```
The Claim automatically creates a composite resource, which creates the managed
resources.
View the Crossplane created composite resource with `kubectl get composite`.
```shell {copy-lines="1"}
kubectl get composite
NAME SYNCED READY COMPOSITION AGE
my-nosql-database-t9qrw True True dynamo-with-bucket 77s
```
Again, view the managed resources with `kubectl get managed`.
```shell {copy-lines="1"}
kubectl get managed
NAME READY SYNCED EXTERNAL-NAME AGE
table.dynamodb.aws.upbound.io/my-nosql-database-t9qrw-dcpwv True True my-nosql-database-t9qrw-dcpwv 116s
NAME READY SYNCED EXTERNAL-NAME AGE
bucket.s3.aws.upbound.io/my-nosql-database-t9qrw-g98lv True True my-nosql-database-t9qrw-g98lv 117s
```
Deleting the Claim deletes all the Crossplane generated resources.
`kubectl delete claim -n crossplane-test my-nosql-database`
```shell {copy-lines="1"}
kubectl delete claim -n crossplane-test my-nosql-database
nosqlclaim.database.example.com "my-nosql-database" deleted
```
{{<hint "note" >}}
It may take up to 5 minutes to delete the resources.
{{< /hint >}}
Verify Crossplane deleted the composite resource with `kubectl get composite`.
```shell {copy-lines="1"}
kubectl get composite
No resources found
```
Verify Crossplane deleted the managed resources with `kubectl get managed`.
```shell {copy-lines="1"}
kubectl get managed
No resources found
```
## Next steps
* Explore AWS resources that Crossplane can configure in the
[provider CRD reference](https://github.com/crossplane-contrib/provider-upjet-aws/blob/main/package/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with
Crossplane users and contributors.
* Read more about the [Crossplane concepts]({{<ref "../concepts">}}) to find out what else you can do
with Crossplane.

View File

@ -1,244 +0,0 @@
---
title: AWS Quickstart
weight: 100
---
Connect Crossplane to AWS to create and manage cloud resources from Kubernetes
with
[provider-upjet-aws](https://github.com/crossplane-contrib/provider-upjet-aws).
This guide is in two parts:
* Part 1 walks through installing Crossplane, configuring the provider to
authenticate to AWS and creating a _Managed Resource_ in AWS directly from your
Kubernetes cluster. This shows Crossplane can communicate with AWS.
* [Part 2]({{< ref "provider-aws-part-2" >}}) shows how to build and access a
custom API with Crossplane.
## Prerequisites
This quickstart requires:
* a Kubernetes cluster with at least 2 GB of RAM
* permissions to create pods and secrets in the Kubernetes cluster
* [Helm](https://helm.sh/) version v3.2.0 or later
* an AWS account with permissions to create an S3 storage bucket
* AWS [access keys](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-creds)
{{<include file="/master/getting-started/install-crossplane-include.md" type="page" >}}
## Install the AWS provider
Install the AWS S3 provider into the Kubernetes cluster with a Kubernetes
configuration file.
```yaml {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v1.21.1
EOF
```
The Crossplane {{< hover label="provider" line="3" >}}Provider{{</hover>}}
installs the Kubernetes _Custom Resource Definitions_ (CRDs) representing AWS S3
services. These CRDs allow you to create AWS resources directly inside
Kubernetes.
Verify the provider installed with `kubectl get providers`.
```shell {copy-lines="1",label="getProvider"}
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-family-aws True True xpkg.crossplane.io/crossplane-contrib/provider-family-aws:v1.21.1 30s
provider-aws-s3 True True xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v1.21.1 34s
```
The S3 Provider installs a second Provider, the
{{<hover label="getProvider" line="4">}}crossplane-contrib-provider-family-aws{{</hover >}}.
The family provider manages authentication to AWS across all AWS family
Providers.
You can view the new CRDs with `kubectl get crds`.
Every CRD maps to a unique AWS service Crossplane can provision and manage.
{{< hint type="tip" >}}
See details about all the supported CRDs in the
[provider examples](https://github.com/crossplane-contrib/provider-upjet-aws/tree/main/examples).
{{< /hint >}}
## Create a Kubernetes secret for AWS
The provider requires credentials to create and manage AWS resources.
Providers use a Kubernetes _Secret_ to connect the credentials to the provider.
Generate a Kubernetes _Secret_ from your AWS key-pair and
then configure the Provider to use it.
### Generate an AWS key-pair file
For basic user authentication, use an AWS Access keys key-pair file.
{{< hint type="tip" >}}
The [AWS documentation](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html#cli-configure-quickstart-creds)
provides information on how to generate AWS Access keys.
{{< /hint >}}
Create a text file containing the AWS account `aws_access_key_id` and `aws_secret_access_key`.
{{< editCode >}}
```ini {copy-lines="all"}
[default]
aws_access_key_id = $@<aws_access_key>$@
aws_secret_access_key = $@<aws_secret_key>$@
```
{{< /editCode >}}
Save this text file as `aws-credentials.txt`.
{{< hint type="note" >}}
The [Authentication](https://docs.upbound.io/providers/provider-aws/authentication/) section of the AWS Provider documentation describes other authentication methods.
{{< /hint >}}
### Create a Kubernetes secret with the AWS credentials
A Kubernetes generic secret has a name and contents.
Use
{{< hover label="kube-create-secret" line="1">}}kubectl create secret{{</hover >}}
to generate the secret object named
{{< hover label="kube-create-secret" line="2">}}aws-secret{{< /hover >}}
in the {{< hover label="kube-create-secret" line="3">}}crossplane-system{{</ hover >}} namespace.
Use the {{< hover label="kube-create-secret" line="4">}}--from-file={{</hover>}} argument to set the value to the contents of the {{< hover label="kube-create-secret" line="4">}}aws-credentials.txt{{< /hover >}} file.
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret \
generic aws-secret \
-n crossplane-system \
--from-file=creds=./aws-credentials.txt
```
View the secret with `kubectl describe secret`
{{< hint type="note" >}}
The size may be larger if there are extra blank spaces in your text file.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl describe secret aws-secret -n crossplane-system
Name: aws-secret
Namespace: crossplane-system
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
creds: 114 bytes
```
## Create a ProviderConfig
A {{< hover label="providerconfig" line="3">}}ProviderConfig{{</ hover >}}
customizes the settings of the AWS Provider.
Apply the
{{< hover label="providerconfig" line="3">}}ProviderConfig{{</ hover >}}
with the this Kubernetes configuration file:
```yaml {label="providerconfig",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-secret
key: creds
EOF
```
This attaches the AWS credentials, saved as a Kubernetes secret, as a
{{< hover label="providerconfig" line="9">}}secretRef{{</ hover>}}.
The
{{< hover label="providerconfig" line="11">}}spec.credentials.secretRef.name{{< /hover >}}
value is the name of the Kubernetes secret containing the AWS credentials in the
{{< hover label="providerconfig" line="10">}}spec.credentials.secretRef.namespace{{< /hover >}}.
## Create a managed resource
A _managed resource_ is anything Crossplane creates and manages outside of the
Kubernetes cluster.
This guide creates an AWS S3 bucket with Crossplane.
The S3 bucket is a _managed resource_.
{{< hint type="note" >}}
AWS S3 bucket names must be globally unique. To generate a unique name the example uses a random hash.
Any unique name is acceptable.
{{< /hint >}}
```yaml {label="xr"}
cat <<EOF | kubectl create -f -
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
generateName: crossplane-bucket-
spec:
forProvider:
region: us-east-2
providerConfigRef:
name: default
EOF
```
The {{< hover label="xr" line="2">}}apiVersion{{< /hover >}} and
{{< hover label="xr" line="3">}}kind{{</hover >}} are from the provider's CRDs.
The {{< hover label="xr" line="5">}}metadata.generateName{{< /hover >}} value is the
name of the created S3 bucket in AWS.
This example uses the generated name `crossplane-bucket-<hash>` in the
{{< hover label="xr" line="5">}}$bucket{{</hover >}} variable.
The {{< hover label="xr" line="8">}}spec.forProvider.region{{< /hover >}} tells
AWS which AWS region to use when deploying resources.
The region can be any
[AWS Regional endpoint](https://docs.aws.amazon.com/general/latest/gr/rande.html#regional-endpoints) code.
Use `kubectl get buckets` to verify Crossplane created the bucket.
{{< hint type="tip" >}}
Crossplane created the bucket when the values `READY` and `SYNCED` are `True`.
This may take up to 5 minutes.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl get buckets
NAME READY SYNCED EXTERNAL-NAME AGE
crossplane-bucket-hhdzh True True crossplane-bucket-hhdzh 5s
```
## Delete the managed resource
Before shutting down your Kubernetes cluster, delete the S3 bucket just created.
Use `kubectl delete bucket <bucketname>` to remove the bucket.
```shell {copy-lines="1"}
kubectl delete bucket crossplane-bucket-hhdzh
bucket.s3.aws.upbound.io "crossplane-bucket-hhdzh" deleted
```
## Next steps
* [**Continue to part 2**]({{< ref "provider-aws-part-2">}}) to create and use a
custom API with Crossplane.
* Explore AWS resources that Crossplane can configure in the
[provider CRD reference](https://github.com/crossplane-contrib/provider-upjet-aws/blob/main/package/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with
Crossplane users and contributors.

View File

@ -1,701 +0,0 @@
---
title: Azure Quickstart Part 2
weight: 120
tocHidden: true
aliases:
- /master/getting-started/provider-azure-part-3
---
{{< hint "important" >}}
This guide is part 2 of a series.
[**Part 1**]({{<ref "provider-azure" >}}) covers
to installing Crossplane and connect your Kubernetes cluster to Azure.
{{< /hint >}}
This guide walks you through building and accessing a custom API with Crossplane.
## Prerequisites
* Complete [quickstart part 1]({{<ref "provider-azure" >}}) connecting Kubernetes
to Azure.
* an Azure account with permissions to create an Azure Virtual Machine, Resource
Group and Virtual Networking.
{{<expand "Skip part 1 and just get started" >}}
1. Add the Crossplane Helm repository and install Crossplane
```shell
helm repo add \
crossplane-stable https://charts.crossplane.io/stable
helm repo update
&&
helm install crossplane \
crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace
```
2. When the Crossplane pods finish installing and are ready, apply the Azure
Provider
```yaml {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-azure-network
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-azure-network:v1.11.2
EOF
```
3. Use the Azure CLI to create a service principal and save the JSON output as
`azure-crednetials.json`
{{< editCode >}}
```console
az ad sp create-for-rbac \
--sdk-auth \
--role Owner \
--scopes /subscriptions/$@<subscription_id>$@
```
{{</ editCode >}}
4. Create a Kubernetes secret from the Azure JSON file.
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret \
generic azure-secret \
-n crossplane-system \
--from-file=creds=./azure-credentials.json
```
5. Create a _ProviderConfig_
```yaml {label="providerconfig",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: azure.upbound.io/v1beta1
metadata:
name: default
kind: ProviderConfig
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: azure-secret
key: creds
EOF
```
{{</expand >}}
## Create a custom API
<!-- vale alex.Condescending = NO -->
Crossplane allows you to build your own custom APIs for your users, abstracting
away details about the cloud provider and their resources. You can make your API
as complex or simple as you wish.
<!-- vale alex.Condescending = YES -->
The custom API is a Kubernetes object.
Here is an example custom API.
```yaml {label="exAPI"}
apiVersion: compute.example.com/v1alpha1
kind: VirtualMachine
metadata:
name: my-vm
spec:
location: "US"
```
Like any Kubernetes object the API has a
{{<hover label="exAPI" line="1">}}version{{</hover>}},
{{<hover label="exAPI" line="2">}}kind{{</hover>}} and
{{<hover label="exAPI" line="5">}}spec{{</hover>}}.
### Define a group and version
To create your own API start by defining an
[API group](https://kubernetes.io/docs/reference/using-api/#api-groups) and
[version](https://kubernetes.io/docs/reference/using-api/#api-versioning).
The _group_ can be any value, but common convention is to map to a fully
qualified domain name.
<!-- vale gitlab.SentenceLength = NO -->
The version shows how mature or stable the API is and increments when changing,
adding or removing fields in the API.
<!-- vale gitlab.SentenceLength = YES -->
Crossplane doesn't require specific versions or a specific version naming
convention, but following
[Kubernetes API versioning guidelines](https://kubernetes.io/docs/reference/using-api/#api-versioning)
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.
This guide uses the group
{{<hover label="version" line="1">}}compute.example.com{{</hover>}}.
Because this is the first version of the API, this guide uses the version
{{<hover label="version" line="1">}}v1alpha1{{</hover>}}.
```yaml {label="version",copy-lines="none"}
apiVersion: compute.example.com/v1alpha1
```
### Define a kind
The API group is a logical collection of related APIs. In a group are
individual kinds representing different resources.
For example a `compute` group may have a `VirtualMachine` and `BareMetal` kinds.
The `kind` can be anything, but it must be
[UpperCamelCased](https://kubernetes.io/docs/contribute/style/style-guide/#use-upper-camel-case-for-api-objects).
This API's kind is
{{<hover label="kind" line="2">}}VirtualMachine{{</hover>}}
```yaml {label="kind",copy-lines="none"}
apiVersion: compute.example.com/v1alpha1
kind: VirtualMachine
```
### Define a spec
The most important part of an API is the schema. The schema defines the inputs
accepted from users.
This API allows users to provide a
{{<hover label="spec" line="4">}}location{{</hover>}} of where to run their
cloud resources.
All other resource settings can't be configurable by the users. This allows
Crossplane to enforce any policies and standards without worrying about
user errors.
```yaml {label="spec",copy-lines="none"}
apiVersion: compute.example.com/v1alpha1
kind: VirtualMachine
spec:
location: "US"
```
### Apply the API
Crossplane uses
{{<hover label="xrd" line="3">}}Composite Resource Definitions{{</hover>}}
(also called an `XRD`) to install your custom API in
Kubernetes.
The XRD {{<hover label="xrd" line="6">}}spec{{</hover>}} contains all the
information about the API including the
{{<hover label="xrd" line="7">}}group{{</hover>}},
{{<hover label="xrd" line="12">}}version{{</hover>}},
{{<hover label="xrd" line="9">}}kind{{</hover>}} and
{{<hover label="xrd" line="13">}}schema{{</hover>}}.
The XRD's {{<hover label="xrd" line="5">}}name{{</hover>}} must be the
combination of the {{<hover label="xrd" line="10">}}plural{{</hover>}} and
{{<hover label="xrd" line="7">}}group{{</hover>}}.
The {{<hover label="xrd" line="13">}}schema{{</hover>}} uses the
{{<hover label="xrd" line="14">}}OpenAPIv3{{</hover>}} specification to define
the API {{<hover label="xrd" line="17">}}spec{{</hover>}}.
The API defines a {{<hover label="xrd" line="20">}}location{{</hover>}} that
must be {{<hover label="xrd" line="22">}}oneOf{{</hover>}} either
{{<hover label="xrd" line="23">}}EU{{</hover>}} or
{{<hover label="xrd" line="24">}}US{{</hover>}}.
Apply this XRD to create the custom API in your Kubernetes cluster.
```yaml {label="xrd",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: virtualmachines.compute.example.com
spec:
group: compute.example.com
names:
kind: VirtualMachine
plural: virtualmachines
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
location:
type: string
oneOf:
- pattern: '^EU$'
- pattern: '^US$'
required:
- location
served: true
referenceable: true
claimNames:
kind: VirtualMachineClaim
plural: virtualmachineclaims
EOF
```
Adding the {{<hover label="xrd" line="29">}}claimNames{{</hover>}} allows users
to access this API either at the cluster level with the
{{<hover label="xrd" line="9">}}VirtualMachine{{</hover>}} endpoint or in a namespace
with the
{{<hover label="xrd" line="30">}}VirtualMachineClaim{{</hover>}} endpoint.
The namespace scoped API is a Crossplane _Claim_.
{{<hint "tip" >}}
For more details on the fields and options of Composite Resource Definitions
read the
[XRD documentation]({{<ref "../concepts/composite-resource-definitions">}}).
{{< /hint >}}
View the installed XRD with `kubectl get xrd`.
```shell {copy-lines="1"}
kubectl get xrd
NAME ESTABLISHED OFFERED AGE
virtualmachines.compute.example.com True True 43s
```
View the new custom API endpoints with `kubectl api-resources | grep VirtualMachine`
```shell {copy-lines="1",label="apiRes"}
kubectl api-resources | grep VirtualMachine
virtualmachineclaims compute.example.com/v1alpha1 true VirtualMachineClaim
virtualmachines compute.example.com/v1alpha1 false VirtualMachine
```
## Create a deployment template
When users access the custom API Crossplane takes their inputs and combines them
with a template describing what infrastructure to deploy. Crossplane calls this
template a _Composition_.
The {{<hover label="comp" line="3">}}Composition{{</hover>}} defines all the
cloud resources to deploy.
Each entry in the template
is a full resource definitions, defining all the resource settings and metadata
like labels and annotations.
This template creates an Azure
{{<hover label="comp" line="11">}}LinuxVirtualMachine{{</hover>}}
{{<hover label="comp" line="46">}}NetworkInterface{{</hover>}},
{{<hover label="comp" line="69">}}Subnet{{</hover>}}
{{<hover label="comp" line="90">}}VirtualNetwork{{</hover>}} and
{{<hover label="comp" line="110">}}ResourceGroup{{</hover>}}.
This Composition takes the user's
{{<hover label="comp" line="36">}}location{{</hover>}} input and uses it as the
{{<hover label="comp" line="37">}}location{{</hover>}} used in the individual
resource.
{{<hint "important" >}}
This Composition uses an array of resource templates. You can patch each
template with data copied from the custom API. Crossplane calls this a _Patch
and Transform_ Composition.
You don't have to use Patch and Transform. Crossplane supports a variety of
alternatives, including Go Templating and CUE. You can also write a function in
Go or Python to template your resources.
Read the [Composition documentation]({{<ref "../concepts/compositions">}}) for
more information on configuring Compositions and all the available options.
{{< /hint >}}
Apply this Composition to your cluster.
```yaml {label="comp",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: crossplane-quickstart-vm-with-network
spec:
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: quickstart-vm
base:
apiVersion: compute.azure.upbound.io/v1beta1
kind: LinuxVirtualMachine
spec:
forProvider:
adminUsername: adminuser
adminSshKey:
- publicKey: ssh-rsa
AAAAB3NzaC1yc2EAAAADAQABAAABAQC+wWK73dCr+jgQOAxNsHAnNNNMEMWOHYEccp6wJm2gotpr9katuF/ZAdou5AaW1C61slRkHRkpRRX9FA9CYBiitZgvCCz+3nWNN7l/Up54Zps/pHWGZLHNJZRYyAB6j5yVLMVHIHriY49d/GZTZVNB8GoJv9Gakwc/fuEZYYl4YDFiGMBP///TzlI4jhiJzjKnEvqPFki5p2ZRJqcbCiF4pJrxUQR/RXqVFQdbRLZgYfJ8xGB878RENq3yQ39d8dVOkq4edbkzwcUmwwwkYVPIoDGsYLaRHnG+To7FvMeyO7xDVQkMKzopTQV8AuKpyvpqu0a9pWOMaiCyDytO7GGN
example@docs.crossplane.io
username: adminuser
location: "Central US"
osDisk:
- caching: ReadWrite
storageAccountType: Standard_LRS
resourceGroupNameSelector:
matchControllerRef: true
size: Standard_B1ms
sourceImageReference:
- offer: debian-11
publisher: Debian
sku: 11-backports-gen2
version: latest
networkInterfaceIdsSelector:
matchControllerRef: true
patches:
- type: FromCompositeFieldPath
fromFieldPath: "spec.location"
toFieldPath: "spec.forProvider.location"
transforms:
- type: map
map:
EU: "Sweden Central"
US: "Central US"
- name: quickstart-nic
base:
apiVersion: network.azure.upbound.io/v1beta1
kind: NetworkInterface
spec:
forProvider:
ipConfiguration:
- name: crossplane-quickstart-configuration
privateIpAddressAllocation: Dynamic
subnetIdSelector:
matchControllerRef: true
location: "Central US"
resourceGroupNameSelector:
matchControllerRef: true
patches:
- type: FromCompositeFieldPath
fromFieldPath: "spec.location"
toFieldPath: "spec.forProvider.location"
transforms:
- type: map
map:
EU: "Sweden Central"
US: "Central US"
- name: quickstart-subnet
base:
apiVersion: network.azure.upbound.io/v1beta1
kind: Subnet
spec:
forProvider:
addressPrefixes:
- 10.0.1.0/24
virtualNetworkNameSelector:
matchControllerRef: true
resourceGroupNameSelector:
matchControllerRef: true
- name: quickstart-network
base:
apiVersion: network.azure.upbound.io/v1beta1
kind: VirtualNetwork
spec:
forProvider:
addressSpace:
- 10.0.0.0/16
location: "Central US"
resourceGroupNameSelector:
matchControllerRef: true
patches:
- type: FromCompositeFieldPath
fromFieldPath: "spec.location"
toFieldPath: "spec.forProvider.location"
transforms:
- type: map
map:
EU: "Sweden Central"
US: "Central US"
- name: crossplane-resourcegroup
base:
apiVersion: azure.upbound.io/v1beta1
kind: ResourceGroup
spec:
forProvider:
location: Central US
patches:
- type: FromCompositeFieldPath
fromFieldPath: "spec.location"
toFieldPath: "spec.forProvider.location"
transforms:
- type: map
map:
EU: "Sweden Central"
US: "Central US"
compositeTypeRef:
apiVersion: compute.example.com/v1alpha1
kind: VirtualMachine
EOF
```
The {{<hover label="comp" line="52">}}compositeTypeRef{{</hover >}} defines
which custom APIs can use this template to create resources.
A Composition uses a pipeline of _composition functions_ to define the cloud
resources to deploy. This template uses
{{<hover label="comp" line="10">}}function-patch-and-transform{{</hover>}}.
You must install the function before you can use it in a Composition.
Apply this Function to install `function-patch-and-transform`:
```yaml {label="install"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: function-patch-and-transform
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2
EOF
```
{{<hint "tip" >}}
Read the [Composition documentation]({{<ref "../concepts/compositions">}}) for
more information on configuring Compositions and all the available options.
Read the
[Patch and Transform function documentation]({{<ref "../guides/function-patch-and-transform">}})
for more information on how it uses patches to map user inputs to Composition
resource templates.
{{< /hint >}}
View the Composition with `kubectl get composition`
```shell {copy-lines="1"}
kubectl get composition
NAME XR-KIND XR-APIVERSION AGE
crossplane-quickstart-vm-with-network XVirtualMachine custom-api.example.org/v1alpha1 77s
```
## Install the Azure virtual machine provider
Part 1 only installed the Azure Virtual Network Provider. To deploying virtual
machines requires the Azure Compute provider as well.
Add the new Provider to the cluster.
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-azure-compute
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-azure-compute:v1.11.2
EOF
```
View the new Compute provider with `kubectl get providers`.
```shell {copy-lines="1"}
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-family-azure True True xpkg.crossplane.io/crossplane-contrib/provider-family-azure:v1.11.2 23m
provider-azure-compute True True xpkg.crossplane.io/crossplane-contrib/provider-azure-compute:v1.11.2 2m54s
provider-azure-network True True xpkg.crossplane.io/crossplane-contrib/provider-azure-network:v1.11.2 23m
```
## Access the custom API
With the custom API (XRD) installed and associated to a resource template
(Composition) users can access the API to create resources.
Create a {{<hover label="xr" line="3">}}VirtualMachine{{</hover>}} object to
create the cloud resources.
```yaml {copy-lines="all",label="xr"}
cat <<EOF | kubectl apply -f -
apiVersion: compute.example.com/v1alpha1
kind: VirtualMachine
metadata:
name: my-vm
spec:
location: "EU"
EOF
```
View the resource with `kubectl get VirtualMachine`.
{{< hint "note" >}}
It may take up to five minutes for the resources to provision.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl get VirtualMachine
NAME SYNCED READY COMPOSITION AGE
my-vm True True crossplane-quickstart-vm-with-network 3m3s
```
This object is a Crossplane _composite resource_ (also called an `XR`).
It's a
single object representing the collection of resources created from the
Composition template.
View the individual resources with `kubectl get managed`
```shell {copy-lines="1"}
kubectl get managed
NAME READY SYNCED EXTERNAL-NAME AGE
resourcegroup.azure.upbound.io/my-vm-7jb4n True True my-vm-7jb4n 3m43s
NAME READY SYNCED EXTERNAL-NAME AGE
linuxvirtualmachine.compute.azure.upbound.io/my-vm-5h7p4 True True my-vm-5h7p4 3m43s
NAME READY SYNCED EXTERNAL-NAME AGE
networkinterface.network.azure.upbound.io/my-vm-j7fpx True True my-vm-j7fpx 3m43s
NAME READY SYNCED EXTERNAL-NAME AGE
subnet.network.azure.upbound.io/my-vm-b2dqt True True my-vm-b2dqt 3m43s
NAME READY SYNCED EXTERNAL-NAME AGE
virtualnetwork.network.azure.upbound.io/my-vm-pd2sw True True my-vm-pd2sw 3m43s
```
Accessing the API created all five resources defined in the template and linked
them together.
Look at a specific resource to see it's created in the location used in the API.
```yaml {copy-lines="1"}
kubectl describe linuxvirtualmachine | grep Location
Location: Sweden Central
Location: swedencentral
```
Delete the resources with `kubectl delete VirtualMachine`.
```shell {copy-lines="1"}
kubectl delete VirtualMachine my-vm
virtualmachine.compute.example.com "my-vm" deleted
```
Verify Crossplane deleted the resources with `kubectl get managed`
{{<hint "note" >}}
It may take up to 5 minutes to delete the resources.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl get managed
No resources found
```
## Using the API with namespaces
Accessing the API `VirtualMachine` happens at the cluster scope.
Most organizations
isolate their users into namespaces.
A Crossplane _Claim_ is the custom API in a namespace.
Creating a _Claim_ is just like accessing the custom API endpoint, but with the
{{<hover label="claim" line="3">}}kind{{</hover>}}
from the custom API's `claimNames`.
Create a new namespace to test create a Claim in.
```shell
kubectl create namespace crossplane-test
```
Then create a Claim in the `crossplane-test` namespace.
```yaml {label="claim",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: compute.example.com/v1alpha1
kind: VirtualMachineClaim
metadata:
name: my-namespaced-vm
namespace: crossplane-test
spec:
location: "EU"
EOF
```
View the Claim with `kubectl get claim -n crossplane-test`.
```shell {copy-lines="1"}
kubectl get claim -n crossplane-test
NAME SYNCED READY CONNECTION-SECRET AGE
my-namespaced-vm True True 5m11s
```
The Claim automatically creates a composite resource, which creates the managed
resources.
View the Crossplane created composite resource with `kubectl get composite`.
```shell {copy-lines="1"}
kubectl get composite
NAME SYNCED READY COMPOSITION AGE
my-namespaced-vm-r7gdr True True crossplane-quickstart-vm-with-network 5m33s
```
Again, view the managed resources with `kubectl get managed`.
```shell {copy-lines="1"}
NAME READY SYNCED EXTERNAL-NAME AGE
resourcegroup.azure.upbound.io/my-namespaced-vm-r7gdr-cvzw6 True True my-namespaced-vm-r7gdr-cvzw6 5m51s
NAME READY SYNCED EXTERNAL-NAME AGE
linuxvirtualmachine.compute.azure.upbound.io/my-namespaced-vm-r7gdr-vrbgb True True my-namespaced-vm-r7gdr-vrbgb 5m51s
NAME READY SYNCED EXTERNAL-NAME AGE
networkinterface.network.azure.upbound.io/my-namespaced-vm-r7gdr-hwrb8 True True my-namespaced-vm-r7gdr-hwrb8 5m51s
NAME READY SYNCED EXTERNAL-NAME AGE
subnet.network.azure.upbound.io/my-namespaced-vm-r7gdr-gh468 True True my-namespaced-vm-r7gdr-gh468 5m51s
NAME READY SYNCED EXTERNAL-NAME AGE
virtualnetwork.network.azure.upbound.io/my-namespaced-vm-r7gdr-5qhz7 True True my-namespaced-vm-r7gdr-5qhz7 5m51s
```
Deleting the Claim deletes all the Crossplane generated resources.
`kubectl delete claim -n crossplane-test my-VirtualMachine-database`
```shell {copy-lines="1"}
kubectl delete claim -n crossplane-test my-namespaced-vm
virtualmachineclaim.compute.example.com "my-namespaced-vm" deleted
```
{{<hint "note" >}}
It may take up to 5 minutes to delete the resources.
{{< /hint >}}
Verify Crossplane deleted the composite resource with `kubectl get composite`.
```shell {copy-lines="1"}
kubectl get composite
No resources found
```
Verify Crossplane deleted the managed resources with `kubectl get managed`.
```shell {copy-lines="1"}
kubectl get managed
No resources found
```
## Next steps
* Explore Azure resources that Crossplane can configure in the
[Provider CRD reference](https://github.com/crossplane-contrib/provider-upjet-azure/tree/main/package/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with
Crossplane users and contributors.
* Read more about the [Crossplane concepts]({{<ref "../concepts">}}) to find out
what else you can do with Crossplane.

View File

@ -1,239 +0,0 @@
---
title: Azure Quickstart
weight: 110
---
Connect Crossplane to Azure to create and manage cloud resources from Kubernetes
with
[provider-upjet-azure](https://github.com/crossplane-contrib/provider-upjet-azure).
This guide is in two parts:
* Part 1 walks through installing Crossplane, configuring the provider to
authenticate to Azure and creating a _Managed Resource_ in Azure directly from
your Kubernetes cluster. This shows Crossplane can communicate with Azure.
* [Part 2]({{< ref "provider-azure-part-2" >}}) shows how to build and access a
custom API with Crossplane.
## Prerequisites
This quickstart requires:
* a Kubernetes cluster with at least 2 GB of RAM
* permissions to create pods and secrets in the Kubernetes cluster
* [Helm](https://helm.sh/) version v3.2.0 or later
* an Azure account with permissions to create an
[Azure Virtual Machine](https://learn.microsoft.com/en-us/azure/virtual-machines/)
and
[Virtual Network](https://learn.microsoft.com/en-us/azure/virtual-network/)
* an Azure account with permissions to create an Azure [service principal](https://learn.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals#service-principal-object) and an [Azure resource group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal)
{{<include file="/master/getting-started/install-crossplane-include.md" type="page" >}}
## Install the Azure provider
Install the Azure Network resource provider into the Kubernetes cluster with a Kubernetes configuration
file.
```yaml {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-azure-network
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-azure-network:v1.11.2
EOF
```
The Crossplane {{< hover label="provider" line="3" >}}Provider{{</hover>}}
installs the Kubernetes _Custom Resource Definitions_ (CRDs) representing Azure Networking
services. These CRDs allow you to create Azure resources directly inside
Kubernetes.
Verify the provider installed with `kubectl get providers`.
```shell {copy-lines="1",label="getProvider"}
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-family-azure True True xpkg.crossplane.io/crossplane-contrib/provider-family-azure:v1.11.2 2m18s
provider-azure-network True True xpkg.crossplane.io/crossplane-contrib/provider-azure-network:v1.11.2 2m23s
```
The Network Provider installs a second Provider, the
{{<hover label="getProvider" line="4">}}crossplane-contrib-provider-family-azure{{</hover>}}
provider.
The family provider manages authentication to Azure across all Azure family
Providers.
You can view the new CRDs with `kubectl get crds`.
Every CRD maps to a unique Azure service Crossplane can provision and manage.
{{< hint type="tip" >}}
See details about all the supported CRDs in the
[provider examples](https://github.com/crossplane-contrib/provider-upjet-azure/tree/main/examples).
{{< /hint >}}
## Create a Kubernetes secret for Azure
The provider requires credentials to create and manage Azure resources.
Providers use a Kubernetes _Secret_ to connect the credentials to the provider.
This guide generates an Azure service principal JSON file and saves it as a
Kubernetes _Secret_.
### Install the Azure command-line
Generating an [authentication file](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-file-based-authentication) requires the Azure command-line.
Follow the documentation from Microsoft to [Download and install the Azure command-line](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli).
Log in to the Azure command-line.
```command
az login
```
### Create an Azure service principal
Follow the Azure documentation to [find your Subscription ID](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id) from the Azure Portal.
Using the Azure command-line and provide your Subscription ID create a service principal and authentication file.
{{< editCode >}}
```console {copy-lines="all"}
az ad sp create-for-rbac \
--sdk-auth \
--role Owner \
--scopes /subscriptions/$@<subscription_id>$@
```
{{< /editCode >}}
Save your Azure JSON output as `azure-credentials.json`.
{{< hint type="note" >}}
The
[Authentication](https://docs.upbound.io/providers/provider-azure/authentication/)
section of the Azure Provider documentation describes other authentication methods.
{{< /hint >}}
### Create a Kubernetes secret with the Azure credentials
A Kubernetes generic secret has a name and contents. Use {{< hover label="kube-create-secret" line="1">}}kubectl create secret{{< /hover >}} to generate the secret object named {{< hover label="kube-create-secret" line="2">}}azure-secret{{< /hover >}} in the {{< hover label="kube-create-secret" line="3">}}crossplane-system{{</ hover >}} namespace.
<!-- vale gitlab.Substitutions = NO -->
<!-- ignore .json file name -->
Use the {{< hover label="kube-create-secret" line="4">}}--from-file={{</hover>}} argument to set the value to the contents of the {{< hover label="kube-create-secret" line="4">}}azure-credentials.json{{< /hover >}} file.
<!-- vale gitlab.Substitutions = YES -->
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret \
generic azure-secret \
-n crossplane-system \
--from-file=creds=./azure-credentials.json
```
View the secret with `kubectl describe secret`
{{< hint type="note" >}}
The size may be larger if there are extra blank spaces in your text file.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl describe secret azure-secret -n crossplane-system
Name: azure-secret
Namespace: crossplane-system
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
creds: 629 bytes
```
## Create a ProviderConfig
A `ProviderConfig` customizes the settings of the Azure Provider.
Apply the {{< hover label="providerconfig" line="5">}}ProviderConfig{{</ hover >}} with the command:
```yaml {label="providerconfig",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: azure.upbound.io/v1beta1
metadata:
name: default
kind: ProviderConfig
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: azure-secret
key: creds
EOF
```
This attaches the Azure credentials, saved as a Kubernetes secret, as a {{< hover label="providerconfig" line="9">}}secretRef{{</ hover>}}.
The {{< hover label="providerconfig" line="11">}}spec.credentials.secretRef.name{{< /hover >}} value is the name of the Kubernetes secret containing the Azure credentials in the {{< hover label="providerconfig" line="10">}}spec.credentials.secretRef.namespace{{< /hover >}}.
## Create a managed resource
A _managed resource_ is anything Crossplane creates and manages outside of the
Kubernetes cluster. This example creates an Azure Virtual Network with
Crossplane. The Virtual Network is a _managed resource_.
{{< hint type="note" >}}
Add your Azure Resource Group name. Follow the Azure documentation to
[create a resource group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal)
if you don't have one.
{{< /hint >}}
{{< editCode >}}
```yaml {label="xr"}
cat <<EOF | kubectl create -f -
apiVersion: network.azure.upbound.io/v1beta1
kind: VirtualNetwork
metadata:
name: crossplane-quickstart-network
spec:
forProvider:
addressSpace:
- 10.0.0.0/16
location: "Sweden Central"
resourceGroupName: docs
EOF
```
{{< /editCode >}}
The {{< hover label="xr" line="2">}}apiVersion{{< /hover >}} and
{{< hover label="xr" line="3">}}kind{{</hover >}} are from the provider's CRDs.
The {{< hover label="xr" line="10">}}spec.forProvider.location{{< /hover >}}
tells Azure which location to use when deploying the resource.
Use `kubectl get virtualnetwork.network` to verify Crossplane created the
Azure Virtual Network.
{{< hint type="tip" >}}
Crossplane created the virtual network when the values `READY` and `SYNCED` are `True`.
This may take up to 5 minutes.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl get virtualnetwork.network
NAME READY SYNCED EXTERNAL-NAME AGE
crossplane-quickstart-network True True crossplane-quickstart-network 10m
```
## Delete the managed resource
Before shutting down your Kubernetes cluster, delete the virtual network just
created.
Use `kubectl delete virtualnetwork.network` to delete the virtual network.
```shell {copy-lines="1"}
kubectl delete virtualnetwork.network crossplane-quickstart-network
virtualnetwork.network.azure.upbound.io "crossplane-quickstart-network" deleted
```
## Next steps
* [**Continue to part 2**]({{< ref "provider-azure-part-2">}}) to create and use
a custom API with Crossplane.
* Explore Azure resources that Crossplane can configure in the
[Provider CRD reference](https://github.com/crossplane-contrib/provider-upjet-azure/tree/main/package/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with
Crossplane users and contributors.

View File

@ -1,608 +0,0 @@
---
title: GCP Quickstart Part 2
weight: 120
tocHidden: true
aliases:
- /master/getting-started/provider-azure-part-3
---
{{< hint "important" >}}
This guide is part 2 of a series.
[**Part 1**]({{<ref "provider-gcp" >}}) covers
to installing Crossplane and connect your Kubernetes cluster to GCP.
{{< /hint >}}
This guide walks you through building and accessing a custom API with
Crossplane.
## Prerequisites
* Complete [quickstart part 1]({{<ref "provider-gcp" >}}) connecting Kubernetes
to GCP.
* a GCP account with permissions to create a GCP
[storage bucket](https://cloud.google.com/storage) and a
[Pub/Sub topic](https://cloud.google.com/pubsub).
{{<expand "Skip part 1 and just get started" >}}
1. Add the Crossplane Helm repository and install Crossplane.
```shell
helm repo add \
crossplane-stable https://charts.crossplane.io/stable
helm repo update
&&
helm install crossplane \
crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace
```
2. When the Crossplane pods finish installing and are ready, apply the GCP
Provider.
```yaml {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-gcp-storage
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-gcp-storage:v1.12.1
EOF
```
3. Create a file called `gcp-credentials.json` with your GCP service account
JSON file.
{{< hint "tip" >}}
The
[GCP documentation](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)
provides information on how to generate a service account JSON file.
{{< /hint >}}
4. Create a Kubernetes secret from the GCP JSON file
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret \
generic gcp-secret \
-n crossplane-system \
--from-file=creds=./gcp-credentials.json
```
5. Create a _ProviderConfig_
Include your
{{< hover label="providerconfig" line="7" >}}GCP project ID{{< /hover >}} in the
_ProviderConfig_ settings.
{{< hint type="tip" >}}
Find your GCP project ID from the `project_id` field of the
`gcp-credentials.json` file.
{{< /hint >}}
{{< editCode >}}
```yaml {label="providerconfig",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: gcp.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
projectID: $@<PROJECT_ID>$@
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: gcp-secret
key: creds
EOF
```
{{< /editCode >}}
{{</expand >}}
## Install the PubSub Provider
Part 1 only installed the GCP Storage Provider. This section deploys a
PubSub Topic along with a GCP storage bucket.
First install the GCP PubSub Provider.
Add the new Provider to the cluster.
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-gcp-pubsub
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-gcp-pubsub:v1.12.1
EOF
```
View the new PubSub provider with `kubectl get providers`.
```shell {copy-lines="1"}
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-family-gcp True True xpkg.crossplane.io/crossplane-contrib/provider-family-gcp:v1.12.1 48m
provider-gcp-pubsub True True xpkg.crossplane.io/crossplane-contrib/provider-gcp-pubsub:v1.12.1 14s
provider-gcp-storage True True xpkg.crossplane.io/crossplane-contrib/provider-gcp-storage:v1.12.1 48m
```
## Create a custom API
<!-- vale alex.Condescending = NO -->
Crossplane allows you to build your own custom APIs for your users, abstracting
away details about the cloud provider and their resources. You can make your API
as complex or simple as you wish.
<!-- vale alex.Condescending = YES -->
The custom API is a Kubernetes object.
Here is an example custom API.
```yaml {label="exAPI"}
apiVersion: database.example.com/v1alpha1
kind: NoSQL
metadata:
name: my-nosql-database
spec:
location: "US"
```
Like any Kubernetes object the API has a
{{<hover label="exAPI" line="1">}}version{{</hover>}},
{{<hover label="exAPI" line="2">}}kind{{</hover>}} and
{{<hover label="exAPI" line="5">}}spec{{</hover>}}.
### Define a group and version
To create your own API start by defining an
[API group](https://kubernetes.io/docs/reference/using-api/#api-groups) and
[version](https://kubernetes.io/docs/reference/using-api/#api-versioning).
The _group_ can be any value, but common convention is to map to a fully
qualified domain name.
<!-- vale gitlab.SentenceLength = NO -->
The version shows how mature or stable the API is and increments when changing,
adding or removing fields in the API.
<!-- vale gitlab.SentenceLength = YES -->
Crossplane doesn't require specific versions or a specific version naming
convention, but following
[Kubernetes API versioning guidelines](https://kubernetes.io/docs/reference/using-api/#api-versioning)
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.
This guide uses the group
{{<hover label="version" line="1">}}database.example.com{{</hover>}}.
Because this is the first version of the API, this guide uses the version
{{<hover label="version" line="1">}}v1alpha1{{</hover>}}.
```yaml {label="version",copy-lines="none"}
apiVersion: database.example.com/v1alpha1
```
### Define a kind
The API group is a logical collection of related APIs. In a group are
individual kinds representing different resources.
For example a `queue` group may have a `PubSub` and `CloudTask` kinds.
The `kind` can be anything, but it must be
[UpperCamelCased](https://kubernetes.io/docs/contribute/style/style-guide/#use-upper-camel-case-for-api-objects).
This API's kind is
{{<hover label="kind" line="2">}}PubSub{{</hover>}}
```yaml {label="kind",copy-lines="none"}
apiVersion: queue.example.com/v1alpha1
kind: PubSub
```
### Define a spec
The most important part of an API is the schema. The schema defines the inputs
accepted from users.
This API allows users to provide a
{{<hover label="spec" line="4">}}location{{</hover>}} of where to run their
cloud resources.
All other resource settings can't be configurable by the users. This allows
Crossplane to enforce any policies and standards without worrying about
user errors.
```yaml {label="spec",copy-lines="none"}
apiVersion: queue.example.com/v1alpha1
kind: PubSub
spec:
location: "US"
```
### Apply the API
Crossplane uses
{{<hover label="xrd" line="3">}}Composite Resource Definitions{{</hover>}}
(also called an `XRD`) to install your custom API in
Kubernetes.
The XRD {{<hover label="xrd" line="6">}}spec{{</hover>}} contains all the
information about the API including the
{{<hover label="xrd" line="7">}}group{{</hover>}},
{{<hover label="xrd" line="12">}}version{{</hover>}},
{{<hover label="xrd" line="9">}}kind{{</hover>}} and
{{<hover label="xrd" line="13">}}schema{{</hover>}}.
The XRD's {{<hover label="xrd" line="5">}}name{{</hover>}} must be the
combination of the {{<hover label="xrd" line="9">}}plural{{</hover>}} and
{{<hover label="xrd" line="7">}}group{{</hover>}}.
The {{<hover label="xrd" line="13">}}schema{{</hover>}} uses the
{{<hover label="xrd" line="14">}}OpenAPIv3{{</hover>}} specification to define
the API {{<hover label="xrd" line="17">}}spec{{</hover>}}.
The API defines a {{<hover label="xrd" line="20">}}location{{</hover>}} that
must be {{<hover label="xrd" line="22">}}oneOf{{</hover>}} either
{{<hover label="xrd" line="23">}}EU{{</hover>}} or
{{<hover label="xrd" line="24">}}US{{</hover>}}.
Apply this XRD to create the custom API in your Kubernetes cluster.
```yaml {label="xrd",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: pubsubs.queue.example.com
spec:
group: queue.example.com
names:
kind: PubSub
plural: pubsubs
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
location:
type: string
oneOf:
- pattern: '^EU$'
- pattern: '^US$'
required:
- location
served: true
referenceable: true
claimNames:
kind: PubSubClaim
plural: pubsubclaims
EOF
```
Adding the {{<hover label="xrd" line="29">}}claimNames{{</hover>}} allows users
to access this API either at the cluster level with the
{{<hover label="xrd" line="9">}}pubsub{{</hover>}} endpoint or in a namespace
with the
{{<hover label="xrd" line="29">}}pubsubclaim{{</hover>}} endpoint.
The namespace scoped API is a Crossplane _Claim_.
{{<hint "tip" >}}
For more details on the fields and options of Composite Resource Definitions
read the
[XRD documentation]({{<ref "../concepts/composite-resource-definitions">}}).
{{< /hint >}}
View the installed XRD with `kubectl get xrd`.
```shell {copy-lines="1"}
kubectl get xrd
NAME ESTABLISHED OFFERED AGE
pubsubs.queue.example.com True True 7s
```
View the new custom API endpoints with `kubectl api-resources | grep pubsub`
```shell {copy-lines="1",label="apiRes"}
kubectl api-resources | grep queue.example
pubsubclaims queue.example.com/v1alpha1 true PubSubClaim
pubsubs queue.example.com/v1alpha1 false PubSub
```
## Create a deployment template
When users access the custom API Crossplane takes their inputs and combines them
with a template describing what infrastructure to deploy. Crossplane calls this
template a _Composition_.
The {{<hover label="comp" line="3">}}Composition{{</hover>}} defines all the
cloud resources to deploy.
Each entry in the template
is a full resource definitions, defining all the resource settings and metadata
like labels and annotations.
This template creates a GCP
{{<hover label="comp" line="10">}}Storage{{</hover>}}
{{<hover label="comp" line="11">}}Bucket{{</hover>}} and a
{{<hover label="comp" line="25">}}PubSub{{</hover>}}
{{<hover label="comp" line="26">}}Topic{{</hover>}}.
This Composition takes the user's
{{<hover label="comp" line="16">}}location{{</hover>}} input and uses it as the
{{<hover label="comp" line="14">}}location{{</hover>}} used in the individual
resource.
{{<hint "important" >}}
This Composition uses an array of resource templates. You can patch each
template with data copied from the custom API. Crossplane calls this a _Patch
and Transform_ Composition.
You don't have to use Patch and Transform. Crossplane supports a variety of
alternatives, including Go Templating and CUE. You can also write a function in
Go or Python to template your resources.
Read the [Composition documentation]({{<ref "../concepts/compositions">}}) for
more information on configuring Compositions and all the available options.
{{< /hint >}}
Apply this Composition to your cluster.
```yaml {label="comp",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: topic-with-bucket
spec:
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: crossplane-quickstart-bucket
base:
apiVersion: storage.gcp.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
location: "US"
patches:
- fromFieldPath: "spec.location"
toFieldPath: "spec.forProvider.location"
transforms:
- type: map
map:
EU: "EU"
US: "US"
- name: crossplane-quickstart-topic
base:
apiVersion: pubsub.gcp.upbound.io/v1beta1
kind: Topic
spec:
forProvider:
messageStoragePolicy:
- allowedPersistenceRegions:
- "us-central1"
patches:
- fromFieldPath: "spec.location"
toFieldPath: "spec.forProvider.messageStoragePolicy[0].allowedPersistenceRegions[0]"
transforms:
- type: map
map:
EU: "europe-central2"
US: "us-central1"
compositeTypeRef:
apiVersion: queue.example.com/v1alpha1
kind: PubSub
EOF
```
The {{<hover label="comp" line="40">}}compositeTypeRef{{</hover >}} defines
which custom APIs can use this template to create resources.
A Composition uses a pipeline of _composition functions_ to define the cloud
resources to deploy. This template uses
{{<hover label="comp" line="10">}}function-patch-and-transform{{</hover>}}.
You must install the function before you can use it in a Composition.
Apply this Function to install `function-patch-and-transform`:
```yaml {label="install"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: function-patch-and-transform
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2
EOF
```
{{<hint "tip" >}}
Read the [Composition documentation]({{<ref "../concepts/compositions">}}) for
more information on configuring Compositions and all the available options.
Read the
[Patch and Transform function documentation]({{<ref "../guides/function-patch-and-transform">}})
for more information on how it uses patches to map user inputs to Composition
resource templates.
{{< /hint >}}
View the Composition with `kubectl get composition`
```shell {copy-lines="1"}
kubectl get composition
NAME XR-KIND XR-APIVERSION AGE
topic-with-bucket PubSub queue.example.com 3s
```
## Access the custom API
With the custom API (XRD) installed and associated to a resource template
(Composition) users can access the API to create resources.
Create a {{<hover label="xr" line="2">}}PubSub{{</hover>}} object to create the
cloud resources.
```yaml {copy-lines="all",label="xr"}
cat <<EOF | kubectl apply -f -
apiVersion: queue.example.com/v1alpha1
kind: PubSub
metadata:
name: my-pubsub-queue
spec:
location: "US"
EOF
```
View the resource with `kubectl get pubsub`.
```shell {copy-lines="1"}
kubectl get pubsub
NAME SYNCED READY COMPOSITION AGE
my-pubsub-queue True True topic-with-bucket 2m12s
```
This object is a Crossplane _composite resource_ (also called an `XR`).
It's a
single object representing the collection of resources created from the
Composition template.
View the individual resources with `kubectl get managed`
```shell {copy-lines="1"}
kubectl get managed
NAME READY SYNCED EXTERNAL-NAME AGE
topic.pubsub.gcp.upbound.io/my-pubsub-queue-cjswx True True my-pubsub-queue-cjswx 3m4s
NAME READY SYNCED EXTERNAL-NAME AGE
bucket.storage.gcp.upbound.io/my-pubsub-queue-vljg9 True True my-pubsub-queue-vljg9 3m4s
```
Delete the resources with `kubectl delete pubsub`.
```shell {copy-lines="1"}
kubectl delete pubsub my-pubsub-queue
pubsub.queue.example.com "my-pubsub-queue" deleted
```
Verify Crossplane deleted the resources with `kubectl get managed`
{{<hint "note" >}}
It may take up to 5 minutes to delete the resources.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl get managed
No resources found
```
## Using the API with namespaces
Accessing the API `pubsub` happens at the cluster scope.
Most organizations
isolate their users into namespaces.
A Crossplane _Claim_ is the custom API in a namespace.
Creating a _Claim_ is just like accessing the custom API endpoint, but with the
{{<hover label="claim" line="3">}}kind{{</hover>}}
from the custom API's `claimNames`.
Create a new namespace to test create a Claim in.
```shell
kubectl create namespace crossplane-test
```
Then create a Claim in the `crossplane-test` namespace.
```yaml {label="claim",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: queue.example.com/v1alpha1
kind: PubSubClaim
metadata:
name: my-pubsub-queue
namespace: crossplane-test
spec:
location: "US"
EOF
```
View the Claim with `kubectl get claim -n crossplane-test`.
```shell {copy-lines="1"}
kubectl get claim -n crossplane-test
NAME SYNCED READY CONNECTION-SECRET AGE
my-pubsub-queue True True 2m10s
```
The Claim automatically creates a composite resource, which creates the managed
resources.
View the Crossplane created composite resource with `kubectl get composite`.
```shell {copy-lines="1"}
kubectl get composite
NAME SYNCED READY COMPOSITION AGE
my-pubsub-queue-7bm9n True True topic-with-bucket 3m10s
```
Again, view the managed resources with `kubectl get managed`.
```shell {copy-lines="1"}
kubectl get managed
NAME READY SYNCED EXTERNAL-NAME AGE
topic.pubsub.gcp.upbound.io/my-pubsub-queue-7bm9n-6kdq4 True True my-pubsub-queue-7bm9n-6kdq4 3m22s
NAME READY SYNCED EXTERNAL-NAME AGE
bucket.storage.gcp.upbound.io/my-pubsub-queue-7bm9n-hhwx8 True True my-pubsub-queue-7bm9n-hhwx8 3m22s
```
Deleting the Claim deletes all the Crossplane generated resources.
`kubectl delete claim -n crossplane-test my-pubsub-queue`
```shell {copy-lines="1"}
kubectl delete pubsubclaim my-pubsub-queue -n crossplane-test
pubsubclaim.queue.example.com "my-pubsub-queue" deleted
```
{{<hint "note" >}}
It may take up to 5 minutes to delete the resources.
{{< /hint >}}
Verify Crossplane deleted the composite resource with `kubectl get composite`.
```shell {copy-lines="1"}
kubectl get composite
No resources found
```
Verify Crossplane deleted the managed resources with `kubectl get managed`.
```shell {copy-lines="1"}
kubectl get managed
No resources found
```
## Next steps
* Explore AWS resources that Crossplane can configure in the
[provider CRD reference](https://github.com/crossplane-contrib/provider-upjet-aws/blob/main/package/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with
Crossplane users and contributors.
* Read more about the [Crossplane concepts]({{<ref "../concepts">}}) to find out what else you can do
with Crossplane.

View File

@ -1,251 +0,0 @@
---
title: GCP Quickstart
weight: 140
---
Connect Crossplane to GCP to create and manage cloud resources from Kubernetes
with
[provider-upjet-gcp](https://github.com/crossplane-contrib/provider-upjet-gcp).
This guide is in two parts:
* Part 1 walks through installing Crossplane, configuring the provider to
authenticate to GCP and creating a _Managed Resource_ in GCP directly from
your Kubernetes cluster. This shows Crossplane can communicate with GCP.
* [Part 2]({{< ref "provider-gcp-part-2" >}}) shows how to build and access a
custom API with Crossplane.
## Prerequisites
This quickstart requires:
* a Kubernetes cluster with at least 2 GB of RAM
* permissions to create pods and secrets in the Kubernetes cluster
* [Helm](https://helm.sh/) version v3.2.0 or later
* a GCP account with permissions to create a storage bucket
* GCP [account keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)
* GCP [Project ID](https://support.google.com/googleapi/answer/7014113?hl=en)
{{<include file="/master/getting-started/install-crossplane-include.md" type="page" >}}
## Install the GCP provider
Install the provider into the Kubernetes cluster with a Kubernetes configuration
file.
```shell {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-gcp-storage
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-gcp-storage:v1.12.1
EOF
```
The Crossplane {{< hover label="provider" line="3" >}}Provider{{</hover>}}
installs the Kubernetes _Custom Resource Definitions_ (CRDs) representing GCP storage
services. These CRDs allow you to create GCP resources directly inside
Kubernetes.
Verify the provider installed with `kubectl get providers`.
```shell {copy-lines="1",label="getProvider"}
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-family-gcp True True xpkg.crossplane.io/crossplane-contrib/provider-family-gcp:v1.12.1 33s
provider-gcp-storage True True xpkg.crossplane.io/crossplane-contrib/provider-gcp-storage:v1.12.1 37s
```
The Storage Provider installs a second Provider, the
{{<hover label="getProvider" line="4">}}crossplane-contrib-provider-family-gcp{{</hover>}}
provider.
The family provider manages authentication to GCP across all GCP family
Providers.
You can view the new CRDs with `kubectl get crds`.
Every CRD maps to a unique GCP service Crossplane can provision and manage.
{{< hint "tip" >}}
See details about all the supported CRDs in the
[provider examples](https://github.com/crossplane-contrib/provider-upjet-gcp/tree/main/examples).
{{< /hint >}}
## Create a Kubernetes secret for GCP
The provider requires credentials to create and manage GCP resources. Providers
use a Kubernetes _Secret_ to connect the credentials to the provider.
First generate a Kubernetes _Secret_ from a Google Cloud service account JSON
file and then configure the Provider to use it.
### Generate a GCP service account JSON file
For basic user authentication, use a Google Cloud service account JSON file.
{{< hint "tip" >}}
The
[GCP documentation](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)
provides information on how to generate a service account JSON file.
{{< /hint >}}
Save this JSON file as `gcp-credentials.json`
### Create a Kubernetes secret with the GCP credentials
A Kubernetes generic secret has a name and contents. Use
{{< hover label="kube-create-secret" line="1">}}kubectl create secret{{< /hover >}}
to generate the secret object named
{{< hover label="kube-create-secret" line="2">}}gcp-secret{{< /hover >}} in the
{{< hover label="kube-create-secret" line="3">}}crossplane-system{{</ hover >}}
namespace.
Use the {{< hover label="kube-create-secret" line="4">}}--from-file={{</hover>}}
argument to set the value to the contents of the
{{< hover label="kube-create-secret" line="4">}}gcp-credentials.json{{< /hover >}}
file.
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret \
generic gcp-secret \
-n crossplane-system \
--from-file=creds=./gcp-credentials.json
```
View the secret with `kubectl describe secret`
{{< hint "note" >}}
The file size may be a different depending on the contents.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl describe secret gcp-secret -n crossplane-system
Name: gcp-secret
Namespace: crossplane-system
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
creds: 2330 bytes
```
{{< hint type="note" >}}
The
[Authentication](https://docs.upbound.io/providers/provider-gcp/authentication/)
section of the GCP Provider documentation describes other authentication methods.
{{< /hint >}}
## Create a ProviderConfig
A `ProviderConfig` customizes the settings of the GCP Provider.
Include your
{{< hover label="providerconfig" line="7" >}}GCP project ID{{< /hover >}} in the
_ProviderConfig_ settings.
{{< hint "tip" >}}
Find your GCP project ID from the `project_id` field of the
`gcp-credentials.json` file.
{{< /hint >}}
Apply the
{{< hover label="providerconfig" line="2">}}ProviderConfig{{</ hover >}} with
the command:
{{< editCode >}}
```yaml {label="providerconfig",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: gcp.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
projectID: $@<PROJECT_ID>$@
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: gcp-secret
key: creds
EOF
```
{{< /editCode >}}
This attaches the GCP credentials, saved as a Kubernetes secret, as a
{{< hover label="providerconfig" line="10">}}secretRef{{</ hover>}}.
The {{< hover label="providerconfig" line="12">}}spec.credentials.secretRef.name{{< /hover >}} value is the name of the Kubernetes secret containing the GCP credentials in the
{{< hover label="providerconfig" line="11">}}spec.credentials.secretRef.namespace{{< /hover >}}.
## Create a managed resource
A _managed resource_ is anything Crossplane creates and manages outside of the
Kubernetes cluster. This example creates a GCP storage bucket with Crossplane.
The storage bucket is a _managed resource_.
{{< hint "note" >}}
To generate a unique name use
{{<hover label="xr" line="5">}}generateName{{</hover >}} instead of `name`.
{{< /hint >}}
Create the Bucket with the following command:
```yaml {label="xr",copy-lines="all"}
cat <<EOF | kubectl create -f -
apiVersion: storage.gcp.upbound.io/v1beta1
kind: Bucket
metadata:
generateName: crossplane-bucket-
labels:
docs.crossplane.io/example: provider-gcp
spec:
forProvider:
location: US
providerConfigRef:
name: default
EOF
```
The {{< hover label="xr" line="2">}}apiVersion{{< /hover >}} and
{{< hover label="xr" line="3">}}kind{{</hover >}} are from the provider's CRDs.
The {{< hover label="xr" line="10">}}spec.forProvider.location{{< /hover >}}
tells GCP which GCP region to use when deploying resources.
For a
{{<hover label="xr" line="3">}}bucket{{</hover >}} the
region can be any
[GCP multi-region location](https://cloud.google.com/storage/docs/locations#location-mr)
Use `kubectl get bucket` to verify Crossplane created the bucket.
{{< hint type="tip" >}}
Crossplane created the bucket when the values `READY` and `SYNCED` are `True`.
This may take up to 5 minutes.
{{< /hint >}}
```shell {copy-lines="1"}
kubectl get bucket
NAME READY SYNCED EXTERNAL-NAME AGE
crossplane-bucket-8b7gw True True crossplane-bucket-8b7gw 2m2s
```
## Delete the managed resource
Before shutting down your Kubernetes cluster, delete the GCP bucket just
created.
Use `kubectl delete bucket` to remove the bucket.
{{<hint "tip" >}}
Use the `--selector` flag to delete by label instead of by name.
{{</hint>}}
```shell {copy-lines="1"}
kubectl delete bucket --selector docs.crossplane.io/example=provider-gcp
bucket.storage.gcp.upbound.io "crossplane-bucket-8b7gw" deleted
```
## Next steps
* [**Continue to part 2**]({{< ref "provider-gcp-part-2">}}) to create a
Crossplane _Composite Resource_ and _Claim_.
* Explore GCP resources that can Crossplane can configure in the
[Provider CRD reference](https://github.com/crossplane-contrib/provider-upjet-gcp/tree/main/package/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with
Crossplane users and contributors.

View File

@ -1,271 +0,0 @@
---
title: Change Logs
weight: 210
description: "Change logs help you audit all changes made to your resources"
state: alpha
alphaVersion: "1.17"
---
The "change logs" feature is designed to help users of Crossplane Providers to
understand what changes a provider is making to the resources it's managing.
Whenever a provider creates, updates, or deletes a managed resource, an entry
explaining the details of the change is recorded in the provider's change log.
Change logs are important for awareness of the changes that a provider is
making to its managed resources. Due to the nature of Crossplane's active
reconciliation, it's possible for a provider to make changes to managed
resources without any user interaction. Consider the scenario when someone
updates a resource outside of Crossplane, for example via the AWS console or
`gcloud` CLI. When Crossplane detects this configuration drift it will
enforce its source of truth to eventually correct this unexpected change
without any user interaction.
With Crossplane acting continuously and autonomously to update critical
infrastructure, it's vital for users to have insight into the operations being
performed, so they can build and maintain a strong sense of confidence and trust
in their control planes. Change logs provide details about all changes the
provider makes, so users can remain aware of any changes, even when they aren't
explicitly expecting any.
{{<hint "tip">}} Change logs help you understand all the changes a provider is
making to your resources, even when changes weren't explicitly requested, for
example as a result of Crossplane's automatic correction of configuration drift.
{{</hint>}}
## Enabling Change Logs
{{<hint "important" >}} Change logs are an alpha feature and must be explicitly
enabled for each provider through the use of a `DeploymentRuntimeConfig`.
{{</hint >}}
To enable change logs for a provider, use a `DeploymentRuntimeConfig` to
configure each provider pod that should start producing change logs. The
`DeploymentRuntimeConfig` has a few important configuration details:
1. A command line argument to the provider container that enables the change
logs feature, for example `--enable-changelogs`.
1. A [side car container](https://github.com/crossplane/changelogs-sidecar) that
collects change events and produces change log entries to the provider's pod
logs.
1. A shared volume mounted to both the provider and sidecar containers that
enables communication of change events between the two containers.
### Prerequisites
This guide assumes you have a control plane with [Crossplane installed]({{<ref "../software/install">}}).
It also assumes you have the [`jq` tool installed](https://jqlang.org/download/),
to perform lightweight querying and filtering of the content in the change logs.
The only other prerequisite for enabling change logs is that the provider must
have added support for the change logs feature. This is optional and not all
providers in the Crossplane ecosystem have added this support yet.
{{<hint "tip">}} Not all providers support the change logs feature. Check with
your provider of choice to confirm it has added support for change logs.
{{</hint>}}
This guide walks through a full example of generating change logs with
[`provider-kubernetes`](https://github.com/crossplane-contrib/provider-kubernetes).
### Create a `DeploymentRuntimeConfig`
Create a `DeploymentRuntimeConfig` that will enable change logs for
the provider when it's installed by performing the necessary configuration
steps:
1. The {{<hover label="drc" line="15">}}--enable-changelogs{{</hover>}} flag is
set on the provider.
1. The {{<hover label="drc" line="19">}}sidecar container{{</hover>}} is added
to the provider pod.
1. A {{<hover label="drc" line="24">}}shared volume{{</hover>}} is declared and
then mounted in the {{<hover label="drc" line="16">}}provider
container{{</hover>}} and the {{<hover label="drc" line="21">}}sidecar
container{{</hover>}}.
```yaml {label="drc",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
name: enable-changelogs
spec:
deploymentTemplate:
spec:
selector: {}
template:
spec:
containers:
- name: package-runtime
args:
- --enable-changelogs
volumeMounts:
- name: changelogs-vol
mountPath: /var/run/changelogs
- name: changelogs-sidecar
image: xpkg.crossplane.io/crossplane/changelogs-sidecar:v0.0.1
volumeMounts:
- name: changelogs-vol
mountPath: /var/run/changelogs
volumes:
- name: changelogs-vol
emptyDir: {}
serviceAccountTemplate:
metadata:
name: provider-kubernetes
EOF
```
### Install the provider
Install the {{<hover label="provider" line="7">}}provider{{</hover>}} and
instruct it to use the {{<hover label="provider" line="8">}}DeploymentRuntimeConfig{{</hover>}}
that was just created.
```yaml {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-kubernetes
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-kubernetes:v0.18.0
runtimeConfigRef:
apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
name: enable-changelogs
EOF
```
### Configure permissions
In order for the provider to create Kubernetes resources within the control
plane, it must be granted the appropriate permissions. This guide only creates a
`ConfigMap`, so only permissions for that resource type are needed.
{{<hint "important">}} This guide grants specific permissions to the provider
for example purposes. This approach isn't intended to be representative of a
production environment. More examples on configuring `provider-kubernetes` can
be found in its [examples directory](https://github.com/crossplane-contrib/provider-kubernetes/tree/main/examples/provider).
{{</hint>}}
```yaml {label="rbac",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: configmap-edit
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- "*"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: provider-kubernetes-configmap-edit
subjects:
- kind: ServiceAccount
name: provider-kubernetes
namespace: crossplane-system
roleRef:
kind: ClusterRole
name: configmap-edit
apiGroup: rbac.authorization.k8s.io
---
apiVersion: kubernetes.crossplane.io/v1alpha1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: InjectedIdentity
EOF
```
### Create a resource
Now that the provider is installed and configured with change logs enabled,
create a resource that will generate change logs entries reflecting the actions
the control plane is taking.
```yaml {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: kubernetes.crossplane.io/v1alpha2
kind: Object
metadata:
name: configmap-for-changelogs
spec:
forProvider:
manifest:
apiVersion: v1
kind: ConfigMap
metadata:
namespace: default
name: configmap-for-changelogs
data:
key-1: cool-value-1
EOF
```
### Examine the change logs
Check to see that the resource creation operation was recorded in the change
logs. Examine the pod logs for `provider-kubernetes`, specifically at the
`changelogs-sidecar` container:
```shell {label="changelogs-output-full",copy-lines="1"}
kubectl -n crossplane-system logs -l pkg.crossplane.io/provider=provider-kubernetes -c changelogs-sidecar | jq
{
"timestamp": "2025-04-25T08:23:34Z",
"provider": "provider-kubernetes:v0.18.0",
"apiVersion": "kubernetes.crossplane.io/v1alpha2",
"kind": "Object",
"name": "configmap-for-changelogs",
"externalName": "configmap-for-changelogs",
"operation": "OPERATION_TYPE_CREATE",
"snapshot": {
...(omitted for brevity)...
```
Each change log entry contains rich information about the state of the resource
when the change operation occurred. Since each entry is a structured `JSON`
object, they can be filtered and queried to find any subset of information you
are interested in:
```shell {label="changelogs-output-scoped",copy-lines="1-2"}
kubectl -n crossplane-system logs -l pkg.crossplane.io/provider=provider-kubernetes -c changelogs-sidecar \
| jq '.timestamp + " " + .provider + " " + .kind + " " + .name + " " + .operation'
"2025-04-25T08:23:34Z provider-kubernetes:v0.18.0 Object configmap-for-changelogs OPERATION_TYPE_CREATE"
```
### Full lifecycle operations
In addition to change log entries that record the creation of resources, update
and delete operations will also generate corresponding change log entries.
Update the resource by patching its data field `key-1` with a new value
`cooler-value-2`:
```shell {label="object-patch",copy-lines="1-2"}
kubectl patch object configmap-for-changelogs --type=json \
-p='[{"op": "replace", "path": "/spec/forProvider/manifest/data/key-1", "value": "cooler-value-2"}]'
object.kubernetes.crossplane.io/configmap-for-changelogs patched
```
Then, delete the object entirely:
```shell {label="object-delete",copy-lines="1"}
kubectl delete object configmap-for-changelogs
object.kubernetes.crossplane.io "configmap-for-changelogs" deleted
```
Check the change logs again to verify that both the update and delete operations
were recorded, and the full lifecycle of the object has been captured in the
change logs:
```shell {label="changelogs-output-final",copy-lines="1-2"}
kubectl -n crossplane-system logs -l pkg.crossplane.io/provider=provider-kubernetes -c changelogs-sidecar \
| jq '.timestamp + " " + .provider + " " + .kind + " " + .name + " " + .operation'
"2025-04-25T08:23:34Z provider-kubernetes:v0.18.0 Object configmap-for-changelogs OPERATION_TYPE_CREATE"
"2025-04-25T08:24:21Z provider-kubernetes:v0.18.0 Object configmap-for-changelogs OPERATION_TYPE_UPDATE"
"2025-04-25T08:24:25Z provider-kubernetes:v0.18.0 Object configmap-for-changelogs OPERATION_TYPE_DELETE"
```

View File

@ -133,7 +133,6 @@ data:
"Composition",
"CompositionRevision",
"DeploymentRuntimeConfig",
"ControllerConfig",
"ProviderConfig",
"ProviderConfigUsage"
}

View File

@ -1,10 +0,0 @@
---
title: Disaster Recovery with Crossplane
weight: 10
---
AWS wrote a guide covering disaster recovery with Crossplane. The guide covers
using Crossplane to provision resources and Velero for Kubernetes backup and
recovery.
[Read the guide on AWS](https://aws.amazon.com/blogs/opensource/disaster-recovery-when-using-crossplane-for-infrastructure-provisioning-on-aws/).

View File

@ -26,7 +26,7 @@ uses today.
{{< hint "tip" >}}
For more information about Crossplane packages, review the
[xpkg concepts]({{<ref "../concepts/packages" >}}).
[xpkg concepts]({{<ref "../packages" >}}).
{{< /hint >}}
## Typical workflow

View File

@ -1,13 +1,13 @@
---
title: Function Patch and Transform
weight: 70
description: "A function that use patches and transforms to modify inputs from claims and composite resources before creating managed resources"
description: "A function that use patches and transforms to modify inputs from composite resources before creating managed resources"
---
Function Patch and Transform allows you to write a Composition that specifies
managed resource (MR) templates, and uses "patch and transform" operations to
fill them out. Crossplane fills the templates out with values copied from a
claim or composite resource (XR).
composite resource (XR).
A [patch](#create-a-patch) copies a value from one resource and _patches_ it
onto another resource. A [transform](#transform-a-patch) modifies the values
@ -51,7 +51,7 @@ spec:
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -67,20 +67,6 @@ Patch and transform is best for simpler compositions. It intentionally doesn't
support features like loops and conditionals.
{{</hint >}}
{{<expand "Confused about Compositions, XRDs, XRs and Claims?" >}}
Crossplane has four core components that users commonly mix up:
* [Composition]({{<ref "../concepts/compositions">}}) - A template to define
how to create resources.
* [composite resource Definition]({{<ref "../concepts/composite-resource-definitions">}})
(`XRD`) - A custom API specification.
* [composite resource]({{<ref "../concepts/composite-resources">}}) (`XR`) -
Created by using the custom API defined in a composite resource Definition.
XRs use the Composition template to create new managed resources.
* [Claim]({{<ref "../concepts/claims" >}}) (`XRC`) - Like a composite resource,
but with namespace scoping.
{{</expand >}}
## Install the function
You must install Function Patch and Transform before you can use it in a
@ -96,7 +82,7 @@ spec:
```
{{<hint "tip" >}}
Read the [Composition page]({{<ref "../concepts/compositions">}}) to learn more
Read the [Composition page]({{<ref "../composition/compositions">}}) to learn more
about Compositions and composition functions.
{{< /hint >}}
@ -119,7 +105,7 @@ identifies the resource inside the Composition. It isn't related to the external
name used with the Provider.
The contents of the `base` are identical to creating a standalone
[managed resource]({{<ref "../concepts/managed-resources">}}).
[managed resource]({{<ref "../managed-resources/managed-resources">}}).
This example uses
[provider-upjet-aws](https://github.com/crossplane-contrib/provider-upjet-aws)
@ -134,14 +120,14 @@ kind: Resources
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: "us-east-2"
- name: vm
base:
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
@ -150,7 +136,7 @@ resources:
region: "us-east-2"
```
When a [composite resource]({{<ref "../concepts/composite-resources" >}}) uses
When a [composite resource]({{<ref "../composition/composite-resources" >}}) uses
this function, the composite resource creates two new managed resources with all
the provided `spec.forProvider` settings.
@ -163,12 +149,8 @@ the resource's name in the external system (like AWS).
{{< /hint >}}
{{<hint "tip" >}}
You can use Function Patch and Transform to template other kinds of Crossplane
resources, like ProviderConfigs.
You can also template other kinds of composite resource (XR).
You can't template namespaced resources.
You can use Function Patch and Transform to template any kind of Kubernetes
resource.
{{< /hint >}}
## Create a patch
@ -194,7 +176,7 @@ kind: Resources
resources:
- name: storage-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -223,34 +205,32 @@ Here are some example selectors from a composite resource object.
| Selector | Selected element |
| --- | --- |
| `kind` | `kind` |
| `metadata.labels['crossplane.io/claim-name']` | `my-example-claim` |
| `spec.desiredRegion` | `eu-north-1` |
| `spec.resourceRefs[0].name` | `my-example-claim-978mh-r6z64` |
| `spec.resourceRefs[0].name` | `my-example-978mh-r6z64` |
{{</table >}}
```yaml {label="select",copy-lines="none"}
$ kubectl get composite -o yaml
apiVersion: example.org/v1alpha1
kind: XExample
kind: Example
metadata:
# Removed for brevity
labels:
crossplane.io/claim-name: my-example-claim
crossplane.io/claim-namespace: default
crossplane.io/composite: my-example-claim-978mh
crossplane.io/composite: my-example-978mh
spec:
desiredRegion: eu-north-1
field1: field1-text
resourceRefs:
- apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
name: my-example-claim-978mh-r6z64
- apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
name: my-example-claim-978mh-cnlhj
- apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
name: my-example-claim-978mh-rv5nm
crossplane:
resourceRefs:
- apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
name: my-example-978mh-r6z64
- apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
name: my-example-978mh-cnlhj
- apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
name: my-example-978mh-rv5nm
```
## Reuse a patch
@ -341,7 +321,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
# Removed for brevity
patches:
@ -350,7 +330,7 @@ resources:
toFieldPath: status.secondResource
- name: bucket2
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
# Removed for brevity
patches:
@ -364,26 +344,26 @@ Describe the composite resource to view the `resources` and the
```yaml {label="descCompPatch",copy-lines="none"}
$ kubectl describe composite
Name: my-example-claim-jp7rx
Name: my-example-jp7rx
Spec:
# Removed for brevity
Resource Refs:
Name: my-example-claim-jp7rx-gfg4m
Name: my-example-jp7rx-gfg4m
# Removed for brevity
Name: my-example-claim-jp7rx-fttpj
Name: my-example-jp7rx-fttpj
Status:
# Removed for brevity
Second Resource: my-example-claim-jp7rx-gfg4m
Second Resource: my-example-jp7rx-gfg4m
```
Describe the destination managed resource to see the label `secondResource`.
```yaml {label="bucketlabel",copy-lines="none"}
$ kubectl describe bucket
kubectl describe bucket my-example-claim-jp7rx-fttpj
Name: my-example-claim-jp7rx-fttpj
Labels: crossplane.io/composite=my-example-claim-jp7rx
secondResource=my-example-claim-jp7rx-gfg4m
kubectl describe bucket my-example-jp7rx-fttpj
Name: my-example-jp7rx-fttpj
Labels: crossplane.io/composite=my-example-jp7rx
secondResource=my-example-jp7rx-gfg4m
```
## Patch with EnvironmentConfigs
@ -398,7 +378,7 @@ can read and write from this data store as part of the patch process.
<!-- vale off -->
{{< hint "note" >}}
<!-- vale on -->
Read the [EnvironmentConfigs]({{<ref "../concepts/environment-configs" >}}) page
Read the [EnvironmentConfigs]({{<ref "../composition/environment-configs" >}}) page
for more information on using EnvironmentConfigs.
{{< /hint >}}
@ -410,8 +390,8 @@ to use with
<!-- vale gitlab.SentenceLength = NO -->
<!-- ignore false positive -->
Use either a
[reference]({{<ref "../concepts/managed-resources#matching-by-name-reference" >}})
or a [selector]({{<ref "../concepts/managed-resources#matching-by-selector" >}}) to
[reference]({{<ref "../managed-resources/managed-resources#matching-by-name-reference" >}})
or a [selector]({{<ref "../managed-resources/managed-resources#matching-by-selector" >}}) to
identify the EnvironmentConfigs to use.
<!-- vale Google.Quotes = YES -->
@ -467,7 +447,7 @@ kind: Resources
resources:
- name: vpc
base:
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: VPC
spec:
forProvider:
@ -481,7 +461,7 @@ resources:
toFieldPath: spec.forProvider.tags
```
The [EnvironmentConfigs]({{<ref "../concepts/environment-configs" >}}) page has
The [EnvironmentConfigs]({{<ref "../composition/environment-configs" >}}) page has
more information on EnvironmentConfigs options and usage.
## Types of patches
@ -504,7 +484,7 @@ Summary of Crossplane patches
{{<hint "note" >}}
All the following examples use the same set of Compositions,
CompositeResourceDefinitions, Claims and EnvironmentConfigs.
CompositeResourceDefinitions and EnvironmentConfigs.
Only the applied patches change between examples.
All examples rely on
@ -520,7 +500,7 @@ metadata:
spec:
compositeTypeRef:
apiVersion: example.org/v1alpha1
kind: xExample
kind: Example
environment:
environmentConfigs:
- ref:
@ -536,14 +516,14 @@ spec:
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: us-east-2
- name: bucket2
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -556,15 +536,12 @@ spec:
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xexamples.example.org
name: examples.example.org
spec:
group: example.org
names:
kind: xExample
plural: xexamples
claimNames:
kind: ExampleClaim
plural: exampleclaims
kind: Example
plural: examples
versions:
- name: v1alpha1
served: true
@ -597,12 +574,13 @@ spec:
{{< /expand >}}
{{< expand "Reference Claim" >}}
{{< expand "Reference XR" >}}
```yaml {copy-lines="all"}
apiVersion: example.org/v1alpha1
kind: ExampleClaim
kind: Example
metadata:
name: my-example-claim
namespace: default
name: my-example
spec:
field1: "field1-text"
field2: "field2-text"
@ -637,8 +615,8 @@ The `FromCompositeFieldPath` patch takes a value in a composite resource and
applies it to a field in the composed resource.
{{< hint "tip" >}}
Use the `FromCompositeFieldPath` patch to apply options from users in their
Claims to settings in managed resource `forProvider` settings.
Use the `FromCompositeFieldPath` patch to apply options from users in their XRs
to settings in managed resource `forProvider` settings.
{{< /hint >}}
For example, to use the value `desiredRegion` provided by a user in a composite
@ -654,7 +632,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -669,7 +647,7 @@ View the managed resource to see the updated `region`
```yaml {label="fromCompMR",copy-lines="1"}
$ kubectl describe bucket
Name: my-example-claim-qlr68-29nqf
Name: my-example-qlr68-29nqf
# Removed for brevity
Spec:
For Provider:
@ -697,7 +675,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -712,7 +690,7 @@ View the created managed resource to see the
`Hosted Zone Id` field.
```yaml {label="toCompMR",copy-lines="none"}
$ kubectl describe bucket
Name: my-example-claim-p5pxf-5vnp8
Name: my-example-p5pxf-5vnp8
# Removed for brevity
Status:
At Provider:
@ -724,7 +702,7 @@ Next view the composite resource and confirm the patch applied the `label`
```yaml {label="toCompositeXR",copy-lines="none"}
$ kubectl describe composite
Name: my-example-claim-p5pxf
Name: my-example-p5pxf
Labels: ZoneID=Z2O1EMRO9K5GLX
```
@ -740,7 +718,7 @@ Use the `CombineFromComposite` patch to create complex strings, like security
policies and apply them to a composed resource.
{{< /hint >}}
For example, use the Claim value `desiredRegion` and `field2` to generate the
For example, use the XR value `desiredRegion` and `field2` to generate the
managed resource's `name`
The `CombineFromComposite` patch only supports the `combine` option.
@ -763,7 +741,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -826,7 +804,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -847,26 +825,19 @@ View the composite resource to verify the applied patch.
```yaml {copy-lines="none"}
$ kubectl describe composite
Name: my-example-claim-bjdjw
Name: my-example-bjdjw
API Version: example.org/v1alpha1
Kind: xExample
Kind: Example
# Removed for brevity
Status:
# Removed for brevity
URL: https://my-example-claim-bjdjw-r6ncd.us-east-2.com
URL: https://my-example-bjdjw-r6ncd.us-east-2.com
```
<!-- vale Google.Headings = NO -->
### FromEnvironmentFieldPath
<!-- vale Google.Headings = YES -->
{{<hint "important" >}}
EnvironmentConfigs are an alpha feature. They aren't enabled by default.
For more information about using an EnvironmentConfig, read the
[EnvironmentConfigs documentation]({{<ref "../concepts/environment-configs">}}).
{{< /hint >}}
The `FromEnvironmentFieldPath` patch takes values from the in-memory environment
and applies them to the composed resource.
@ -884,7 +855,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -899,8 +870,7 @@ Verify managed resource to confirm the applied patch.
```yaml {copy-lines="none"}
kubectl describe bucket
Name: my-example-claim-8vrvc-xx5sr
Labels: crossplane.io/claim-name=my-example-claim
Name: my-example-8vrvc-xx5sr
# Removed for brevity
Spec:
For Provider:
@ -914,7 +884,7 @@ Spec:
{{<hint "important" >}}
For more information about using an EnvironmentConfig, read the
[EnvironmentConfigs documentation]({{<ref "../concepts/environment-configs">}}).
[EnvironmentConfigs documentation]({{<ref "../composition/environment-configs">}}).
{{< /hint >}}
The `ToEnvironmentFieldPath` patch takes a value from the composed resource and
@ -935,7 +905,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -956,7 +926,7 @@ wrote the value to the environment.
{{<hint "important" >}}
For more information about using an EnvironmentConfig, read the
[EnvironmentConfigs documentation]({{<ref "../concepts/environment-configs">}}).
[EnvironmentConfigs documentation]({{<ref "../composition/environment-configs">}}).
{{< /hint >}}
The `CombineFromEnvironment` patch combines multiple values from the in-memory
@ -990,7 +960,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -1012,7 +982,7 @@ Describe the managed resource to see new
```yaml {copy-lines="none",label="combineFromEnvDesc"}
$ kubectl describe bucket
Name: my-example-claim-zmxdg-grl6p
Name: my-example-zmxdg-grl6p
# Removed for brevity
Annotations: EnvironmentPatch: value1-value2
# Removed for brevity
@ -1024,7 +994,7 @@ Annotations: EnvironmentPatch: value1-value2
{{<hint "important" >}}
For more information about using an EnvironmentConfig, read the
[EnvironmentConfigs documentation]({{<ref "../concepts/environment-configs">}}).
[EnvironmentConfigs documentation]({{<ref "../composition/environment-configs">}}).
{{< /hint >}}
The `CombineToEnvironment` patch combines multiple values from the composed
@ -1059,7 +1029,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -1113,7 +1083,7 @@ kind: Resources
resources:
- name: bucket1
base:
apiVersion: s3.aws.upbound.io/v1beta1
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
@ -1295,7 +1265,7 @@ In this example, the value of `spec.field1` is `field1-text`.
```yaml {label="comositeMap",copy-lines="none"}
$ kubectl describe composite
Name: my-example-claim-twx7n
Name: my-example-twx7n
Spec:
# Removed for brevity
field1: field1-text
@ -1305,7 +1275,7 @@ The annotation applied to the managed resource is `firstField`.
```yaml {label="mrMap",copy-lines="none"}
$ kubectl describe bucket
Name: my-example-claim-twx7n-ndb2f
Name: my-example-twx7n-ndb2f
Annotations: crossplane.io/composition-resource-name: bucket1
myAnnotation: firstField
# Removed for brevity.
@ -1763,7 +1733,6 @@ only appears in the combined composite resource secret.
```yaml {label="conDeet",copy-lines="none"}
kind: Composition
spec:
writeConnectionSecretsToNamespace: other-namespace
mode: Pipeline
pipeline:
- step: patch-and-transform
@ -1841,18 +1810,16 @@ the composite resources.
By default an XRD writes all secret keys listed in the composed resources
`connectionDetails` to the combined secret object.
Read the
[CompositeResourceDefinition documentation]({{<ref "../concepts/composite-resource-definitions#manage-connection-secrets">}})
for more information on restricting secret keys.
{{< /hint >}}
For more information on connection secrets read the
[Connection Secrets concepts age]({{<ref "../concepts/connection-details">}}).
For more information on connection secrets read about
[managed resources]({{<ref "../managed-resources/managed-resources">}}).
{{</hint>}}
## Resource readiness checks
By default Crossplane considers a composite resource or Claim as `READY` when
the status of all created resource are `Type: Ready` and `Status: True`
By default function-patch-and-transform considers a composite resource as
`READY` when the status of all created resource are `Type: Ready` and `Status:
True`
Some resources, for example, a ProviderConfig, don't have a Kubernetes status
and are never considered `Ready`.

View File

@ -1,285 +0,0 @@
---
title: Import Existing Resources
weight: 200
---
If you have resources that are already provisioned in a Provider,
you can import them as managed resources and let Crossplane manage them.
A managed resource's [`managementPolicies`]({{<ref "../concepts/managed-resources#managementpolicies">}})
field enables importing external resources into Crossplane.
Crossplane can import resources either [manually]({{<ref "#import-resources-manually">}})
or [automatically]({{<ref "#import-resources-automatically">}}).
## Import resources manually
Crossplane can discover and import existing Provider resources by matching the
`crossplane.io/external-name` annotation in a managed resource.
To import an existing external resource in a Provider, create a new managed
resource with the `crossplane.io/external-name` annotation. Set the annotation
value to the name of the resource in the Provider.
For example, to import an existing GCP Network named
{{<hover label="annotation" line="5">}}my-existing-network{{</hover>}},
create a new managed resource and use the
{{<hover label="annotation" line="5">}}my-existing-network{{</hover>}} in the
annotation.
```yaml {label="annotation",copy-lines="none"}
apiVersion: compute.gcp.crossplane.io/v1beta1
kind: Network
metadata:
annotations:
crossplane.io/external-name: my-existing-network
```
The {{<hover label="name" line="5">}}metadata.name{{</hover>}}
field can be anything you want. For example,
{{<hover label="name" line="5">}}imported-network{{</hover>}}.
{{< hint "note" >}}
This name is the
name of the Kubernetes object. It's not related to the resource name inside the
Provider.
{{< /hint >}}
```yaml {label="name",copy-lines="none"}
apiVersion: compute.gcp.crossplane.io/v1beta1
kind: Network
metadata:
name: imported-network
annotations:
crossplane.io/external-name: my-existing-network
```
Leave the
{{<hover label="fp" line="8">}}spec.forProvider{{</hover>}} field empty.
Crossplane imports the settings and automatically applies them to the managed
resource.
{{< hint "important" >}}
If the managed resource has _required_ fields in the
{{<hover label="fp" line="8">}}spec.forProvider{{</hover>}} you must add it to
the `forProvider` field.
The values of those fields must match what's inside the Provider or Crossplane
overwrites the existing values.
{{< /hint >}}
```yaml {label="fp",copy-lines="all"}
apiVersion: compute.gcp.crossplane.io/v1beta1
kind: Network
metadata:
name: imported-network
annotations:
crossplane.io/external-name: my-existing-network
spec:
forProvider: {}
```
Crossplane now controls and manages this imported resource. Any changes to the
managed resource `spec` changes the external resource.
## Import resources automatically
Automatically import external resources with an `Observe` [management policy]({{<ref "../concepts/managed-resources#managementpolicies">}}).
Crossplane imports observe only resources but never changes or deletes the
resources.
{{<hint "important" >}}
The managed resource `managementPolicies` option is a beta feature.
The Provider determines support for management policies.
Refer to the Provider's documentation to see if the Provider supports
management policies.
{{< /hint >}}
<!-- vale off -->
### Apply the Observe management policy
<!-- vale on -->
Create a new managed resource matching the
{{<hover label="oo-policy" line="1">}}apiVersion{{</hover>}} and
{{<hover label="oo-policy" line="2">}}kind{{</hover>}} of the resource
to import and add
{{<hover label="oo-policy" line="4">}}managementPolicies: ["Observe"]{{</hover>}} to the
{{<hover label="oo-policy" line="3">}}spec{{</hover>}}
For example, to import a GCP SQL DatabaseInstance, create a new resource with
the {{<hover label="oo-policy" line="4">}}managementPolicies: ["Observe"]{{</hover>}}
set.
```yaml {label="oo-policy",copy-lines="none"}
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
spec:
managementPolicies: ["Observe"]
```
### Add the external-name annotation
Add the {{<hover label="oo-ex-name" line="5">}}crossplane.io/external-name{{</hover>}}
annotation for the resource. This name must match the name inside the Provider.
For example, for a GCP database named
{{<hover label="oo-ex-name" line="5">}}my-external-database{{</hover>}}, apply
the
{{<hover label="oo-ex-name" line="5">}}crossplane.io/external-name{{</hover>}}
annotation with the value
{{<hover label="oo-ex-name" line="5">}}my-external-database{{</hover>}}.
```yaml {label="oo-ex-name",copy-lines="none"}
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["Observe"]
```
### Create a Kubernetes object name
Create a {{<hover label="oo-name" line="4">}}name{{</hover>}} to use for the
Kubernetes object.
For example, name the Kubernetes object
{{<hover label="oo-name" line="4">}}my-imported-database{{</hover>}}.
```yaml {label="oo-name",copy-lines="none"}
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
name: my-imported-database
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["Observe"]
```
### Identify a specific external resource
If more than one resource inside the Provider shares the same name, identify the
specific resource with a unique
{{<hover line="9" label="oo-region">}}spec.forProvider{{</hover>}} field.
For example, only import the GCP SQL database in the
{{<hover line="10" label="oo-region">}}us-central1{{</hover>}} region.
```yaml {label="oo-region"}
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
name: my-imported-database
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["Observe"]
forProvider:
region: "us-central1"
```
### Apply the managed resource
Apply the new managed resource. Crossplane syncs the status of the external
resource in the cloud with the newly created managed resource.
### View the discovered resource
Crossplane discovers the managed resource and populates the
{{<hover label="ooPopulated" line="12">}}status.atProvider{{</hover>}}
fields with the values from the external resource.
```yaml {label="ooPopulated",copy-lines="none"}
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
name: my-imported-database
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["Observe"]
forProvider:
region: us-central1
status:
atProvider:
connectionName: crossplane-playground:us-central1:my-external-database
databaseVersion: POSTGRES_14
deletionProtection: true
firstIpAddress: 35.184.74.79
id: my-external-database
publicIpAddress: 35.184.74.79
region: us-central1
# Removed for brevity
settings:
- activationPolicy: ALWAYS
availabilityType: REGIONAL
diskSize: 100
# Removed for brevity
pricingPlan: PER_USE
tier: db-custom-4-26624
version: 4
conditions:
- lastTransitionTime: "2023-02-22T07:16:51Z"
reason: Available
status: "True"
type: Ready
- lastTransitionTime: "2023-02-22T07:16:51Z"
reason: ReconcileSuccess
status: "True"
type: Synced
```
<!-- vale off -->
## Control imported ObserveOnly resources
<!-- vale on -->
Crossplane can take active control of observe only imported resources by
changing the `managementPolicies` after import.
Change the {{<hover label="fc" line="8">}}managementPolicies{{</hover>}} field
of the managed resource to
{{<hover label="fc" line="8">}}["*"]{{</hover>}}.
Copy any required parameter values from
{{<hover label="fc" line="16">}}status.atProvider{{</hover>}} and provide them
in {{<hover label="fc" line="9">}}spec.forProvider{{</hover>}}.
{{< hint "tip" >}}
Manually copy the important `spec.atProvider` values to `spec.forProvider`.
{{< /hint >}}
```yaml {label="fc"}
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
name: my-imported-database
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["*"]
forProvider:
databaseVersion: POSTGRES_14
region: us-central1
settings:
- diskSize: 100
tier: db-custom-4-26624
status:
atProvider:
databaseVersion: POSTGRES_14
region: us-central1
# Removed for brevity
settings:
- diskSize: 100
tier: db-custom-4-26624
# Removed for brevity
conditions:
- lastTransitionTime: "2023-02-22T07:16:51Z"
reason: Available
status: "True"
type: Ready
- lastTransitionTime: "2023-02-22T11:16:45Z"
reason: ReconcileSuccess
status: "True"
type: Synced
```
Crossplane now fully manages the imported resource. Crossplane applies any
changes to the managed resource in the Provider's external resource.

View File

@ -1,325 +0,0 @@
---
title: Multi-Tenant Crossplane
weight: 240
---
This guide describes how to use Crossplane effectively in multi-tenant
environments by utilizing Kubernetes primitives and compatible policy
enforcement projects in the cloud native ecosystem.
## Summary
Infrastructure operators in multi-tenant Crossplane environments typically
utilize composition and Kubernetes RBAC to define lightweight, standardized
policies that dictate what level of self-service developers are given when
requesting infrastructure. This is primarily achieved through exposing abstract
resource types at the namespace scope, defining `Roles` for teams and
individuals within that namespace, and patching the `spec.providerConfigRef` of
the underlying managed resources so that they use a specific `ProviderConfig`
and credentials when provisioned from each namespace. Larger organizations, or
those with more complex environments, may choose to incorporate third-party
policy engines, or scale to multiple Crossplane clusters. The following sections
describe each of these scenarios in greater detail.
- [Summary](#summary)
- [Background](#background)
- [Cluster-Scoped Managed Resources](#cluster-scoped-managed-resources)
- [Namespace Scoped Claims](#namespace-scoped-claims)
- [Single Cluster Multi-Tenancy](#single-cluster-multi-tenancy)
- [Composition as an Isolation Mechanism](#composition-as-an-isolation-mechanism)
- [Namespaces as an Isolation Mechanism](#namespaces-as-an-isolation-mechanism)
- [Policy Enforcement with Open Policy Agent](#policy-enforcement-with-open-policy-agent)
- [Multi-Cluster Multi-Tenancy](#multi-cluster-multi-tenancy)
- [Reproducible Platforms with Configuration Packages](#reproducible-platforms-with-configuration-packages)
- [Control Plane of Control Planes](#control-plane-of-control-planes)
## Background
Crossplane is designed to run in multi-tenant environments where many teams are
consuming the services and abstractions provided by infrastructure operators in
the cluster. This functionality is facilitated by two major design patterns in
the Crossplane ecosystem.
### Cluster-Scoped Managed Resources
Typically, Crossplane providers, which supply granular [managed resources] that
reflect an external API, authenticate by using a `ProviderConfig` object that
points to a credentials source (such as a Kubernetes `Secret`, the `Pod`
filesystem, or an environment variable). Then, every managed resource references
a `ProviderConfig` that points to credentials with sufficient permissions to
manage that resource type.
For example, the following `ProviderConfig` for `provider-aws` points to a
Kubernetes `Secret` with AWS credentials.
```yaml
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: cool-aws-creds
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds
key: creds
```
If a user desired for these credentials to be used to provision an
`RDSInstance`, they would reference the `ProviderConfig` in the object manifest:
```yaml
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
metadata:
name: rdsmysql
spec:
forProvider:
region: us-east-1
dbInstanceClass: db.t3.medium
masterUsername: masteruser
allocatedStorage: 20
engine: mysql
engineVersion: "5.6.35"
skipFinalSnapshotBeforeDeletion: true
providerConfigRef:
name: cool-aws-creds # name of ProviderConfig above
writeConnectionSecretToRef:
namespace: crossplane-system
name: aws-rdsmysql-conn
```
Since both the `ProviderConfig` and all managed resources are cluster-scoped,
the RDS controller in `provider-aws` will resolve this reference by fetching the
`ProviderConfig`, obtaining the credentials it points to, and using those
credentials to reconcile the `RDSInstance`. This means that anyone who has been
given [RBAC] to manage `RDSInstance` objects can use any credentials to do so.
In practice, Crossplane assumes that only folks acting as infrastructure
administrators or platform builders will interact directly with cluster-scoped
resources.
### Namespace Scoped Claims
While managed resources exist at the cluster scope, composite resources, which
are defined using a **CompositeResourceDefinition (XRD)** may exist at either
the cluster or namespace scope. Platform builders define XRDs and
**Compositions** that specify what granular managed resources should be created
in response to the creation of an instance of the XRD. More information about
this architecture can be found in the [Composition] documentation.
Every XRD is exposed at the cluster scope, but only those with `spec.claimNames`
defined will have a namespace scoped variant.
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xmysqlinstances.example.org
spec:
group: example.org
names:
kind: XMySQLInstance
plural: xmysqlinstances
claimNames:
kind: MySQLInstance
plural: mysqlinstances
...
```
When the example above is created, Crossplane will produce two
[CustomResourceDefinitions]:
1. A cluster-scoped type with `kind: XMySQLInstance`. This is referred to as a
**Composite Resource (XR)**.
2. A namespace scoped type with `kind: MySQLInstance`. This is referred to as a
**Claim (XRC)**.
Platform builders may choose to define an arbitrary number of Compositions that
map to these types, meaning that creating a `MySQLInstance` in a given namespace
can result in the creations of any set of managed resources at the cluster
scope. For instance, creating a `MySQLInstance` could result in the creation of
the `RDSInstance` defined above.
## Single Cluster Multi-Tenancy
Depending on the size and scope of an organization, platform teams may choose to
run one central Crossplane control plane, or many different ones for each team
or business unit. This section will focus on servicing multiple teams within a
single cluster, which may or may not be one of many other Crossplane clusters in
the organization.
### Composition as an Isolation Mechanism
While managed resources always reflect every field that the underlying provider
API exposes, XRDs can have any schema that a platform builder chooses. The
fields in the XRD schema can then be patched onto fields in the underlying
managed resource defined in a Composition, essentially exposing those fields as
configurable to the consumer of the XR or XRC.
This feature serves as a lightweight policy mechanism by only giving the
consumer the ability to customize the underlying resources to the extent the
platform builder desires. For instance, in the examples above, a platform
builder may choose to define a `spec.location` field in the schema of the
`XMySQLInstance` that's an enum with options `east` and `west`. In the
Composition, those fields could map to the `RDSInstance` `spec.region` field,
making the value either `us-east-1` or `us-west-1`. If no other patches were
defined for the `RDSInstance`, giving a user the ability (using RBAC) to create
a `XMySQLInstance` / `MySQLInstance` would be akin to giving the ability to
create a specifically configured `RDSInstance`, where they can only decide
the region where it lives and they're restricted to two options.
This model is in contrast to many infrastructure as code tools where the end
user must have provider credentials to create the underlying resources that are
rendered from the abstraction. Crossplane takes a different approach, defining
various credentials in the cluster (using the `ProviderConfig`), then giving
only the provider controllers the ability to utilize those credentials and
provision infrastructure on the users behalf. This creates a consistent
permission model, even when using many providers with differing IAM models, by
standardizing on Kubernetes RBAC.
### Namespaces as an Isolation Mechanism
While the ability to define abstract schemas and patches to concrete resource
types using composition is powerful, the ability to define Claim types at the
namespace scope enhances the functionality further by enabling RBAC to be
applied with namespace restrictions. Most users in a cluster don't have access
to cluster-scoped resources as they're considered only relevant to
infrastructure admins by both Kubernetes and Crossplane.
Building on our `XMySQLInstance` / `MySQLInstance` example, a platform
builder may choose to define permissions on `MySQLInstance` at the namespace
scope using a `Role`. This allows for giving users the ability to create and
manage `MySQLInstances` in their given namespace, but not the ability to see
those defined in other namespaces.
Furthermore, because the `metadata.namespace` is a field on the XRC, patching can
be utilized to configure managed resources based on the namespace in which the
corresponding XRC was defined. This is especially useful if a platform builder
wants to designate specific credentials or a set of credentials that users in a
given namespace can utilize when provisioning infrastructure using an XRC. This
can be accomplished today by creating one or more `ProviderConfig` objects that
include the name of the namespace in the `ProviderConfig` name. For example, if
any `MySQLInstance` created in the `team-1` namespace should use specific AWS
credentials when the provider controller creates the underlying `RDSInstance`,
the platform builder could:
1. Define a `ProviderConfig` with name `team-1`.
```yaml
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: team-1
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: team-1-creds
key: creds
```
2. Define a `Composition` that patches the namespace of the Claim reference in the XR
to the `providerConfigRef` of the `RDSInstance`.
```yaml
...
resources:
- base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
spec:
forProvider:
...
patches:
- fromFieldPath: spec.claimRef.namespace
toFieldPath: spec.providerConfigRef.name
policy:
fromFieldPath: Required
```
This would result in the `RDSInstance` using the `ProviderConfig` of whatever
namespace the corresponding `MySQLInstance` was created in.
> Note that this model currently only allows for a single `ProviderConfig` per
> namespace. However, future Crossplane releases should allow for defining a set
> of `ProviderConfig` that can be selected from using [Multiple Source Field
> patching].
### Policy Enforcement with Open Policy Agent
In some Crossplane deployment models, only using composition and RBAC to define
policy won't be flexible enough. However, because Crossplane brings
management of external infrastructure to the Kubernetes API, it's well suited
to integrate with other projects in the cloud native ecosystem. Organizations
and individuals that need a more robust policy engine, or just prefer a more
general language for defining policy, often turn to [Open Policy Agent] (OPA).
OPA allows platform builders to write custom logic in [Rego], a domain specific
language. Writing policy in this manner allows for not only incorporating the
information available in the specific resource being evaluated, but also using
other state represented in the cluster. Crossplane users typically install OPA
[Gatekeeper] to make policy management as streamlined as possible.
> A live demo of using OPA with Crossplane can be viewed [here].
## Multi-Cluster Multi-Tenancy
Organizations that deploy Crossplane across many clusters typically take
advantage of two major features that make managing multiple control planes much
simpler.
### Reproducible Platforms with Configuration Packages
[Configuration packages] allow platform builders to package their XRDs and
Compositions into [OCI images] that can be distributed via any OCI compliant
image registry. These packages can also declare dependencies on providers,
meaning that a single package can declare all of the granular managed resources,
the controllers that must be deployed to reconcile them, and the abstract types
that expose the underlying resources using composition.
Organizations with many Crossplane deployments utilize Configuration packages to
<!-- vale alex.Condescending = NO -->
reproduce their platform in each cluster. This can be as simple as installing
<!-- vale alex.Condescending = YES -->
Crossplane with the flag to automatically install a Configuration package
alongside it.
```
helm install crossplane --namespace crossplane-system crossplane-stable/crossplane --set configuration.packages='{"registry.upbound.io/xp/getting-started-with-aws:latest"}'
```
### Control Plane of Control Planes
Taking the multi-cluster multi-tenancy model one step further, some
organizations opt to manage their many Crossplane clusters using a single
central Crossplane control plane. This requires setting up the central cluster,
then using a provider to spin up new clusters (such as an [EKS Cluster] using
[provider-aws]), then using [provider-helm] to install Crossplane into the new
remote cluster, potentially bundling a common Configuration package into each
install using the method described above.
This advanced pattern allows for full management of Crossplane clusters using
Crossplane itself, and when done properly, is a scalable solution to providing
dedicated control planes to many tenants within a single organization.
<!-- Named Links -->
[managed resources]: {{<ref "../../master/concepts/managed-resources" >}}
[RBAC]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
[Composition]: {{<ref "../../master/concepts/compositions" >}}
[CustomResourceDefinitions]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
[Open Policy Agent]: https://www.openpolicyagent.org/
[Rego]: https://www.openpolicyagent.org/docs/latest/policy-language/
[Gatekeeper]: https://open-policy-agent.github.io/gatekeeper/website/docs/
[here]: https://youtu.be/TaF0_syejXc
[Multiple Source Field patching]: https://github.com/crossplane/crossplane/pull/2093
[Configuration packages]: {{<ref "../../master/concepts/packages" >}}
[OCI images]: https://github.com/opencontainers/image-spec
[EKS Cluster]: https://github.com/crossplane-contrib/provider-upjet-aws/blob/main/examples/eks/v1beta2/cluster.yaml
[provider-aws]: https://github.com/crossplane-contrib/provider-upjet-aws
[provider-helm]: https://github.com/crossplane-contrib/provider-helm
[Open Service Broker API]: https://github.com/openservicebrokerapi/servicebroker
[Crossplane Service Broker]: https://github.com/vshn/crossplane-service-broker
[Cloudfoundry]: https://www.cloudfoundry.org/
[Kubernetes Service Catalog]: https://github.com/kubernetes-sigs/service-catalog
[vshn/application-catalog-demo]: https://github.com/vshn/application-catalog-demo

View File

@ -31,12 +31,10 @@ The core CRDs installed by the init container include:
* CompositeResourceDefinitions, Compositions, Configurations and Providers
* Locks to manage package dependencies
* DeploymentRuntimeConfigs to apply settings to installed Providers and Functions
* StoreConfigs for connecting external secret stores like
[HashiCorp Vault](https://www.vaultproject.io/)
{{< hint "note" >}}
The [Install Crossplane]({{< ref "../software/install" >}}) section has more
The [Install Crossplane]({{< ref "../get-started/install" >}}) section has more
information about customizing the Crossplane install.
{{< /hint >}}
@ -64,8 +62,8 @@ the desired state of Crossplane resources, manages leader elections and process
webhooks.
{{<hint "note" >}}
The Crossplane pod only reconciles core Crossplane components, including Claims
and composite resources. Providers are responsible for reconciling their managed
The Crossplane pod only reconciles core Crossplane components, including
composite resources. Providers are responsible for reconciling their managed
resources.
{{< /hint >}}
@ -169,7 +167,7 @@ spec:
{{<hint "tip" >}}
The [Crossplane install guide]({{<ref "../software/install#feature-flags">}})
The [Crossplane install guide]({{<ref "../get-started/install#feature-flags">}})
describes enabling feature flags like
{{<hover label="deployment" line="12">}}--enable-realtime-compositions{{</hover>}}
with Helm.
@ -222,7 +220,7 @@ file, setting `rbacManager.deploy` to `false`.
{{< hint "note" >}}
Instructions for changing Crossplane pod settings during installation are in the
[Crossplane Install]({{<ref "../software/install">}}) section.
[Crossplane Install]({{<ref "../get-started/install">}}) section.
{{< /hint >}}
<!-- vale Microsoft.HeadingAcronyms = NO -->
@ -299,19 +297,6 @@ View the full RBAC policy with
kubectl describe clusterrole crossplane-view
```
##### crossplane-browse
The `crossplane-browse` ClusterRole has the following permissions:
* read-only access to Crossplane compositions and XRDs. This allows resource claim
creators to discover and select an appropriate composition.
View the full RBAC policy with
```shell
kubectl describe clusterrole crossplane-browse
```
## Leader election
By default only a single Crossplane pod runs in a cluster. If more than one
@ -348,17 +333,17 @@ Change Crossplane pod settings either before installing Crossplane by editing
the Helm `values.yml` file or after installation by editing the `Deployment`.
The full list of
[configuration options]({{<ref "../software/install#customize-the-crossplane-helm-chart">}})
[configuration options]({{<ref "../get-started/install#customize-the-crossplane-helm-chart">}})
and
[feature flags]({{<ref "../software/install#feature-flags">}})
[feature flags]({{<ref "../get-started/install#feature-flags">}})
are available in the
[Crossplane Install]({{<ref "../software/install">}})
[Crossplane Install]({{<ref "../get-started/install">}})
section.
{{< hint "note" >}}
Instructions for changing Crossplane pod settings during installation are in the
[Crossplane Install]({{<ref "../software/install">}}) section.
[Crossplane Install]({{<ref "../get-started/install">}}) section.
{{< /hint >}}
### Edit the deployment
@ -404,4 +389,4 @@ The core Crossplane pod checks for configured environmental variables at startup
to change default settings.
The full list of configurable environmental variables are available in the
[Crossplane Install]({{<ref "../software/install">}}) section.
[Crossplane Install]({{<ref "../get-started/install">}}) section.

View File

@ -11,7 +11,7 @@ registries, it must be configured to trust the CA and Intermediate certs.
Crossplane needs to be installed via the Helm chart with the
`registryCaBundleConfig.name` and `registryCaBundleConfig.key` parameters
defined. See [Install Crossplane]({{<ref "../../master/software/install" >}}).
defined. See [Install Crossplane]({{<ref "../get-started/install" >}}).
## Configure

View File

@ -113,216 +113,6 @@ spec:
> Note that a reference to a `DeploymentRuntimeConfig` can be added to an already
> installed `Provider` and it will update its `Deployment` accordingly.
## Compositions and composite resource definition
### General troubleshooting steps
Crossplane and its providers log most error messages to resources' event fields. Whenever your Composite Resources aren't getting provisioned, follow the following steps:
1. Get the events for the root resource using `kubectl describe` or `kubectl get event`
2. If there are errors in the events, address them.
3. If there are no errors, follow its subresources.
`kubectl get <KIND> <NAME> -o=jsonpath='{.spec.resourceRef}{" "}{.spec.resourceRefs}' | jq`
4. Repeat this process for each resource returned.
{{< hint "note" >}}
The rest of this section show you how to debug issues related to compositions without using external tooling.
If you are using ArgoCD or FluxCD with UI, you can visualize object relationships in the UI.
You can also use the `kube-lineage` plugin to visualize object relationships in your terminal.
{{< /hint >}}
### Examples
#### Composition
<!-- vale Google.WordList = NO -->
You deployed an example application using a claim. Kind = `ExampleApp`. Name = `example-application`.
The example application never reaches available state as shown below.
1. View the claim.
```shell
kubectl describe exampleapp example-application
Status:
Conditions:
Last Transition Time: 2022-03-01T22:57:38Z
Reason: Composite resource claim is waiting for composite resource to become Ready
Status: False
Type: Ready
Events: <none>
```
2. If the claim doesn't have errors, inspect the `.spec.resourceRef` field of the claim.
```shell
kubectl get exampleapp example-application -o=jsonpath='{.spec.resourceRef}{" "}{.spec.resourceRefs}' | jq
{
"apiVersion": "awsblueprints.io/v1alpha1",
"kind": "XExampleApp",
"name": "example-application-xqlsz"
}
```
3. In the preceding output, you see the cluster scoped resource for this claim. Kind = `XExampleApp` name = `example-application-xqlsz`
4. View the cluster scoped resource's events.
```shell
kubectl describe xexampleapp example-application-xqlsz
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal PublishConnectionSecret 9s (x2 over 10s) defined/compositeresourcedefinition.apiextensions.crossplane.io Successfully published connection details
Normal SelectComposition 6s (x6 over 11s) defined/compositeresourcedefinition.apiextensions.crossplane.io Successfully selected composition
Warning ComposeResources 6s (x6 over 10s) defined/compositeresourcedefinition.apiextensions.crossplane.io can't render composed resource from resource template at index 3: can't use dry-run create to name composed resource: an empty namespace may not be set during creation
Normal ComposeResources 6s (x6 over 10s) defined/compositeresourcedefinition.apiextensions.crossplane.io Successfully composed resources
```
5. You see errors in the events. it's complaining about not specifying namespace in its compositions. For this particular kind of error, you can get its subresources and check which one isn't created.
```shell
kubectl get xexampleapp example-application-xqlsz -o=jsonpath='{.spec.resourceRef}{" "}{.spec.resourceRefs}' | jq
[
{
"apiVersion": "awsblueprints.io/v1alpha1",
"kind": "XDynamoDBTable",
"name": "example-application-xqlsz-6j9nm"
},
{
"apiVersion": "awsblueprints.io/v1alpha1",
"kind": "XIAMPolicy",
"name": "example-application-xqlsz-lp9wt"
},
{
"apiVersion": "awsblueprints.io/v1alpha1",
"kind": "XIAMPolicy",
"name": "example-application-xqlsz-btwkn"
},
{
"apiVersion": "awsblueprints.io/v1alpha1",
"kind": "IRSA"
}
]
```
6. Notice the last element in the array doesn't have a name. When a resource in composition fails validation, the resource object isn't created and doesn't have a name. For this particular issue, you must specify the namespace for the IRSA resource.
#### Composite resource definition
Debugging Composite Resource Definition (XRD) is like debugging Compositions.
1. Get the XRD
```shell
kubectl get xrd testing.awsblueprints.io
NAME ESTABLISHED OFFERED AGE
testing.awsblueprints.io 66s
```
2. Notice its status it not established. You describe this XRD to get its events.
```shell
kubectl describe xrd testing.awsblueprints.io
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ApplyClusterRoles 3m19s (x3 over 3m19s) rbac/compositeresourcedefinition.apiextensions.crossplane.io Applied RBAC ClusterRoles
Normal RenderCRD 18s (x9 over 3m19s) defined/compositeresourcedefinition.apiextensions.crossplane.io Rendered composite resource CustomResourceDefinition
Warning EstablishComposite 18s (x9 over 3m19s) defined/compositeresourcedefinition.apiextensions.crossplane.io can't apply rendered composite resource CustomResourceDefinition: can't create object: CustomResourceDefinition.apiextensions.k8s.io "testing.awsblueprints.io" is invalid: metadata.name: Invalid value: "testing.awsblueprints.io": must be spec.names.plural+"."+spec.group
```
3. You see in the events that Crossplane can't generate corresponding CRDs for this XRD. In this case, ensure the name is `spec.names.plural+"."+spec.group`
#### Providers
You can use install providers in two ways: `configuration.pkg.crossplane.io` and `provider.pkg.crossplane.io`. You can use either one to install providers with no functional differences to providers themselves.
If you define a `configuration.pkg.crossplane.io` object, Crossplane creates a
`provider.pkg.crossplane.io` object and manages it. Refer to [the Packages documentation]({{<ref "/master/concepts/packages">}})
for more information about Crossplane Packages.
If you are experiencing provider issues, steps below are a good starting point.
1. Check the status of provider object.
```shell
kubectl describe provider.pkg.crossplane.io provider-aws
Status:
Conditions:
Last Transition Time: 2022-08-04T16:19:44Z
Reason: HealthyPackageRevision
Status: True
Type: Healthy
Last Transition Time: 2022-08-04T16:14:29Z
Reason: ActivePackageRevision
Status: True
Type: Installed
Current Identifier: crossplane/provider-aws:v0.29.0
Current Revision: provider-aws-a2e16ca2fc1a
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal InstallPackageRevision 9m49s (x237 over 4d17h) packages/provider.pkg.crossplane.io Successfully installed package revision
```
In the output above you see that this provider is healthy. To get more information about this provider, you can dig deeper. The `Current Revision` field let you know of your next object to look at.
2. When you create a provider object, Crossplane creates a `ProviderRevision` object based on the contents of the OCI image. In this example, you're specifying the OCI image to be `crossplane/provider-aws:v0.29.0`. This image contains a YAML file which defines Kubernetes objects such as Deployment, ServiceAccount, and CRDs.
The `ProviderRevision` object creates resources necessary for a provider to function based on the contents of the YAML file. To inspect what's deployed as part of the provider package, you inspect the ProviderRevision object. The `Current Revision` field above indicates which ProviderRevision object this provider uses.
```shell
kubectl get providerrevision provider-aws-a2e16ca2fc1a
NAME HEALTHY REVISION IMAGE STATE DEP-FOUND DEP-INSTALLED AGE
provider-aws-a2e16ca2fc1a True 1 crossplane/provider-aws:v0.29.0 Active 19d
```
When you describe the object, you find all CRDs managed by this object.
```shell
kubectl describe providerrevision provider-aws-a2e16ca2fc1a
Status:
Controller Ref:
Name: provider-aws-a2e16ca2fc1a
Object Refs:
API Version: apiextensions.k8s.io/v1
Kind: CustomResourceDefinition
Name: natgateways.ec2.aws.crossplane.io
UID: 5c36d1bc-61b8-44f8-bca0-47e368af87a9
....
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SyncPackage 22m (x369 over 4d18h) packages/providerrevision.pkg.crossplane.io Successfully configured package revision
Normal BindClusterRole 15m (x348 over 4d18h) rbac/providerrevision.pkg.crossplane.io Bound system ClusterRole to provider ServiceAccount
Normal ApplyClusterRoles 15m (x364 over 4d18h) rbac/providerrevision.pkg.crossplane.io Applied RBAC ClusterRoles
```
The event field also indicates any issues that may have occurred during this process.
<!-- vale Google.WordList = YES -->
3. If you don't see any errors in the event field above, you should check if Crossplane provisioned deployments and their status.
```shell
kubectl get deployment -n crossplane-system
NAME READY UP-TO-DATE AVAILABLE AGE
crossplane 1/1 1 1 105d
crossplane-rbac-manager 1/1 1 1 105d
provider-aws-a2e16ca2fc1a 1/1 1 1 19d
kubectl get pods -n crossplane-system
NAME READY STATUS RESTARTS AGE
crossplane-54db688c8d-qng6b 2/2 Running 0 4d19h
crossplane-rbac-manager-5776c9fbf4-wn5rj 1/1 Running 0 4d19h
provider-aws-a2e16ca2fc1a-776769ccbd-4dqml 1/1 Running 0 4d23h
```
If there are any pods failing, check its logs and remedy the problem.
## Pausing Crossplane
Sometimes, for example when you encounter a bug, it can be useful to pause
@ -408,37 +198,6 @@ for working with Composite Resources. If you're trying to track down why your
Composite Resources aren't working the [Troubleshooting][trouble-ref] page also
has some useful information.
### Troubleshooting Claims and XRs
Crossplane relies heavily on status conditions and events for troubleshooting.
You can see both using `kubectl describe` - for example:
```console
# Describe the PostgreSQLInstance claim named my-db
kubectl describe postgresqlinstance.database.example.org my-db
```
Per Kubernetes convention, Crossplane keeps errors close to the place they
happen. This means that if your claim isn't becoming ready due to an issue with
your `Composition` or with a composed resource you'll need to "follow the
references" to find out why. Your claim will only tell you that the XR isn't
yet ready.
To follow the references:
1. Find your XR by running `kubectl describe` on your claim and looking for its
"Resource Ref" (aka `spec.resourceRef`).
1. Run `kubectl describe` on your XR. This is where you'll find out about issues
with the `Composition` you're using, if any.
1. If there are no issues but your XR doesn't seem to be becoming ready, take a
look for the "Resource Refs" (or `spec.resourceRefs`) to find your composed
resources.
1. Run `kubectl describe` on each referenced composed resource to determine
whether it's ready and what issues, if any, it's encountering.
<!-- Named Links -->
[Requested Resource Not Found]: #requested-resource-not-found
[install Crossplane CLI]: "../getting-started/install-configure"
@ -450,7 +209,7 @@ To follow the references:
[Pausing Providers]: #pausing-providers
[Deleting When a Resource Hangs]: #deleting-when-a-resource-hangs
[Installing Crossplane Package]: #installing-crossplane-package
[Crossplane package]: /master/concepts/packages/
[Crossplane package]: {{<ref "../packages/configurations/">}}
[Handling Crossplane Package Dependency]: #handling-crossplane-package-dependency
[semver spec]: https://github.com/Masterminds/semver#basic-comparisons

View File

@ -1,6 +1,6 @@
---
title: Uninstall Crossplane
weight: 300
weight: 500
---
{{<hint "warning" >}}
@ -23,7 +23,7 @@ Removing Crossplane resources should happen in the following order:
2. Remove all remaining _managed resources_
3. Remove all _providers_
Deleting the Crossplane pod removes remaining Crossplane components like _claims_.
Deleting the Crossplane pod removes remaining Crossplane components.
{{<hint "tip" >}}
Collect an inventory of all external resources with `kubectl get managed`.

View File

@ -1,6 +1,6 @@
---
title: Upgrade Crossplane
weight: 200
weight: 400
---
The recommended upgrade method for an existing Crossplane install is to use
@ -10,14 +10,14 @@ The recommended upgrade method for an existing Crossplane install is to use
* [Helm](https://helm.sh/docs/intro/install/) version `v3.2.0` or later
## Add the Crossplane Helm repository
## Add the Crossplane Preview Helm repository
Verify Helm has the Crossplane repository.
```shell
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo add crossplane-preview https://charts.crossplane.io/preview
```
## Update the Helm repository
## Update the Helm Preview repository
Update the local Crossplane Helm chart with `helm repo update`.
@ -37,7 +37,7 @@ By default, Crossplane installs into the `crossplane-system`
namespace.
```shell
helm upgrade crossplane --namespace crossplane-system crossplane-stable/crossplane
helm upgrade crossplane --namespace crossplane-system crossplane-preview/crossplane --devel
```
Helm preserves any arguments or flags originally used when installing
@ -51,10 +51,10 @@ For example, in v1.20.0 Crossplane changed the default image registry from
before v1.20.0 updates the default package registry.
Override new defaults by
[customizing the Helm chart]({{<ref "install#customize-the-crossplane-helm-chart" >}})
[customizing the Helm chart]({{<ref "../get-started/install#customize-the-crossplane-helm-chart" >}})
with the upgrade command.
For example, to maintain the original image registry use
```shell
helm upgrade crossplane --namespace crossplane-system crossplane-stable/crossplane --set 'args={"--registry=index.docker.io"}'
helm upgrade crossplane --namespace crossplane-system crossplane-preview/crossplane --set 'args={"--registry=index.docker.io"}'
```

View File

@ -1,638 +0,0 @@
---
title: Vault as an External Secret Store
weight: 230
---
This guide walks through the steps required to configure Crossplane and
its Providers to use [Vault] as an [External Secret Store] (`ESS`) with [ESS Plugin Vault].
{{<hint "warning" >}}
External Secret Stores are an alpha feature.
They're not recommended for production use. Crossplane disables External Secret
Stores by default.
{{< /hint >}}
Crossplane uses sensitive information including Provider credentials, inputs to
managed resources and connection details.
The [Vault credential injection guide]({{<ref "vault-injection" >}}) details
using Vault and Crossplane for Provider credentials.
Crossplane doesn't support for using Vault for managed resources input.
[Crossplane issue #2985](https://github.com/crossplane/crossplane/issues/2985)
tracks support for this feature.
Supporting connection details with Vault requires a Crossplane external secret
store.
## Prerequisites
This guide requires [Helm](https://helm.sh) version 3.11 or later.
## Install Vault
{{<hint "note" >}}
Detailed instructions on [installing Vault](https://developer.hashicorp.com/vault/docs/platform/k8s/helm)
are available from the Vault documentation.
{{< /hint >}}
### Add the Vault Helm chart
Add the Helm repository for `hashicorp`.
```shell
helm repo add hashicorp https://helm.releases.hashicorp.com --force-update
```
Install Vault using Helm.
```shell
helm -n vault-system upgrade --install vault hashicorp/vault --create-namespace
```
### Unseal Vault
If Vault is [sealed](https://developer.hashicorp.com/vault/docs/concepts/seal)
unseal Vault using the unseal keys.
Get the Vault keys.
```shell
kubectl -n vault-system exec vault-0 -- vault operator init -key-shares=1 -key-threshold=1 -format=json > cluster-keys.json
VAULT_UNSEAL_KEY=$(cat cluster-keys.json | jq -r ".unseal_keys_b64[]")
```
Unseal the vault using the keys.
```shell {copy-lines="1"}
kubectl -n vault-system exec vault-0 -- vault operator unseal $VAULT_UNSEAL_KEY
Key Value
--- -----
Seal Type shamir
Initialized true
Sealed false
Total Shares 1
Threshold 1
Version 1.13.1
Build Date 2023-03-23T12:51:35Z
Storage Type file
Cluster Name vault-cluster-df884357
Cluster ID b3145d26-2c1a-a7f2-a364-81753033c0d9
HA Enabled false
```
## Configure Vault Kubernetes authentication
Enable the [Kubernetes auth method] for Vault to authenticate requests based on
Kubernetes service accounts.
### Get the Vault root token
The Vault root token is inside the JSON file created when
[unsealing Vault](#unseal-vault).
```shell
cat cluster-keys.json | jq -r ".root_token"
```
### Enable Kubernetes authentication
Connect to a shell in the Vault pod.
```shell {copy-lines="1"}
kubectl -n vault-system exec -it vault-0 -- /bin/sh
/ $
```
From the Vault shell, login to Vault using the _root token_.
```shell {copy-lines="1"}
vault login # use the root token from above
Token (will be hidden):
Success! You are now authenticated. The token information displayed below
is already stored in the token helper. You do NOT need to run "vault login"
again. Future Vault requests will automatically use this token.
Key Value
--- -----
token hvs.TSN4SssfMBM0HAtwGrxgARgn
token_accessor qodxHrINVlRXKyrGeeDkxnih
token_duration ∞
token_renewable false
token_policies ["root"]
identity_policies []
policies ["root"]
```
Enable the Kubernetes authentication method in Vault.
```shell {copy-lines="1"}
vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/
```
Configure Vault to communicate with Kubernetes and exit the Vault shell
```shell {copy-lines="1-4"}
vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Success! Data written to: auth/kubernetes/config
/ $ exit
```
## Configure Vault for Crossplane integration
Crossplane relies on the Vault key-value secrets engine to store information and
Vault requires a permissions policy for the Crossplane service account.
<!-- vale Crossplane.Spelling = NO -->
<!-- allow "kv" -->
### Enable the Vault kv secrets engine
<!-- vale Crossplane.Spelling = YES -->
Enable the [Vault KV Secrets Engine].
{{< hint "important" >}}
Vault has two versions of the
[KV Secrets Engine](https://developer.hashicorp.com/vault/docs/secrets/kv).
This example uses version 2.
{{</hint >}}
```shell {copy-lines="1"}
kubectl -n vault-system exec -it vault-0 -- vault secrets enable -path=secret kv-v2
Success! Enabled the kv-v2 secrets engine at: secret/
```
### Create a Vault policy for Crossplane
Create the Vault policy to allow Crossplane to read and write data from Vault.
```shell {copy-lines="1-8"}
kubectl -n vault-system exec -i vault-0 -- vault policy write crossplane - <<EOF
path "secret/data/*" {
capabilities = ["create", "read", "update", "delete"]
}
path "secret/metadata/*" {
capabilities = ["create", "read", "update", "delete"]
}
EOF
Success! Uploaded policy: crossplane
```
Apply the policy to Vault.
```shell {copy-lines="1-5"}
kubectl -n vault-system exec -it vault-0 -- vault write auth/kubernetes/role/crossplane \
bound_service_account_names="*" \
bound_service_account_namespaces=crossplane-system \
policies=crossplane \
ttl=24h
Success! Data written to: auth/kubernetes/role/crossplane
```
## Install Crossplane
{{<hint "important" >}}
Crossplane v1.12 introduced the plugin support. Make sure your version of Crossplane supports plugins.
{{< /hint >}}
Install the Crossplane with the External Secrets Stores feature enabled.
```shell
helm upgrade --install crossplane crossplane-stable/crossplane --namespace crossplane-system --create-namespace --set args='{--enable-external-secret-stores}'
```
## Install the Crossplane Vault plugin
The Crossplane Vault plugin isn't part of the default Crossplane install.
The plugin installs as a unique Pod that uses the [Vault Agent Sidecar
Injection] to connect the Vault secret store to Crossplane.
First, configure annotations for the Vault plugin pod.
```yaml
cat > values.yaml <<EOF
podAnnotations:
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-token: "true"
vault.hashicorp.com/role: crossplane
vault.hashicorp.com/agent-run-as-user: "65532"
EOF
```
Next, install the Crossplane ESS Plugin pod to the `crossplane-system` namespace
and apply the Vault annotations.
```shell
helm upgrade --install ess-plugin-vault oci://xpkg.crossplane.io/crossplane-contrib/ess-plugin-vault --namespace crossplane-system -f values.yaml
```
## Configure Crossplane
Using the Vault plugin requires configuration to connect to the Vault
service. The plugin also requires Providers to enable external secret stores.
With the plugin and providers configured, Crossplane requires two `StoreConfig`
objects to describe how Crossplane and the Providers communicate with vault.
### Enable external secret stores in the Provider
{{<hint "note">}}
This example uses Provider GCP, but the
{{<hover label="ControllerConfig" line="2">}}ControllerConfig{{</hover>}} is the
same for all Providers.
{{</hint >}}
Create a `ControllerConfig` object to enable external secret stores.
```yaml {label="ControllerConfig"}
echo "apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
name: vault-config
spec:
args:
- --enable-external-secret-stores" | kubectl apply -f -
```
Install the Provider and apply the ControllerConfig.
```yaml
echo "apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-gcp
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-gcp:v0.23.0-rc.0.19.ge9b75ee5
controllerConfigRef:
name: vault-config" | kubectl apply -f -
```
### Connect the Crossplane plugin to Vault
Create a {{<hover label="VaultConfig" line="2">}}VaultConfig{{</hover>}}
resource for the plugin to connect to the Vault service:
```yaml {label="VaultConfig"}
echo "apiVersion: secrets.crossplane.io/v1alpha1
kind: VaultConfig
metadata:
name: vault-internal
spec:
server: http://vault.vault-system:8200
mountPath: secret/
version: v2
auth:
method: Token
token:
source: Filesystem
fs:
path: /vault/secrets/token" | kubectl apply -f -
```
### Create a Crossplane StoreConfig
Create a {{<hover label="xp-storeconfig" line="2">}}StoreConfig{{</hover >}}
object from the
{{<hover label="xp-storeconfig" line="1">}}secrets.crossplane.io{{</hover >}}
group. Crossplane uses the StoreConfig to connect to the Vault plugin service.
The {{<hover label="xp-storeconfig" line="10">}}configRef{{</hover >}} connects
the StoreConfig to the specific Vault plugin configuration.
```yaml {label="xp-storeconfig"}
echo "apiVersion: secrets.crossplane.io/v1alpha1
kind: StoreConfig
metadata:
name: vault
spec:
type: Plugin
defaultScope: crossplane-system
plugin:
endpoint: ess-plugin-vault.crossplane-system:4040
configRef:
apiVersion: secrets.crossplane.io/v1alpha1
kind: VaultConfig
name: vault-internal" | kubectl apply -f -
```
### Create a Provider StoreConfig
Create a {{<hover label="gcp-storeconfig" line="2">}}StoreConfig{{</hover >}}
object from the Provider's API group,
{{<hover label="gcp-storeconfig" line="1">}}gcp.crossplane.io{{</hover >}}.
The Provider uses this StoreConfig to communicate with Vault for
Managed Resources.
The {{<hover label="gcp-storeconfig" line="10">}}configRef{{</hover >}} connects
the StoreConfig to the specific Vault plugin configuration.
```yaml {label="gcp-storeconfig"}
echo "apiVersion: gcp.crossplane.io/v1alpha1
kind: StoreConfig
metadata:
name: vault
spec:
type: Plugin
defaultScope: crossplane-system
plugin:
endpoint: ess-plugin-vault.crossplane-system:4040
configRef:
apiVersion: secrets.crossplane.io/v1alpha1
kind: VaultConfig
name: vault-internal" | kubectl apply -f -
```
## Create Provider resources
Check that Crossplane installed the Provider and the Provider is healthy.
```shell {copy-lines="1"}
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
provider-gcp True True xpkg.crossplane.io/crossplane-contrib/provider-gcp:v0.23.0-rc.0.19.ge9b75ee5 10m
```
### Create a CompositeResourceDefinition
Create a `CompositeResourceDefinition` to define a custom API endpoint.
```yaml
echo "apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: compositeessinstances.ess.example.org
annotations:
feature: ess
spec:
group: ess.example.org
names:
kind: CompositeESSInstance
plural: compositeessinstances
claimNames:
kind: ESSInstance
plural: essinstances
connectionSecretKeys:
- publicKey
- publicKeyType
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
serviceAccount:
type: string
required:
- serviceAccount
required:
- parameters" | kubectl apply -f -
```
### Create a Composition
Create a `Composition` to create a Service Account and Service Account Key
inside GCP.
Creating a Service Account Key generates
{{<hover label="comp" line="39" >}}connectionDetails{{</hover>}} that the
Provider stores in Vault using the
{{<hover label="comp" line="31">}}publishConnectionDetailsTo{{</hover>}} details.
```yaml {label="comp"}
echo "apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: essinstances.ess.example.org
labels:
feature: ess
spec:
publishConnectionDetailsWithStoreConfigRef:
name: vault
compositeTypeRef:
apiVersion: ess.example.org/v1alpha1
kind: CompositeESSInstance
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: serviceaccount
base:
apiVersion: iam.gcp.crossplane.io/v1alpha1
kind: ServiceAccount
metadata:
name: ess-test-sa
spec:
forProvider:
displayName: a service account to test ess
- name: serviceaccountkey
base:
apiVersion: iam.gcp.crossplane.io/v1alpha1
kind: ServiceAccountKey
spec:
forProvider:
serviceAccountSelector:
matchControllerRef: true
publishConnectionDetailsTo:
name: ess-mr-conn
metadata:
labels:
environment: development
team: backend
configRef:
name: vault
connectionDetails:
- name: publicKey
type: FromConnectionSecretKey
fromConnectionSecretKey: publicKey
- name: publicKey
type: FromConnectionSecretKey
fromConnectionSecretKey: publicKeyType" | kubectl apply -f -
```
### Create a Claim
Now create a `Claim` to have Crossplane create the GCP resources and associated
secrets.
Like the Composition, the Claim uses
{{<hover label="claim" line="12">}}publishConnectionDetailsTo{{</hover>}} to
connect to Vault and store the secrets.
```yaml {label="claim"}
echo "apiVersion: ess.example.org/v1alpha1
kind: ESSInstance
metadata:
name: my-ess
namespace: default
spec:
parameters:
serviceAccount: ess-test-sa
compositionSelector:
matchLabels:
feature: ess
publishConnectionDetailsTo:
name: ess-claim-conn
metadata:
labels:
environment: development
team: backend
configRef:
name: vault" | kubectl apply -f -
```
## Verify the resources
Verify all resources are `READY` and `SYNCED`:
```shell {copy-lines="1"}
kubectl get managed
NAME READY SYNCED DISPLAYNAME EMAIL DISABLED
serviceaccount.iam.gcp.crossplane.io/my-ess-zvmkz-vhklg True True a service account to test ess my-ess-zvmkz-vhklg@testingforbugbounty.iam.gserviceaccount.com
NAME READY SYNCED KEY_ID CREATED_AT EXPIRES_AT
serviceaccountkey.iam.gcp.crossplane.io/my-ess-zvmkz-bq8pz True True 5cda49b7c32393254b5abb121b4adc07e140502c 2022-03-23T10:54:50Z
```
View the claims
```shell {copy-lines="1"}
kubectl -n default get claim
NAME READY CONNECTION-SECRET AGE
my-ess True 19s
```
View the composite resources.
```shell {copy-lines="1"}
kubectl get composite
NAME READY COMPOSITION AGE
my-ess-zvmkz True essinstances.ess.example.org 32s
```
## Verify Vault secrets
Look inside Vault to view the secrets from the managed resources.
```shell {copy-lines="1",label="vault-key"}
kubectl -n vault-system exec -i vault-0 -- vault kv list /secret/default
Keys
----
ess-claim-conn
```
The key {{<hover label="vault-key" line="4">}}ess-claim-conn{{</hover>}}
is the name of the Claim's
{{<hover label="claim" line="12">}}publishConnectionDetailsTo{{</hover>}}
configuration.
Check connection secrets in the `crossplane-system` Vault scope.
```shell {copy-lines="1",label="scope-key"}
kubectl -n vault-system exec -i vault-0 -- vault kv list /secret/crossplane-system
Keys
----
d2408335-eb88-4146-927b-8025f405da86
ess-mr-conn
```
The key
{{<hover label="scope-key"line="4">}}d2408335-eb88-4146-927b-8025f405da86{{</hover>}}
comes from
<!-- ## WHERE DOES IT COME FROM? -->
and the key
{{<hover label="scope-key"line="5">}}ess-mr-conn{{</hover>}}
comes from the Composition's
{{<hover label="comp" line="31">}}publishConnectionDetailsTo{{</hover>}}
configuration.
Check contents of Claim's connection secret `ess-claim-conn` to see the key
created by the managed resource.
```shell {copy-lines="1"}
kubectl -n vault-system exec -i vault-0 -- vault kv get /secret/default/ess-claim-conn
======= Metadata =======
Key Value
--- -----
created_time 2022-03-18T21:24:07.2085726Z
custom_metadata map[environment:development secret.crossplane.io/ner-uid:881cd9a0-6cc6-418f-8e1d-b36062c1e108 team:backend]
deletion_time n/a
destroyed false
version 1
======== Data ========
Key Value
--- -----
publicKey -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsEYCokmYEsZJCc9QN/8
Fm1M/kTPp7Gat/MXLTP3zFyCTBFVNLN79MbAKdinWi6ePXEb75vzB79IdZcWj8lo
8trnS64QjNB9Vs4Xk5UvDALwleFN/bZeperxivDPwVPvT9Aqy/U9kohoS/LHyE8w
uWQb5AuMeVQ1gtCTnCqQZ4d2MSVhQXYVvAWax1spJ9LT7mHub5j95xDdYIcOV3VJ
l9CIo4VrWIT8THFN2NnjTrGq9+0TzXY0bV674bjJkfBC6v6yXs5HTetG+Uekq/xf
FCjrrDi1+2UR9Mu2WTuvl8qn50be+mbwdJO5wE32jewxdYrVVmj19+PkaEeAwGTc
vwIDAQAB
-----END PUBLIC KEY-----
publicKeyType TYPE_RAW_PUBLIC_KEY
```
Check contents of managed resource connection secret `ess-mr-conn`. The public
key is identical to the public key in the Claim since the Claim is using this
managed resource.
```shell {copy-lines="1"}
kubectl -n vault-system exec -i vault-0 -- vault kv get /secret/crossplane-system/ess-mr-conn
======= Metadata =======
Key Value
--- -----
created_time 2022-03-18T21:21:07.9298076Z
custom_metadata map[environment:development secret.crossplane.io/ner-uid:4cd973f8-76fc-45d6-ad45-0b27b5e9252a team:backend]
deletion_time n/a
destroyed false
version 2
========= Data =========
Key Value
--- -----
privateKey {
"type": "service_account",
"project_id": "REDACTED",
"private_key_id": "REDACTED",
"private_key": "-----BEGIN PRIVATE KEY-----\nREDACTED\n-----END PRIVATE KEY-----\n",
"client_email": "ess-test-sa@REDACTED.iam.gserviceaccount.com",
"client_id": "REDACTED",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/ess-test-sa%40REDACTED.iam.gserviceaccount.com"
}
privateKeyType TYPE_GOOGLE_CREDENTIALS_FILE
publicKey -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsEYCokmYEsZJCc9QN/8
Fm1M/kTPp7Gat/MXLTP3zFyCTBFVNLN79MbAKdinWi6ePXEb75vzB79IdZcWj8lo
8trnS64QjNB9Vs4Xk5UvDALwleFN/bZeperxivDPwVPvT9Aqy/U9kohoS/LHyE8w
uWQb5AuMeVQ1gtCTnCqQZ4d2MSVhQXYVvAWax1spJ9LT7mHub5j95xDdYIcOV3VJ
l9CIo4VrWIT8THFN2NnjTrGq9+0TzXY0bV674bjJkfBC6v6yXs5HTetG+Uekq/xf
FCjrrDi1+2UR9Mu2WTuvl8qn50be+mbwdJO5wE32jewxdYrVVmj19+PkaEeAwGTc
vwIDAQAB
-----END PUBLIC KEY-----
publicKeyType TYPE_RAW_PUBLIC_KEY
```
### Remove the resources
Deleting the Claim removes the managed resources and associated keys from Vault.
```shell
kubectl delete claim my-ess
```
<!-- named links -->
[Vault]: https://www.vaultproject.io/
[External Secret Store]: https://github.com/crossplane/crossplane/blob/main/design/design-doc-external-secret-stores.md
[this issue]: https://github.com/crossplane/crossplane/issues/2985
[Kubernetes Auth Method]: https://www.vaultproject.io/docs/auth/kubernetes
[Unseal]: https://www.vaultproject.io/docs/concepts/seal
[Vault KV Secrets Engine]: https://developer.hashicorp.com/vault/docs/secrets/kv
[Vault Agent Sidecar Injection]: https://www.vaultproject.io/docs/platform/k8s/injector
[ESS Plugin Vault]: https://github.com/crossplane-contrib/ess-plugin-vault

View File

@ -1,502 +0,0 @@
---
title: Vault Credential Injection
weight: 230
---
> This guide is adapted from the [Vault on Minikube] and [Vault Kubernetes
> Sidecar] guides.
Most Crossplane providers support supplying credentials from at least the
following sources:
- Kubernetes Secret
- Environment Variable
- Filesystem
A provider may optionally support additional credentials sources, but the common
sources cover a wide variety of use cases. One specific use case that's popular
among organizations that use [Vault] for secrets management is using a sidecar
to inject credentials into the filesystem. This guide will demonstrate how to
use the [Vault Kubernetes Sidecar] to provide credentials for [provider-gcp]
and [provider-aws].
> Note: in this guide we will copy GCP credentials and AWS access keys
> into Vault's KV secrets engine. This is a generic approach to
> managing secrets with Vault, but isn't as robust as using Vault's
> dedicated cloud provider secrets engines for [AWS], [Azure], and [GCP].
## Setup
> Note: this guide walks through setting up Vault running in the same cluster as
> Crossplane. You may also choose to use an existing Vault instance that runs
> outside the cluster but has Kubernetes authentication enabled.
Before getting started, you must ensure that you have installed Crossplane and
Vault and that they're running in your cluster.
1. Install Crossplane
```console
kubectl create namespace crossplane-system
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane --namespace crossplane-system crossplane-stable/crossplane
```
2. Install Vault Helm Chart
```console
helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault
```
3. Unseal Vault Instance
In order for Vault to access encrypted data from physical storage, it must be
[unsealed].
```console
kubectl exec vault-0 -- vault operator init -key-shares=1 -key-threshold=1 -format=json > cluster-keys.json
VAULT_UNSEAL_KEY=$(cat cluster-keys.json | jq -r ".unseal_keys_b64[]")
kubectl exec vault-0 -- vault operator unseal $VAULT_UNSEAL_KEY
```
4. Enable Kubernetes Authentication Method
In order for Vault to be able to authenticate requests based on Kubernetes
service accounts, the [Kubernetes authentication method] must be enabled. This
requires logging in to Vault and configuring it with a service account token,
API server address, and certificate. Because we're running Vault in Kubernetes,
these values are already available via the container filesystem and environment
variables.
```console
cat cluster-keys.json | jq -r ".root_token" # get root token
kubectl exec -it vault-0 -- /bin/sh
vault login # use root token from above
vault auth enable kubernetes
vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
```
5. Exit Vault Container
The next steps will be executed in your local environment.
```console
exit
```
{{< tabs >}}
{{< tab "GCP" >}}
## Create GCP Service Account
In order to provision infrastructure on GCP, you will need to create a service
account with appropriate permissions. In this guide we will only provision a
CloudSQL instance, so the service account will be bound to the `cloudsql.admin`
role. The following steps will setup a GCP service account, give it the
necessary permissions for Crossplane to be able to manage CloudSQL instances,
and emit the service account credentials in a JSON file.
```console
# replace this with your own gcp project id and the name of the service account
# that will be created.
PROJECT_ID=my-project
NEW_SA_NAME=test-service-account-name
# create service account
SA="${NEW_SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
gcloud iam service-accounts create $NEW_SA_NAME --project $PROJECT_ID
# enable cloud API
SERVICE="sqladmin.googleapis.com"
gcloud services enable $SERVICE --project $PROJECT_ID
# grant access to cloud API
ROLE="roles/cloudsql.admin"
gcloud projects add-iam-policy-binding --role="$ROLE" $PROJECT_ID --member "serviceAccount:$SA"
# create service account keyfile
gcloud iam service-accounts keys create creds.json --project $PROJECT_ID --iam-account $SA
```
You should now have valid service account credentials in `creds.json`.
## Store Credentials in Vault
After setting up Vault, you will need to store your credentials in the [kv
secrets engine].
> Note: the steps below involve copying credentials into the container
> filesystem before storing them in Vault. You may also choose to use Vault's
> HTTP API or UI by port forwarding the container to your local environment
> (`kubectl port-forward vault-0 8200:8200`).
1. Copy Credentials File into Vault Container
Copy your credentials into the container filesystem so that your can store them
in Vault.
```console
kubectl cp creds.json vault-0:/tmp/creds.json
```
2. Enable KV Secrets Engine
Secrets engines must be enabled before they can be used. Enable the `kv-v2`
secrets engine at the `secret` path.
```console
kubectl exec -it vault-0 -- /bin/sh
vault secrets enable -path=secret kv-v2
```
3. Store GCP Credentials in KV Engine
The path of your GCP credentials is how the secret will be referenced when
injecting it into the `provider-gcp` controller `Pod`.
```console
vault kv put secret/provider-creds/gcp-default @tmp/creds.json
```
4. Clean Up Credentials File
You no longer need our GCP credentials file in the container filesystem, so go
ahead and clean it up.
```console
rm tmp/creds.json
```
{{< /tab >}}
{{< tab "AWS" >}}
## Create AWS IAM User
In order to provision infrastructure on AWS, you will need to use an existing or create a new IAM
user with appropriate permissions. The following steps will create an AWS IAM user and give it the necessary
permissions.
> Note: if you have an existing IAM user with appropriate permissions, you can skip this step but you will
> still need to provide the values for the `ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables.
```console
# create a new IAM user
IAM_USER=test-user
aws iam create-user --user-name $IAM_USER
# grant the IAM user the necessary permissions
aws iam attach-user-policy --user-name $IAM_USER --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
# create a new IAM access key for the user
aws iam create-access-key --user-name $IAM_USER > creds.json
# assign the access key values to environment variables
ACCESS_KEY_ID=$(jq -r .AccessKey.AccessKeyId creds.json)
AWS_SECRET_ACCESS_KEY=$(jq -r .AccessKey.SecretAccessKey creds.json)
```
## Store Credentials in Vault
After setting up Vault, you will need to store your credentials in the [kv
secrets engine].
1. Enable KV Secrets Engine
Secrets engines must be enabled before they can be used. Enable the `kv-v2`
secrets engine at the `secret` path.
```console
kubectl exec -it vault-0 -- env \
ACCESS_KEY_ID=${ACCESS_KEY_ID} \
AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} \
/bin/sh
vault secrets enable -path=secret kv-v2
```
2. Store AWS Credentials in KV Engine
The path of your AWS credentials is how the secret will be referenced when
injecting it into the `provider-aws` controller `Pod`.
```
vault kv put secret/provider-creds/aws-default access_key="$ACCESS_KEY_ID" secret_key="$AWS_SECRET_ACCESS_KEY"
```
{{< /tab >}}
{{< /tabs >}}
## Create a Vault Policy for Reading Provider Credentials
In order for our controllers to have the Vault sidecar inject the credentials
into their filesystem, you must associate the `Pod` with a [policy]. This policy
will allow for reading and listing all secrets on the `provider-creds` path in
the `kv-v2` secrets engine.
```console
vault policy write provider-creds - <<EOF
path "secret/data/provider-creds/*" {
capabilities = ["read", "list"]
}
EOF
```
## Create a Role for Crossplane Provider Pods
1. Create Role
The last step is to create a role that's bound to the policy you created and
associate it with a group of Kubernetes service accounts. This role can be
assumed by any (`*`) service account in the `crossplane-system` namespace.
```console
vault write auth/kubernetes/role/crossplane-providers \
bound_service_account_names="*" \
bound_service_account_namespaces=crossplane-system \
policies=provider-creds \
ttl=24h
```
2. Exit Vault Container
The next steps will be executed in your local environment.
```console
exit
```
{{< tabs >}}
{{< tab "GCP" >}}
## Install provider-gcp
You are now ready to install `provider-gcp`. Crossplane provides a
`ControllerConfig` type that allows you to customize the deployment of a
provider's controller `Pod`. A `ControllerConfig` can be created and referenced
by any number of `Provider` objects that wish to use its configuration. In the
example below, the `Pod` annotations indicate to the Vault mutating webhook that
we want for the secret stored at `secret/provider-creds/gcp-default` to be
injected into the container filesystem by assuming role `crossplane-providers`.
Template formatting has been added to make sure the secret data is
presented in a form that `provider-gcp` is expecting.
```console
echo "apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
name: vault-config
spec:
metadata:
annotations:
vault.hashicorp.com/agent-inject: \"true\"
vault.hashicorp.com/role: "crossplane-providers"
vault.hashicorp.com/agent-inject-secret-creds.txt: "secret/provider-creds/gcp-default"
vault.hashicorp.com/agent-inject-template-creds.txt: |
{{- with secret \"secret/provider-creds/gcp-default\" -}}
{{ .Data.data | toJSON }}
{{- end -}}
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-gcp
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-gcp:v0.22.0
controllerConfigRef:
name: vault-config" | kubectl apply -f -
```
## Configure provider-gcp
One `provider-gcp` is installed and running, you will want to create a
`ProviderConfig` that specifies the credentials in the filesystem that should be
used to provision managed resources that reference this `ProviderConfig`.
Because the name of this `ProviderConfig` is `default` it will be used by any
managed resources that don't explicitly reference a `ProviderConfig`.
> Note: make sure that the `PROJECT_ID` environment variable that was defined
> earlier is still set correctly.
```console
echo "apiVersion: gcp.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
projectID: ${PROJECT_ID}
credentials:
source: Filesystem
fs:
path: /vault/secrets/creds.txt" | kubectl apply -f -
```
To verify that the GCP credentials are being injected into the container run the
following command:
```console
PROVIDER_CONTROLLER_POD=$(kubectl -n crossplane-system get pod -l pkg.crossplane.io/provider=provider-gcp -o name --no-headers=true)
kubectl -n crossplane-system exec -it $PROVIDER_CONTROLLER_POD -c provider-gcp -- cat /vault/secrets/creds.txt
```
## Provision Infrastructure
The final step is to actually provision a `CloudSQLInstance`. Creating the
object below will result in the creation of a Cloud SQL PostgreSQL database on
GCP.
```console
echo "apiVersion: database.gcp.crossplane.io/v1beta1
kind: CloudSQLInstance
metadata:
name: postgres-vault-demo
spec:
forProvider:
databaseVersion: POSTGRES_12
region: us-central1
settings:
tier: db-custom-1-3840
dataDiskType: PD_SSD
dataDiskSizeGb: 10
writeConnectionSecretToRef:
namespace: crossplane-system
name: cloudsqlpostgresql-conn" | kubectl apply -f -
```
You can monitor the progress of the database provisioning with the following
command:
```console
kubectl get cloudsqlinstance -w
```
{{< /tab >}}
{{< tab "AWS" >}}
## Install provider-aws
You are now ready to install `provider-aws`. Crossplane provides a
`ControllerConfig` type that allows you to customize the deployment of a
provider's controller `Pod`. A `ControllerConfig` can be created and referenced
by any number of `Provider` objects that wish to use its configuration. In the
example below, the `Pod` annotations indicate to the Vault mutating webhook that
we want for the secret stored at `secret/provider-creds/aws-default` to be
injected into the container filesystem by assuming role `crossplane-providers`.
Template formatting has been added to make sure the secret data is
presented in a form that `provider-aws` is expecting.
```console
echo "apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
name: aws-vault-config
spec:
args:
- --debug
metadata:
annotations:
vault.hashicorp.com/agent-inject: \"true\"
vault.hashicorp.com/role: \"crossplane-providers\"
vault.hashicorp.com/agent-inject-secret-creds.txt: \"secret/provider-creds/aws-default\"
vault.hashicorp.com/agent-inject-template-creds.txt: |
{{- with secret \"secret/provider-creds/aws-default\" -}}
[default]
aws_access_key_id="{{ .Data.data.access_key }}"
aws_secret_access_key="{{ .Data.data.secret_key }}"
{{- end -}}
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws
spec:
package: xpkg.crossplane.io/crossplane-contrib/provider-aws:v0.33.0
controllerConfigRef:
name: aws-vault-config" | kubectl apply -f -
```
## Configure provider-aws
Once `provider-aws` is installed and running, you will want to create a
`ProviderConfig` that specifies the credentials in the filesystem that should be
used to provision managed resources that reference this `ProviderConfig`.
Because the name of this `ProviderConfig` is `default` it will be used by any
managed resources that don't explicitly reference a `ProviderConfig`.
```console
echo "apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Filesystem
fs:
path: /vault/secrets/creds.txt" | kubectl apply -f -
```
To verify that the AWS credentials are being injected into the container run the
following command:
```console
PROVIDER_CONTROLLER_POD=$(kubectl -n crossplane-system get pod -l pkg.crossplane.io/provider=provider-aws -o name --no-headers=true)
kubectl -n crossplane-system exec -it $PROVIDER_CONTROLLER_POD -c provider-aws -- cat /vault/secrets/creds.txt
```
## Provision Infrastructure
The final step is to actually provision a `Bucket`. Creating the
object below will result in the creation of a S3 bucket on AWS.
```console
echo "apiVersion: s3.aws.crossplane.io/v1beta1
kind: Bucket
metadata:
name: s3-vault-demo
spec:
forProvider:
acl: private
locationConstraint: us-east-1
publicAccessBlockConfiguration:
blockPublicPolicy: true
tagging:
tagSet:
- key: Name
value: s3-vault-demo
providerConfigRef:
name: default" | kubectl apply -f -
```
You can monitor the progress of the bucket provisioning with the following
command:
```console
kubectl get bucket -w
```
{{< /tab >}}
{{< /tabs >}}
<!-- named links -->
[Vault on Minikube]: https://learn.hashicorp.com/tutorials/vault/kubernetes-minikube
[Vault Kubernetes Sidecar]: https://learn.hashicorp.com/tutorials/vault/kubernetes-sidecar
[Vault]: https://www.vaultproject.io/
[Vault Kubernetes Sidecar]: https://www.vaultproject.io/docs/platform/k8s/injector
[provider-gcp]: https://github.com/crossplane-contrib/provider-upjet-gcp
[provider-aws]: https://github.com/crossplane-contrib/provider-upjet-aws
[AWS]: https://www.vaultproject.io/docs/secrets/aws
[Azure]: https://www.vaultproject.io/docs/secrets/azure
[GCP]: https://www.vaultproject.io/docs/secrets/gcp
[unsealed]: https://www.vaultproject.io/docs/concepts/seal
[Kubernetes authentication method]: https://www.vaultproject.io/docs/auth/kubernetes
[kv secrets engine]: https://www.vaultproject.io/docs/secrets/kv/kv-v2
[policy]: https://www.vaultproject.io/docs/concepts/policies

View File

@ -8,7 +8,7 @@ Composition functions (or just functions, for short) are custom programs that
template Crossplane resources. Crossplane calls composition functions to
determine what resources it should create when you create a composite resource
(XR). Read the
[concepts]({{<ref "../concepts/compositions" >}})
[concepts]({{<ref "../composition/compositions" >}})
page to learn more about composition functions.
You can write a function to template resources using a general purpose
@ -19,7 +19,7 @@ conditionals. This guide explains how to write a composition function in
{{< hint "important" >}}
It helps to be familiar with
[how composition functions work]({{<ref "../concepts/compositions#how-composition-functions-work" >}})
[how composition functions work]({{<ref "../composition/compositions#how-composition-functions-work" >}})
before following this guide.
{{< /hint >}}
@ -139,7 +139,7 @@ should delete the `input` and `package/input` directories.
The `input` directory defines a Go struct that a function can use to take input,
using the `input` field from a Composition. The
[composition functions]({{<ref "../concepts/compositions/#function-input" >}})
[composition functions]({{<ref "../composition/compositions/#function-input" >}})
documentation explains how to pass an input to a composition function.
The `package/input` directory contains an OpenAPI schema generated from the
@ -306,17 +306,17 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1.RunFunctionRequest)
// to add desired managed resources.
xr, err := request.GetObservedCompositeResource(req)
if err != nil {
// You can set a custom status condition on the claim. This
// You can set a custom status condition on the XR. This
// allows you to communicate with the user.
response.ConditionFalse(rsp, "FunctionSuccess", "InternalError").
WithMessage("Something went wrong.").
TargetCompositeAndClaim()
TargetComposite()
// You can emit an event regarding the claim. This allows you to
// You can emit an event regarding the XR. This allows you to
// communicate with the user. Note that events should be used
// sparingly and are subject to throttling
response.Warning(rsp, errors.New("something went wrong")).
TargetCompositeAndClaim()
TargetComposite()
// If the function can't read the XR, the request is malformed. This
// should never happen. The function returns a fatal result. This tells
@ -408,10 +408,10 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1.RunFunctionRequest)
// Kubernetes events associated with the XR it's operating on.
log.Info("Added desired buckets", "region", region, "count", len(names))
// You can set a custom status condition on the claim. This allows you
// You can set a custom status condition on the XR. This allows you
// to communicate with the user.
response.ConditionTrue(rsp, "FunctionSuccess", "Success").
TargetCompositeAndClaim()
TargetComposite()
return rsp, nil
}
@ -568,7 +568,7 @@ func TestRunFunction(t *testing.T) {
Type: "FunctionSuccess",
Status: fnv1.Status_STATUS_CONDITION_TRUE,
Reason: "Success",
Target: fnv1.Target_TARGET_COMPOSITE_AND_CLAIM.Enum(),
Target: fnv1.Target_TARGET_COMPOSITE.Enum(),
},
},
},
@ -775,7 +775,7 @@ spec:
{{<hint "tip">}}
Read the composition functions documentation to learn more about
[testing composition functions]({{< ref "../concepts/compositions#test-a-composition" >}}).
[testing composition functions]({{< ref "../composition/compositions#test-a-composition" >}}).
{{</hint>}}
## Build and push the function to a package registry
@ -792,7 +792,7 @@ then pushing all the packages to a single tag in the registry.
Pushing your function to a registry allows you to use your function in a
Crossplane control plane. See the
[composition functions documentation]({{<ref "../concepts/compositions" >}})
[composition functions documentation]({{<ref "../composition/compositions" >}})
to learn how to use a function in a control plane.
Use Docker to build a runtime for each platform.
@ -843,7 +843,7 @@ crossplane xpkg build \
{{<hint "tip">}}
Crossplane packages are special OCI images. Read more about packages in the
[packages documentation]({{< ref "../concepts/packages" >}}).
[packages documentation]({{< ref "../packages/configurations" >}}).
{{</hint>}}
Push both package files to a registry. Pushing both files to one tag in the

View File

@ -8,7 +8,7 @@ Composition functions (or just functions, for short) are custom programs that
template Crossplane resources. Crossplane calls composition functions to
determine what resources it should create when you create a composite resource
(XR). Read the
[concepts]({{<ref "../concepts/compositions" >}})
[concepts]({{<ref "../composition/compositions" >}})
page to learn more about composition functions.
You can write a function to template resources using a general purpose
@ -19,7 +19,7 @@ conditionals. This guide explains how to write a composition function in
{{< hint "important" >}}
It helps to be familiar with
[how composition functions work]({{<ref "../concepts/compositions#how-composition-functions-work" >}})
[how composition functions work]({{<ref "../composition/compositions#how-composition-functions-work" >}})
before following this guide.
{{< /hint >}}
@ -129,7 +129,7 @@ The `package/input` directory defines the OpenAPI schema for the a function's
input. The function in this guide doesn't accept an input. Delete the
`package/input` directory.
The [composition functions]({{<ref "../concepts/compositions" >}})
The [composition functions]({{<ref "../composition/compositions" >}})
documentation explains composition function inputs.
{{<hint "tip">}}
@ -636,7 +636,7 @@ spec:
{{<hint "tip">}}
Read the composition functions documentation to learn more about
[testing composition functions]({{< ref "../concepts/compositions#test-a-composition" >}}).
[testing composition functions]({{< ref "../composition/compositions#test-a-composition" >}}).
{{</hint>}}
## Build and push the function to a package registry
@ -653,7 +653,7 @@ then pushing all the packages to a single tag in the registry.
Pushing your function to a registry allows you to use your function in a
Crossplane control plane. See the
[composition functions documentation]({{<ref "../concepts/compositions" >}}).
[composition functions documentation]({{<ref "../composition/compositions" >}}).
to learn how to use a function in a control plane.
Use Docker to build a runtime for each platform.
@ -712,7 +712,7 @@ crossplane xpkg build \
{{<hint "tip">}}
Crossplane packages are special OCI images. Read more about packages in the
[packages documentation]({{< ref "../concepts/packages" >}}).
[packages documentation]({{< ref "../packages/configurations" >}}).
{{</hint>}}
Push both package files to a registry. Pushing both files to one tag in the

View File

@ -0,0 +1,5 @@
---
title: Managed Resources
weight: 52
description: Understand Crossplane's core components
---

View File

@ -19,12 +19,15 @@ Examples of managed resources include:
* Google Cloud GKE `Cluster` defined in [provider-upjet-gcp](https://github.com/crossplane-contrib/provider-upjet-gcp).
* Microsoft Azure PostgreSQL `Database` defined in [provider-upjet-azure](https://github.com/crossplane-contrib/provider-upjet-azure).
{{< hint "tip" >}}
{{<hint "important">}}
Only AWS managed resources support the Crossplane v2 preview.
<!-- vale gitlab.FutureTense = NO -->
Maintainers will update the managed resources for other systems including Azure,
GCP, Terraform, Helm, GitHub, etc to support Crossplane v2 soon.
<!-- vale gitlab.FutureTense = YES -->
{{</hint>}}
You can create individual managed resources, but Crossplane recommends using
[Compositions]({{<ref "./compositions" >}}) and Claims to create
managed resources.
{{< /hint >}}
## Managed resource fields
@ -37,48 +40,13 @@ group, kind and version.
For example the [AWS Provider](https://github.com/crossplane-contrib/provider-upjet-aws)
defines the {{<hover label="gkv" line="2">}}Instance{{</hover>}} kind from the
group {{<hover label="gkv" line="1">}}ec2.aws.upbound.io{{</hover>}}
group {{<hover label="gkv" line="1">}}ec2.aws.m.upbound.io{{</hover>}}
```yaml {label="gkv",copy-lines="none"}
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
```
<!-- vale off -->
### deletionPolicy
<!-- vale on -->
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.
#### Interaction with management policies
The [management policy](#managementpolicies) takes precedence over the
`deletionPolicy` when:
<!-- vale write-good.Passive = NO -->
- The related management policy alpha feature is enabled.
<!-- vale write-good.Passive = YES -->
- The resource configures a management policy other than the default value.
See the table below for more details.
{{< table "table table-sm table-hover">}}
| managementPolicies | deletionPolicy | result |
|-----------------------------|------------------|---------|
| "*" (default) | Delete (default) | Delete |
| "*" (default) | Orphan | Orphan |
| contains "Delete" | Delete (default) | Delete |
| contains "Delete" | Orphan | Delete |
| doesn't contain "Delete" | Delete (default) | Orphan |
| doesn't contain "Delete" | Orphan | Orphan |
{{< /table >}}
<!-- vale off -->
### forProvider
<!-- vale on -->
@ -100,7 +68,7 @@ Refer to the documentation of your specific Provider for details.
```yaml {label="forProvider",copy-lines="none"}
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
# Removed for brevity
spec:
@ -143,7 +111,7 @@ To match the VPC by name, use the external name. For example, creating a Subnet
managed resource attached to this VPC.
```yaml {copy-lines="none"}
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Subnet
spec:
forProvider:
@ -169,7 +137,7 @@ To match the VPC by name reference, use the managed resource name. For example,
creating a Subnet managed resource attached to this VPC.
```yaml {copy-lines="none"}
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Subnet
spec:
forProvider:
@ -188,7 +156,7 @@ Subnet resource only matches VPC resources with the label
`my-label: label-value`.
```yaml {copy-lines="none"}
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Subnet
spec:
forProvider:
@ -200,12 +168,15 @@ spec:
##### Matching by controller reference
Matching a controller reference ensures that the matching resource is part of
the same composite resource.
Matching a controller reference ensures that the matching resource has the same
Kubernetes controller reference.
This is useful for matching a resource that's composed by the same composite
resource (XR).
{{<hint "note" >}}
Learn more about composite resources in the
[Composite Resources]({{<ref "./composite-resources">}}) section.
[Composite Resources]({{<ref "../composition/composite-resources">}}) section.
{{</hint >}}
Matching only a controller reference simplifies the matching process without
@ -219,80 +190,6 @@ Composition shares the same label.
Using `matchControllerRef` matches only the VPC created in the same composite
resource that created the `InternetGateway`.
```yaml {label="controller1",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- base:
apiVersion: ec2.aws.upbound.io/v1beta1
kind: VPC
name: my-vpc
spec:
forProvider:
# Removed for brevity
- base:
apiVersion: ec2.aws.upbound.io/v1beta1
kind: InternetGateway
name: my-gateway
spec:
forProvider:
vpcIdSelector:
matchControllerRef: true
```
Resources can match both labels and a controller reference to match a specific
resource in the larger composite resource.
For example, this Composition creates two `VPC` resources, but the
`InternetGateway` must match only one.
Applying a `label` to the second `VPC` allows the `InternetGateway` to match the
label `type: internet` and only match objects in the same composite resource
with `matchControllerRef`.
```yaml {label="controller2",copy-lines="none"}
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: my-first-vpc
base:
apiVersion: ec2.aws.upbound.io/v1beta1
kind: VPC
metadata:
labels:
type: backend
spec:
forProvider:
# Removed for brevity
- name: my-second-vpc
base:
apiVersion: ec2.aws.upbound.io/v1beta1
kind: VPC
metadata:
labels:
type: internet
spec:
forProvider:
# Removed for brevity
- name: my-gateway
base:
apiVersion: ec2.aws.upbound.io/v1beta1
kind: InternetGateway
spec:
forProvider:
vpcIdSelector:
matchControllerRef: true
matchLabels:
type: internet
```
{{<hint "note" >}}
These examples use Function Patch and Transform. Learn more about functions and
Compositions in the [Compositions]({{<ref "./compositions">}}) section.
{{</hint >}}
#### Immutable fields
Some providers don't support changing the fields of some managed resources after
@ -309,8 +206,7 @@ doesn't apply the change. Crossplane never deletes a resource based on a
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`.
resource object is deleted from Kubernetes.
<!-- vale write-good.Passive = YES -->
{{< /hint >}}
@ -376,9 +272,10 @@ Crossplane recommends configuring
{{< /hint >}}
```yaml {label="initProvider",copy-lines="none"}
apiVersion: eks.aws.upbound.io/v1beta1
apiVersion: eks.aws.m.upbound.io/v1beta1
kind: NodeGroup
metadata:
namespace: default
name: sample-eks-ng
spec:
managementPolicies: ["Observe", "Create", "Update", "Delete"]
@ -419,7 +316,7 @@ but not make any changes, set the policies to
{{<hover label="managementPol1" line="4">}}["Create", "Delete", "Observe"]{{</hover>}}.
```yaml {label="managementPol1"}
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Subnet
spec:
managementPolicies: ["Create", "Delete", "Observe"]
@ -445,7 +342,7 @@ Crossplane supports the following policies:
| `Create` | If the external resource doesn't exist, Crossplane creates it based on the managed resource settings. |
| `Delete` | Crossplane can delete the external resource when deleting the managed resource. |
| `LateInitialize` | Crossplane initializes some external resource settings not defined in the `spec.forProvider` of the managed resource. See [the late initialization]({{<ref "./managed-resources#late-initialization" >}}) section for more details. |
| `Observe` | Crossplane only observes the resource and doesn't make any changes. Used for [observe only resources]({{<ref "../guides/import-existing-resources#import-resources-automatically">}}). |
| `Observe` | Crossplane only observes the resource and doesn't make any changes. Used for observe only resources. |
| `Update` | Crossplane changes the external resource when changing the managed resource. |
{{</table >}}
@ -461,7 +358,7 @@ The following is a list of common policy combinations:
| {{<check>}} | | {{<check>}} | {{<check>}} | | Crossplane doesn't delete the external resource when deleting the managed resource. Crossplane doesn't apply changes to the external resource after creation. |
| {{<check>}} | | | {{<check>}} | {{<check>}} | Crossplane doesn't delete the external resource when deleting the managed resource. Crossplane doesn't import any settings from the external resource. |
| {{<check>}} | | | {{<check>}} | | Crossplane creates the external resource but doesn't apply any changes to the external resource or managed resource. Crossplane can't delete the resource. |
| | | | {{<check>}} | | Crossplane only observes a resource. Used for [observe only resources]({{<ref "../guides/import-existing-resources#import-resources-automatically">}}). |
| | | | {{<check>}} | | Crossplane only observes a resource. |
| | | | | | No policy set. An alternative method for [pausing](#paused) a resource. |
{{< /table >}}
@ -470,7 +367,7 @@ The following is a list of common policy combinations:
<!-- vale on -->
The `providerConfigRef` on a managed resource tells the Provider which
[ProviderConfig]({{<ref "./providers#provider-configuration">}}) to
[ProviderConfig]({{<ref "../packages/providers#provider-configuration">}}) to
use when creating the managed resource.
Use a ProviderConfig to define the authentication method to use when
@ -486,7 +383,7 @@ For example, a managed resource references a ProviderConfig named
This matches the {{<hover label="pc" line="4">}}name{{</hover>}} of a ProviderConfig.
```yaml {label="pcref",copy-lines="none"}}
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
@ -495,7 +392,7 @@ spec:
```
```yaml {label="pc"}
apiVersion: aws.crossplane.io/v1beta1
apiVersion: aws.m.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: user-keys
@ -508,16 +405,6 @@ different managed resources to authenticate with different credentials to the
same Provider.
{{< /hint >}}
<!-- vale off -->
### providerRef
<!-- vale on -->
<!-- vale Crossplane.Spelling = NO -->
Crossplane deprecated the `providerRef` field in `crossplane-runtime`
[v0.10.0](https://github.com/crossplane/crossplane-runtime/releases/tag/v0.10.0).
Managed resources using `providerRef`must use [`providerConfigRef`](#providerconfigref).
<!-- vale Crossplane.Spelling = YES -->
<!-- vale off -->
### writeConnectionSecretToRef
<!-- vale on -->
@ -538,7 +425,7 @@ the
field.
```yaml {label="secretname",copy-lines="none"}
apiVersion: database.aws.crossplane.io/v1beta1
apiVersion: database.aws.m.crossplane.io/v1beta1
kind: RDSInstance
metadata:
name: my-rds-instance
@ -568,97 +455,6 @@ The Provider determines the data written to the Secret object. Refer to the
specific Provider documentation for the generated Secret data.
{{< /hint >}}
<!-- vale off -->
### publishConnectionDetailsTo
<!-- vale on -->
The `publishConnectionDetailsTo` field expands on
[`writeConnectionSecretToRef`](#writeconnectionsecrettoref) supporting storing
managed resource information as a Kubernetes Secret object or in an external
secrets store like [HashiCorp Vault](https://www.vaultproject.io/).
Using `publishConnectionDetailsTo` requires enabling Crossplane
External Secrets Stores (ESS). Enable ESS inside a Provider with a
[DeploymentRuntimeConfig]({{<ref "providers#runtime-configuration" >}}) and
in Crossplane with the `--enable-external-secret-stores` argument.
{{< hint "note" >}}
Not all Providers support `publishConnectionDetailsTo`. Check your Provider
documentation for details.
{{< /hint >}}
#### Publish secrets to Kubernetes
To publish the data generated by a managed resource as a Kubernetes Secret
object provide a
{{<hover label="k8secret" line="7">}}publishConnectionDetailsTo.name{{< /hover >}}
```yaml {label="k8secret",copy-lines="none"}
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
# Removed for brevity
publishConnectionDetailsTo:
name: rds-kubernetes-secret
```
Crossplane can apply labels and annotations to the Kubernetes secret as well
using
{{<hover label="k8label" line="8">}}publishConnectionDetailsTo.metadata{{</hover>}}.
```yaml {label="k8label",copy-lines="none"}
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
# Removed for brevity
publishConnectionDetailsTo:
name: rds-kubernetes-secret
metadata:
labels:
label-tag: label-value
annotations:
annotation-tag: annotation-value
```
#### Publish secrets to an external secrets store
Publishing secrets data to an external secret store like
[HashiCorp Vault](https://www.vaultproject.io/) relies on a
{{<hover label="configref" line="8">}}publishConnectionDetailsTo.configRef{{</hover>}}.
The
{{<hover label="configref" line="9">}}configRef.name{{</hover>}} references a
{{<hover label="storeconfig" line="4">}}StoreConfig{{</hover>}}
object.
```yaml {label="configref",copy-lines="none"}
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
# Removed for brevity
publishConnectionDetailsTo:
name: rds-kubernetes-secret
configRef:
name: my-vault-storeconfig
```
```yaml {label="storeconfig",copy-lines="none"}
apiVersion: secrets.crossplane.io/v1alpha1
kind: StoreConfig
metadata:
name: my-vault-storeconfig
# Removed for brevity
```
{{<hint "tip" >}}
Read the
[Vault as an External Secrets Store]({{<ref "../guides/vault-as-secret-store">}})
guide for details on using StoreConfig objects.
{{< /hint >}}
## Annotations
Crossplane applies a standard set of Kubernetes `annotations` to managed
@ -672,7 +468,6 @@ resources.
| `crossplane.io/external-create-succeeded` | The timestamp of when the Provider successfully created the managed resource. |
| `crossplane.io/external-create-failed` | The timestamp of when the Provider failed to create the managed resource. |
| `crossplane.io/paused` | Indicates Crossplane isn't reconciling this resource. Read the [Pause Annotation](#paused) for more details. |
| `crossplane.io/composition-resource-name` | For managed resource created by a Composition, this is the Composition's `resources.name` value. |
{{</table >}}
### Naming external resources
@ -685,9 +480,10 @@ the name `my-rds-instance` as an external resource inside the Provider's
environment.
```yaml {label="external-name",copy-lines="none"}
apiVersion: database.aws.crossplane.io/v1beta1
apiVersion: database.aws.m.crossplane.io/v1beta1
kind: RDSInstance
metadata:
namespace: default
name: my-rds-instance
```
@ -707,9 +503,10 @@ the name {{<hover label="custom-name" line="5">}}my-custom-name{{</hover >}}
for the external resource inside AWS.
```yaml {label="custom-name",copy-lines="none"}
apiVersion: database.aws.crossplane.io/v1beta1
apiVersion: database.aws.m.crossplane.io/v1beta1
kind: RDSInstance
metadata:
namespace: default
name: my-rds-instance
annotations:
crossplane.io/external-name: my-custom-name
@ -746,9 +543,10 @@ AWS VPC resource:
```yaml {label="creation" copy-lines="2-9"}
$ kubectl get -o yaml vpc my-vpc
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: VPC
metadata:
namespace: default
name: my-vpc
annotations:
crossplane.io/external-name: vpc-1234567890abcdef0
@ -803,7 +601,7 @@ kubectl describe queue my-sqs-queue
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning CannotInitializeManagedResource 29m (x19 over 19h) managed/queue.sqs.aws.crossplane.io cannot determine creation result - remove the crossplane.io/external-create-pending annotation if it is safe to proceed
Warning CannotInitializeManagedResource 29m (x19 over 19h) managed/queue.sqs.aws.m.crossplane.io cannot determine creation result - remove the crossplane.io/external-create-pending annotation if it is safe to proceed
```
Providers use the creation annotations to detect that they might have leaked a
@ -876,9 +674,10 @@ Only the value `"true"` pauses reconciliation.
{{< /hint >}}
```yaml {label="pause"}
apiVersion: ec2.aws.upbound.io/v1beta1
apiVersion: ec2.aws.m.upbound.io/v1beta1
kind: Instance
metadata:
namespace: default
name: my-rds-instance
annotations:
crossplane.io/paused: "true"

View File

@ -1,14 +1,13 @@
---
title: Usages
weight: 95
weight: 30
state: beta
alphaVersion: "1.14"
betaVersion: "1.19"
description: "Usage defines a usage relationship for Managed Resources or Composites"
description: "Usage indicates a resource is in use"
---
A `Usage` is a Crossplane resource that defines a usage relationship for a
Managed Resource or a Composite Resource. Two main use cases for the Usages are
A `Usage` indicates a resource is in use. Two main use cases for Usages are
as follows:
1. Protecting a resource from accidental deletion.
@ -25,7 +24,7 @@ Usages are a beta feature. Beta features are enabled by default.
<!-- vale write-good.Passive = YES -->
Disable `Usage` support by
[changing the Crossplane pod setting]({{<ref "./pods#change-pod-settings">}})
[changing the Crossplane pod setting]({{<ref "../guides/pods#change-pod-settings">}})
and setting
{{<hover label="deployment" line="12">}}--enable-usages=false{{</hover>}}
argument.
@ -47,7 +46,7 @@ spec:
{{<hint "tip" >}}
The [Crossplane install guide]({{<ref "../software/install#feature-flags">}})
The [Crossplane install guide]({{<ref "../get-started/install#feature-flags">}})
describes enabling feature flags like
{{<hover label="deployment" line="12">}}\-\-enable-usages{{</hover>}}
with Helm.
@ -68,18 +67,6 @@ defines the using resource. Both fields are optional, but at least one of them
must be provided.
<!-- vale write-good.Passive = YES -->
{{<hint "important" >}}
<!-- vale write-good.Passive = NO -->
Usage relationships can be defined between `Managed Resources` and `Composites`.
<!-- vale write-good.TooWordy = NO -->
However, a `Composite` as the using resource (`spec.by`) would be ineffective
unless the `compositeDeletePolicy` `Foreground` is used because it wouldn't block
deletion of its child resources before its own deletion with the default deletion
policy `Background`.
<!-- vale write-good.TooWordy = YES -->
<!-- vale write-good.Passive = YES -->
{{< /hint >}}
### Usage for deletion protection
The following example prevents the deletion of the
@ -88,13 +75,14 @@ any deletion request with the
{{<hover label="protect" line="11">}}reason{{</hover>}} defined.
```yaml {label="protect"}
apiVersion: apiextensions.crossplane.io/v1beta1
apiVersion: protection.crossplane.io/v1beta1
kind: Usage
metadata:
namespace: default
name: protect-production-database
spec:
of:
apiVersion: rds.aws.upbound.io/v1beta1
apiVersion: rds.m.aws.m.upbound.io/v1beta1
kind: Instance
resourceRef:
name: my-database
@ -109,18 +97,19 @@ any deletion request before the deletion of
{{<hover label="order" line="15">}}my-prometheus-chart{{</hover>}} resource.
```yaml {label="order"}
apiVersion: apiextensions.crossplane.io/v1beta1
apiVersion: protection.crossplane.io/v1beta1
kind: Usage
metadata:
namespace: default
name: release-uses-cluster
spec:
of:
apiVersion: eks.upbound.io/v1beta1
apiVersion: eks.m.upbound.io/v1beta1
kind: Cluster
resourceRef:
name: my-cluster
by:
apiVersion: helm.crossplane.io/v1beta1
apiVersion: helm.m.crossplane.io/v1beta1
kind: Release
resourceRef:
name: my-prometheus-chart
@ -135,20 +124,21 @@ This enables using {{<hover label="selectors" line="12">}}labels{{</hover>}} or
to define resource instead of providing the resource name.
```yaml {label="selectors"}
apiVersion: apiextensions.crossplane.io/v1beta1
apiVersion: protection.crossplane.io/v1beta1
kind: Usage
metadata:
namespace: default
name: release-uses-cluster
spec:
of:
apiVersion: eks.upbound.io/v1beta1
apiVersion: eks.m.upbound.io/v1beta1
kind: Cluster
resourceSelector:
matchControllerRef: false # default, and could be omitted
matchLabels:
foo: bar
by:
apiVersion: helm.crossplane.io/v1beta1
apiVersion: helm.m.crossplane.io/v1beta1
kind: Release
resourceSelector:
matchLabels:
@ -169,13 +159,14 @@ random resource is selected from the list of matched resources.
{{< /hint >}}
```yaml {label="selectors-resolved"}
apiVersion: apiextensions.crossplane.io/v1beta1
apiVersion: protection.crossplane.io/v1beta1
kind: Usage
metadata:
namespace: default
name: release-uses-cluster
spec:
of:
apiVersion: eks.upbound.io/v1beta1
apiVersion: eks.m.upbound.io/v1beta1
kind: Cluster
resourceRef:
name: my-cluster
@ -183,7 +174,7 @@ spec:
matchLabels:
foo: bar
by:
apiVersion: helm.crossplane.io/v1beta1
apiVersion: helm.m.crossplane.io/v1beta1
kind: Release
resourceRef:
name: my-cluster
@ -200,19 +191,20 @@ Replaying the blocked deletion is possible by setting the
{{<hover label="replay" line="6">}}replayDeletion{{</hover>}} field to `true`.
```yaml {label="replay"}
apiVersion: apiextensions.crossplane.io/v1beta1
apiVersion: protection.crossplane.io/v1beta1
kind: Usage
metadata:
namespace: default
name: release-uses-cluster
spec:
replayDeletion: true
of:
apiVersion: eks.upbound.io/v1beta1
apiVersion: eks.m.upbound.io/v1beta1
kind: Cluster
resourceRef:
name: my-cluster
by:
apiVersion: helm.crossplane.io/v1beta1
apiVersion: helm.m.crossplane.io/v1beta1
kind: Release
resourceRef:
name: my-prometheus-chart
@ -235,51 +227,6 @@ resources in a Composition. The Usages support
in selectors to ensures that the matching resource is in the same composite
resource in the same way as [cross-resource referencing]({{<ref "./managed-resources#referencing-other-resources" >}}).
The following example shows a Composition that defines a deletion ordering
between a `Cluster` and a `Release` resource. The `Usage` blocks deletion of
the `Cluster` resource until the `Release` resource is successfully deleted.
```yaml {label="composition"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
spec:
mode: Pipeline
pipeline:
- step: patch-and-transform
functionRef:
name: function-patch-and-transform
input:
apiVersion: pt.fn.crossplane.io/v1beta1
kind: Resources
resources:
- name: cluster
base:
apiVersion: container.gcp.upbound.io/v1beta1
kind: Cluster
# Removed for brevity
- name: release
base:
apiVersion: helm.crossplane.io/v1beta1
kind: Release
# Removed for brevity
- name: release-uses-cluster
base:
apiVersion: apiextensions.crossplane.io/v1beta1
kind: Usage
spec:
replayDeletion: true
of:
apiVersion: container.gcp.upbound.io/v1beta1
kind: Cluster
resourceSelector:
matchControllerRef: true
by:
apiVersion: helm.crossplane.io/v1beta1
kind: Release
resourceSelector:
matchControllerRef: true
```
{{<hint "tip" >}}
<!-- vale write-good.Passive = NO -->
@ -288,8 +235,55 @@ When there are multiple resources of same type in a Composition, the
uniquely identify the resource in use or the using one. This could be
accomplished by using extra labels and combining
{{<hover label="composition" line="24">}}matchControllerRef{{</hover>}}
with a `matchLabels` selector. Another alternative is patching `resourceRef.name`
directly with the help of `ToCompositeFieldPath` and `FromCompositeFieldPath`
or `ToEnvironmentFieldPath` and `FromEnvironmentFieldPath` type patches.
with a `matchLabels` selector.
<!-- vale write-good.Passive = YES -->
{{< /hint >}}
{{< /hint >}}
## Usage across namespaces
A `Usage` with `of` and `by` represents a usage relationship between two
resources in the same namespace as the `Usage` by default.
A `Usage` can represent a usage relationship between a `by` resource in the same
namespace as the `Usage` and an `of` resource in a different namespace.
To use a resource in a different namespace, specify the `namespace` in the `of`
`resourceRef` or `resourceSelector`.
```yaml {label="order"}
apiVersion: protection.crossplane.io/v1beta1
kind: Usage
metadata:
namespace: default
name: release-uses-cluster
spec:
of:
apiVersion: eks.m.upbound.io/v1beta1
kind: Cluster
resourceRef:
namespace: cluster-infra
name: my-cluster
by:
apiVersion: helm.m.crossplane.io/v1beta1
kind: Release
resourceRef:
name: my-prometheus-chart
```
## ClusterUsages
Use a `ClusterUsage` to protect cluster scoped resources.
```yaml {label="protect"}
apiVersion: protection.crossplane.io/v1beta1
kind: ClusterUsage
metadata:
name: protect-important-crd
spec:
of:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
resourceRef:
name: importantresources.example.crossplane.io
reason: "Very important CRD - should never be deleted!"
```

View File

@ -0,0 +1,5 @@
---
title: Packages
weight: 53
description: Understand Crossplane's core components
---

View File

@ -1,48 +1,47 @@
---
title: Configuration Packages
title: Configurations
description: "Packages combine multiple Crossplane resources into a single, portable, OCI image."
altTitle: "Crossplane Packages"
weight: 200
---
A _Configuration_ package is an
A _Configuration_ package is an
[OCI container image](https://opencontainers.org/) containing a collection of
[Compositions]({{<ref "./compositions" >}}),
[Composite Resource Definitions]({{<ref "./composite-resource-definitions" >}})
and any required [Providers]({{<ref "./providers">}}) or
[Functions]({{<ref "./compositions" >}}).
[Compositions]({{<ref "../composition/compositions" >}}),
[Composite Resource Definitions]({{<ref "../composition/composite-resource-definitions" >}})
and any required [Providers]({{<ref "./providers">}}) or
[Functions]({{<ref "./functions" >}}).
Configuration packages make your Crossplane configuration fully portable.
Configuration packages make your Crossplane configuration fully portable.
{{<hint "important" >}}
Crossplane [Providers]({{<ref "./providers">}}) and
[Functions]({{<ref "./compositions">}}) are also Crossplane packages.
Crossplane Providers and Functions are also Crossplane packages.
This document describes how to install and manage configuration packages.
This document describes how to install and manage configuration packages.
Refer to the
[Provider]({{<ref "./providers">}}) and
[Composition Functions]({{<ref "./compositions">}}) chapters for
details on their usage of packages.
Refer to the
[Provider]({{<ref "./providers">}}) and
[Functions]({{<ref "./functions">}}) chapters for
details on their usage of packages.
{{< /hint >}}
## Install a Configuration
Install a Configuration with a Crossplane
{{<hover line="2" label="install">}}Configuration{{</hover>}} object by setting
Install a Configuration with a Crossplane
{{<hover line="2" label="install">}}Configuration{{</hover>}} object by setting
the {{<hover line="6" label="install">}}spec.package{{</hover>}} value to the
location of the configuration package.
{{< hint "important" >}}
Beginning with Crossplane version 1.20.0 Crossplane uses the [crossplane-contrib](https://github.com/orgs/crossplane-contrib/packages) GitHub Container Registry at `xpkg.crossplane.io` by default for downloading and
installing packages.
installing packages.
Specify the full domain name with the `package` or change the default Crossplane
registry with the `--registry` flag on the [Crossplane pod]({{<ref "./pods">}})
registry with the `--registry` flag on the [Crossplane pod]({{<ref "../guides/pods">}})
{{< /hint >}}
For example to install the
[Getting Started Configuration](https://github.com/crossplane-contrib/configuration-quickstart),
For example to install the
[Getting Started Configuration](https://github.com/crossplane-contrib/configuration-quickstart),
```yaml {label="install"}
apiVersion: pkg.crossplane.io/v1
@ -68,7 +67,7 @@ spec:
{{< /hint >}}
Crossplane installs the Compositions, Composite Resource Definitions and
Providers listed in the Configuration.
Providers listed in the Configuration.
### Install with Helm
@ -93,7 +92,7 @@ crossplane-stable/crossplane \
Installing Crossplane packages offline requires a local container registry, such as
[Harbor](https://goharbor.io/) to host the packages. Crossplane only
supports installing packages from a container registry.
supports installing packages from a container registry.
Crossplane doesn't support installing packages directly from Kubernetes
volumes.
@ -101,15 +100,15 @@ volumes.
### Installation options
Configurations support multiple options to change configuration package related
settings.
settings.
#### Configuration revisions
When installing a newer version of an existing Configuration Crossplane creates
a new configuration revision.
a new configuration revision.
View the configuration revisions with
View the configuration revisions with
{{<hover label="rev" line="1">}}kubectl get configurationrevisions{{</hover>}}.
```shell {label="rev",copy-lines="1"}
@ -120,20 +119,20 @@ platform-ref-aws-3ac761211893 True 1 xpkg.crossplane.io/crosspla
```
Only a single revision is active at a time. The active revision determines the
available resources, including Compositions and Composite Resource Definitions.
available resources, including Compositions and Composite Resource Definitions.
By default Crossplane keeps only a single _Inactive_ revision.
Change the number of revisions Crossplane maintains with a Configuration package
{{<hover label="revHistory" line="6">}}revisionHistoryLimit{{</hover>}}.
Change the number of revisions Crossplane maintains with a Configuration package
{{<hover label="revHistory" line="6">}}revisionHistoryLimit{{</hover>}}.
The {{<hover label="revHistory" line="6">}}revisionHistoryLimit{{</hover>}}
field is an integer.
The default value is `1`.
Disable storing revisions by setting
field is an integer.
The default value is `1`.
Disable storing revisions by setting
{{<hover label="revHistory" line="6">}}revisionHistoryLimit{{</hover>}} to `0`.
For example, to change the default setting and store 10 revisions use
For example, to change the default setting and store 10 revisions use
{{<hover label="revHistory" line="6">}}revisionHistoryLimit: 10{{</hover>}}.
```yaml {label="revHistory"}
@ -152,26 +151,26 @@ Use a {{<hover label="pullpolicy" line="6">}}packagePullPolicy{{</hover>}} to
define when Crossplane should download the Configuration package to the local
Crossplane package cache.
The `packagePullPolicy` options are:
The `packagePullPolicy` options are:
* `IfNotPresent` - (**default**) Only download the package if it isn't in the cache.
* `Always` - Check for new packages every minute and download any matching
package that isn't in the cache.
* `Never` - Never download the package. Packages are only installed from the
local package cache.
local package cache.
{{<hint "tip" >}}
The Crossplane
The Crossplane
{{<hover label="pullpolicy" line="6">}}packagePullPolicy{{</hover>}} works
like the Kubernetes container image
[image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy).
like the Kubernetes container image
[image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy).
Crossplane supports the use of tags and package digest hashes like
Kubernetes images.
Kubernetes images.
{{< /hint >}}
For example, to `Always` download a given Configuration package use the
For example, to `Always` download a given Configuration package use the
{{<hover label="pullpolicy" line="6">}}packagePullPolicy: Always{{</hover>}}
configuration.
configuration.
```yaml {label="pullpolicy",copy-lines="6"}
apiVersion: pkg.crossplane.io/v1
@ -186,20 +185,20 @@ spec:
#### Revision activation policy
The `Active` package revision
is the package controller actively reconciling resources.
is the package controller actively reconciling resources.
By default Crossplane sets the most recently installed package revision as
By default Crossplane sets the most recently installed package revision as
`Active`.
Control the Configuration upgrade behavior with a
{{<hover label="revision" line="6">}}revisionActivationPolicy{{</hover>}}.
The {{<hover label="revision" line="6">}}revisionActivationPolicy{{</hover>}}
The {{<hover label="revision" line="6">}}revisionActivationPolicy{{</hover>}}
options are:
* `Automatic` - (**default**) Automatically activate the last installed configuration.
* `Manual` - Don't automatically activate a configuration.
* `Manual` - Don't automatically activate a configuration.
For example, to change the upgrade behavior to require manual upgrades, set
For example, to change the upgrade behavior to require manual upgrades, set
{{<hover label="revision" line="6">}}revisionActivationPolicy: Manual{{</hover>}}.
```yaml {label="revision"}
@ -215,14 +214,14 @@ spec:
#### Install a Configuration from a private registry
Like Kubernetes uses `imagePullSecrets` to
[install images from private registries](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/),
Crossplane uses `packagePullSecrets` to install Configuration packages from a
private registry.
Like Kubernetes uses `imagePullSecrets` to
[install images from private registries](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/),
Crossplane uses `packagePullSecrets` to install Configuration packages from a
private registry.
Use {{<hover label="pps" line="6">}}packagePullSecrets{{</hover>}} to provide a
Kubernetes secret to use for authentication when downloading a Configuration
package.
Kubernetes secret to use for authentication when downloading a Configuration
package.
{{<hint "important" >}}
The Kubernetes secret must be in the same namespace as Crossplane.
@ -232,7 +231,7 @@ The {{<hover label="pps" line="6">}}packagePullSecrets{{</hover>}} is a list of
secrets.
For example, to use the secret named
{{<hover label="pps" line="6">}}example-secret{{</hover>}} configure a
{{<hover label="pps" line="6">}}example-secret{{</hover>}} configure a
{{<hover label="pps" line="6">}}packagePullSecrets{{</hover>}}.
```yaml {label="pps"}
@ -241,7 +240,7 @@ kind: Configuration
metadata:
name: platform-ref-aws
spec:
packagePullSecrets:
packagePullSecrets:
- name: example-secret
# Removed for brevity
```
@ -249,19 +248,19 @@ spec:
#### Ignore dependencies
By default Crossplane installs any [dependencies](#manage-dependencies) listed
in a Configuration package.
in a Configuration package.
Crossplane can ignore a Configuration package's dependencies with
Crossplane can ignore a Configuration package's dependencies with
{{<hover label="pkgDep" line="6" >}}skipDependencyResolution{{</hover>}}.
{{< hint "warning" >}}
Most Configurations include dependencies for the required Providers.
Most Configurations include dependencies for the required Providers.
If a Configuration ignores dependencies, the required Providers must be
If a Configuration ignores dependencies, the required Providers must be
manually installed.
{{< /hint >}}
For example, to disable dependency resolution configure
For example, to disable dependency resolution configure
{{<hover label="pkgDep" line="6" >}}skipDependencyResolution: true{{</hover>}}.
```yaml {label="pkgDep"}
@ -285,31 +284,31 @@ installations. Suppose configuration A, which depends on package X with the
constraint`>=v0.0.0`, is installed on the control plane. In this case, the package
manager installs the latest version of package X, such as `v3.0.0`. Later, you decide
to install configuration B, which depends on package X with the constraint `<=v2.0.0`.
Since version `v2.0.0` satisfies both conditions, package X must be downgraded to
Since version `v2.0.0`satisfies both conditions, package X must be downgraded to
allow the installation of configuration B which is disabled by default.
Automatic dependency version downgrades is also an alpha feature that can be
enabled with the `--enable-dependency-version-downgrades` flag. Downgrading a
package can cause unexpected behavior, therefore, this option is disabled by
default. After enabling this option, the package manager will automatically
downgrade a package's dependency version to the maximum valid version that
satisfies the constraints.
For enabling automatic dependency version downgrades, there is a configuration
option as a helm value `packageManager.enableAutomaticDependencyDowngrade=true`.
Downgrading a package can cause unexpected behavior, therefore, this
option is disabled by default. After enabling this option, the package manager will
automatically downgrade a package's dependency version to the maximum valid version
that satisfies the constraints.
{{<hint "note" >}}
This configuration requires the `--enable-dependency-version-upgrades` flag.
Please check the
[configuration options]({{<ref "../software/install#customize-the-crossplane-helm-chart">}})
[configuration options]({{<ref "../get-started/install#customize-the-crossplane-helm-chart">}})
and
[feature flags]({{<ref "../software/install#feature-flags">}})
[feature flags]({{<ref "../get-started/install#feature-flags">}})
are available in the
[Crossplane Install]({{<ref "../software/install">}})
[Crossplane Install]({{<ref "../get-started/install">}})
section for more details.
{{</hint >}}
{{<hint "important" >}}
Enabling automatic dependency downgrades may have unintended consequences, such as:
1) CRDs missing in the downgraded version, possibly leaving orphaned MRs without
1) CRDs missing in the downgraded version, possibly leaving orphaned MRs without
controllers to reconcile them.
2) Loss of data if downgraded CRD versions omit fields that were set before.
3) Changes in the CRD storage version, which may prevent package version update.
@ -317,15 +316,15 @@ controllers to reconcile them.
#### Ignore Crossplane version requirements
A Configuration package may require a specific or minimum Crossplane version
before installing. By default, Crossplane doesn't install a Configuration if
the Crossplane version doesn't meet the required version.
A Configuration package may require a specific or minimum Crossplane version
before installing. By default, Crossplane doesn't install a Configuration if
the Crossplane version doesn't meet the required version.
Crossplane can ignore the required version with
Crossplane can ignore the required version with
{{<hover label="xpVer" line="6">}}ignoreCrossplaneConstraints{{</hover>}}.
For example, to install a Configuration package into an unsupported Crossplane
version, configure
version, configure
{{<hover label="xpVer" line="6">}}ignoreCrossplaneConstraints: true{{</hover>}}.
```yaml {label="xpVer"}
@ -341,7 +340,7 @@ spec:
### Verify a Configuration
Verify a Configuration with
Verify a Configuration with
{{<hover label="verify" line="1">}}kubectl get configuration{{</hover >}}.
A working configuration reports `Installed` and `Healthy` as `True`.
@ -355,10 +354,10 @@ platform-ref-aws True True xpkg.crossplane.io/crossplane-contrib/c
### Manage dependencies
Configuration packages may include dependencies on other packages including
Functions, Providers or other Configurations.
Functions, Providers or other Configurations.
If Crossplane can't meet the dependencies of a Configuration the Configuration
reports `HEALTHY` as `False`.
reports `HEALTHY` as `False`.
For example, this installation of the Getting Started Configuration is
`HEALTHY: False`.
@ -369,7 +368,7 @@ NAME INSTALLED HEALTHY PACKAGE
platform-ref-aws True False xpkg.crossplane.io/crossplane-contrib/configuration-quickstart:v0.1.0 71s
```
To see more information on why the Configuration isn't `HEALTHY` use
To see more information on why the Configuration isn't `HEALTHY` use
{{<hover label="depend" line="1">}}kubectl describe configurationrevisions{{</hover>}}.
```yaml {copy-lines="1",label="depend"}
@ -396,64 +395,64 @@ Events:
Warning LintPackage 29s (x2 over 29s) packages/configurationrevision.pkg.crossplane.io incompatible Crossplane version: package isn't compatible with Crossplane version (v1.12.0)
```
The {{<hover label="depend" line="18">}}Events{{</hover>}} show a
The {{<hover label="depend" line="18">}}Events{{</hover>}} show a
{{<hover label="depend" line="21">}}Warning{{</hover>}} with a message that the
current version of Crossplane doesn't meet the Configuration package
current version of Crossplane doesn't meet the Configuration package
requirements.
## Create a Configuration
Crossplane Configuration packages are
Crossplane Configuration packages are
[OCI container images](https://opencontainers.org/) containing one or more YAML
files.
files.
{{<hint "important" >}}
Configuration packages are fully OCI compliant. Any tool that builds OCI images
can build Configuration packages.
can build Configuration packages.
It's strongly recommended to use the Crossplane command-line tool to
provide error checking and formatting to Crossplane package builds.
provide error checking and formatting to Crossplane package builds.
Read the
[Crossplane package specification](https://github.com/crossplane/crossplane/blob/main/contributing/specifications/xpkg.md)
Read the
[Crossplane package specification](https://github.com/crossplane/crossplane/blob/main/contributing/specifications/xpkg.md)
for package requirements when building packages with third-party tools.
{{</hint >}}
A Configuration package requires a `crossplane.yaml` file and may include
Composition and CompositeResourceDefinition files.
Composition and CompositeResourceDefinition files.
<!-- vale Google.Headings = NO -->
### The crossplane.yaml file
<!-- vale Google.Headings = YES -->
To build a Configuration package using the Crossplane CLI, create a file
named
{{<hover label="cfgMeta" line="1">}}crossplane.yaml{{</hover>}}.
The
named
{{<hover label="cfgMeta" line="1">}}crossplane.yaml{{</hover>}}.
The
{{<hover label="cfgMeta" line="1">}}crossplane.yaml{{</hover>}}
file defines the requirements and name of the
file defines the requirements and name of the
Configuration.
{{<hint "important" >}}
The Crossplane CLI only supports a file named `crossplane.yaml`.
{{< /hint >}}
Configuration package uses the
Configuration package uses the
{{<hover label="cfgMeta" line="2">}}meta.pkg.crossplane.io{{</hover>}}
Crossplane API group.
Specify any other Configurations, Functions or Providers in the
{{<hover label="cfgMeta" line="7">}}dependsOn{{</hover>}} list.
Optionally, you can require a specific or minimum package version with the
Specify any other Configurations, Functions or Providers in the
{{<hover label="cfgMeta" line="7">}}dependsOn{{</hover>}} list.
Optionally, you can require a specific or minimum package version with the
{{<hover label="cfgMeta" line="9">}}version{{</hover>}} option.
You can also define a specific or minimum version of Crossplane for this
Configuration with the
{{<hover label="cfgMeta" line="11">}}crossplane.version{{</hover>}} option.
Configuration with the
{{<hover label="cfgMeta" line="11">}}crossplane.version{{</hover>}} option.
{{<hint "note" >}}
Defining the {{<hover label="cfgMeta" line="10">}}crossplane{{</hover>}} object
or required versions is optional.
Defining the {{<hover label="cfgMeta" line="10">}}crossplane{{</hover>}} object
or required versions is optional.
{{< /hint >}}
```yaml {label="cfgMeta",copy-lines="all"}
@ -474,8 +473,8 @@ spec:
### Build the package
Create the package using the
[Crossplane CLI]({{<ref "../cli">}}) command
Create the package using the
[Crossplane CLI]({{<ref "../cli">}}) command
`crossplane xpkg build --package-root=<directory>`.
Where the `<directory>` is the directory containing the `crossplane.yaml` file
@ -485,19 +484,19 @@ The CLI recursively searches for `.yml` or `.yaml` files in the directory to
include in the package.
{{<hint "important" >}}
You must ignore any other YAML files with `--ignore=<file_list>`.
You must ignore any other YAML files with `--ignore=<file_list>`.
For
example, `crossplane xpkg build --package-root=test-directory --ignore=".tmp/*"`.
Including YAML files that aren't Compositions or CompositeResourceDefinitions,
including Claims isn't supported.
Including YAML files that aren't Compositions or CompositeResourceDefinitions
isn't supported.
{{</hint >}}
By default, Crossplane creates a `.xpkg` file of the Configuration name and
By default, Crossplane creates a `.xpkg` file of the Configuration name and
a SHA-256 hash of the package contents.
For example, a {{<hover label="xpkgName" line="2">}}Configuration{{</hover>}}
named {{<hover label="xpkgName" line="4">}}test-configuration{{</hover>}}.
named {{<hover label="xpkgName" line="4">}}test-configuration{{</hover>}}.
The
Crossplane CLI builds a package named `test-configuration-e8c244f6bf21.xpkg`.

View File

@ -0,0 +1,79 @@
---
title: Functions
weight: 100
description: "Functions extend Crossplane with new ways to configure composition"
---
Functions extend Crossplane with new ways to configure
[composition]({{<ref "../composition">}}).
You can use different _composition functions_ to configure what Crossplane does
when someone creates or updates a
[composite resource (XR)]({{<ref "../composition/composite-resources">}}).
{{<hint "important">}}
This page is a work in progress.
Functions are packages, like [Providers]({{<ref "./providers">}}) and
[Configurations]({{<ref "./configurations">}}). Their APIs are similar. You
install and configure them the same way as a provider.
Read the [composition]({{<ref "../composition/compositions">}}) documentation to
learn how to use functions in a composition.
{{</hint>}}
## Install a Function
Install a Function with a Crossplane
{{<hover label="install" line="2">}}Function{{</hover >}} object setting the
{{<hover label="install" line="6">}}spec.package{{</hover >}} value to the
location of the function package.
{{< hint "important" >}}
Beginning with Crossplane version 1.20.0 Crossplane uses the [crossplane-contrib](https://github.com/orgs/crossplane-contrib/packages) GitHub Container Registry at `xpkg.crossplane.io` by default for downloading and
installing packages.
Specify the full domain name with the `package` or change the default Crossplane
registry with the `--registry` flag on the [Crossplane pod]({{<ref "../guides/pods">}})
{{< /hint >}}
For example, to install the
[patch and transform function](https://github.com/crossplane-contrib/function-patch-and-transform),
```yaml {label="install"}
apiVersion: pkg.crossplane.io/v1
kind: Function
metadata:
name: crossplane-contrib-function-patch-and-transform
spec:
package: xpkg.crossplane.io/crossplane-contrib/function-patch-and-transform:v0.8.2
```
By default, the Function pod installs in the same namespace as Crossplane
(`crossplane-system`).
{{<hint "note" >}}
Functions are part of the
{{<hover label="install" line="1">}}pkg.crossplane.io{{</hover>}} group.
The {{<hover label="meta-pkg" line="1">}}meta.pkg.crossplane.io{{</hover>}}
group is for creating Function packages.
Instructions on building Functions are outside of the scope of this
document.
Read the Crossplane contributing
[Function Development Guide](https://github.com/crossplane/crossplane/blob/main/contributing/guide-provider-development.md)
for more information.
For information on the specification of Function packages read the
[Crossplane Function Package specification](https://github.com/crossplane/crossplane/blob/main/contributing/specifications/xpkg.md#provider-package-requirements).
```yaml {label="meta-pkg"}
apiVersion: meta.pkg.crossplane.io/v1
kind: Function
metadata:
name: provider-aws
spec:
# Removed for brevity
```
{{</hint >}}

View File

@ -10,35 +10,6 @@ description: "Image Configs is an API for centralized control of the configurati
Crossplane package images. It allows you to configure package manager behavior
for images globally, without needing to be referenced by other objects.
## Matching image references
`spec.matchImages` is a list of image references that the `ImageConfig` applies
to. Each item in the list specifies the type and configuration of the image
reference to match. The only supported type is `Prefix`, which matches the
prefix of the image reference. No wildcards are supported. The `type` defaults
to `Prefix` and can be omitted.
When there are multiple `ImageConfigs` matching an image reference, the one with
the longest matching prefix is selected. If there are multiple `ImageConfigs`
with the same longest matching prefix, one of them is selected
arbitrarily. Please note that this situation occurs only if there are
overlapping prefixes in the `matchImages` lists of different `ImageConfig`
resources, which should be avoided.
The default registry isn't taken into account for `ImageConfig` matching. That
is, an `ImageConfig` matching the prefix `xpkg.crossplane.io/crossplane-contrib`
doesn't match the following provider, even if the default registry is
`xpkg.crossplane.io`:
```yaml
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-nop
spec:
package: crossplane-contrib/provider-nop:v0.4.0
```
## Configuring a pull secret
You can use `ImageConfig` to inject a pull secret into the Crossplane package
@ -75,6 +46,43 @@ following command:
kubectl -n crossplane-system create secret docker-registry acme-registry-credentials --docker-server=registry1.com --docker-username=<user> --docker-password=<password>
```
### Matching image references
`spec.matchImages` is a list of image references that the `ImageConfig` applies
to. Each item in the list specifies the type and configuration of the image
reference to match. The only supported type is `Prefix`, which matches the
prefix of the image reference. No wildcards are supported. The `type` defaults
to `Prefix` and can be omitted.
When there are multiple `ImageConfigs` matching an image reference, the one
with the longest matching prefix is selected. If there are multiple
`ImageConfigs` with the same longest matching prefix, one of them is selected
arbitrarily. Please note that this situation occurs only if there are
overlapping prefixes in the `matchImages` lists of different `ImageConfig`
resources, which should be avoided.
### Debugging
When the package manager selects an `ImageConfig` for a package, it throws an
event with the reason `ImageConfigSelection` and the name of the selected
`ImageConfig` and injected pull secret. You can find these events both on the
package and package revision resources.
For example, the following event indicates that the `ImageConfig` named
`acme-packages` was selected for the configuration named `acme-configuration-foo`:
```shell
$ kubectl describe configuration acme-configuration-foo
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ImageConfigSelection 45s packages/configuration.pkg.crossplane.io Selected pullSecret "acme-registry-credentials" from ImageConfig "acme-packages" for registry authentication
```
If you can't find the expected event, ensure the prefix of the image reference
matches the `matchImages` list of any `ImageConfig` resources in the cluster.
## Configuring signature verification
{{<hint "important" >}}
@ -130,7 +138,7 @@ contains the configuration for verifying the attestations of the images.
The `ImageConfig` API follows the same API shape as [Policy Controller](https://docs.sigstore.dev/policy-controller/overview/)
from [Sigstore](https://docs.sigstore.dev/). Crossplane initially supports a
subset of the Policy Controller configuration options which can be found in the
[API reference](https://docs.crossplane.io/master/api/#ImageConfig-spec-verification-cosign)
[API reference]({{<ref "../api/#ImageConfig-spec-verification-cosign">}})
for the `ImageConfig` resource together with their descriptions.
When multiple authorities are provided, the package manager verifies the
@ -203,129 +211,4 @@ If you can't see this condition on the package revision resource, namely
`ProviderRevision`, `ConfigurationRevision`, or `FunctionRevision`, ensure that
the feature is enabled.
## Rewriting image paths
You can use an `ImageConfig` to pull package images from an alternative location
such as a private registry. `spec.rewriteImages` specifies how to rewrite the
paths of matched images.
Only prefix replacement is supported. The prefix specified in
`spec.rewriteImage.prefix` replaces the matched prefix from `matchImages`. For
example, the following `ImageConfig` replaces `xpkg.crossplane.io` with
`registry1.com` for any image with the prefix `xpkg.crossplane.io`.
```yaml
apiVersion: pkg.crossplane.io/v1beta1
kind: ImageConfig
metadata:
name: private-registry-rewrite
spec:
matchImages:
- prefix: xpkg.crossplane.io
rewriteImage:
prefix: registry1.com
```
In this example, installing the provider package
`xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.4.0` will result in the
package manager pulling the provider from
`registry1.com/crossplane-contrib/provider-nop:v0.4.0`.
Rewriting image paths via `ImageConfig` is useful when mirroring packages to a
private registry, because it allows a package and all its dependencies to be
pulled from the same registry. For example, the provider
`xpkg.crossplane.io/crossplane-contrib/provider-aws-s3` has a dependency on
`xpkg.crossplane.io/crossplane-contrib/provider-family-aws`. If you mirror the
packages to your own registry at `registry1.com` and install them without an
`ImageConfig`, the package manager still attempts to pull the dependency from
`xpkg.crossplane.io`. With the preceding `ImageConfig`, the dependency is pulled
from `registry1.com`.
Rewriting an image path with `ImageConfig` doesn't change the `spec.package`
field of the package resource. The rewritten path is recorded in the
`status.resolvedPackage` field. The preceding example results in the following:
```shell
kubectl describe provider crossplane-contrib-provider-family-aws
...
Spec:
...
Package: xpkg.crossplane.io/crossplane-contrib/provider-family-aws:v1.22.0
Status:
...
Resolved Package: registry1.com/crossplane-contrib/provider-family-aws:v1.22.0
```
### Interaction with other operations
{{<hint "tip" >}}
Image rewriting is always done before other `ImageConfig` operations. If you
wish to configure pull secrets or signature verification as well as rewriting,
additional `ImageConfig` resources must match the rewritten image path.
{{< /hint >}}
For example, if you are mirroring packages from `xpkg.crossplane.io` to
`registry1.com` and need to configure pull secrets for `registry1.com`, two
`ImageConfig` resources are necessary:
```yaml
# Rewrite xpkg.crossplane.io -> registry1.com
---
apiVersion: pkg.crossplane.io/v1beta1
kind: ImageConfig
metadata:
name: private-registry-rewrite
spec:
matchImages:
- prefix: xpkg.crossplane.io
rewriteImage:
prefix: registry1.com
# Configure pull secrets for registry1.com
---
apiVersion: pkg.crossplane.io/v1beta1
kind: ImageConfig
metadata:
name: private-registry-auth
spec:
matchImages:
- type: Prefix
prefix: registry1.com
registry:
authentication:
pullSecretRef:
name: private-registry-credentials
```
## Debugging
When the package manager selects an `ImageConfig` for a package, it throws an
event with the reason `ImageConfigSelection` and the name of the selected
`ImageConfig` and injected pull secret. You can find these events both on the
package and package revision resources. The package manager also updates the
`appliedImageConfigRefs` field in the package status to show the purpose for
which each `ImageConfig` was selected.
For example, the following event and status show that the `ImageConfig` named
`acme-packages` was used to provide a pull secret for the configuration named
`acme-configuration-foo`:
```shell
kubectl describe configuration acme-configuration-foo
...
Status:
Applied Image Config Refs:
Name: acme-packages
Reason: SetImagePullSecret
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ImageConfigSelection 45s packages/configuration.pkg.crossplane.io Selected pullSecret "acme-registry-credentials" from ImageConfig "acme-packages" for registry authentication
```
If you can't find the expected event and `appliedImageConfigRefs` entry, ensure
the prefix of the image reference matches the `matchImages` list of any
`ImageConfig` resources in the cluster.
<!-- vale write-good.Passive = YES -->
<!-- vale write-good.Passive = YES -->

View File

@ -24,18 +24,18 @@ Examples of providers include:
<!-- vale write-good.Passive = NO -->
<!-- "are Managed" isn't passive in this context -->
Providers define every external resource they can create in Kubernetes as a
Kubernetes API endpoint.
Kubernetes API endpoint.
These endpoints are
[_Managed Resources_]({{<ref "managed-resources" >}}).
[_Managed Resources_]({{<ref "../managed-resources/managed-resources" >}}).
<!-- vale write-good.Passive = YES -->
## Install a Provider
Installing a provider creates new Kubernetes resources representing the
Provider's APIs. Installing a provider also creates a Provider pod that's
responsible for reconciling the Provider's APIs into the Kubernetes cluster.
Providers constantly watch the state of the desired managed resources and create
Installing a provider creates new Kubernetes resources representing the
Provider's APIs. Installing a provider also creates a Provider pod that's
responsible for reconciling the Provider's APIs into the Kubernetes cluster.
Providers constantly watch the state of the desired managed resources and create
any external resources that are missing.
Install a Provider with a Crossplane
@ -45,10 +45,10 @@ location of the provider package.
{{< hint "important" >}}
Beginning with Crossplane version 1.20.0 Crossplane uses the [crossplane-contrib](https://github.com/orgs/crossplane-contrib/packages) GitHub Container Registry at `xpkg.crossplane.io` by default for downloading and
installing packages.
installing packages.
Specify the full domain name with the `package` or change the default Crossplane
registry with the `--registry` flag on the [Crossplane pod]({{<ref "./pods">}})
registry with the `--registry` flag on the [Crossplane pod]({{<ref "../guides/pods">}})
{{< /hint >}}
For example, to install the
@ -67,19 +67,19 @@ By default, the Provider pod installs in the same namespace as Crossplane
(`crossplane-system`).
{{<hint "note" >}}
Providers are part of the
{{<hover label="install" line="1">}}pkg.crossplane.io{{</hover>}} group.
Providers are part of the
{{<hover label="install" line="1">}}pkg.crossplane.io{{</hover>}} group.
The {{<hover label="meta-pkg" line="1">}}meta.pkg.crossplane.io{{</hover>}}
group is for creating Provider packages.
group is for creating Provider packages.
Instructions on building Providers are outside of the scope of this
document.
Read the Crossplane contributing
document.
Read the Crossplane contributing
[Provider Development Guide](https://github.com/crossplane/crossplane/blob/main/contributing/guide-provider-development.md)
for more information.
For information on the specification of Provider packages read the
For information on the specification of Provider packages read the
[Crossplane Provider Package specification](https://github.com/crossplane/crossplane/blob/main/contributing/specifications/xpkg.md#provider-package-requirements).
```yaml {label="meta-pkg"}
@ -113,9 +113,9 @@ crossplane-stable/crossplane \
### Install offline
Installing Crossplane Providers offline requires a local container registry like
Installing Crossplane Providers offline requires a local container registry like
[Harbor](https://goharbor.io/) to host Provider packages. Crossplane only
supports installing Provider packages from a container registry.
supports installing Provider packages from a container registry.
Crossplane doesn't support installing Provider packages directly from Kubernetes
volumes.
@ -123,11 +123,11 @@ volumes.
### Installation options
Providers support multiple configuration options to change installation related
settings.
settings.
{{<hint "tip" >}}
Crossplane supports installations with image digests instead of tags to get deterministic
and repeatable installations.
and repeatable installations.
```yaml {label="digest"}
apiVersion: pkg.crossplane.io/v1
@ -145,26 +145,26 @@ Use a {{<hover label="pullpolicy" line="6">}}packagePullPolicy{{</hover>}} to
define when Crossplane should download the Provider package to the local
Crossplane package cache.
The `packagePullPolicy` options are:
The `packagePullPolicy` options are:
* `IfNotPresent` - (**default**) Only download the package if it isn't in the cache.
* `Always` - Check for new packages every minute and download any matching
package that isn't in the cache.
* `Never` - Never download the package. Packages are only installed from the
local package cache.
local package cache.
{{<hint "tip" >}}
The Crossplane
The Crossplane
{{<hover label="pullpolicy" line="6">}}packagePullPolicy{{</hover>}} works
like the Kubernetes container image
[image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy).
like the Kubernetes container image
[image pull policy](https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy).
Crossplane supports the use of tags and package digest hashes like
Kubernetes images.
Kubernetes images.
{{< /hint >}}
For example, to `Always` download a given Provider package use the
For example, to `Always` download a given Provider package use the
{{<hover label="pullpolicy" line="6">}}packagePullPolicy: Always{{</hover>}}
configuration.
configuration.
```yaml {label="pullpolicy",copy-lines="6"}
apiVersion: pkg.crossplane.io/v1
@ -179,20 +179,20 @@ spec:
#### Revision activation policy
The `Active` package revision
is the package controller actively reconciling resources.
is the package controller actively reconciling resources.
By default Crossplane sets the most recently installed package revision as
By default Crossplane sets the most recently installed package revision as
`Active`.
Control the Provider upgrade behavior with a
{{<hover label="revision" line="6">}}revisionActivationPolicy{{</hover>}}.
The {{<hover label="revision" line="6">}}revisionActivationPolicy{{</hover>}}
The {{<hover label="revision" line="6">}}revisionActivationPolicy{{</hover>}}
options are:
* `Automatic` - (**default**) Automatically activate the last installed Provider.
* `Manual` - Don't automatically activate a Provider.
For example, to change the upgrade behavior to require manual upgrades, set
For example, to change the upgrade behavior to require manual upgrades, set
{{<hover label="revision" line="6">}}revisionActivationPolicy: Manual{{</hover>}}.
```yaml {label="revision"}
@ -207,26 +207,26 @@ spec:
#### Package revision history limit
When Crossplane installs a different version of the same Provider package
Crossplane creates a new _revision_.
When Crossplane installs a different version of the same Provider package
Crossplane creates a new _revision_.
By default Crossplane maintains one _Inactive_ revision.
By default Crossplane maintains one _Inactive_ revision.
{{<hint "note" >}}
Read the [Provider upgrade](#upgrade-a-provider) section for
more information on the use of package revisions.
{{< /hint >}}
Change the number of revisions Crossplane maintains with a Provider Package
{{<hover label="revHistoryLimit" line="6">}}revisionHistoryLimit{{</hover>}}.
Change the number of revisions Crossplane maintains with a Provider Package
{{<hover label="revHistoryLimit" line="6">}}revisionHistoryLimit{{</hover>}}.
The {{<hover label="revHistoryLimit" line="6">}}revisionHistoryLimit{{</hover>}}
field is an integer.
The default value is `1`.
Disable storing revisions by setting
field is an integer.
The default value is `1`.
Disable storing revisions by setting
{{<hover label="revHistoryLimit" line="6">}}revisionHistoryLimit{{</hover>}} to `0`.
For example, to change the default setting and store 10 revisions use
For example, to change the default setting and store 10 revisions use
{{<hover label="revHistoryLimit" line="6">}}revisionHistoryLimit: 10{{</hover>}}.
```yaml {label="revHistoryLimit"}
@ -241,13 +241,13 @@ spec:
#### Install a provider from a private registry
Like Kubernetes uses `imagePullSecrets` to
[install images from private registries](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/),
Like Kubernetes uses `imagePullSecrets` to
[install images from private registries](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/),
Crossplane uses `packagePullSecrets` to install Provider packages from a private
registry.
registry.
Use {{<hover label="pps" line="6">}}packagePullSecrets{{</hover>}} to provide a
Kubernetes secret to use for authentication when downloading a Provider package.
Kubernetes secret to use for authentication when downloading a Provider package.
{{<hint "important" >}}
The Kubernetes secret must be in the same namespace as Crossplane.
@ -257,7 +257,7 @@ The {{<hover label="pps" line="6">}}packagePullSecrets{{</hover>}} is a list of
secrets.
For example, to use the secret named
{{<hover label="pps" line="6">}}example-secret{{</hover>}} configure a
{{<hover label="pps" line="6">}}example-secret{{</hover>}} configure a
{{<hover label="pps" line="6">}}packagePullSecrets{{</hover>}}.
```yaml {label="pps"}
@ -266,25 +266,25 @@ kind: Provider
metadata:
name: provider-aws
spec:
packagePullSecrets:
packagePullSecrets:
- name: example-secret
# Removed for brevity
```
{{<hint "note" >}}
Configured `packagePullSecrets` aren't passed to any Provider package
dependencies.
dependencies.
{{< /hint >}}
#### Ignore dependencies
By default Crossplane installs any [dependencies](#manage-dependencies) listed
in a Provider package.
in a Provider package.
Crossplane can ignore a Provider package's dependencies with
Crossplane can ignore a Provider package's dependencies with
{{<hover label="pkgDep" line="6" >}}skipDependencyResolution{{</hover>}}.
For example, to disable dependency resolution configure
For example, to disable dependency resolution configure
{{<hover label="pkgDep" line="6" >}}skipDependencyResolution: true{{</hover>}}.
```yaml {label="pkgDep"}
@ -308,24 +308,24 @@ installations. Suppose configuration A, which depends on package X with the
constraint`>=v0.0.0`, is installed on the control plane. In this case, the package
manager installs the latest version of package X, such as `v3.0.0`. Later, you decide
to install configuration B, which depends on package X with the constraint `<=v2.0.0`.
Since version `v2.0.0` satisfies both conditions, package X must be downgraded to
Since version `v2.0.0`satisfies both conditions, package X must be downgraded to
allow the installation of configuration B which is disabled by default.
Automatic dependency version downgrades is also an alpha feature that can be
enabled with the `--enable-dependency-version-downgrades` flag. Downgrading a
package can cause unexpected behavior, therefore, this option is disabled by
default. After enabling this option, the package manager will automatically
downgrade a package's dependency version to the maximum valid version that
satisfies the constraints.
For enabling automatic dependency version downgrades, there is a configuration
option as a helm value `packageManager.enableAutomaticDependencyDowngrade=true`.
Downgrading a package can cause unexpected behavior, therefore, this
option is disabled by default. After enabling this option, the package manager will
automatically downgrade a package's dependency version to the maximum valid version
that satisfies the constraints.
{{<hint "note" >}}
This configuration requires the `--enable-dependency-version-upgrades` flag.
Please check the
[configuration options]({{<ref "../software/install#customize-the-crossplane-helm-chart">}})
[configuration options]({{<ref "../get-started/install#customize-the-crossplane-helm-chart">}})
and
[feature flags]({{<ref "../software/install#feature-flags">}})
[feature flags]({{<ref "../get-started/install#feature-flags">}})
are available in the
[Crossplane Install]({{<ref "../software/install">}})
[Crossplane Install]({{<ref "../get-started/install">}})
section for more details.
{{</hint >}}
@ -342,13 +342,13 @@ controllers to reconcile them.
A Provider package may require a specific or minimum Crossplane version before
installing. By default, Crossplane doesn't install a Provider if the Crossplane
version doesn't meet the required version.
version doesn't meet the required version.
Crossplane can ignore the required version with
Crossplane can ignore the required version with
{{<hover label="xpVer" line="6">}}ignoreCrossplaneConstraints{{</hover>}}.
For example, to install a Provider package into an unsupported Crossplane
version, configure
version, configure
{{<hover label="xpVer" line="6">}}ignoreCrossplaneConstraints: true{{</hover>}}.
```yaml {label="xpVer"}
@ -364,10 +364,10 @@ spec:
### Manage dependencies
Providers packages may include dependencies on other packages including
Configurations or other Providers.
Configurations or other Providers.
If Crossplane can't meet the dependencies of a Provider package the Provider
reports `HEALTHY` as `False`.
reports `HEALTHY` as `False`.
For example, this installation of the Getting Started Configuration is
`HEALTHY: False`.
@ -404,9 +404,9 @@ Events:
Warning LintPackage 41s (x3 over 47s) packages/providerrevision.pkg.crossplane.io incompatible Crossplane version: package isn't compatible with Crossplane version (v1.10.0)
```
The {{<hover label="depend" line="17">}}Events{{</hover>}} show a
The {{<hover label="depend" line="17">}}Events{{</hover>}} show a
{{<hover label="depend" line="20">}}Warning{{</hover>}} with a message that the
current version of Crossplane doesn't meet the Configuration package
current version of Crossplane doesn't meet the Configuration package
requirements.
## Upgrade a Provider
@ -420,7 +420,7 @@ Crossplane installs the new image and creates a new `ProviderRevision`.
The `ProviderRevision` allows Crossplane to store deprecated Provider CRDs
without removing them until you decide.
View the `ProviderRevisions` with
View the `ProviderRevisions` with
{{<hover label="getPR" line="1">}}kubectl get providerrevisions{{</hover>}}
```shell {label="getPR",copy-lines="1"}
@ -436,14 +436,14 @@ By default Crossplane keeps a single
{{<hover label="getPR" line="5">}}Inactive{{</hover>}} Provider.
Read the [revision history limit](#package-revision-history-limit) section to
change the default value.
change the default value.
Only a single revision of a Provider is
Only a single revision of a Provider is
{{<hover label="getPR" line="4">}}Active{{</hover>}} at a time.
## Remove a Provider
Remove a Provider by deleting the Provider object with
Remove a Provider by deleting the Provider object with
`kubectl delete provider`.
{{< hint "warning" >}}
@ -495,7 +495,7 @@ The Crossplane community has more
### Provider conditions
Crossplane uses a standard set of `Conditions` for Providers.
Crossplane uses a standard set of `Conditions` for Providers.
View the conditions of a provider under their `Status` with
`kubectl describe provider`.
@ -614,45 +614,13 @@ Reason: UnknownPackageRevisionHealth
Providers have two different types of configurations:
* _Controller configurations_ that change the settings of the Provider pod
* _Runtime configurations_ that change the settings of the Provider pod
running inside the Kubernetes cluster. For example, setting a `toleration` on
the Provider pod.
* _Provider configurations_ that change settings used when communicating with
an external provider. For example, cloud provider authentication.
{{<hint "important" >}}
Apply `ControllerConfig` objects to Providers.
Apply `ProviderConfig` objects to managed resources.
{{< /hint >}}
### Controller configuration
{{< hint "important" >}}
<!-- vale write-good.Passive = NO -->
<!-- vale gitlab.FutureTense = NO -->
The `ControllerConfig` type was deprecated in v1.11 and will be removed in
a future release.
<!-- vale write-good.Passive = YES -->
<!-- vale gitlab.FutureTense = YES -->
[`DeploymentRuntimeConfig`]({{<ref "#runtime-configuration" >}}) is the
replacement for Controller configuration and is available in v1.14+.
{{< /hint >}}
Applying a Crossplane `ControllerConfig` to a Provider changes the settings of
the Provider's pod. The
[Crossplane ControllerConfig schema]({{< ref "../api#ControllerConfig-spec" >}})
defines the supported set of ControllerConfig settings.
The most common use case for ControllerConfigs are providing `args` to a
Provider's pod enabling optional services. For example, enabling
[external secret stores]({{< ref "../guides/vault-as-secret-store#enable-external-secret-stores-in-the-provider" >}})
for a Provider.
Each Provider determines their supported set of `args`.
### Runtime configuration
{{<hint "important" >}}
@ -663,8 +631,7 @@ It's on by default, and you can disable it by passing
{{< /hint >}}
Runtime configuration is a generalized mechanism for configuring the runtime for
Crossplane packages with a runtime, namely `Providers` and `Functions`. It
replaces the deprecated `ControllerConfig` type and is available in v1.14+.
Crossplane packages with a runtime, namely `Providers` and `Functions`.
With its default configuration, Crossplane uses Kubernetes Deployments to
deploy runtime for packages, more specifically, a controller for a `Provider`
@ -672,13 +639,6 @@ or a gRPC server for a `Function`. It's possible to configure the runtime
manifest by applying a `DeploymentRuntimeConfig` and referencing it in the
`Provider` or `Function` object.
{{<hint "note" >}}
Different from `ControllerConfig`, `DeploymentRuntimeConfig` embed the whole
Kubernetes Deployment spec, which allows for more flexibility in configuring
the runtime. Refer to the [design document](https://github.com/crossplane/crossplane/blob/2c5e7f07ba9e3d83d1c85169bbde685de8514ab8/design/one-pager-package-runtime-config.md)
for more details.
{{< /hint >}}
As an example, to enable the external secret stores alpha feature for a `Provider`
by adding the `--enable-external-secret-stores` argument to the controller,
one can apply the following:

View File

@ -1,14 +0,0 @@
---
title: Install, Upgrade and Uninstall
weight: 10
description: Manage Crossplane installations
---
## [Install Crossplane](install/)
How to install and customize Crossplane in an existing Kubernetes cluster.
## [Upgrade Crossplane](upgrade/)
How to upgrade Crossplane to newer versions of the software.
## [Uninstall Crossplane](uninstall/)
How to remove Crossplane from a Kubernetes cluster.

View File

@ -1,342 +0,0 @@
---
title: Install Crossplane
weight: 100
---
Crossplane installs into an existing Kubernetes cluster, creating the
`Crossplane` pod, enabling the installation of Crossplane _Provider_ resources.
{{< hint type="tip" >}}
If you don't have a Kubernetes cluster create one locally with [Kind](https://kind.sigs.k8s.io/).
{{< /hint >}}
## Prerequisites
* An actively [supported Kubernetes version](https://kubernetes.io/releases/patch-releases/#support-period)
* [Helm](https://helm.sh/docs/intro/install/) version `v3.2.0` or later
## Install Crossplane
Install Crossplane using the Crossplane published _Helm chart_.
### Add the Crossplane Helm repository
Add the Crossplane repository with the `helm repo add` command.
```shell
helm repo add crossplane-stable https://charts.crossplane.io/stable
```
Update the
local Helm chart cache with `helm repo update`.
```shell
helm repo update
```
### Install the Crossplane Helm chart
Install the Crossplane Helm chart with `helm install`.
{{< hint "tip" >}}
View the changes Crossplane makes to your cluster with the
`helm install --dry-run --debug` options. Helm shows what configurations it
applies without making changes to the Kubernetes cluster.
{{< /hint >}}
Crossplane creates and installs into the `crossplane-system` namespace.
```shell
helm install crossplane \
--namespace crossplane-system \
--create-namespace crossplane-stable/crossplane
```
View the installed Crossplane pods with `kubectl get pods -n crossplane-system`.
```shell {copy-lines="1"}
kubectl get pods -n crossplane-system
NAME READY STATUS RESTARTS AGE
crossplane-6d67f8cd9d-g2gjw 1/1 Running 0 26m
crossplane-rbac-manager-86d9b5cf9f-2vc4s 1/1 Running 0 26m
```
{{< hint "tip" >}}
Install a specific version of Crossplane with the `--version <version>` option. For example, to install version `1.10.0`:
```shell
helm install crossplane \
--namespace crossplane-system \
--create-namespace crossplane-stable/crossplane \
--version 1.10.0
```
{{< /hint >}}
## Installed deployments
Crossplane creates two Kubernetes _deployments_ in the `crossplane-system`
namespace to deploy the Crossplane pods.
```shell {copy-lines="1"}
kubectl get deployments -n crossplane-system
NAME READY UP-TO-DATE AVAILABLE AGE
crossplane 1/1 1 1 8m13s
crossplane-rbac-manager 1/1 1 1 8m13s
```
### Crossplane deployment
The Crossplane deployment starts with the `crossplane-init container`. The
`init` container installs the Crossplane _Custom Resource Definitions_ into the
Kubernetes cluster.
After the `init` container finishes, the `crossplane` pod manages two Kubernetes
controllers.
* The _Package Manager controller_ installs the
provider, function and configuration packages.
* The _Composition controller_ installs and manages the
Crossplane _Composite Resource Definitions_, _Compositions_ and _Claims_.
### Crossplane RBAC manager deployment
The `crossplane-rbac-manager` creates and manages Kubernetes _ClusterRoles_ for
installed Crossplane _Provider_ and their _Custom Resource Definitions_.
The
[Crossplane RBAC Manager design document](https://github.com/crossplane/crossplane/blob/main/design/design-doc-rbac-manager.md)
has more information on the installed _ClusterRoles_.
## Installation options
### Customize the Crossplane Helm chart
Crossplane supports customizations at install time by configuring the Helm
chart.
Apply customizations with the command line or with a Helm _values_ file.
<!-- Generated from Helm README at https://github.com/crossplane/crossplane/blob/main/cluster/charts/crossplane/README.md -->
<!-- vale gitlab.Substitutions = NO -->
<!-- allow lowercase yaml -->
{{<expand "All Crossplane customization options" >}}
{{< table "table table-hover table-striped table-sm">}}
| Parameter | Description | Default |
| --- | --- | --- |
| `affinity` | Add `affinities` to the Crossplane pod deployment. | `{}` |
| `args` | Add custom arguments to the Crossplane pod. | `[]` |
| `configuration.packages` | A list of Configuration packages to install. | `[]` |
| `customAnnotations` | Add custom `annotations` to the Crossplane pod deployment. | `{}` |
| `customLabels` | Add custom `labels` to the Crossplane pod deployment. | `{}` |
| `deploymentStrategy` | The deployment strategy for the Crossplane and RBAC Manager pods. | `"RollingUpdate"` |
| `dnsPolicy` | Specify the `dnsPolicy` to be used by the Crossplane pod. | `""` |
| `extraEnvVarsCrossplane` | Add custom environmental variables to the Crossplane pod deployment. Replaces any `.` in a variable name with `_`. For example, `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`. | `{}` |
| `extraEnvVarsRBACManager` | Add custom environmental variables to the RBAC Manager pod deployment. Replaces any `.` in a variable name with `_`. For example, `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`. | `{}` |
| `extraObjects` | To add arbitrary Kubernetes Objects during a Helm Install | `[]` |
| `extraVolumeMountsCrossplane` | Add custom `volumeMounts` to the Crossplane pod. | `{}` |
| `extraVolumesCrossplane` | Add custom `volumes` to the Crossplane pod. | `{}` |
| `function.packages` | A list of Function packages to install | `[]` |
| `functionCache.medium` | Set to `Memory` to hold the function cache in a RAM backed file system. Useful for Crossplane development. | `""` |
| `functionCache.pvc` | The name of a PersistentVolumeClaim to use as the function cache. Disables the default function cache `emptyDir` Volume. | `""` |
| `functionCache.sizeLimit` | The size limit for the function cache. If medium is `Memory` the `sizeLimit` can't exceed Node memory. | `"512Mi"` |
| `hostNetwork` | Enable `hostNetwork` for the Crossplane deployment. Caution: enabling `hostNetwork` grants the Crossplane Pod access to the host network namespace. Consider setting `dnsPolicy` to `ClusterFirstWithHostNet`. | `false` |
| `image.pullPolicy` | The image pull policy used for Crossplane and RBAC Manager pods. | `"IfNotPresent"` |
| `image.repository` | Repository for the Crossplane pod image. | `"xpkg.crossplane.io/crossplane/crossplane"` |
| `image.tag` | The Crossplane image tag. Defaults to the value of `appVersion` in `Chart.yaml`. | `""` |
| `imagePullSecrets` | The imagePullSecret names to add to the Crossplane ServiceAccount. | `[]` |
| `leaderElection` | Enable [leader election](https://docs.crossplane.io/latest/concepts/pods/#leader-election) for the Crossplane pod. | `true` |
| `metrics.enabled` | Enable Prometheus path, port and scrape annotations and expose port 8080 for both the Crossplane and RBAC Manager pods. | `false` |
| `metrics.port` | The port the metrics server listens on. | `""` |
| `nodeSelector` | Add `nodeSelectors` to the Crossplane pod deployment. | `{}` |
| `packageCache.configMap` | The name of a ConfigMap to use as the package cache. Disables the default package cache `emptyDir` Volume. | `""` |
| `packageCache.medium` | Set to `Memory` to hold the package cache in a RAM backed file system. Useful for Crossplane development. | `""` |
| `packageCache.pvc` | The name of a PersistentVolumeClaim to use as the package cache. Disables the default package cache `emptyDir` Volume. | `""` |
| `packageCache.sizeLimit` | The size limit for the package cache. If medium is `Memory` the `sizeLimit` can't exceed Node memory. | `"20Mi"` |
| `podSecurityContextCrossplane` | Add a custom `securityContext` to the Crossplane pod. | `{}` |
| `podSecurityContextRBACManager` | Add a custom `securityContext` to the RBAC Manager pod. | `{}` |
| `priorityClassName` | The PriorityClass name to apply to the Crossplane and RBAC Manager pods. | `""` |
| `provider.packages` | A list of Provider packages to install. | `[]` |
| `rbacManager.affinity` | Add `affinities` to the RBAC Manager pod deployment. | `{}` |
| `rbacManager.args` | Add custom arguments to the RBAC Manager pod. | `[]` |
| `rbacManager.deploy` | Deploy the RBAC Manager pod and its required roles. | `true` |
| `rbacManager.leaderElection` | Enable [leader election](https://docs.crossplane.io/latest/concepts/pods/#leader-election) for the RBAC Manager pod. | `true` |
| `rbacManager.nodeSelector` | Add `nodeSelectors` to the RBAC Manager pod deployment. | `{}` |
| `rbacManager.replicas` | The number of RBAC Manager pod `replicas` to deploy. | `1` |
| `rbacManager.revisionHistoryLimit` | The number of RBAC Manager ReplicaSets to retain. | `nil` |
| `rbacManager.skipAggregatedClusterRoles` | Don't install aggregated Crossplane ClusterRoles. | `false` |
| `rbacManager.tolerations` | Add `tolerations` to the RBAC Manager pod deployment. | `[]` |
| `rbacManager.topologySpreadConstraints` | Add `topologySpreadConstraints` to the RBAC Manager pod deployment. | `[]` |
| `readiness.port` | The port the readyz server listens on. | `""` |
| `registryCaBundleConfig.key` | The ConfigMap key containing a custom CA bundle to enable fetching packages from registries with unknown or untrusted certificates. | `""` |
| `registryCaBundleConfig.name` | The ConfigMap name containing a custom CA bundle to enable fetching packages from registries with unknown or untrusted certificates. | `""` |
| `replicas` | The number of Crossplane pod `replicas` to deploy. | `1` |
| `resourcesCrossplane.limits.cpu` | CPU resource limits for the Crossplane pod. | `"500m"` |
| `resourcesCrossplane.limits.memory` | Memory resource limits for the Crossplane pod. | `"1024Mi"` |
| `resourcesCrossplane.requests.cpu` | CPU resource requests for the Crossplane pod. | `"100m"` |
| `resourcesCrossplane.requests.memory` | Memory resource requests for the Crossplane pod. | `"256Mi"` |
| `resourcesRBACManager.limits.cpu` | CPU resource limits for the RBAC Manager pod. | `"100m"` |
| `resourcesRBACManager.limits.memory` | Memory resource limits for the RBAC Manager pod. | `"512Mi"` |
| `resourcesRBACManager.requests.cpu` | CPU resource requests for the RBAC Manager pod. | `"100m"` |
| `resourcesRBACManager.requests.memory` | Memory resource requests for the RBAC Manager pod. | `"256Mi"` |
| `revisionHistoryLimit` | The number of Crossplane ReplicaSets to retain. | `nil` |
| `runtimeClassName` | The runtimeClassName name to apply to the Crossplane and RBAC Manager pods. | `""` |
| `securityContextCrossplane.allowPrivilegeEscalation` | Enable `allowPrivilegeEscalation` for the Crossplane pod. | `false` |
| `securityContextCrossplane.readOnlyRootFilesystem` | Set the Crossplane pod root file system as read-only. | `true` |
| `securityContextCrossplane.runAsGroup` | The group ID used by the Crossplane pod. | `65532` |
| `securityContextCrossplane.runAsUser` | The user ID used by the Crossplane pod. | `65532` |
| `securityContextRBACManager.allowPrivilegeEscalation` | Enable `allowPrivilegeEscalation` for the RBAC Manager pod. | `false` |
| `securityContextRBACManager.readOnlyRootFilesystem` | Set the RBAC Manager pod root file system as read-only. | `true` |
| `securityContextRBACManager.runAsGroup` | The group ID used by the RBAC Manager pod. | `65532` |
| `securityContextRBACManager.runAsUser` | The user ID used by the RBAC Manager pod. | `65532` |
| `service.customAnnotations` | Configure annotations on the service object. Only enabled when webhooks.enabled = true | `{}` |
| `serviceAccount.create` | Specifies whether Crossplane ServiceAccount should be created | `true` |
| `serviceAccount.customAnnotations` | Add custom `annotations` to the Crossplane ServiceAccount. | `{}` |
| `serviceAccount.name` | Provide the name of an already created Crossplane ServiceAccount. Required when `serviceAccount.create` is `false` | `""` |
| `tolerations` | Add `tolerations` to the Crossplane pod deployment. | `[]` |
| `topologySpreadConstraints` | Add `topologySpreadConstraints` to the Crossplane pod deployment. | `[]` |
| `webhooks.enabled` | Enable webhooks for Crossplane and installed Provider packages. | `true` |
| `webhooks.port` | The port the webhook server listens on. | `""` |
{{< /table >}}
{{< /expand >}}
<!-- vale gitlab.Substitutions = YES -->
#### Command line customization
Apply custom settings at the command line with
`helm install crossplane --set <setting>=<value>`.
For example, to change the image pull policy:
```shell
helm install crossplane \
--namespace crossplane-system \
--create-namespace \
crossplane-stable/crossplane \
--set image.pullPolicy=Always
```
Helm supports comma-separated arguments.
For example, to change the image pull policy and number of replicas:
```shell
helm install crossplane \
--namespace crossplane-system \
--create-namespace \
crossplane-stable/crossplane \
--set image.pullPolicy=Always,replicas=2
```
#### Helm values file
Apply custom settings in a Helm _values_ file with
`helm install crossplane -f <filename>`.
A YAML file defines the customized settings.
For example, to change the image pull policy and number of replicas:
Create a YAML with the customized settings.
```yaml
replicas: 2
image:
pullPolicy: Always
```
Apply the file with `helm install`:
```shell
helm install crossplane \
--namespace crossplane-system \
--create-namespace \
crossplane-stable/crossplane \
-f settings.yaml
```
#### Feature flags
Crossplane introduces new features behind feature flags. By default
alpha features are off. Crossplane enables beta features by default. To enable a
feature flag, set the `args` value in the Helm chart. Available feature flags
can be directly found by running `crossplane core start --help`, or by looking
at the table below.
{{< expand "Feature flags" >}}
{{< table caption="Feature flags" >}}
| Status | Flag | Description |
| --- | --- | --- |
| Beta | `--enable-composition-webhook-schema-validation` | Enable Composition validation using schemas. |
| Beta | `--enable-deployment-runtime-configs` | Enable support for DeploymentRuntimeConfigs. |
| Beta | `--enable-usages` | Enable support for Usages. |
| Beta | `--enable-ssa-claims` | Enable support for using server-side apply to sync claims with XRs. |
| Beta | `--enable-realtime-compositions` | Enable support for real time compositions. |
| Alpha | `--enable-external-secret-stores` | Enable support for External Secret Stores. |
| Alpha | `--enable-dependency-version-upgrades` | Enable automatic version upgrades of dependencies when updating packages. |
| Alpha | `--enable-dependency-version-downgrades` | Enable automatic version downgrades of dependencies when updating packages. |
| Alpha | `--enable-signature-verification` | Enable support for package signature verification via ImageConfig API. |
| Alpha | `--enable-function-response-cache` | Enable support for caching composition function responses. |
{{< /table >}}
{{< /expand >}}
Set these flags either in the `values.yaml` file or at install time using the
`--set` flag, for example: `--set
args='{"--enable-composition-functions","--enable-composition-webhook-schema-validation"}'`.
#### Change the default package registry
Beginning with Crossplane version 1.20.0 Crossplane uses the [crossplane-contrib](https://github.com/orgs/crossplane-contrib/packages) GitHub Container Registry at `xpkg.crossplane.io` by default for downloading and
installing packages.
Change the default registry location during the Crossplane install with
`--set args='{"--registry=index.docker.io"}'`.
### Install pre-release Crossplane versions
Install a pre-release versions of Crossplane from the `master` Crossplane Helm channel.
Versions in the `master` channel are under active development and may be unstable.
{{< hint "warning" >}}
Don't use Crossplane `master` releases in production. Only use `stable` channel.
Only use `master` for testing and development.
{{< /hint >}}
#### Add the Crossplane master Helm repository
Add the Crossplane repository with the `helm repo add` command.
```shell
helm repo add crossplane-master https://charts.crossplane.io/master/
```
Update the
local Helm chart cache with `helm repo update`.
```shell
helm repo update
```
#### Install the Crossplane master Helm chart
Install the Crossplane `master` Helm chart with `helm install`.
{{< hint "tip" >}}
View the changes Crossplane makes to your cluster with the
`helm install --dry-run --debug` options. Helm shows what configurations it
applies without making changes to the Kubernetes cluster.
{{< /hint >}}
Crossplane creates and installs into the `crossplane-system` namespace.
```shell
helm install crossplane \
--namespace crossplane-system \
--create-namespace crossplane-master/crossplane \
--devel
```
## Crossplane distributions
Third-party vendors may maintain their own Crossplane distributions. Vendor
supported distribution may have features or tooling that isn't in the
Community Crossplane distribution.
The CNCF certified third-party distributions as
"[conformant](https://github.com/cncf/crossplane-conformance)" with the
Community Crossplane distribution.

View File

@ -0,0 +1,237 @@
---
title: What's Crossplane?
weight: 3
description: Learn what Crossplane is and why you'd use it.
---
Crossplane is a control plane framework for platform engineering.
**Crossplane lets you build control planes to manage your cloud native software.**
It lets you design the APIs and abstractions that your users use to interact
with your control planes.
{{< hint "tip" >}}
**A control plane is software that controls other software.**
Control planes are a core cloud native pattern. The major cloud providers are
all built using control planes.
Control planes expose an API. You use the API to tell the control plane what
software it should configure and how - this is your _desired state_.
A control plane can configure any cloud native software. It could deploy an app,
create a load balancer, or create a GitHub repository.
The control plane configures your software, then monitors it throughout its
lifecycle. If your software ever _drifts_ from your desired state, the control
plane automatically corrects the drift.
{{< /hint >}}
Crossplane has a rich ecosystem of extensions that make building a control plane
faster and easier. It's built on Kubernetes, so it works with all the Kubernetes
tools you already use.
**Crossplane's key value is that it unlocks the benefits of building your own
Kubernetes custom resources without having to write controllers for them.**
Not familiar with Kubernetes custom resources and controllers?
[This DevOps Toolkit video](https://www.youtube.com/watch?v=aM2Y9m2Kazk) has a
great explanation.
{{<hint "note">}}
Kubebuilder is a popular project for building Kubernetes controllers. Look at
the [Kubebuilder documentation](https://book.kubebuilder.io) to see what's
involved in writing a controller.
{{</hint>}}
## Crossplane components
Crossplane has three major components:
* [Composition](#composition)
* [Managed resources](#managed-resources)
* [Package manager](#package-manager)
You can use all three components to build your control plane, or pick only the
ones you need.
### Composition
Composition lets you build custom APIs to control your cloud native software.
Crossplane extends Kubernetes. You build your custom APIs by using Crossplane to
extend Kubernetes with new custom resources.
**To extend Kubernetes without using Crossplane you need a Kubernetes
controller.** The controller is the software that reacts when a user calls the
custom resource API.
Say you want your control plane to serve an `App` custom resource API. When
someone creates an `App`, the control plane should create a Kubernetes
`Deployment` and a `Service`.
**If there's not already a controller that does what you want - and exposes the
API you want - you have to write the controller yourself.**
```mermaid
flowchart TD
user(User)
subgraph control [Control Plane]
api(App API)
controller[Your App Controller]
deployment(Deployment API)
service(Service API)
end
user -- create --> api
controller watch@<-- watch --> api
controller -- create --> deployment
controller -- create --> service
watch@{animate: true}
```
**With Crossplane you don't have to write a controller**. Instead you configure
a pipeline of functions. The functions return declarative configuration that
Crossplane should apply.
```mermaid
flowchart TD
user(User)
subgraph control [Control Plane]
api(App API)
subgraph crossplane [Composition Engine]
fn(Python Function)
end
deployment(Deployment API)
service(Service API)
end
user -- create --> api
crossplane watch@<-- watch --> api
crossplane -- create --> deployment
crossplane -- create --> service
watch@{animate: true}
```
With Composition you avoid writing and maintaining complex controller code
that's hard to get right. Instead you focus on expressing your business
logic, and work in your preferred language.
{{<hint "important">}}
Composition functions are like configuration language plugins.
Functions allow you to write your configuration in several languages, including
[YAML](https://yaml.org), [KCL](https://www.kcl-lang.io),
[Python](https://python.org), and [Go](https://go.dev).
{{</hint>}}
You can use composition together with [managed resources](#managed-resources) to
build new custom resource APIs powered by managed resources.
Follow [Get Started with Composition]({{<ref "../get-started/get-started-with-composition">}})
to see how composition works.
### Managed resources
Managed resources (MRs) are ready-made Kubernetes custom resources.
Each MR extends Kubernetes with the ability to manage a new system. For example
there's an RDS instance MR that extends Kubernetes with the ability to manage
[AWS RDS](https://aws.amazon.com/rds/) instances.
Crossplane has an extensive library of managed resources you can use to manage
almost any cloud provider, or cloud native software.
**With Crossplane you don't have to write a controller if you want to manage
something outside of your Kubernetes cluster using a custom resource.** There's
already a Crossplane managed resource for that.
```mermaid
flowchart TD
user(User)
subgraph control [Control Plane]
instance(RDS Instance API)
controller(Managed Resource Controller)
end
subgraph aws [Amazon Web Services]
rds(RDS Instance)
end
user -- create --> instance
controller watch-rds@<-- watch --> instance
controller -- create --> rds
watch-rds@{animate: true}
```
You can use managed resources together with [composition](#composition) to build
new custom resource APIs powered by MRs.
```mermaid
flowchart TD
user(User)
subgraph control [Control Plane]
api(App API)
subgraph crossplane [Composition Engine]
fn(Python Function)
end
deployment(Deployment API)
service(Service API)
instance(RDS Instance API)
controller(Managed Resource Controller)
end
subgraph aws [Amazon Web Services]
rds(RDS Instance)
end
user -- create --> api
crossplane watch-apps@<-- watch --> api
crossplane -- create --> deployment
crossplane -- create --> service
crossplane -- create --> instance
controller watch-rds@<-- watch --> instance
controller -- create --> rds
watch-apps@{animate: true}
watch-rds@{animate: true}
```
Follow [Get Started with Managed Resources]({{<ref "../get-started/get-started-with-managed-resources">}})
to see how managed resources work.
{{<hint "note">}}
Only AWS managed resources support the Crossplane v2 preview.
<!-- vale gitlab.FutureTense = NO -->
Maintainers will update the managed resources for other systems including Azure,
GCP, Terraform, Helm, GitHub, etc to support Crossplane v2 soon.
<!-- vale gitlab.FutureTense = YES -->
{{</hint>}}
### Package manager
The Crossplane package manager lets you install new managed resources and
composition functions.
You can also package any part of a control plane's configuration and install it
using the package manager. This allows you to deploy several control planes with
identical capabilities - for example one control plane per region or per
service.
Read about Crossplane [packages]({{<ref "../packages">}})
to learn about the package manager.

View File

@ -0,0 +1,262 @@
---
title: What's New in v2?
weight: 4
description: Learn what's new in the Crossplane v2 preview
---
**Crossplane v2 makes Crossplane more useful, more intuitive, and less
opinionated.**
Crossplane v2 makes three major changes:
* **Composite resources are now namespaced**
* **Managed resources are now namespaced**
* **Composition supports any Kubernetes resource**
**Crossplane v2 is better suited to building control planes for applications,
not just infrastructure.** It removes the need for awkward abstractions like
claims and provider-kubernetes Objects.
```mermaid
flowchart LR
user(User)
subgraph ns [my-namespace]
direction LR
xr("App (XR)")
dply("Deployment")
svc("Service")
rds("RDSInstance (MR)")
end
user --create-->xr
xr compose-dply@--compose--> dply
xr compose-svc@--compose--> svc
xr compose-rds@--compose--> rds
compose-dply@{animate: true}
compose-dply@{animate: true}
compose-svc@{animate: true}
compose-rds@{animate: true}
```
{{<hint "tip">}}
Most users can upgrade to Crossplane v2 without breaking changes.
Read about Crossplane v2's [backward compatibility](#backward-compatibility).
{{</hint>}}
{{<hint "note">}}
This page assumes you're familiar with Crossplane. New to Crossplane? Read
[What's Crossplane]({{<ref "whats-crossplane">}}) instead.
{{</hint>}}
## Namespaced composite resources
Crossplane v2 makes composite resources (XRs) namespaced by default.
A namespaced XR can compose any resource ([not just Crossplane resources](#compose-any-resource))
in its namespace.
A namespaced XR looks like this:
```yaml
apiVersion: example.crossplane.io/v1
kind: App
metadata:
namespace: default
name: my-app
spec:
image: nginx
crossplane:
compositionRef:
name: app-kcl
compositionRevisionRef:
name: app-kcl-41b6efe
resourceRefs:
- apiVersion: apps/v1
kind: Deployment
name: my-app-9bj8j
- apiVersion: v1
kind: Service
name: my-app-bflc4
```
{{<hint "note">}}
Crossplane v2 moves all an XR's "Crossplane machinery" under `spec.crossplane`.
This makes it easier for users to tell which fields are important to them, and
which are just "Crossplane stuff" they can ignore.
{{</hint>}}
Composite resource definitions (XRDs) now have a `scope` field. The `scope`
field defaults to `Namespaced` in the new v2 version of the XRD API.
```yaml
apiVersion: apiextensions.crossplane.io/v2
kind: CompositeResourceDefinition
metadata:
name: apps.example.crossplane.io
spec:
scope: Namespaced
group: example.crossplane.io
names:
kind: App
plural: apps
versions:
- name: v1
# Removed for brevity
```
You can also set the `scope` field to `Cluster` to create a cluster scoped XR. A
cluster scoped XR can compose any cluster scoped resource. A cluster scoped XR
can also compose any namespaced resource in any namespace.
With namespaced XRs there's no longer a need for claims. **The new namespaced
and cluster scoped XRs in Crossplane v2 don't support claims.**
{{<hint "tip">}}
Crossplane v2 is backward compatible with v1-style XRs.
When you use v1 of the XRD API `scope` defaults to a special `LegacyCluster`
mode. `LegacyCluster` XRs support claims and don't use `spec.crossplane`.
Read more about Crossplane v2's [backward compatibility](#backward-compatibility).
{{</hint>}}
## Namespaced managed resources
Crossplane v2 makes all managed resources (MRs) namespaced.
This enables a namespaced XR to by composed entirely of namespaced resources -
whether they're a Crossplane MR like an `RDSInstance`, a Kubernetes resource
like a `Deployment`, or a third party custom resource like a
[Cluster API](https://cluster-api.sigs.k8s.io) `Cluster`.
A namespaced MR looks like this:
```yaml
apiVersion: s3.aws.m.upbound.io/v1beta1
kind: Bucket
metadata:
namespace: default
generateName: my-bucket
spec:
forProvider:
region: us-east-2
```
Namespaced MRs work great with or without composition. Crossplane v2 isn't
opinionated about using composition and MRs together. Namespaces enable fine
grained access control over who can create what MRs.
{{<hint "note">}}
During the Crossplane v2 preview only namespaced AWS managed resources are
available.
<!-- vale gitlab.FutureTense = NO -->
Maintainers will update the managed resources for other systems including Azure,
GCP, Terraform, Helm, GitHub, etc to support namespaced MRs soon.
<!-- vale gitlab.FutureTense = YES -->
{{</hint>}}
{{<hint "tip">}}
Crossplane v2 is backward compatible with v1-style cluster scoped MRs.
<!-- vale gitlab.FutureTense = NO -->
New provider releases will support both namespaced and cluster scoped MRs.
Crossplane v2 considers cluster scoped MRs a legacy feature. Crossplane will
deprecate and remove cluster scoped MRs at a future date.
<!-- vale gitlab.FutureTense = YES -->
Read more about Crossplane v2's [backward compatibility](#backward-compatibility).
{{</hint>}}
## Compose any resource
Crossplane v2 isn't opinionated about using composition together with managed
resources.
You can create a composite resource (XR) that composes any resource, whether
it's a Crossplane MR like an `RDSInstance`, a Kubernetes resource like a
`Deployment`, or a third party custom resource like a
[CloudNativePG](https://cloudnative-pg.io) PostgreSQL `Cluster`.
```mermaid
flowchart LR
user(User)
subgraph ns [my-namespace]
direction LR
xr("App (XR)")
dply("Deployment")
svc("Service")
pg("CloudNativePG Cluster")
end
user --create-->xr
xr compose-dply@--compose--> dply
xr compose-svc@--compose--> svc
xr compose-pg@--compose--> pg
compose-dply@{animate: true}
compose-dply@{animate: true}
compose-svc@{animate: true}
compose-pg@{animate: true}
```
This opens composition to exciting new use cases - for example building custom
app models with Crossplane.
{{<hint "tip">}}
You must grant Crossplane access to compose resources that aren't Crossplane
resources like MRs or XRs. Read
[the composition documentation]({{<ref "../composition/compositions#grant-access-to-composed-resources">}})
to learn how to grant Crossplane access.
{{</hint>}}
## Backward compatibility
Crossplane v2 makes the following breaking changes:
* It removes native patch and transform composition.
* It removes the `ControllerConfig` type.
* It removes support for external secret stores.
* It removes the default registry for Crossplane Packages.
Crossplane deprecated native patch and transform composition in Crossplane
v1.17. It's replaced by composition functions.
Crossplane deprecated the `ControllerConfig` type in v1.11. It's replaced by the
`DeploymentRuntimeConfig` type.
Crossplane added external secret stores in v1.7. External secret stores have
remained in alpha for over two years and are now unmaintained.
Crossplane v2 drops the `--registry` flag that allowed users to specify a default
registry value and now requires users to always specify a fully qualified URL when
installing packages, both directly via `spec.package` and indirectly as dependencies.
Using fully qualified images was already a best practice, but it's now enforced
to avoid confusion and unexpected behavior, to ensure users are aware of the
registry used by their packages.
{{<hint "important">}}
As long as you're not using these deprecated or alpha features, Crossplane v2 is
backward compatible with Crossplane v1.x.
{{</hint>}}
{{<hint "important">}}
Before upgrading to Crossplane v2, please ensure all your Packages are using fully
qualified images that explicitly specify a registry (`registry.example.com/repo/package:tag`).
Run `kubectl get pkg` to look for any packages that aren't fully qualified, then
update or rebuild any Packages to use fully qualified images as needed.
{{</hint>}}
<!-- vale gitlab.FutureTense = NO -->
Crossplane v2 supports legacy v1-style XRs and MRs. Most users will be able to
upgrade from v1.x to Crossplane v2 without breaking changes.
Existing Compositions will require minor updates to work with Crossplane v2
style XRs. A migration guide will be available closer to the final release of
Crossplane v2.
<!-- vale gitlab.FutureTense = YES -->