mirror of https://github.com/crossplane/docs.git
Replace content/master with a copy of content/v2.0-preview
Signed-off-by: Nic Cope <nicc@rk0n.org>
This commit is contained in:
parent
431e87a035
commit
fe508db0b1
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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: {}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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: {}
|
||||
|
|
|
|||
|
|
@ -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: |-
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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: {}
|
||||
|
|
@ -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: {}
|
||||
|
|
@ -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: {}
|
||||
|
|
@ -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`
|
||||
|
|
@ -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 >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Composition
|
||||
weight: 51
|
||||
description: Understand Crossplane's core components
|
||||
---
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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">}}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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:
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
||||

|
||||
|
||||
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">}}).
|
||||
|
|
@ -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.
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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>}}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Get Started
|
||||
weight: 40
|
||||
description: Get started with Crossplane.
|
||||
---
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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"}'`.
|
||||
|
|
@ -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
|
|
@ -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" >}})
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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"
|
||||
```
|
||||
|
|
@ -133,7 +133,6 @@ data:
|
|||
"Composition",
|
||||
"CompositionRevision",
|
||||
"DeploymentRuntimeConfig",
|
||||
"ControllerConfig",
|
||||
"ProviderConfig",
|
||||
"ProviderConfigUsage"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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/).
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
@ -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"}'
|
||||
```
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Managed Resources
|
||||
weight: 52
|
||||
description: Understand Crossplane's core components
|
||||
---
|
||||
|
|
@ -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"
|
||||
|
|
@ -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!"
|
||||
```
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Packages
|
||||
weight: 53
|
||||
description: Understand Crossplane's core components
|
||||
---
|
||||
|
|
@ -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`.
|
||||
|
||||
|
|
@ -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 >}}
|
||||
|
|
@ -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 -->
|
||||
|
|
@ -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:
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 -->
|
||||
Loading…
Reference in New Issue