mirror of https://github.com/crossplane/docs.git
create v1.13 docs set
Signed-off-by: Pete Lumbis <pete@upbound.io>
This commit is contained in:
parent
7f443f319d
commit
f474acf16b
|
@ -0,0 +1,49 @@
|
|||
---
|
||||
title: "Overview"
|
||||
weight: -1
|
||||
cascade:
|
||||
version: "master"
|
||||
---
|
||||
|
||||
{{< img src="/media/banner.png" alt="Crossplane Popsicle Truck" size="large" >}}
|
||||
|
||||
<br />
|
||||
|
||||
Crossplane is an open source Kubernetes extension that transforms your Kubernetes
|
||||
cluster into a **universal control plane**.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
**What's a control plane?**
|
||||
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.
|
||||
|
||||
Crossplane extends the Kubernetes control plane to be a **universal control
|
||||
plane** to check, report and act on any resource, anywhere.
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
# 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.
|
||||
|
||||
|
||||
Crossplane is a [Cloud Native Compute Foundation](https://www.cncf.io/) project.
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
title: Concepts
|
||||
weight: 100
|
||||
description: Understand Crossplane's core components
|
||||
---
|
||||
|
||||
Crossplane introduces multiple building blocks that enable you to provision,
|
||||
compose, and consume infrastructure using the Kubernetes API. These individual
|
||||
concepts work together to allow for powerful separation of concern between
|
||||
different personas in an organization, meaning that each member of a team
|
||||
interacts with Crossplane at an appropriate level of abstraction.
|
||||
|
||||
## Packages
|
||||
|
||||
[Packages] allow Crossplane to be extended to include new functionality. This
|
||||
typically looks like bundling a set of Kubernetes [CRDs] and [controllers] that
|
||||
represent and manage external infrastructure (i.e. a provider), then installing
|
||||
them into a cluster where Crossplane is running. Crossplane handles making sure
|
||||
any new CRDs do not conflict with existing ones, as well as manages the RBAC and
|
||||
security of new packages. Packages are not strictly required to be providers,
|
||||
but it is the most common use-case for packages at this time.
|
||||
|
||||
## Providers
|
||||
|
||||
Providers are packages that enable Crossplane to provision infrastructure on an
|
||||
external service. They bring CRDs (i.e. managed resources) that map one-to-one
|
||||
to external infrastructure resources, as well as controllers to manage the
|
||||
life-cycle of those resources. You can read more about providers, including how
|
||||
to install and configure them, in the [providers documentation].
|
||||
|
||||
## Managed Resources
|
||||
|
||||
Managed resources are Kubernetes custom resources that represent infrastructure
|
||||
primitives. Managed resources with an API version of `v1beta1` or higher support
|
||||
every field that the cloud provider does for the given resource. You can find
|
||||
the Managed Resources and their API specifications for each provider on
|
||||
the [Upbound Marketplace] and learn more in the [managed resources documentation].
|
||||
|
||||
## Composite Resources
|
||||
|
||||
A composite resource (XR) is a special kind of custom resource that is defined
|
||||
by a `CompositeResourceDefinition`. It composes one or more managed resources
|
||||
into a higher level infrastructure unit. Composite resources are infrastructure
|
||||
operator facing, but may optionally offer an application developer facing
|
||||
composite resource claim that acts as a proxy for a composite resource. You can
|
||||
learn more about all of these concepts in the [composition documentation].
|
||||
|
||||
<!-- Named Links -->
|
||||
|
||||
[Packages]: {{<ref "packages" >}}
|
||||
[CRDs]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
|
||||
[controllers]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#custom-controllers
|
||||
[providers documentation]: {{<ref "providers" >}}
|
||||
[Upbound Marketplace]: https://marketplace.upbound.io
|
||||
[managed resources documentation]: {{<ref "managed-resources" >}}
|
||||
[composition documentation]: {{<ref "./compositions" >}}
|
|
@ -0,0 +1,208 @@
|
|||
---
|
||||
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 "/knowledge-base/guides/connection-details">}}).
|
|
@ -0,0 +1,841 @@
|
|||
---
|
||||
title: Composite Resource Definitions
|
||||
weight: 40
|
||||
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`.
|
||||
|
||||
|
||||
{{< 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 >}}
|
||||
|
||||
|
||||
{{<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 (`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.
|
||||
{{</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.
|
||||
|
||||
## Creating a CompositeResourceDefinition
|
||||
|
||||
Creating a CompositeResourceDefinition consists of:
|
||||
* [Defining a custom API group](#xrd-groups).
|
||||
* [Defining a custom API name](#xrd-names).
|
||||
* [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
|
||||
Kubernetes cluster.
|
||||
|
||||
Creating a new API requires defining an API
|
||||
{{<hover label="xrd1" line="6">}}group{{</hover>}},
|
||||
{{<hover label="xrd1" line="7">}}name{{</hover>}} and
|
||||
{{<hover label="xrd1" line="10">}}version{{</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
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
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 >}}
|
||||
creates a custom resource definition
|
||||
{{<hover label="kubeapi" line="2">}}xmydatabases.example.org{{</hover >}}.
|
||||
|
||||
```shell {label="kubeapi",copy-lines="3"}
|
||||
kubectl api-resources
|
||||
NAME SHORTNAMES APIVERSION NAMESPACED KIND
|
||||
xmydatabases.example.org v1alpha1 false xmydatabases
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
{{<hint "warning">}}
|
||||
You can't change the XRD
|
||||
{{<hover label="xrd1" line="6">}}group{{</hover>}} or
|
||||
{{<hover label="xrd1" line="7">}}names{{</hover>}}.
|
||||
You must delete and
|
||||
recreate the XRD to change the
|
||||
{{<hover label="xrd1" line="6">}}group{{</hover>}} or
|
||||
{{<hover label="xrd1" line="7">}}names{{</hover>}}.
|
||||
{{</hint >}}
|
||||
|
||||
### XRD groups
|
||||
|
||||
Groups define a collection of related API endpoints. The `group` can be any
|
||||
value, but common convention is to map to a fully qualified domain name.
|
||||
|
||||
<!-- vale write-good.Weasel = NO -->
|
||||
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.
|
||||
The required name fields are:
|
||||
|
||||
* `kind` - the `kind` value to use when calling this API. The kind is
|
||||
[UpperCamelCased](https://kubernetes.io/docs/contribute/style/style-guide/#use-upper-camel-case-for-api-objects).
|
||||
Crossplane recommends starting XRD `kinds` with an `X` to show
|
||||
it's a custom Crossplane API definition.
|
||||
* `plural` - the plural name used for the API URL. The plural name must be
|
||||
lowercase.
|
||||
|
||||
{{<hint "important" >}}
|
||||
The XRD
|
||||
{{<hover label="xrdName" line="4">}}metadata.name{{</hover>}} must be
|
||||
{{<hover label="xrdName" line="9">}}plural{{</hover>}} name, `.` (dot character),
|
||||
{{<hover label="xrdName" line="6">}}group{{</hover>}}.
|
||||
|
||||
For example, {{<hover label="xrdName"
|
||||
line="4">}}xmydatabases.example.org{{</hover>}} matches the {{<hover
|
||||
label="xrdName" line="9">}}plural{{</hover>}} name
|
||||
{{<hover label="xrdName" line="9">}}xmydatabases{{</hover>}}, `.`
|
||||
{{<hover label="xrdName" line="6">}}group{{</hover>}} name,
|
||||
{{<hover label="xrdName" line="6">}}example.org{{</hover>}}.
|
||||
|
||||
```yaml {label="xrdName",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
|
||||
```
|
||||
{{</hint >}}
|
||||
|
||||
### XRD versions
|
||||
|
||||
<!-- vale gitlab.SentenceLength = NO -->
|
||||
The XRD `version` is like the
|
||||
[API versioning used by Kubernetes](https://kubernetes.io/docs/reference/using-api/#api-versioning).
|
||||
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.
|
||||
|
||||
#### Define a schema
|
||||
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
<!-- vale write-good.TooWordy = NO -->
|
||||
The `schema` defines the names
|
||||
of the parameters, the data types of the parameters and which parameters are
|
||||
required or optional.
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
<!-- vale write-good.TooWordy = YES -->
|
||||
|
||||
{{<hint "note" >}}
|
||||
All `schemas` follow the Kubernetes custom resource definition
|
||||
[OpenAPIv3 structural schema](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema).
|
||||
{{< /hint >}}
|
||||
|
||||
Each
|
||||
{{<hover label="schema" line="11">}}version{{</hover>}} of the API has a unique
|
||||
{{<hover label="schema" line="12">}}schema{{</hover>}}.
|
||||
|
||||
All XRD {{<hover label="schema" line="12">}}schemas{{</hover>}} validate against
|
||||
the {{<hover label="schema" line="13">}}openAPIV3Schema{{</hover>}}. The schema
|
||||
is an OpenAPI
|
||||
{{<hover label="schema" line="14">}}object{{</hover>}} with the
|
||||
{{<hover label="schema" line="15">}}properties{{</hover>}} of a
|
||||
{{<hover label="schema" line="16">}}spec{{</hover>}}
|
||||
{{<hover label="schema" line="17">}}object{{</hover>}}.
|
||||
|
||||
Inside the {{<hover label="schema" line="18">}}spec.properties{{</hover>}} is the custom
|
||||
API definition.
|
||||
|
||||
In this example, the key {{<hover label="schema" line="19">}}region{{</hover>}}
|
||||
is a {{<hover label="schema" line="20">}}string{{</hover>}}.
|
||||
|
||||
```yaml {label="schema",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
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
A composite resource using this API references the
|
||||
{{<hover label="xr" line="1">}}group/version{{</hover>}} and
|
||||
{{<hover label="xr" line="2">}}kind{{</hover>}}. The
|
||||
{{<hover label="xr" line="5">}}spec{{</hover>}} has the
|
||||
{{<hover label="xr" line="6">}}region{{</hover>}} key with a string value.
|
||||
|
||||
```yaml {label="xr"}
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: xDatabase
|
||||
metadata:
|
||||
name: my-composite-resource
|
||||
spec:
|
||||
region: "US"
|
||||
```
|
||||
|
||||
|
||||
{{<hint "tip" >}}
|
||||
The custom API defined inside the
|
||||
{{<hover label="schema" line="18">}}spec.properties{{</hover>}} is an OpenAPIv3
|
||||
specification. The
|
||||
[data models page](https://swagger.io/docs/specification/data-models/) of
|
||||
the Swagger documentation provides a list of examples using data types and input
|
||||
restrictions.
|
||||
|
||||
The Kubernetes documentation lists
|
||||
[the set of special restrictions](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation)
|
||||
on what your OpenAPIv3 custom API can use.
|
||||
{{< /hint >}}
|
||||
|
||||
{{<hint "important" >}}
|
||||
|
||||
Changing or expanding the XRD schema requires restarting the [Crossplane
|
||||
pod]({{<ref "./pods#crossplane-pod">}}) to take effect.
|
||||
{{< /hint >}}
|
||||
|
||||
##### Required fields
|
||||
|
||||
By default all fields in a schema are optional. Define a parameter as required
|
||||
with the
|
||||
{{< hover label="required" line="25">}}required{{</hover>}} attribute.
|
||||
|
||||
In this example the XRD requires
|
||||
{{< hover label="required" line="19">}}region{{</hover>}} and
|
||||
{{< hover label="required" line="21">}}size{{</hover>}} but
|
||||
{{< hover label="required" line="23">}}name{{</hover>}} is optional.
|
||||
```yaml {label="required",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
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
size:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
required:
|
||||
- region
|
||||
- size
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
According to the OpenAPIv3 specification, the `required` field is per-object. If
|
||||
a schema contains multiple objects the schema may need multiple `required`
|
||||
fields.
|
||||
|
||||
This XRD defines two objects:
|
||||
1. the top-level {{<hover label="required2" line="7">}}spec{{</hover>}} object
|
||||
2. a second {{<hover label="required2" line="14">}}location{{</hover>}} object
|
||||
|
||||
The {{<hover label="required2" line="7">}}spec{{</hover>}} object
|
||||
{{<hover label="required2" line="23">}}requires{{</hover>}} the
|
||||
{{<hover label="required2" line="10">}}size{{</hover>}} and
|
||||
{{<hover label="required2" line="14">}}location{{</hover>}} but
|
||||
{{<hover label="required2" line="12">}}name{{</hover>}} is optional.
|
||||
|
||||
Inside the required {{<hover label="required2" line="14">}}location{{</hover>}}
|
||||
object,
|
||||
{{<hover label="required2" line="17">}}country{{</hover>}} is
|
||||
{{<hover label="required2" line="21">}}required{{</hover>}} and
|
||||
{{<hover label="required2" line="19">}}zone{{</hover>}} is optional.
|
||||
|
||||
```yaml {copy-lines="none",label="required2"}
|
||||
# Removed for brevity
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
size:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
location:
|
||||
type: object
|
||||
properties:
|
||||
country:
|
||||
type: string
|
||||
zone:
|
||||
type: string
|
||||
required:
|
||||
- country
|
||||
required:
|
||||
- size
|
||||
- location
|
||||
```
|
||||
|
||||
The Swagger "[Describing
|
||||
Parameters](https://swagger.io/docs/specification/describing-parameters/)"
|
||||
documentation has more examples.
|
||||
|
||||
##### Crossplane reserved fields
|
||||
|
||||
Crossplane doesn't allow the following fields in a schema:
|
||||
* `spec.resourceRef`
|
||||
* `spec.resourceRefs`
|
||||
* `spec.claimRef`
|
||||
* `spec.writeConnectionSecretToRef`
|
||||
* `status.conditions`
|
||||
* `status.connectionDetails`
|
||||
|
||||
Crossplane ignores any fields matching the reserved fields.
|
||||
|
||||
#### Serve and reference a schema
|
||||
|
||||
To use a schema it must be
|
||||
{{<hover label="served" line="12" >}}served: true{{</hover >}}
|
||||
and
|
||||
{{<hover label="served" line="13" >}}referenceable: true{{</hover>}}.
|
||||
|
||||
```yaml {label="served"}
|
||||
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
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
```
|
||||
|
||||
Composite resources can use any schema version set as
|
||||
{{<hover label="served" line="12" >}}served: true{{</hover >}}.
|
||||
Kubernetes rejects any composite resource using a schema version set as `served:
|
||||
false`.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Setting a schema version as `served:false` causes errors for users using an older
|
||||
schema. This can be an effective way to identify and upgrade users before
|
||||
deleting the older schema version.
|
||||
{{< /hint >}}
|
||||
|
||||
The {{<hover label="served" line="13" >}}referenceable: true{{</hover>}}
|
||||
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#enabling-composite-resources" >}})
|
||||
of any Compositions referencing that XRD.
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
#### Multiple schema versions
|
||||
|
||||
{{<hint "warning" >}}
|
||||
Crossplane supports defining multiple `versions`, but the schema of each version
|
||||
can't change any existing fields, also called "making a breaking change."
|
||||
|
||||
Breaking schema changes between versions requires the use of [conversion
|
||||
webhooks](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#webhook-conversion).
|
||||
|
||||
New versions may define new optional parameters, but new required fields are
|
||||
a "breaking change."
|
||||
|
||||
<!-- vale Crossplane.Spelling = NO -->
|
||||
<!-- ignore to allow for CRDs -->
|
||||
<!-- don't add to the spelling exceptions to catch when it's used instead of XRD -->
|
||||
Crossplane XRDs use Kubernetes custom resource definitions for versioning.
|
||||
Read the Kubernetes documentation on
|
||||
[versions in CustomResourceDefinitions](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/)
|
||||
for more background on versions and breaking changes.
|
||||
<!-- vale Crossplane.Spelling = YES -->
|
||||
|
||||
Crossplane recommends implementing breaking schema changes as brand new XRDs.
|
||||
{{< /hint >}}
|
||||
|
||||
For XRDs, to create a new version of an API add a new
|
||||
{{<hover label="ver" line="21">}}name{{</hover>}} in the
|
||||
{{<hover label="ver" line="10">}}versions{{</hover>}}
|
||||
list.
|
||||
|
||||
For example, this XRD version
|
||||
{{<hover label="ver" line="11">}}v1alpha1{{</hover>}} only has the field
|
||||
{{<hover label="ver" line="19">}}region{{</hover>}}.
|
||||
|
||||
A second version,
|
||||
{{<hover label="ver" line="21">}}v1{{</hover>}} expands the API to have both
|
||||
{{<hover label="ver" line="29">}}region{{</hover>}} and
|
||||
{{<hover label="ver" line="31">}}size{{</hover>}}.
|
||||
|
||||
```yaml {label="ver",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
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
- name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
size:
|
||||
type: string
|
||||
```
|
||||
|
||||
{{<hint "important" >}}
|
||||
|
||||
Changing or expanding the XRD schema requires restarting the [Crossplane
|
||||
pod]({{<ref "./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#storing-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 "/knowledge-base/guides/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 deletion policy for composite
|
||||
resources and claims.
|
||||
|
||||
Using a `defaultCompositeDeletePolicy: Background` policy deletes
|
||||
the composite resource or Claim and relies on Kubernetes to delete the remaining
|
||||
dependent objects, like managed resources or secrets.
|
||||
|
||||
Using `defaultCompositeDeletePolicy: Foreground` causes Kubernetes to attach a
|
||||
`foregroundDeletion` finalizer to the composite resource or Claim. Kubernetes
|
||||
deletes all the dependent objects before deleting the composite resource or
|
||||
Claim.
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
<!-- 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.
|
||||
|
||||
An XRD can define the default Composition to use with the
|
||||
`defaultCompositionRef` value.
|
||||
|
||||
Set a
|
||||
{{<hover label="defaultComp" line="6">}}defaultCompositionRef{{</hover>}}
|
||||
to set the default Composition.
|
||||
|
||||
```yaml {label="defaultComp",copy-lines="none"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xdatabases.custom-api.example.org
|
||||
spec:
|
||||
defaultCompositionRef:
|
||||
name: myComposition
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
# Removed for brevity
|
||||
versions:
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
#### defaultCompositionUpdatePolicy
|
||||
<!-- vale on -->
|
||||
|
||||
Changes to a Composition generate a new Composition revision. By default all
|
||||
composite resources and Claims use the updated Composition revision.
|
||||
|
||||
Set the XRD `defaultCompositionUpdatePolicy` to `Manual` to prevent composite
|
||||
resources and Claims from automatically using the new revision.
|
||||
|
||||
The default value is `defaultCompositionUpdatePolicy: Automatic`.
|
||||
|
||||
Set {{<hover label="compRev" line="6">}}defaultCompositionUpdatePolicy: Manual{{</hover>}}
|
||||
to set the default Composition update policy for composite resources and Claims
|
||||
using this XRD.
|
||||
|
||||
```yaml {label="compRev",copy-lines="none"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xdatabases.custom-api.example.org
|
||||
spec:
|
||||
defaultCompositionUpdatePolicy: Manual
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
# Removed for brevity
|
||||
versions:
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
#### enforcedCompositionRef
|
||||
<!-- vale on -->
|
||||
To require all composite resources or Claims to use a specific Composition use
|
||||
the `enforcedCompositionRef` setting in the XRD.
|
||||
|
||||
For example, to require all composite resources and Claims using this XRD to use
|
||||
the Composition
|
||||
{{<hover label="enforceComp" line="6">}}myComposition{{</hover>}}
|
||||
set
|
||||
{{<hover label="enforceComp" line="6">}}enforcedCompositionRef.name: myComposition{{</hover>}}.
|
||||
|
||||
```yaml {label="defaultComp",copy-lines="none"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xdatabases.custom-api.example.org
|
||||
spec:
|
||||
enforcedCompositionRef:
|
||||
name: myComposition
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
# Removed for brevity
|
||||
versions:
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
## Verify a CompositeResourceDefinition
|
||||
|
||||
Verify an XRD with `kubectl get compositeresourcedefinition` or the short form,
|
||||
{{<hover label="getxrd" line="1">}}kubectl get xrd{{</hover>}}.
|
||||
|
||||
```yaml {label="getxrd",copy-lines="1"}
|
||||
kubectl get xrd
|
||||
NAME ESTABLISHED OFFERED AGE
|
||||
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
|
||||
`kubectl describe xrd`.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
kubectl describe xrd
|
||||
Name: xpostgresqlinstances.database.starter.org
|
||||
API Version: apiextensions.crossplane.io/v1
|
||||
Kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
Status:
|
||||
Conditions:
|
||||
Reason: WatchingCompositeResource
|
||||
Status: True
|
||||
Type: Established
|
||||
Reason: WatchingCompositeResourceClaim
|
||||
Status: True
|
||||
Type: Offered
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
#### WatchingCompositeResource
|
||||
<!-- vale on -->
|
||||
`Reason: WatchingCompositeResource` indicates Crossplane defined the new
|
||||
Kubernetes custom resource definitions related to the composite resource and is
|
||||
watching for the creation of new composite resources.
|
||||
|
||||
```yaml
|
||||
Type: Established
|
||||
Status: True
|
||||
Reason: WatchingCompositeResource
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
#### TerminatingCompositeResource
|
||||
<!-- vale on -->
|
||||
`Reason: TerminatingCompositeResource` indicates Crossplane is deleting the
|
||||
custom resource definitions related to the composite resource and is
|
||||
terminating the composite resource controller.
|
||||
|
||||
```yaml
|
||||
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,472 @@
|
|||
---
|
||||
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:
|
||||
resources:
|
||||
- name: database
|
||||
base:
|
||||
# Removed for brevity
|
||||
patches:
|
||||
- fromFieldPath: metadata.annotations
|
||||
toFieldPath: metadata.annotations
|
||||
```
|
||||
|
||||
For more information on patching resources refer to the [Patch and
|
||||
Transform]({{<ref "./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
|
||||
[Enabling Composite Resources]({{<ref "./compositions#enabling-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 "/knowledge-base/guides/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 "/knowledge-base/guides/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:
|
||||
compositionRevisionRef: 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 "/knowledge-base/integrations/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 "/knowledge-base/integrations/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 "/knowledge-base/guides/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 manged 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.
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,303 @@
|
|||
---
|
||||
title: Environment Configurations
|
||||
weight: 90
|
||||
state: alpha
|
||||
alphaVersion: "1.11"
|
||||
description: "Environment Configurations or EnvironmentConfigs are an in-memory datastore used in patching Compositions"
|
||||
---
|
||||
|
||||
A Crossplane EnvironmentConfig is an in-memory data store. Composition
|
||||
patches can read from and write to an environment.
|
||||
|
||||
Crossplane supports multiple EnvironmentConfigs, each acting as a unique
|
||||
data store.
|
||||
|
||||
## Enable EnvironmentConfigs
|
||||
EnvironmentConfigs are an alpha feature. Alpha features aren't enabled by
|
||||
default.
|
||||
|
||||
Enable EnvironmentConfig support by
|
||||
[changing the Crossplane pod setting]({{<ref "./pods#change-pod-settings">}})
|
||||
and enabling
|
||||
{{<hover label="deployment" line="12">}}--enable-environment-configs{{</hover>}}
|
||||
argument.
|
||||
|
||||
```yaml {label="deployment",copy-lines="12"}
|
||||
$ kubectl edit deployment crossplane --namespace crossplane-system
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# Removed for brevity
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- core
|
||||
- start
|
||||
- --enable-environment-configs
|
||||
```
|
||||
|
||||
{{<hint "tip" >}}
|
||||
|
||||
The [Crossplane install guide]({{<ref "../software/install#feature-flags">}})
|
||||
describes enabling feature flags like
|
||||
{{<hover label="deployment" line="12">}}--enable-environment-configs{{</hover>}}
|
||||
with Helm.
|
||||
{{< /hint >}}
|
||||
|
||||
<!-- vale Google.Headings = NO -->
|
||||
## Create an EnvironmentConfig
|
||||
<!-- vale Google.Headings = YES -->
|
||||
|
||||
An {{<hover label="env1" line="2">}}EnvironmentConfig{{</hover>}} has a single
|
||||
object field,
|
||||
{{<hover label="env1" line="5">}}data{{</hover>}}.
|
||||
|
||||
An EnvironmentConfig supports any data inside the
|
||||
{{<hover label="env1" line="5">}}data{{</hover>}} field.
|
||||
|
||||
Here an example
|
||||
{{<hover label="env1" line="2">}}EnvironmentConfig{{</hover>}}.
|
||||
|
||||
```yaml {label="env1"}
|
||||
apiVersion: apiextensions.crossplane.io/v1alpha1
|
||||
kind: EnvironmentConfig
|
||||
metadata:
|
||||
name: example-environment
|
||||
data:
|
||||
locations:
|
||||
us: us-east-2
|
||||
eu: eu-north-1
|
||||
key1: value1
|
||||
key2: value2
|
||||
key3:
|
||||
- item1
|
||||
- item2
|
||||
```
|
||||
|
||||
## Patching with EnvironmentConfigs
|
||||
|
||||
To patch data from or to an EnvironmentConfig, reference the EnvironmentConfig
|
||||
inside a Composition's
|
||||
{{<hover label="comp" line="6">}}environment{{</hover>}} field.
|
||||
|
||||
The {{<hover label="comp" line="7">}}environmentConfigs{{</hover>}} field is a
|
||||
list of environments this Composition can use.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Read about EnvironmentConfig patch types in the
|
||||
[Patch and Transform]({{<ref "./patch-and-transform">}}) documentation.
|
||||
{{< /hint >}}
|
||||
|
||||
Select an environment by
|
||||
{{<hover label="comp" line="8">}}Reference{{</hover>}} or
|
||||
by
|
||||
{{<hover label="comp" line="11">}}Selector{{</hover>}}.
|
||||
|
||||
A
|
||||
{{<hover label="comp" line="8">}}Reference{{</hover>}}
|
||||
selects an environment by
|
||||
{{<hover label="comp" line="10">}}name{{</hover>}}.
|
||||
The
|
||||
{{<hover label="comp" line="11">}}Selector{{</hover>}} selects an environment
|
||||
based on the
|
||||
{{<hover label="comp" line="13">}}Labels{{</hover>}} applied to the environment.
|
||||
|
||||
```yaml {label="comp",copy-lines="none"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: example-composition
|
||||
spec:
|
||||
environment:
|
||||
environmentConfigs:
|
||||
- type: Reference
|
||||
ref:
|
||||
name: example-environment
|
||||
- type: Selector
|
||||
selector:
|
||||
matchLabels:
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
If a Composition uses multiple
|
||||
{{<hover label="comp" line="7">}}environmentConfigs{{</hover>}}
|
||||
Crossplane merges them together in the order they're listed.
|
||||
|
||||
{{<hint "note" >}}
|
||||
If multiple
|
||||
{{<hover label="comp" line="7">}}environmentConfigs{{</hover>}}
|
||||
use the same key, the Composition uses the value of the last environment listed.
|
||||
{{</hint >}}
|
||||
|
||||
### Select by name
|
||||
|
||||
Select an environment by name with
|
||||
{{<hover label="byName" line="8">}}type: Reference{{</hover>}}.
|
||||
|
||||
Define the
|
||||
{{<hover label="byName" line="9">}}ref{{</hover>}} object and the
|
||||
{{<hover label="byName" line="10">}}name{{</hover>}} matching the exact name of
|
||||
the environment.
|
||||
|
||||
|
||||
For example, select the
|
||||
{{<hover label="byName" line="7">}}environmentConfig{{</hover>}}
|
||||
named
|
||||
{{<hover label="byName" line="10">}}example-environment{{</hover>}}
|
||||
|
||||
```yaml {label="byName",copy-lines="all"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: example-composition
|
||||
spec:
|
||||
environment:
|
||||
environmentConfigs:
|
||||
- type: Reference
|
||||
ref:
|
||||
name: example-environment
|
||||
```
|
||||
|
||||
### Select by label
|
||||
|
||||
Select an environment by labels with a
|
||||
{{<hover label="byLabel" line="8">}}type: Selector{{</hover>}}.
|
||||
|
||||
Define the {{<hover label="byLabel" line="9">}}selector{{</hover>}} object.
|
||||
|
||||
The
|
||||
{{<hover label="byLabel" line="10">}}matchLabels{{</hover>}} object contains a
|
||||
list of labels to match on.
|
||||
|
||||
Selecting a label requires matching both the label
|
||||
{{<hover label="byLabel" line="11">}}key{{</hover>}}
|
||||
and the value of key.
|
||||
|
||||
When matching the label's value, provide an exact value with a
|
||||
{{<hover label="byLabel" line="12">}}type: Value{{</hover>}} and provide the value
|
||||
to match in the
|
||||
{{<hover label="byLabel" line="13">}}value{{</hover>}} field.
|
||||
|
||||
Crossplane can also match a label's value based on an input in the composite
|
||||
resource. Use
|
||||
{{<hover label="byLabel" line="15">}}type: FromCompositeFieldPath{{</hover>}}
|
||||
and provide the field to match in the
|
||||
{{<hover label="byLabel" line="16">}}valueFromFieldPath{{</hover>}} field.
|
||||
|
||||
```yaml {label="byLabel",copy-lines="all"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: example-composition
|
||||
spec:
|
||||
environment:
|
||||
environmentConfigs:
|
||||
- type: Selector
|
||||
selector:
|
||||
matchLabels:
|
||||
- key: my-label-key
|
||||
type: Value
|
||||
value: my-label-value
|
||||
- key: my-label-key
|
||||
type: FromCompositeFieldPath
|
||||
valueFromFieldPath: spec.parameters.deploy
|
||||
resources:
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
#### Manage selector results
|
||||
|
||||
Selecting environments by labels may return more than one environment.
|
||||
The Composition sorts all the results by the name of the environments and
|
||||
only uses the first environment in the sorted list.
|
||||
|
||||
Set the {{<hover label="selectResults" line="10">}}mode{{</hover>}} as
|
||||
{{<hover label="selectResults" line="10">}}mode: Multiple{{</hover>}} to return
|
||||
all matched environments. Use
|
||||
{{<hover label="selectResults" line="19">}}mode: Single{{</hover>}} to
|
||||
return a single environment.
|
||||
|
||||
{{<hint "note" >}}
|
||||
Sorting and the selection
|
||||
{{<hover label="selectResults" line="10">}}mode{{</hover>}}
|
||||
only applies to a single
|
||||
{{<hover label="selectResults" line="8">}}type: Selector{{</hover>}}.
|
||||
|
||||
This doesn't change how Compositions merge multiple
|
||||
{{<hover label="selectResults" line="7">}}environmentConfigs{{</hover>}}.
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
```yaml {label="selectResults"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: example-composition
|
||||
spec:
|
||||
environment:
|
||||
environmentConfigs:
|
||||
- type: Selector
|
||||
selector:
|
||||
mode: Multiple
|
||||
matchLabels:
|
||||
- key: my-label-key
|
||||
type: Value
|
||||
value: my-label-value
|
||||
- key: my-label-key
|
||||
type: FromCompositeFieldPath
|
||||
valueFromFieldPath: spec.parameters.deploy
|
||||
- type: Selector
|
||||
selector:
|
||||
mode: Single
|
||||
matchLabels:
|
||||
- key: my-other-label-key
|
||||
type: Value
|
||||
value: my-other-label-value
|
||||
- key: my-other-label-key
|
||||
type: FromCompositeFieldPath
|
||||
valueFromFieldPath: spec.parameters.deploy
|
||||
```
|
||||
|
||||
When using
|
||||
{{<hover label="maxMatch" line="10">}}mode: Multiple{{</hover>}} limit the
|
||||
number of returned environments with
|
||||
{{<hover label="maxMatch" line="11">}}maxMatch{{</hover>}} and define the
|
||||
maximum number of environments returned.
|
||||
|
||||
The Composition sorts the returned environments alphabetically by name. Sort the
|
||||
environments on a different field with
|
||||
{{<hover label="maxMatch" line="12">}}sortByFieldPath{{</hover>}} and define
|
||||
the field to sort by.
|
||||
|
||||
|
||||
```yaml {label="maxMatch"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: example-composition
|
||||
spec:
|
||||
environment:
|
||||
environmentConfigs:
|
||||
- type: Selector
|
||||
selector:
|
||||
mode: Multiple
|
||||
maxMatch: 4
|
||||
sortByFieldPath: metadata.annotations[sort.by/weight]
|
||||
matchLabels:
|
||||
- key: my-label-key
|
||||
type: Value
|
||||
value: my-label-value
|
||||
- key: my-label-key
|
||||
type: FromCompositeFieldPath
|
||||
valueFromFieldPath: spec.parameters.deploy
|
||||
```
|
||||
|
||||
The environments selected by
|
||||
{{<hover label="maxMatch" line="18">}}matchLabels{{</hover>}} are then merged
|
||||
into any other environments listed in the
|
||||
{{<hover label="maxMatch" line="7">}}environmentConfigs{{</hover>}}.
|
||||
<!--
|
||||
TODO: Add Policies
|
||||
TODO: Add webhook validations
|
||||
-->
|
|
@ -0,0 +1,760 @@
|
|||
---
|
||||
title: Managed Resources
|
||||
weight: 10
|
||||
description: "Managed resources are the Crossplane representation of external provider resources"
|
||||
---
|
||||
|
||||
A _managed resource_ (`MR`) represents an external service in a Provider. When
|
||||
users create a new managed resource, the Provider reacts by creating an external
|
||||
resource inside the Provider's environment. Every external service managed by
|
||||
Crossplane maps to a managed resource.
|
||||
|
||||
{{< hint "note" >}}
|
||||
Crossplane calls the object inside Kubernetes a _managed resource_ and the
|
||||
external object inside the Provider an _external resource_.
|
||||
{{< /hint >}}
|
||||
|
||||
Examples of managed resources include:
|
||||
* Amazon AWS EC2 [`Instance`](https://marketplace.upbound.io/providers/upbound/provider-aws/latest/resources/ec2.aws.upbound.io/Instance/v1beta1)
|
||||
* Google Cloud GKE [`Cluster`](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/resources/container.gcp.upbound.io/Cluster/v1beta1)
|
||||
* Microsoft Azure PostgreSQL [`Database`](https://marketplace.upbound.io/providers/upbound/provider-azure/latest/resources/dbforpostgresql.azure.upbound.io/Database/v1beta1)
|
||||
|
||||
{{< hint "tip" >}}
|
||||
|
||||
You can create individual managed resources, but Crossplane recommends using
|
||||
[Compositions]({{<ref "./compositions" >}}) and Claims to create
|
||||
managed resources.
|
||||
{{< /hint >}}
|
||||
|
||||
## Managed resource fields
|
||||
|
||||
The Provider defines the group, kind and version of a managed resource. The
|
||||
Provider also define the available settings of a managed resource.
|
||||
|
||||
### Group, kind and version
|
||||
Each managed resource is a unique API endpoint with their own
|
||||
group, kind and version.
|
||||
|
||||
For example the [Upbound AWS
|
||||
Provider](https://marketplace.upbound.io/providers/upbound/provider-aws/latest/)
|
||||
defines the {{<hover label="gkv" line="2">}}Instance{{</hover>}} kind from the
|
||||
group {{<hover label="gkv" line="1">}}ec2.aws.upbound.io{{</hover>}}
|
||||
|
||||
```yaml {label="gkv",copy-lines="none"}
|
||||
apiVersion: ec2.aws.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.
|
||||
|
||||
<!-- vale off -->
|
||||
### forProvider
|
||||
<!-- vale on -->
|
||||
|
||||
The {{<hover label="forProvider" line="4">}}spec.forProvider{{</hover>}} of a
|
||||
managed resource maps to the parameters of the external resource.
|
||||
|
||||
For example, when creating an AWS EC2 instance, the Provider supports defining
|
||||
the AWS {{<hover label="forProvider" line="5">}}region{{</hover>}} and the VM
|
||||
size, called the
|
||||
{{<hover label="forProvider" line="6">}}instanceType{{</hover>}}.
|
||||
|
||||
{{< hint "note" >}}
|
||||
The Provider defines the settings and their valid values. Providers also define
|
||||
required and optional values in the `forProvider` definition.
|
||||
|
||||
Refer to the documentation of your specific Provider for details.
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
```yaml {label="forProvider",copy-lines="none"}
|
||||
apiVersion: ec2.aws.upbound.io/v1beta1
|
||||
kind: Instance
|
||||
# Removed for brevity
|
||||
spec:
|
||||
forProvider:
|
||||
region: us-west-1
|
||||
instanceType: t2.micro
|
||||
```
|
||||
|
||||
{{< hint "important">}}
|
||||
Crossplane considers the `forProvider` field of a managed resource
|
||||
the "source of truth" for external resources. Crossplane overrides any changes
|
||||
made to an external resource outside of Crossplane. If a user makes a change
|
||||
inside a Provider's web console, Crossplane reverts that change back to what's
|
||||
configured in the `forProvider` setting.
|
||||
{{< /hint >}}
|
||||
|
||||
Providers add any settings not manually set to the `forProvider` field of the
|
||||
created managed resource object.
|
||||
Use `kubectl describe <managed_resource>` to view the applied values.
|
||||
|
||||
#### Referencing other resources
|
||||
|
||||
Some fields in a managed resource may depend on values from other managed
|
||||
resources. For example a VM may need the name of a virtual network to use.
|
||||
|
||||
Managed resources can reference other managed resources by external name, name
|
||||
reference or selector.
|
||||
|
||||
##### Matching by external name
|
||||
|
||||
When matching a resource by name Crossplane looks for the name of the external
|
||||
resource in the Provider.
|
||||
|
||||
For example, a AWS VPC object named `my-test-vpc` has the external name
|
||||
`vpc-01353cfe93950a8ff`.
|
||||
|
||||
```shell {copy-lines="1"
|
||||
kubectl get vpc
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-test-vpc True True vpc-01353cfe93950a8ff 49m
|
||||
```
|
||||
|
||||
To match the VPC by name, use the external name. For example, creating a Subnet
|
||||
managed resource attached to this VPC.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
apiVersion: ec2.aws.upbound.io/v1beta1
|
||||
kind: Subnet
|
||||
spec:
|
||||
forProvider:
|
||||
# Removed for brevity
|
||||
vpcId: vpc-01353cfe93950a8ff
|
||||
```
|
||||
|
||||
##### Matching by name reference
|
||||
|
||||
To match a resource based on the name of the managed resource and not the
|
||||
external resource name inside the Provider, use a `nameRef`.
|
||||
|
||||
For example, a AWS VPC object named `my-test-vpc` has the external name
|
||||
`vpc-01353cfe93950a8ff`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get vpc
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-test-vpc True True vpc-01353cfe93950a8ff 49m
|
||||
```
|
||||
|
||||
To match the VPC by name reference, use the managed resource name. For example,
|
||||
creating a Subnet managed resource attached to this VPC.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
apiVersion: ec2.aws.upbound.io/v1beta1
|
||||
kind: Subnet
|
||||
spec:
|
||||
forProvider:
|
||||
# Removed for brevity
|
||||
vpcIdRef:
|
||||
name: my-test-vpc
|
||||
```
|
||||
|
||||
|
||||
##### Matching by selector
|
||||
|
||||
Matching by selector is the most flexible matching method.
|
||||
|
||||
{{<hint "note" >}}
|
||||
|
||||
The [Compositions]({{<ref "./compositions">}}) section covers the
|
||||
`matchControllerRef` selector.
|
||||
{{</hint >}}
|
||||
|
||||
Use `matchLabels` to match the labels applied to a resource. For example, this
|
||||
Subnet resource only matches VPC resources with the label
|
||||
`my-label: label-value`.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
apiVersion: ec2.aws.upbound.io/v1beta1
|
||||
kind: Subnet
|
||||
spec:
|
||||
forProvider:
|
||||
# Removed for brevity
|
||||
vpcIdSelector:
|
||||
matchLabels:
|
||||
my-label: label-value
|
||||
```
|
||||
|
||||
|
||||
#### Immutable fields
|
||||
|
||||
Some providers don't support changing the fields of some managed resources after
|
||||
creation. For example, you can't change the `region` of an Amazon AWS
|
||||
`RDSInstance`. These fields are _immutable fields_. Amazon requires you delete
|
||||
and recreate the resource.
|
||||
|
||||
Crossplane allows you to edit the immutable field of a managed resource, but
|
||||
doesn't apply the change. Crossplane never deletes a resource based on a
|
||||
`forProvider` change.
|
||||
|
||||
{{<hint "note" >}}
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
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`.
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
<!-- vale off -->
|
||||
### managementPolicy
|
||||
<!-- vale on -->
|
||||
|
||||
{{<hint "important" >}}
|
||||
The managed resource `managementPolicy` option is an alpha feature.
|
||||
|
||||
Enable the `managementPolicy` in a provider with `--enable-management-policies`
|
||||
in a
|
||||
[ControllerConfig]({{<ref "./providers#controller-configuration" >}}).
|
||||
{{< /hint >}}
|
||||
|
||||
A `managementPolicy` determines if Crossplane can make changes to managed
|
||||
resources. The `ObserveOnly` policy imports existing external resources not
|
||||
originally created by Crossplane.
|
||||
This allows new managed resources to reference
|
||||
the `ObserveOnly` resource, for example, a shared database or network.
|
||||
The `ObserveOnly` policy can also place existing resources under the control of
|
||||
Crossplane.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Read the [Import Existing Resources]({{<ref "/knowledge-base/guides/import-existing-resources" >}})
|
||||
guide for more
|
||||
information on using the `managementPolicy` to import existing resources.
|
||||
{{< /hint >}}
|
||||
|
||||
#### Options
|
||||
* `managementPolicy: FullControl` - **Default** - Crossplane can create, change
|
||||
and delete the managed resource.
|
||||
* `managementPolicy: ObserveOnly` - Crossplane only imports the details of the
|
||||
external resource, but doesn't make any changes to the managed resource.
|
||||
|
||||
|
||||
<!-- vale off -->
|
||||
### providerConfigRef
|
||||
<!-- vale on -->
|
||||
|
||||
The `providerConfigRef` on a managed resource tells the Provider which
|
||||
[ProviderConfig]({{<ref "./providers#provider-configuration">}}) to
|
||||
use when creating the managed resource.
|
||||
|
||||
Use a ProviderConfig to define the authentication method to use when
|
||||
communicating to the Provider.
|
||||
|
||||
{{< hint "important" >}}
|
||||
If `providerConfigRef` isn't applied, Providers use the ProviderConfig named `default`.
|
||||
{{< /hint >}}
|
||||
|
||||
For example, a managed resource references a ProviderConfig named
|
||||
{{<hover label="pcref" line="6">}}user-keys{{</hover>}}.
|
||||
|
||||
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
|
||||
kind: Instance
|
||||
spec:
|
||||
forProvider:
|
||||
# Removed for brevity
|
||||
providerConfigRef: user-keys
|
||||
```
|
||||
|
||||
```yaml {label="pc"}
|
||||
apiVersion: aws.crossplane.io/v1beta1
|
||||
kind: ProviderConfig
|
||||
metadata:
|
||||
name: user-keys
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Each managed resource can reference different ProviderConfigs. This allows
|
||||
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 -->
|
||||
|
||||
When a Provider creates a managed resource it may generate resource-specific
|
||||
details, like usernames, passwords or connection details like an IP address.
|
||||
|
||||
Crossplane stores these details in a Kubernetes Secret object specified by the
|
||||
`writeConnectionSecretToRef` values.
|
||||
|
||||
For example, when creating an AWS RDS database instance with the Crossplane
|
||||
[community AWS provider](https://marketplace.upbound.io/providers/crossplane-contrib/provider-aws/v0.40.0)
|
||||
generates an endpoint, password, port and username data. The Provider saves
|
||||
these variables in the Kubernetes secret
|
||||
{{<hover label="secretname" line="9" >}}rds-secret{{</hover>}}, referenced by
|
||||
the
|
||||
{{<hover label="secretname" line="9" >}}writeConnectionSecretToRef{{</hover>}}
|
||||
field.
|
||||
|
||||
```yaml {label="secretname",copy-lines="none"}
|
||||
apiVersion: database.aws.crossplane.io/v1beta1
|
||||
kind: RDSInstance
|
||||
metadata:
|
||||
name: my-rds-instance
|
||||
spec:
|
||||
forProvider:
|
||||
# Removed for brevity
|
||||
writeConnectionSecretToRef:
|
||||
name: rds-secret
|
||||
```
|
||||
|
||||
Viewing the Secret object shows the saved fields.
|
||||
|
||||
```yaml {copy-lines="1"}
|
||||
kubectl describe secret rds-secret
|
||||
Name: rds-secret
|
||||
# Removed for brevity
|
||||
Data
|
||||
====
|
||||
port: 4 bytes
|
||||
username: 10 bytes
|
||||
endpoint: 54 bytes
|
||||
password: 27 bytes
|
||||
```
|
||||
|
||||
{{<hint "important" >}}
|
||||
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
|
||||
[ControllerConfig]({{<ref "providers#controller-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 "knowledge-base/integrations/vault-as-secret-store">}})
|
||||
guide for details on using StoreConfig objects.
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
## Annotations
|
||||
|
||||
Crossplane applies a standard set of Kubernetes `annotations` to managed
|
||||
resources.
|
||||
|
||||
{{<table "table table-sm">}}
|
||||
| Annotation | Definition |
|
||||
| --- | --- |
|
||||
| `crossplane.io/external-name` | The name of the managed resource inside the Provider. |
|
||||
| `crossplane.io/external-create-pending` | The timestamp of when Crossplane
|
||||
began creating a new managed resource. |
|
||||
| `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
|
||||
By default Providers give external resources the same name as the Kubernetes
|
||||
object.
|
||||
|
||||
For example, a managed resource named
|
||||
{{<hover label="external-name" line="4">}}my-rds-instance{{</hover >}} has
|
||||
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
|
||||
kind: RDSInstance
|
||||
metadata:
|
||||
name: my-rds-instance
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl get rdsinstance
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-rds-instance True True my-rds-instance 11m
|
||||
```
|
||||
|
||||
Managed resource created with a `crossplane.io/external-name`
|
||||
annotation already provided use the annotation value as the external
|
||||
resource name.
|
||||
|
||||
For example, the Provider creates managed resource named
|
||||
{{< hover label="custom-name" line="6">}}my-rds-instance{{</hover>}} but uses
|
||||
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
|
||||
kind: RDSInstance
|
||||
metadata:
|
||||
name: my-rds-instance
|
||||
annotations:
|
||||
crossplane.io/external-name: my-custom-namee
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get rdsinstance
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-rds-instance True True my-custom-name 11m
|
||||
```
|
||||
|
||||
### Creation annotations
|
||||
|
||||
Providers create new managed resources with the
|
||||
`crossplane.io/external-create-pending` annotation.
|
||||
|
||||
The Provider applies the `crossplane.io/external-create-succeeded` or
|
||||
`crossplane.io/external-create-failed` annotation after making the external API
|
||||
call and receiving a response.
|
||||
|
||||
{{<hint "note" >}}
|
||||
If a Provider restarts before creating the `succeed` or `fail` annotations the
|
||||
Provider can't reconcile the manged resource.
|
||||
|
||||
Read Crossplane [issue
|
||||
#3037](https://github.com/crossplane/crossplane/issues/3037#issuecomment-1110142427)
|
||||
for more details
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
### Paused
|
||||
Manually applying the `crossplane.io/paused` annotation causes the Provider to
|
||||
stop reconciling the managed resource.
|
||||
|
||||
Pausing a resource is useful when modifying Providers or preventing
|
||||
race-conditions when editing Kubernetes objects.
|
||||
|
||||
Apply a {{<hover label="pause" line="6">}}crossplane.io/paused: "true"{{</hover>}}
|
||||
annotation to a managed resource to pause reconciliation.
|
||||
|
||||
{{< hint "note" >}}
|
||||
Only the value `"true"` pauses reconciliation.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml {label="pause"}
|
||||
apiVersion: ec2.aws.upbound.io/v1beta1
|
||||
kind: Instance
|
||||
metadata:
|
||||
name: my-rds-instance
|
||||
annotations:
|
||||
crossplane.io/paused: "true"
|
||||
spec:
|
||||
forProvider:
|
||||
region: us-west-1
|
||||
instanceType: t2.micro
|
||||
```
|
||||
|
||||
Remove the annotation to resume reconciliation.
|
||||
|
||||
## Finalizers
|
||||
Crossplane applies a
|
||||
[Finalizer](https://kubernetes.io/docs/concepts/overview/working-with-objects/finalizers/)
|
||||
on managed resources to control their deletion.
|
||||
|
||||
{{< hint "note" >}}
|
||||
Kubernetes can't delete objects with Finalizers.
|
||||
{{</hint >}}
|
||||
|
||||
When Crossplane deletes a managed resource the Provider begins deleting the
|
||||
external resource, but the managed resource remains until the external
|
||||
resource is fully deleted.
|
||||
|
||||
When the external resource is fully deleted Crossplane removes the Finalizer and
|
||||
deletes the managed resource object.
|
||||
|
||||
## Conditions
|
||||
|
||||
Crossplane has a standard set of `Conditions` for a managed
|
||||
resource. View the `Conditions` of a managed resource with
|
||||
`kubectl describe <managed_resource>`
|
||||
|
||||
|
||||
{{<hint "note" >}}
|
||||
Providers may define their own custom `Conditions`.
|
||||
{{</hint >}}
|
||||
|
||||
|
||||
### Available
|
||||
`Reason: Available` indicates the Provider created the managed resource and it's
|
||||
ready for use.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: Ready
|
||||
Status: True
|
||||
Reason: Available
|
||||
```
|
||||
### Creating
|
||||
|
||||
`Reason: Creating` indicates the Provider is attempting to create the managed
|
||||
resource.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: Ready
|
||||
Status: False
|
||||
Reason: Creating
|
||||
```
|
||||
|
||||
### Deleting
|
||||
`Reason: Deleting` indicates the Provider is attempting to delete the managed
|
||||
resource.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: Ready
|
||||
Status: False
|
||||
Reason: Deleting
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
### ReconcilePaused
|
||||
<!-- vale on -->
|
||||
`Reason: ReconcilePaused` indicates the managed resource has a [Pause](#paused)
|
||||
annotation
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: Synced
|
||||
Status: False
|
||||
Reason: ReconcilePaused
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
### ReconcileError
|
||||
<!-- vale on -->
|
||||
`Reason: ReconcileError` indicates Crossplane encountered an error while
|
||||
reconciling the managed resource. The `Message:` value of the `Condition` helps
|
||||
identify the Crossplane error.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: Synced
|
||||
Status: False
|
||||
Reason: ReconcileError
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
### ReconcileSuccess
|
||||
<!-- vale on -->
|
||||
`Reason: ReconcileSuccess` indicates the Provider created and is monitoring the
|
||||
managed resource.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: Synced
|
||||
Status: True
|
||||
Reason: ReconcileSuccess
|
||||
```
|
||||
|
||||
### Unavailable
|
||||
`Reason: Unavailable` indicates Crossplane expects the managed resource to be
|
||||
available, but the Provider reports the resource is unhealthy.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: Ready
|
||||
Status: False
|
||||
Reason: Unavailable
|
||||
```
|
||||
|
||||
### Unknown
|
||||
`Reason: Unknown` indicates the Provider has an unexpected error with the
|
||||
managed resource. The `conditions.message` provides more information on what
|
||||
went wrong.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: Unknown
|
||||
Status: False
|
||||
Reason: Unknown
|
||||
```
|
||||
|
||||
|
||||
### Upjet Provider conditions
|
||||
[Upjet](https://github.com/upbound/upjet), the open source tool to generate
|
||||
Crossplane Providers, also has a set of standard `Conditions`.
|
||||
|
||||
|
||||
<!-- vale off -->
|
||||
#### AsyncOperation
|
||||
<!-- vale on -->
|
||||
|
||||
Some resources may take more than a minute to create. Upjet based providers can
|
||||
complete their Kubernetes command before creating the managed resource by using
|
||||
an asynchronous operation.
|
||||
|
||||
|
||||
##### Finished
|
||||
The `Reason: Finished` indicates the asynchronous operation completed
|
||||
successfully.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: AsyncOperation
|
||||
Status: True
|
||||
Reason: Finished
|
||||
```
|
||||
|
||||
|
||||
##### Ongoing
|
||||
|
||||
`Reason: Ongoing` indicates the managed resource operation is still in progress.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: AsyncOperation
|
||||
Status: True
|
||||
Reason: Ongoing
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
#### LastAsyncOperation
|
||||
<!-- vale on -->
|
||||
|
||||
The Upjet `Type: LastAsyncOperation` captures the previous asynchronous
|
||||
operation status as either `Success` or a failure `Reason`.
|
||||
|
||||
<!-- vale off -->
|
||||
##### ApplyFailure
|
||||
<!-- vale on -->
|
||||
|
||||
`Reason: ApplyFailure` indicates the Provider failed to apply a setting to the
|
||||
managed resource. The `conditions.message` provides more information on what
|
||||
went wrong.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: LastAsyncOperation
|
||||
Status: False
|
||||
Reason: ApplyFailure
|
||||
```
|
||||
|
||||
<!-- vale off -->
|
||||
##### DestroyFailure
|
||||
<!-- vale on -->
|
||||
|
||||
`Reason: DestroyFailure` indicates the Provider failed to delete the managed
|
||||
resource. The `conditions.message` provides more information on what
|
||||
went wrong.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: LastAsyncOperation
|
||||
Status: False
|
||||
Reason: DestroyFailure
|
||||
```
|
||||
|
||||
##### Success
|
||||
`Reason: Success` indicates the Provider successfully created the managed
|
||||
resource asynchronously.
|
||||
|
||||
```yaml {copy-lines="none"}
|
||||
Conditions:
|
||||
Type: LastAsyncOperation
|
||||
Status: True
|
||||
Reason: Success
|
||||
```
|
|
@ -0,0 +1,513 @@
|
|||
---
|
||||
title: Crossplane Packages
|
||||
weight: 104
|
||||
description: "Packages combine multiple Crossplane resources into a single, portable, OCI image."
|
||||
---
|
||||
<!--
|
||||
Install packages behind a proxy.
|
||||
https://github.com/upbound/provider-azure/issues/475#issuecomment-1608390254 -->
|
||||
|
||||
Crossplane packages are opinionated [OCI images] that contain a stream of YAML
|
||||
that can be parsed by the Crossplane package manager. Crossplane packages come
|
||||
in two varieties: [Providers] and Configurations. Ultimately, the primary
|
||||
purposes of Crossplane packages are as follows:
|
||||
|
||||
- **Convenient Distribution**: Crossplane packages can be pushed to or installed
|
||||
from any OCI-compatible registry.
|
||||
- **Version Upgrade**: Crossplane can update packages in-place, meaning that you
|
||||
can pick up support for new resource types or controller bug-fixes without
|
||||
modifying your existing infrastructure.
|
||||
- **Permissions**: Crossplane allocates permissions to packaged controllers in a
|
||||
manner that ensures they will not maliciously take over control of existing
|
||||
resources owned by other packages. Installing CRDs via packages also allows
|
||||
Crossplane itself to manage those resources, allowing for powerful
|
||||
[composition] features to be enabled.
|
||||
- **Dependency Management**: Crossplane resolves dependencies between packages,
|
||||
automatically installing a package's dependencies if they are not present in
|
||||
the cluster, and checking if dependency versions are valid if they are already
|
||||
installed.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
The following packaging operations are covered in detail below:
|
||||
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Building a Package](#building-a-package)
|
||||
- [Provider Packages](#provider-packages)
|
||||
- [Configuration Packages](#configuration-packages)
|
||||
- [Pushing a Package](#pushing-a-package)
|
||||
- [Installing a Package](#installing-a-package)
|
||||
- [spec.package](#specpackage)
|
||||
- [spec.packagePullPolicy](#specpackagepullpolicy)
|
||||
- [spec.revisionActivationPolicy](#specrevisionactivationpolicy)
|
||||
- [spec.revisionHistoryLimit](#specrevisionhistorylimit)
|
||||
- [spec.packagePullSecrets](#specpackagepullsecrets)
|
||||
- [spec.skipDependencyResolution](#specskipdependencyresolution)
|
||||
- [spec.ignoreCrossplaneConstraints](#specignorecrossplaneconstraints)
|
||||
- [spec.controllerConfigRef](#speccontrollerconfigref)
|
||||
- [Upgrading a Package](#upgrading-a-package)
|
||||
- [Package Upgrade Issues](#package-upgrade-issues)
|
||||
- [The Package Cache](#the-package-cache)
|
||||
- [Pre-Populating the Package Cache](#pre-populating-the-package-cache)
|
||||
|
||||
## Building a Package
|
||||
|
||||
As stated above, Crossplane packages are just opinionated OCI images, meaning
|
||||
they can be constructed using any tool that outputs files that comply the the
|
||||
OCI specification. However, constructing packages using the Crossplane CLI is a
|
||||
more streamlined experience, as it will perform build-time checks on your
|
||||
packages to ensure that they are compliant with the Crossplane [package format].
|
||||
|
||||
Providers and Configurations vary in the types of resources they may contain in
|
||||
their packages. All packages must have a `crossplane.yaml` file in the root
|
||||
directory with package contents. The `crossplane.yaml` contains the package's
|
||||
metadata, which governs how Crossplane will install the package.
|
||||
|
||||
### Provider Packages
|
||||
|
||||
A Provider package contains a `crossplane.yaml` with the following format:
|
||||
|
||||
```yaml
|
||||
apiVersion: meta.pkg.crossplane.io/v1
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: provider-gcp
|
||||
spec:
|
||||
crossplane:
|
||||
version: ">=v1.0.0"
|
||||
controller:
|
||||
image: crossplane/provider-gcp-controller:v0.14.0
|
||||
permissionRequests:
|
||||
- apiGroups:
|
||||
- apiextensions.crossplane.io
|
||||
resources:
|
||||
- compositions
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- create
|
||||
- update
|
||||
- patch
|
||||
- watch
|
||||
```
|
||||
|
||||
See all available fields in the [official documentation][provider-docs].
|
||||
|
||||
> Note: The `meta.pkg.crossplane.io` group does not contain custom resources
|
||||
> that may be installed into the cluster. They are strictly used as metadata in
|
||||
> a Crossplane package.
|
||||
|
||||
A Provider package may optionally contain one or more CRDs. These CRDs will be
|
||||
installed prior to the creation of the Provider's `Deployment`. Crossplane will
|
||||
not install _any_ CRDs for a package unless it can determine that _all_ CRDs can
|
||||
be installed. This guards against multiple Providers attempting to reconcile the
|
||||
same CRDs. Crossplane will also create a `ServiceAccount` with permissions to
|
||||
reconcile these CRDs and it will be assigned to the controller `Deployment`.
|
||||
|
||||
The `spec.controller.image` fields specifies that the `Provider` desires for the
|
||||
controller `Deployment` to be created with the provided image. It is important
|
||||
to note that this image is separate from the package image itself. In the case
|
||||
above, it is an image containing the `provider-gcp` controller binary.
|
||||
|
||||
The `spec.controller.permissionRequests` field allows a package author to
|
||||
request additional RBAC for the packaged controller. The controller's
|
||||
`ServiceAccount` will automatically give the controller permission to reconcile
|
||||
all types that its package installs, as well as `Secrets`, `ConfigMaps`, and
|
||||
`Events`. Any additional permissions must be explicitly requested.
|
||||
|
||||
> Note that the Crossplane RBAC manager can be configured to reject permissions
|
||||
> for certain API groups. If a package requests permissions that Crossplane is
|
||||
> configured to reject, the package will fail to be installed.
|
||||
> Authorized permissions should be aggregated to the rbac manager clusterrole
|
||||
> (the cluster role defined by the provider-clusterrole flag in the rbac manager)
|
||||
> by using the label `rbac.crossplane.io/aggregate-to-allowed-provider-permissions: "true"`
|
||||
|
||||
The `spec.crossplane.version` field specifies the version constraints for core
|
||||
Crossplane that the `Provider` is compatible with. It is advisable to use this
|
||||
field if a package relies on specific features in a minimum version of
|
||||
Crossplane.
|
||||
|
||||
> All version constraints used in packages follow the [specification] outlined
|
||||
> in the `Masterminds/semver` repository.
|
||||
|
||||
For an example Provider package, see [provider-gcp].
|
||||
|
||||
To build a Provider package, navigate to the package root directory and execute
|
||||
the following command:
|
||||
|
||||
```
|
||||
kubectl crossplane build provider
|
||||
```
|
||||
|
||||
If the Provider package is valid, you will see a file with the `.xpkg`
|
||||
extension.
|
||||
|
||||
> Note that the Crossplane CLI will not follow symbolic links for files in the
|
||||
> root package directory.
|
||||
|
||||
### Configuration Packages
|
||||
|
||||
A Configuration package contains a `crossplane.yaml` with the following format:
|
||||
|
||||
```yaml
|
||||
apiVersion: meta.pkg.crossplane.io/v1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: my-org-infra
|
||||
spec:
|
||||
crossplane:
|
||||
version: ">=v1.0.0"
|
||||
dependsOn:
|
||||
- provider: xpkg.upbound.io/crossplane-contrib/provider-gcp
|
||||
version: ">=v0.14.0"
|
||||
```
|
||||
|
||||
See all available fields in the [official documentation][configuration-docs].
|
||||
|
||||
A Configuration package may also specify one or more of
|
||||
`CompositeResourceDefinition` and `Composition` types. These resources will be
|
||||
installed and will be solely owned by the Configuration package. No other
|
||||
package will be able to modify them.
|
||||
|
||||
The `spec.crossplane.version` field serves the same purpose that it does in a
|
||||
`Provider` package.
|
||||
|
||||
The `spec.dependsOn` field specifies packages that this package depends on. When
|
||||
installed, the package manager will ensure that all dependencies are present and
|
||||
have a valid version given the constraint. If a dependency is not installed, the
|
||||
package manager will install it at the latest version that fits within the
|
||||
provided constraints.
|
||||
|
||||
> Dependency resolution is a `beta` feature and depends on the `v1beta1`
|
||||
> [`Lock` API][lock-api].
|
||||
|
||||
For an example Configuration package, see [getting-started-with-gcp](https://github.com/crossplane/docs/tree/master/content/v1.10/snippets/package/gcp).
|
||||
|
||||
To build a Configuration package, navigate to the package root directory and
|
||||
execute the following command:
|
||||
|
||||
```
|
||||
kubectl crossplane build configuration
|
||||
```
|
||||
|
||||
If the Provider package is valid, you will see a file with the `.xpkg`
|
||||
extension.
|
||||
|
||||
## Pushing a Package
|
||||
|
||||
Crossplane packages can be pushed to any OCI-compatible registry. If a specific
|
||||
registry is not specified they will be pushed to Docker Hub.
|
||||
|
||||
To push a Provider package, execute the following command:
|
||||
|
||||
```
|
||||
kubectl crossplane push provider xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0
|
||||
```
|
||||
|
||||
To push a Configuration package, execute the following command:
|
||||
|
||||
```
|
||||
kubectl crossplane push configuration xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0
|
||||
```
|
||||
|
||||
> Note: Both of the above commands assume a single `.xpkg` file exists in the
|
||||
> directory. If multiple exist or you would like to specify a package in a
|
||||
> different directory, you can supply the `-f` flag with the path to the
|
||||
> package.
|
||||
|
||||
## Installing a Package
|
||||
|
||||
Packages can be installed into a Crossplane cluster using the Crossplane CLI.
|
||||
|
||||
To install a Provider package, execute the following command:
|
||||
|
||||
```
|
||||
kubectl crossplane install provider xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0
|
||||
```
|
||||
|
||||
To install a Configuration package, execute the following command:
|
||||
|
||||
```
|
||||
kubectl crossplane install configuration xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0
|
||||
```
|
||||
|
||||
Packages can also be installed manually by creating a `Provider` or
|
||||
`Configuration` object directly. The preceding commands would result in the
|
||||
creation of the following two resources, which could have been authored by hand:
|
||||
|
||||
```yaml
|
||||
apiVersion: pkg.crossplane.io/v1
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: provider-gcp
|
||||
spec:
|
||||
package: xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0
|
||||
packagePullPolicy: IfNotPresent
|
||||
revisionActivationPolicy: Automatic
|
||||
revisionHistoryLimit: 1
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: pkg.crossplane.io/v1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: my-org-infra
|
||||
spec:
|
||||
package: xpkg.upbound.io/crossplane-contrib/my-org-infra:v0.1.0
|
||||
packagePullPolicy: IfNotPresent
|
||||
revisionActivationPolicy: Automatic
|
||||
revisionHistoryLimit: 1
|
||||
```
|
||||
|
||||
> Note: These types differ from the `Provider` and `Configuration` types we saw
|
||||
> earlier. They exist in the `pkg.crossplane.io` group rather than the
|
||||
> `meta.pkg.crossplane.io` group and are actual custom resources created in the
|
||||
> cluster.
|
||||
|
||||
The default fields specified above can be configured with different values to
|
||||
modify the installation and upgrade behavior of a package. In addition, there
|
||||
are multiple other fields which can further customize how the package manager
|
||||
handles a specific revision.
|
||||
|
||||
### spec.package
|
||||
|
||||
This is the package image that we built, pushed, and are asking Crossplane to
|
||||
install. The tag we specify here is important. Crossplane will periodically
|
||||
check if the installed image matches the digest of the image in the remote
|
||||
registry. If it does not, Crossplane will create a new _Revision_ (either
|
||||
`ProviderRevision` or `ConfigurationRevision`). If you do not wish Crossplane to
|
||||
ever update your packages without explicitly instructing it to do so, you should
|
||||
consider specifying a tag which you know will not have the underlying contents
|
||||
change unexpectedly (e.g. a specific semantic version, such as `v0.1.0`) or, for
|
||||
an even stronger guarantee, providing the image with a `@sha256` extension
|
||||
instead of a tag.
|
||||
|
||||
### spec.packagePullPolicy
|
||||
|
||||
Valid values: `IfNotPresent`, `Always`, or `Never` (default: `IfNotPresent`)
|
||||
|
||||
When a package is installed, Crossplane downloads the image contents into a
|
||||
cache. Depending on the image identifier (tag or digest) and the
|
||||
`packagePullPolicy`, the Crossplane package manager will decide if and when to
|
||||
check and see if newer package contents are available. The following table
|
||||
describes expected behavior based on the supplied fields:
|
||||
|
||||
| | `IfNotPresent` | `Always` | `Never` |
|
||||
|---------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
|
||||
| Semver Tag (e.g. `v1.3.0`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost and the a new version of the package image has been pushed for the same tag, package could inadvertently be upgraded. <br><br> **Upgrade Safety: Strong** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. New content would have to be pushed for the same semver tag for upgrade to take place. <br><br> **Upgrade Safety: Weak** | Crossplane will never download content. Must manually load package image in cache. <br><br> **Upgrade Safety: Strongest** |
|
||||
| Digest (e.g. `@sha256:28b6...`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost but an image with this digest is still available, it will be downloaded again. The package will never be upgraded without a user changing the digest. <br><br> **Upgrade Safety: Very Strong** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. Because image digest is used, new content will never be downloaded. <br><br> **Upgrade Safety: Strong** | Crossplane will never download content. Must manually load package image in cache. <br><br> **Upgrade Safety: Strongest** |
|
||||
| Channel Tag (e.g. `latest`) | Package is downloaded when initially installed, and as long as it is present in the cache, it will not be downloaded again. If the cache is lost, the latest version of this package image will be downloaded again, which will frequently have different contents. <br><br> **Upgrade Safety: Weak** | Package is downloaded when initially installed, but Crossplane will check every minute if new content is available. When the image content is new, Crossplane will download the new contents and create a new revision. <br><br> **Upgrade Safety: Very Weak** | Crossplane will never download content. Must manually load package image in cache. <br><br> **Upgrade Safety: Strongest** |
|
||||
|
||||
### spec.revisionActivationPolicy
|
||||
|
||||
Valid values: `Automatic` or `Manual` (default: `Automatic`)
|
||||
|
||||
When Crossplane downloads new contents for a package, regardless of whether it
|
||||
was a manual upgrade (i.e. user updating package image tag), or an automatic one
|
||||
(enabled by the `packagePullPolicy`), it will create a new package revision.
|
||||
However, the new objects and / or controllers will not be installed until the
|
||||
new revision is marked as `Active`. This activation process is configured by the
|
||||
`revisionActivationPolicy` field.
|
||||
|
||||
An `Active` package revision attempts to become the _controller_ of all
|
||||
resources it installs. There can only be one controller of a resource, so if two
|
||||
`Active` revisions both install the same resource, one will fail to install
|
||||
until the other cedes control.
|
||||
|
||||
An `Inactive` package revision attempts to become the _owner_ of all resources
|
||||
it installs. There can be an arbitrary number of owners of a resource, so
|
||||
multiple `Inactive` revisions and a single `Active` revision can exist for a
|
||||
resource. Importantly, an `Inactive` package revision will not perform any
|
||||
auxiliary actions (such as creating a `Deployment` in the case of a `Provider`),
|
||||
meaning we will not encounter a situation where two revisions are fighting over
|
||||
reconciling a resource.
|
||||
|
||||
With `revisionActivationPolicy: Automatic`, Crossplane will mark any new
|
||||
revision as `Active` when it is created, as well as transition any old revisions
|
||||
to `Inactive`. When `revisionActivationPolicy: Manual`, the user must manually
|
||||
edit a new revision and mark it as `Active`. This can be useful if you are using
|
||||
a `packagePullPolicy: Automatic` with a channel tag (e.g. `latest`) and you want
|
||||
Crossplane to create new revisions when a new version is available, but you
|
||||
don't want to automatically update to that newer revision.
|
||||
|
||||
It is recommended for most users to use semver tags or image digests and
|
||||
manually update their packages, but use a `revisionActivationPolicy: Automatic`
|
||||
to avoid having to manually activate new versions. However, each user should
|
||||
consider their specific environment and choose a combination that makes sense
|
||||
for them.
|
||||
|
||||
For security reasons, it's suggested using image digests instead or alongside
|
||||
tags (`vx.y.z@sha256:...`), to ensure that the package content wasn't tampered
|
||||
with.
|
||||
|
||||
### spec.revisionHistoryLimit
|
||||
|
||||
Valid values: any integer, disabled by explicitly setting to `0` (default `1`)
|
||||
|
||||
When a revision transitions from `Inactive` to `Active`, its revision number
|
||||
gets set to one greater than the largest revision number of all revisions for
|
||||
its package. Therefore, as the number of revisions increases, the least recently
|
||||
`Active` revision will have the lowest revision number. Crossplane will garbage
|
||||
collect old `Inactive` revisions if they fall outside the
|
||||
`spec.revisionHistoryLimit`. For instance, if my revision history limit is `3`
|
||||
and I currently have three old `Inactive` revisions and one `Active` revision,
|
||||
when I upgrade the next time, the new revision will be given the highest
|
||||
revision number when it becomes `Active`, the previously `Active` revision will
|
||||
become `Inactive`, and the oldest `Inactive` revision will be garbage collected.
|
||||
|
||||
> Note: In the case that `spec.revisionActivationPolicy: Manual` and you upgrade
|
||||
> enough times (but do not make `Active` the new revisions), it is possible that
|
||||
> activating a newer revision could cause the previously `Active` revision to
|
||||
> immediately be garbage collected if it is outside the
|
||||
> `spec.revisionHistoryLimit`.
|
||||
|
||||
### spec.packagePullSecrets
|
||||
|
||||
Valid values: slice of `Secret` names (secrets must exist in `namespace`
|
||||
Crossplane was installed in, typically `crossplane-system`)
|
||||
|
||||
This field allows a user to provide credentials required to pull a package from
|
||||
a private repository on a registry. The credentials are passed along to a
|
||||
packaged controller if the package is a `Provider`, but are not passed along to
|
||||
any dependencies.
|
||||
|
||||
### spec.skipDependencyResolution
|
||||
|
||||
Valid values: `true` or `false` (default: `false`)
|
||||
|
||||
If `skipDependencyResolution: true`, the package manager will install a package
|
||||
without considering its dependencies.
|
||||
|
||||
### spec.ignoreCrossplaneConstraints
|
||||
|
||||
Valid values: `true` or `false` (default: `false`)
|
||||
|
||||
If `ignoreCrossplaneConstraints: true`, the package manager will install a
|
||||
package without considering the version of Crossplane that is installed.
|
||||
|
||||
### spec.controllerConfigRef
|
||||
|
||||
{{< hint "warning" >}}
|
||||
The `ControllerConfig` API has been deprecated and will be removed in a future
|
||||
release when a comparable alternative is available.
|
||||
{{< /hint >}}
|
||||
|
||||
Valid values: name of a `ControllerConfig` object
|
||||
|
||||
Packaged `Provider` controllers are installed in the form of a `Deployment`.
|
||||
Crossplane populates the `Deployment` with default values that may not be
|
||||
appropriate for every use-case. In the event that a user wants to override some
|
||||
of the defaults that Crossplane has set, they may create and reference a
|
||||
`ControllerConfig`.
|
||||
|
||||
An example of when this may be useful is when a user is running Crossplane on
|
||||
EKS and wants to take advantage of [IAM Roles for Service Accounts]. This
|
||||
requires setting an `fsGroup` and annotating the `ServiceAccount` that
|
||||
Crossplane creates for the controller. This could be accomplished with the
|
||||
following `ControllerConfig` and `Provider`:
|
||||
|
||||
```yaml
|
||||
apiVersion: pkg.crossplane.io/v1alpha1
|
||||
kind: ControllerConfig
|
||||
metadata:
|
||||
name: aws-config
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: arn:aws:iam::$AWS_ACCOUNT_ID\:role/$IAM_ROLE_NAME
|
||||
spec:
|
||||
podSecurityContext:
|
||||
fsGroup: 2000
|
||||
---
|
||||
apiVersion: pkg.crossplane.io/v1
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: provider-aws
|
||||
spec:
|
||||
package: xpkg.upbound.io/crossplane-contrib/provider-aws:v0.33.0
|
||||
controllerConfigRef:
|
||||
name: aws-config
|
||||
```
|
||||
|
||||
You can find all configurable values in the [official `ControllerConfig`
|
||||
documentation][controller-config-docs].
|
||||
|
||||
## Upgrading a Package
|
||||
|
||||
Upgrading a `Provider` or `Configuration` to a new version can be accomplished
|
||||
by editing the existing manifest and applying it with a new version tag in
|
||||
`spec.package`. Crossplane will observe the updated manifest and create a new
|
||||
`ProviderRevision` or `ConfigurationRevision` for the specified version. The new
|
||||
revision will be activated in accordance with `spec.revisionActivationPolicy`.
|
||||
|
||||
### Package Upgrade Issues
|
||||
|
||||
Upgrading a package can require manual intervention in the event that the
|
||||
previous version of the package supported a version of a custom resource that
|
||||
has been dropped and replaced by a new version in the new package revision.
|
||||
Kubernetes does not allow for applying a `CustomResourceDefinition` (CRD) that
|
||||
drops a version in the `spec` that is in the current `status.storedVersions`
|
||||
list, meaning that a revision cannot update and become the _controller_ of all
|
||||
of its resources.
|
||||
|
||||
This situation can be remedied by manually deleting the offending CRD and
|
||||
letting the new revision re-create it. In the event that custom resources exist
|
||||
for the given CRD, they must be deleted before the CRD can be removed.
|
||||
|
||||
## The Package Cache
|
||||
|
||||
When a package is installed into a cluster, Crossplane fetches the package image
|
||||
and stores its contents in a dedicated package cache. By default, this cache is
|
||||
backed by an [`emptyDir` Volume][emptyDir-volume], meaning that all cached data
|
||||
is lost when a `Pod` restarts. Users who wish for cache contents to be persisted
|
||||
between `Pod` restarts may opt to instead use a [`persistentVolumeClaim`
|
||||
(PVC)][pvc] by setting the `packageCache.pvc` Helm chart parameter to the name
|
||||
of the PVC.
|
||||
|
||||
### Pre-Populating the Package Cache
|
||||
|
||||
Because the package cache can be backed by any storage medium, users are able to
|
||||
optionally to pre-populate the cache with images that are not present on an
|
||||
external [OCI registry]. To utilize a package that has been manually stored in
|
||||
the cache, users must specify the name of the package in `spec.package` and use
|
||||
`packagePullPolicy: Never`. For instance, if a user built a `Configuration`
|
||||
package named `mycoolpkg.xpkg` and loaded it into the volume that was to be used
|
||||
for the package cache (i.e. copied the `.xpkg` file into the storage medium
|
||||
backing the PVC), the package could be utilized with the following manifest:
|
||||
|
||||
```yaml
|
||||
apiVersion: pkg.crossplane.io/v1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: my-cool-pkg
|
||||
spec:
|
||||
package: mycoolpkg
|
||||
packagePullPolicy: Never
|
||||
```
|
||||
|
||||
Importantly, as long as a package is being used as the `spec.package` of a
|
||||
`Configuration` or `Provider`, it must remain in the cache. For this reason, it
|
||||
is recommended that users opt for a durable storage medium when manually loading
|
||||
packages into the cache.
|
||||
|
||||
In addition, if manually loading a `Provider` package into the cache, users must
|
||||
ensure that the controller image that it references is able to be pulled by the
|
||||
cluster nodes. This can be accomplished either by pushing it to a registry, or
|
||||
by [pre-pulling images] onto nodes in the cluster.
|
||||
|
||||
|
||||
<!-- Named Links -->
|
||||
|
||||
[OCI images]: https://github.com/opencontainers/image-spec
|
||||
[Providers]: {{<ref "providers" >}}
|
||||
[provider-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Provider/v1
|
||||
[configuration-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Configuration/v1
|
||||
[lock-api]: https://doc.crds.dev/github.com/crossplane/crossplane/pkg.crossplane.io/Lock/v1beta1
|
||||
[specification]: https://github.com/Masterminds/semver#basic-comparisons
|
||||
[composition]: {{<ref "compositions" >}}
|
||||
[IAM Roles for Service Accounts]: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html
|
||||
[controller-config-docs]: https://doc.crds.dev/github.com/crossplane/crossplane/pkg.crossplane.io/ControllerConfig/v1alpha1
|
||||
[package format]: https://github.com/crossplane/crossplane/blob/1aa83092172bdf0d2ed64754d33517c612ff7368/design/one-pager-package-format-v2.md
|
||||
[provider-gcp]: https://doc.crds.dev/github.com/crossplane/crossplane/meta.pkg.crossplane.io/Provider/v1
|
||||
[emptyDir-volume]: https://kubernetes.io/docs/concepts/storage/volumes/#emptydir
|
||||
[pvc]: https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim
|
||||
[OCI registry]: https://github.com/opencontainers/distribution-spec
|
||||
[pre-pulling images]: https://kubernetes.io/docs/concepts/containers/images/#pre-pulled-images
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,381 @@
|
|||
---
|
||||
title: Crossplane Pods
|
||||
weight: 1
|
||||
description: Background on the components installed with Crossplane and their functions.
|
||||
---
|
||||
|
||||
The base Crossplane installation consists of two pods, the `crossplane` pod and
|
||||
the `crossplane-rbac-manager` pod. Both pods install in the `crossplane-system`
|
||||
namespace by default.
|
||||
|
||||
|
||||
## Crossplane pod
|
||||
|
||||
### Init container
|
||||
Before starting the core Crossplane container an _init_ container runs. The init
|
||||
container installs the core Crossplane
|
||||
[Custom Resource Definitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions)
|
||||
(`CRDs`), configures Crossplane webhooks and installs any supplied Providers or
|
||||
Configurations.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
The Kubernetes documentation contains more information about
|
||||
[init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/).
|
||||
{{< /hint >}}
|
||||
|
||||
The settings the init container sets include installing Provider or Configuration
|
||||
packages with Crossplane, customizing the namespace Crossplane installs in and
|
||||
defining webhook configurations.
|
||||
|
||||
The core CRDs installed by the init container include:
|
||||
* CompositeResourceDefinitions, Compositions, Configurations and Providers
|
||||
* Locks to manage package dependencies
|
||||
* ControllerConfigs to apply settings to installed Providers
|
||||
* StoreConfigs for connecting external secret stores like
|
||||
[HashiCorp Vault](https://www.vaultproject.io/)
|
||||
|
||||
{{< hint "note" >}}
|
||||
|
||||
The [Install Crossplane]({{< ref "../software/install" >}}) section has more
|
||||
information about customizing the Crossplane install.
|
||||
{{< /hint >}}
|
||||
|
||||
The status `Init` on the Crossplane pod is the init container running.
|
||||
|
||||
```shell
|
||||
kubectl get pods -n crossplane-system
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
crossplane-9f6d5cd7b-r9j8w 0/1 Init:0/1 0 6s
|
||||
```
|
||||
|
||||
The init container completes and starts the Crossplane core container
|
||||
automatically.
|
||||
|
||||
```shell
|
||||
kubectl get pods -n crossplane-system
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
crossplane-9f6d5cd7b-r9j8w 1/1 Running 0 15s
|
||||
```
|
||||
|
||||
### Core container
|
||||
|
||||
The main Crossplane container, called the _core_ container, enforces
|
||||
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
|
||||
resources.
|
||||
{{< /hint >}}
|
||||
|
||||
#### Reconcile loop
|
||||
|
||||
The core container operates on a _reconcile loop_, constantly checking the
|
||||
status of deployed resources and correcting any "drift." After checking a
|
||||
resource Crossplane waits some time and checks again.
|
||||
|
||||
Crossplane monitors resources through a Kubernetes
|
||||
[_watch_](https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes)
|
||||
or through periodic polling. Some resources may be both watched and polled.
|
||||
|
||||
Crossplane requests that the API server notifies Crossplane of any changes on
|
||||
objects. This notification tool is a _watch_.
|
||||
|
||||
Watched objects include Providers, managed resources and
|
||||
CompositeResourceDefinitions.
|
||||
|
||||
For objects that Kubernetes can't provide a watch for, Crossplane
|
||||
periodically poll the resource to find it's state. The default polling rate is
|
||||
one minute. Change the polling rate with the `--poll-interval` pod argument.
|
||||
|
||||
Reducing the poll-interval value causes Crossplane to poll resources more
|
||||
frequently. This increases the load of the Crossplane pod and
|
||||
results in more frequent provider API calls.
|
||||
|
||||
<!-- vale write-good.TooWordy = NO -->
|
||||
<!-- allow "maximum" -->
|
||||
Increasing the poll-interval causes Crossplane to poll resources less
|
||||
frequently. This increases the maximum time until Crossplane
|
||||
discovers changes in the cloud provider that require updating.
|
||||
<!-- vale write-good.TooWordy = YES -->
|
||||
|
||||
Managed resources use polling.
|
||||
|
||||
{{< hint "note" >}}
|
||||
Managed resources watch for Kubernetes events like deletion or changes to
|
||||
their `spec`. Managed resources rely on polling to detect changes in the
|
||||
external system.
|
||||
{{< /hint >}}
|
||||
|
||||
Crossplane double-checks all resources to
|
||||
confirm they're in the desired state. Crossplane does this every one hour by
|
||||
default. Use the `--sync-interval` Crossplane pod argument to change this
|
||||
interval.
|
||||
|
||||
The `--max-reconcile-rate` rate defines the rate, in times per second,
|
||||
Crossplane reconciles resources.
|
||||
|
||||
Reducing the `--max-reconcile-rate`, or making it smaller, reduces CPU
|
||||
resources Crossplane uses, but increases the amount of time until changed
|
||||
resources are fully synced.
|
||||
|
||||
Increasing the `--max-reconcile-rate`, or making it larger, increases the
|
||||
CPU resources Crossplane uses but allows Crossplane to reconcile all resources
|
||||
faster.
|
||||
|
||||
{{< hint "important" >}}
|
||||
Most Providers use their own `--max-reconcile-rate`. This determines the
|
||||
same settings for Providers and their managed resources. Applying the
|
||||
`--max-reconcile-rate` to Crossplane only controls the rate for
|
||||
core Crossplane resources.
|
||||
{{< /hint >}}
|
||||
##### Reconcile retry rate
|
||||
|
||||
The `--max-reconcile-rate` setting configures the number of times per second
|
||||
Crossplane or a provider attempts to correct a resource. The default value is
|
||||
10 times per second.
|
||||
|
||||
All core Crossplane components share the reconcile rate. Each Provider
|
||||
implements their own max reconcile rate setting.
|
||||
|
||||
##### Number of reconcilers
|
||||
|
||||
The second value `--max-reconcile-rate` defines is the number of
|
||||
resources that Crossplane can reconcile at once. If there are more resources than
|
||||
the configured `--max-reconcile-rate` the remaining resources must wait until
|
||||
Crossplane reconciles a an existing resource.
|
||||
|
||||
Read the [Change Pod Settings]({{<ref "#change-pod-settings">}}) section for
|
||||
instructions on applying these settings.
|
||||
|
||||
<!-- vale Microsoft.HeadingAcronyms = NO -->
|
||||
<!-- allow 'RBAC' since that's the name -->
|
||||
## RBAC manager pod
|
||||
<!-- vale Microsoft.HeadingAcronyms = YES -->
|
||||
The Crossplane RBAC manager pod automates required Kubernetes RBAC permissions
|
||||
for Crossplane and Crossplane Providers.
|
||||
|
||||
{{<hint "note" >}}
|
||||
Crossplane installs and enables the RBAC manager by default.
|
||||
Disabling the RBAC manager requires manual Kubernetes permissions definitions
|
||||
for proper Crossplane operations.
|
||||
|
||||
The
|
||||
[RBAC manager design document](https://github.com/crossplane/crossplane/blob/master/design/design-doc-rbac-manager.md)
|
||||
provides more comprehensive details on the Crossplane RBAC requirements.
|
||||
{{< /hint >}}
|
||||
|
||||
### Disable the RBAC manager
|
||||
|
||||
Disable the RBAC manager after installation by deleting the
|
||||
`crossplane-rbac-manager` deployment from the `crossplane-system` namespace.
|
||||
|
||||
Disable the RBAC manager before installation by editing the Helm `values.yaml`
|
||||
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.
|
||||
{{< /hint >}}
|
||||
|
||||
<!-- vale Microsoft.HeadingAcronyms = NO -->
|
||||
<!-- allow 'RBAC' since that's the name -->
|
||||
### RBAC init container
|
||||
<!-- vale Microsoft.HeadingAcronyms = YES -->
|
||||
|
||||
The RBAC manager requires the `CompositeResourceDefinition` and
|
||||
`ProviderRevision` resources to be available before starting.
|
||||
|
||||
The RBAC manager init container waits for these resources before starting the
|
||||
main RBAC manager container.
|
||||
|
||||
### RBAC manager container
|
||||
|
||||
The RBAC manager container preforms the following tasks:
|
||||
* creating and binding RBAC roles to Provider ServiceAccounts, allowing
|
||||
them to control their managed resources
|
||||
* allowing the `crossplane` ServiceAccount to create managed resources
|
||||
* creating ClusterRoles to access Crossplane resources in all namespaces
|
||||
* creating Roles to access Crossplane resources in specific namespaces
|
||||
|
||||
Use the [ClusterRoles]({{<ref "#crossplane-clusterroles">}}) to grant access to all Crossplane resources in the
|
||||
cluster.
|
||||
Use the [Roles]({{<ref "#crossplane-roles" >}}) to only grant access to Crossplane Claims.
|
||||
|
||||
#### Crossplane ClusterRoles
|
||||
|
||||
The RBAC manager creates four Kubernetes ClusterRoles. These Roles grant
|
||||
permissions over cluster wide Crossplane resources.
|
||||
|
||||
<!-- vale Google.Headings = NO -->
|
||||
<!-- disable heading checking for the role names -->
|
||||
<!-- vale Google.WordList = NO -->
|
||||
<!-- allow "admin" -->
|
||||
##### crossplane-admin
|
||||
<!-- vale Google.WordList = YES -->
|
||||
<!-- vale Crossplane.Spelling = NO -->
|
||||
The `crossplane-admin` ClusterRole has the following permissions:
|
||||
* full access to all Crossplane types
|
||||
* full access to all secrets and namespaces (even those unrelated to Crossplane)
|
||||
* read-only access to all cluster RBAC roles, CustomResourceDefinitions and
|
||||
events
|
||||
* ability to bind RBAC roles to other entities.
|
||||
<!-- vale Crossplane.Spelling = YES -->
|
||||
View the full RBAC policy with
|
||||
|
||||
```shell
|
||||
kubectl describe clusterrole crossplane:admin
|
||||
```
|
||||
|
||||
##### crossplane-edit
|
||||
|
||||
The `crossplane-edit` ClusterRole has the following permissions:
|
||||
|
||||
* full access to all Crossplane types
|
||||
* full access to all secrets (even those unrelated to Crossplane)
|
||||
* read-only access to all namespaces and events (even those unrelated to Crossplane).
|
||||
|
||||
View the full RBAC policy with
|
||||
|
||||
```shell
|
||||
kubectl describe clusterrole crossplane:edit
|
||||
```
|
||||
|
||||
##### crossplane-view
|
||||
|
||||
The `crossplane-view` ClusterRole has the following permissions:
|
||||
|
||||
* read-only access to all Crossplane types
|
||||
* read-only access to all namespaces and events (even those unrelated to Crossplane).
|
||||
|
||||
View the full RBAC policy with
|
||||
|
||||
```shell
|
||||
kubectl describe clusterrole crossplane:view
|
||||
```
|
||||
|
||||
##### crossplane-browse
|
||||
|
||||
The `crossplane-browse` ClusterRole has the following permissions:
|
||||
|
||||
* read-only access to all Crossplane types
|
||||
* read-only access to all namespaces and events (even those unrelated to Crossplane).
|
||||
|
||||
View the full RBAC policy with
|
||||
|
||||
```shell
|
||||
kubectl describe clusterrole crossplane:browse
|
||||
```
|
||||
|
||||
#### Crossplane Roles
|
||||
By default the RBAC manager creates three Roles in every namespace. These Roles
|
||||
grant access to Claims in a specific namespace. The RBAC manager dynamically
|
||||
updates the Roles to access the specific API endpoints in a Claim.
|
||||
|
||||
{{< hint "note" >}}
|
||||
The specific details of the namespace Roles are beyond this guide. For more
|
||||
information read the [Composite Resource ClusterRole
|
||||
Mechanics](https://github.com/crossplane/crossplane/blob/master/design/design-doc-rbac-manager.md#composite-resource-clusterrole-mechanics)
|
||||
section of the RBAC Manager design document.
|
||||
{{< /hint >}}
|
||||
|
||||
You can disable these namespace specific roles by configuring the RBAC manager
|
||||
with `--manage=Basic`.
|
||||
|
||||
|
||||
{{< hint "note" >}}
|
||||
|
||||
Instructions for changing Crossplane pod settings during installation are in the
|
||||
[Crossplane Install]({{<ref "../software/install">}}) section.
|
||||
{{< /hint >}}
|
||||
|
||||
## Leader election
|
||||
|
||||
By default only a single Crossplane pod runs in a cluster. If more than one
|
||||
Crossplane pod runs both pods try to manage Crossplane resources. To prevent
|
||||
conflicts Crossplane uses a _leader election_ to have a single pod in control at
|
||||
a time. Other Crossplane pods standby until the leader fails.
|
||||
|
||||
{{< hint "note" >}}
|
||||
It's possible to run more than one Crossplane or RBAC manager pods for
|
||||
redundancy.
|
||||
|
||||
Kubernetes restarts any failed Crossplane or RBAC manager pods.
|
||||
Redundant pods aren't required in most deployments.
|
||||
{{< /hint >}}
|
||||
|
||||
Both the Crossplane pod and the RBAC manager pods support leader elections.
|
||||
|
||||
Enable leader elections with the `--leader-election` pod argument.
|
||||
|
||||
{{< hint "warning" >}}
|
||||
<!-- vale write-good.TooWordy = NO -->
|
||||
<!-- "multiple" -->
|
||||
<!-- vale write-good.Passive = NO -->
|
||||
<!-- allow "is unsupported" -->
|
||||
Running multiple Crossplane pods without leader election is unsupported.
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
<!-- vale write-good.TooWordy = YES -->
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
## Change pod settings
|
||||
|
||||
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 are available in the
|
||||
[Crossplane Install]({{<ref "../software/install">}}) section.
|
||||
|
||||
{{< hint "note" >}}
|
||||
|
||||
Instructions for changing Crossplane pod settings during installation are in the
|
||||
[Crossplane Install]({{<ref "../software/install">}}) section.
|
||||
{{< /hint >}}
|
||||
|
||||
### Edit the deployment
|
||||
{{< hint "note" >}}
|
||||
These settings apply to both the `crossplane` and `rbac-manager` pods and
|
||||
`Deployments`.
|
||||
{{< /hint >}}
|
||||
|
||||
To change the settings of an installed Crossplane pod, edit the `crossplane`
|
||||
deployment in the `crossplane-system` namespace with the command
|
||||
|
||||
`kubectl edit deployment crossplane --namespace crossplane-system`
|
||||
|
||||
{{< hint "warning" >}}
|
||||
Updating the Crossplane deployment restarts the Crossplane pod.
|
||||
{{< /hint >}}
|
||||
|
||||
Add Crossplane pod arguments to the
|
||||
{{<hover label="args" line="9" >}}spec.template.spec.containers[].args{{< /hover >}}
|
||||
section of the deployment.
|
||||
|
||||
For example, to change the `sync-interval` add
|
||||
{{<hover label="args" line="12" >}}--sync-interval=30m{{< /hover >}}.
|
||||
|
||||
```yaml {label="args", copy-lines="1"}
|
||||
kubectl edit deployment crossplane --namespace crossplane-system
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
spec:
|
||||
# Removed for brevity
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- core
|
||||
- start
|
||||
- --sync-interval=30m
|
||||
```
|
||||
|
||||
### Use environmental variables
|
||||
|
||||
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.
|
|
@ -0,0 +1,438 @@
|
|||
---
|
||||
title: Providers
|
||||
weight: 5
|
||||
description: "Providers connect Crossplane to external APIs"
|
||||
---
|
||||
|
||||
Providers enable Crossplane to provision infrastructure on an
|
||||
external service. Providers create new Kubernetes APIs and map them to external
|
||||
APIs.
|
||||
|
||||
Providers are responsible for all aspects of connecting to non-Kubernetes
|
||||
resources. This includes authentication, making external API calls and
|
||||
providing
|
||||
[Kubernetes Controller](https://kubernetes.io/docs/concepts/architecture/controller/)
|
||||
logic for any external resources.
|
||||
|
||||
Examples of providers include:
|
||||
* [Provider AWS](https://github.com/upbound/provider-aws)
|
||||
* [Provider Azure](https://github.com/upbound/provider-azure)
|
||||
* [Provider GCP](https://github.com/upbound/provider-gcp)
|
||||
* [Provider Kubernetes](https://github.com/crossplane-contrib/provider-kubernetes)
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Find more providers in the [Upbound Marketplace](https://marketplace.upbound.io).
|
||||
{{< /hint >}}
|
||||
|
||||
<!-- 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. These endpoints are
|
||||
[_Managed Resources_]({{<ref "managed-resources" >}}).
|
||||
<!-- vale write-good.Passive = YES -->
|
||||
|
||||
{{< hint "note" >}}
|
||||
Instructions on building your own Provider are outside of the scope of this
|
||||
document. Read the Crossplane contributing [Provider Development
|
||||
Guide](https://github.com/crossplane/crossplane/blob/master/contributing/guide-provider-development.md)
|
||||
for more information.
|
||||
{{< /hint >}}
|
||||
|
||||
## Install a Provider
|
||||
|
||||
Installing a provider creates a Provider pod that's responsible for installing
|
||||
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
|
||||
{{<hover label="install" line="2">}}Provider{{</hover >}} object setting the
|
||||
{{<hover label="install" line="6">}}spec.package{{</hover >}} value to the
|
||||
location of the provider package.
|
||||
|
||||
For example, to install the
|
||||
[AWS Community Provider](https://github.com/crossplane-contrib/provider-aws),
|
||||
|
||||
```yaml {label="install"}
|
||||
apiVersion: pkg.crossplane.io/v1
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: provider-aws
|
||||
spec:
|
||||
package: xpkg.upbound.io/crossplane-contrib/provider-aws:v0.39.0
|
||||
```
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Providers are Crossplane Packages. Read more about Packages in the
|
||||
[Packages documentation]({{<ref "packages" >}}).
|
||||
{{< /hint >}}
|
||||
|
||||
By default, the Provider pod installs in the same namespace as Crossplane
|
||||
(`crossplane-system`).
|
||||
|
||||
### Install with Helm
|
||||
|
||||
Crossplane supports installing Providers during an initial Crossplane
|
||||
installation with the Crossplane Helm chart.
|
||||
|
||||
Use the
|
||||
{{<hover label="helm" line="5" >}}--set provider.packages{{</hover >}}
|
||||
argument with `helm install`.
|
||||
|
||||
For example, to install the AWS Community Provider,
|
||||
|
||||
```shell {label="helm"}
|
||||
helm install crossplane \
|
||||
crossplane-stable/crossplane \
|
||||
--namespace crossplane-system \
|
||||
--create-namespace \
|
||||
--set provider.packages={xpkg.upbound.io/crossplane-contrib/provider-aws:v0.39.0}
|
||||
```
|
||||
|
||||
### Install from a private repository
|
||||
|
||||
Installing a Provider from a private package repository requires a
|
||||
Kubernetes secret object. The Provider uses the secret with the
|
||||
{{<hover label="pps" line="7" >}}packagePullSecrets{{</hover>}} option.
|
||||
|
||||
```yaml {label="pps"}
|
||||
apiVersion: pkg.crossplane.io/v1
|
||||
kind: Provider
|
||||
metadata:
|
||||
name: private-provider
|
||||
spec:
|
||||
package: private-repo.example.org/providers/my-provider
|
||||
packagePullSecrets:
|
||||
- name: my-secret
|
||||
```
|
||||
|
||||
{{< hint "note" >}}
|
||||
The Kubernetes secret object the Provider uses must be in the same namespace as
|
||||
the Crossplane pod.
|
||||
{{< /hint >}}
|
||||
|
||||
## Upgrade a Provider
|
||||
|
||||
To upgrade an existing Provider edit the installed Provider Package by either
|
||||
applying a new Provider manifest or with `kubectl edit providers`.
|
||||
|
||||
Update the version number in the Provider's `spec.package` and apply the change.
|
||||
Crossplane installs the new image and creates a new `ProviderRevision`.
|
||||
|
||||
## Remove a Provider
|
||||
|
||||
Remove a Provider by deleting the Provider object with `kubectl delete
|
||||
provider`.
|
||||
|
||||
{{< hint "warning" >}}
|
||||
Removing a Provider without first removing the Provider's managed resources
|
||||
may abandon the resources. The external resources aren't deleted.
|
||||
|
||||
If you remove the Provider first, you must manually delete external resources
|
||||
through your cloud provider. Managed resources must be manually deleted by
|
||||
removing their finalizers.
|
||||
|
||||
For more information on deleting abandoned resources read the [Crossplane
|
||||
troubleshooting guide]({{<ref "/knowledge-base/guides/troubleshoot#deleting-when-a-resource-hangs" >}}).
|
||||
{{< /hint >}}
|
||||
|
||||
## Verify a Provider
|
||||
|
||||
Providers install their own APIs representing the managed resources they support.
|
||||
Providers may also create Deployments, Service Accounts or RBAC configuration.
|
||||
|
||||
View the status of a Provider with
|
||||
|
||||
`kubectl get providers`
|
||||
|
||||
During the install a Provider report `INSTALLED` as `True` and `HEALTHY` as
|
||||
`Unknown`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get providers
|
||||
NAME INSTALLED HEALTHY PACKAGE AGE
|
||||
crossplane-contrib-provider-aws True Unknown xpkg.upbound.io/crossplane-contrib/provider-aws:v0.39.0 63s
|
||||
```
|
||||
|
||||
After the Provider install completes and it's ready for use the `HEALTHY` status
|
||||
reports `True`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get providers
|
||||
NAME INSTALLED HEALTHY PACKAGE AGE
|
||||
crossplane-contrib-provider-aws True True xpkg.upbound.io/crossplane-contrib/provider-aws:v0.39.0 88s
|
||||
```
|
||||
|
||||
{{<hint "important" >}}
|
||||
Some Providers install hundreds of Kubernetes Custom Resource Definitions (`CRDs`).
|
||||
This can create significant strain on undersized API Servers, impacting Provider
|
||||
install times.
|
||||
|
||||
The Crossplane community has more
|
||||
[details on scaling CRDs](https://github.com/crossplane/crossplane/blob/master/design/one-pager-crd-scaling.md).
|
||||
{{< /hint >}}
|
||||
### Provider conditions
|
||||
|
||||
Crossplane uses a standard set of `Conditions` for Providers.
|
||||
View the conditions of a provider under their `Status` with
|
||||
`kubectl describe provider`.
|
||||
|
||||
```yaml
|
||||
kubectl describe provider
|
||||
Name: my-provider
|
||||
API Version: pkg.crossplane.io/v1
|
||||
Kind: Provider
|
||||
# Removed for brevity
|
||||
Status:
|
||||
Conditions:
|
||||
Reason: HealthyPackageRevision
|
||||
Status: True
|
||||
Type: Healthy
|
||||
Reason: ActivePackageRevision
|
||||
Status: True
|
||||
Type: Installed
|
||||
# Removed for brevity
|
||||
```
|
||||
|
||||
#### Types
|
||||
Provider `Conditions` support two `Types`:
|
||||
* `Type: Installed` - the Provider package installed but isn't ready for use.
|
||||
* `Type: Healthy` - The Provider package is ready to use.
|
||||
|
||||
#### Reasons
|
||||
Each `Reason` relates to a specific `Type` and `Status`. Crossplane uses the
|
||||
following `Reasons` for Provider `Conditions`.
|
||||
|
||||
<!-- vale Google.Headings = NO -->
|
||||
##### InactivePackageRevision
|
||||
`Reason: InactivePackageRevision` indicates the Provider Package is using an
|
||||
inactive Provider Package Revision.
|
||||
|
||||
<!-- vale Google.Headings = YES -->
|
||||
```yaml
|
||||
Type: Installed
|
||||
Status: False
|
||||
Reason: InactivePackageRevision
|
||||
```
|
||||
|
||||
<!-- vale Google.Headings = NO -->
|
||||
##### ActivePackageRevision
|
||||
<!-- vale Google.Headings = YES -->
|
||||
The Provider Package is the current Package Revision, but Crossplane hasn't
|
||||
finished installing the Package Revision yet.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Providers stuck in this state are because of a problem with Package Revisions.
|
||||
|
||||
Use `kubectl describe providerrevisions` for more details.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml
|
||||
Type: Installed
|
||||
Status: True
|
||||
Reason: ActivePackageRevision
|
||||
```
|
||||
|
||||
<!-- vale Google.Headings = NO -->
|
||||
##### HealthyPackageRevision
|
||||
The Provider is fully installed and ready to use.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
`Reason: HealthyPackageRevision` is the normal state of a working Provider.
|
||||
{{< /hint >}}
|
||||
|
||||
<!-- vale Google.Headings = YES -->
|
||||
```yaml
|
||||
Type: Healthy
|
||||
Status: True
|
||||
Reason: HealthyPackageRevision
|
||||
```
|
||||
|
||||
<!-- vale Google.Headings = NO -->
|
||||
##### UnhealthyPackageRevision
|
||||
<!-- vale Google.Headings = YES -->
|
||||
|
||||
There was an error installing the Provider Package Revision, preventing
|
||||
Crossplane from installing the Provider Package.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Use `kubectl describe providerrevisions` for more details on why the Package
|
||||
Revision failed.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml
|
||||
Type: Healthy
|
||||
Status: False
|
||||
Reason: UnhealthyPackageRevision
|
||||
```
|
||||
<!-- vale Google.Headings = NO -->
|
||||
##### UnknownPackageRevisionHealth
|
||||
<!-- vale Google.Headings = YES -->
|
||||
|
||||
|
||||
The status of the Provider Package Revision is `Unknown`. The Provider Package
|
||||
Revision may be installing or has an issue.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Use `kubectl describe providerrevisions` for more details on why the Package
|
||||
Revision failed.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml
|
||||
Type: Healthy
|
||||
Status: Unknown
|
||||
Reason: UnknownPackageRevisionHealth
|
||||
```
|
||||
|
||||
## Configure a Provider
|
||||
|
||||
Providers have two different types of configurations:
|
||||
* _Controller configurations_ that change the settings of the Provider pod
|
||||
running inside the Kubernetes cluster. For example, Pod `toleration`.
|
||||
* _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" >}}
|
||||
The Crossplane community deprecated the `ControllerConfig` type in v1.11.
|
||||
Applying a Controller configuration generates a deprecation warning.
|
||||
|
||||
Controller configurations are still supported until there is a replacement type
|
||||
in a future Crossplane version.
|
||||
{{< /hint >}}
|
||||
|
||||
Applying a Crossplane `ControllerConfig` to a Provider changes the settings of
|
||||
the Provider's pod. The
|
||||
[Crossplane ControllerConfig schema](https://doc.crds.dev/github.com/crossplane/crossplane/pkg.crossplane.io/ControllerConfig/v1alpha1)
|
||||
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](https://docs.crossplane.io/knowledge-base/integrations/vault-as-secret-store/#enable-external-secret-stores-in-the-provider)
|
||||
for a Provider.
|
||||
|
||||
Each Provider determines their supported set of `args`.
|
||||
|
||||
### Provider configuration
|
||||
|
||||
The `ProviderConfig` determines settings the Provider uses communicating to the
|
||||
external provider. Each Provider determines available settings of their
|
||||
`ProviderConfig`.
|
||||
|
||||
<!-- vale write-good.Weasel = NO -->
|
||||
<!-- allow "usually" -->
|
||||
Provider authentication is usually configured with a `ProviderConfig`. For
|
||||
example, to use basic key-pair authentication with Provider AWS a
|
||||
{{<hover label="providerconfig" line="2" >}}ProviderConfig{{</hover >}}
|
||||
{{<hover label="providerconfig" line="5" >}}spec{{</hover >}}
|
||||
defines the
|
||||
{{<hover label="providerconfig" line="6" >}}credentials{{</hover >}} and that
|
||||
the Provider pod should look in the Kubernetes
|
||||
{{<hover label="providerconfig" line="7" >}}Secrets{{</hover >}} objects and use
|
||||
the key named
|
||||
{{<hover label="providerconfig" line="10" >}}aws-creds{{</hover >}}.
|
||||
<!-- vale write-good.Weasel = YES -->
|
||||
```yaml {label="providerconfig"}
|
||||
apiVersion: aws.crossplane.io/v1beta1
|
||||
kind: ProviderConfig
|
||||
metadata:
|
||||
name: aws-provider
|
||||
spec:
|
||||
credentials:
|
||||
source: Secret
|
||||
secretRef:
|
||||
namespace: crossplane-system
|
||||
name: aws-creds
|
||||
key: creds
|
||||
```
|
||||
|
||||
{{< hint "important" >}}
|
||||
Authentication configuration may be different across Providers.
|
||||
|
||||
Read the documentation on a specific Provider for instructions on configuring
|
||||
authentication for that Provider.
|
||||
{{< /hint >}}
|
||||
|
||||
<!-- vale write-good.TooWordy = NO -->
|
||||
<!-- allow multiple -->
|
||||
ProviderConfig objects apply to individual Managed Resources. A single
|
||||
Provider can authenticate with multiple users or accounts through
|
||||
ProviderConfigs.
|
||||
<!-- vale write-good.TooWordy = YES -->
|
||||
|
||||
Each account's credentials tie to a unique ProviderConfig. When creating a
|
||||
managed resource, attach the desired ProviderConfig.
|
||||
|
||||
For example, two AWS ProviderConfigs, named
|
||||
{{<hover label="user" line="4">}}user-keys{{</hover >}} and
|
||||
{{<hover label="admin" line="4">}}admin-keys{{</hover >}}
|
||||
use different Kubernetes secrets.
|
||||
|
||||
```yaml {label="user"}
|
||||
apiVersion: aws.crossplane.io/v1beta1
|
||||
kind: ProviderConfig
|
||||
metadata:
|
||||
name: user-keys
|
||||
spec:
|
||||
credentials:
|
||||
source: Secret
|
||||
secretRef:
|
||||
namespace: crossplane-system
|
||||
name: my-key
|
||||
key: secret-key
|
||||
```
|
||||
|
||||
```yaml {label="admin"}
|
||||
apiVersion: aws.crossplane.io/v1beta1
|
||||
kind: ProviderConfig
|
||||
metadata:
|
||||
name: admin-keys
|
||||
spec:
|
||||
credentials:
|
||||
source: Secret
|
||||
secretRef:
|
||||
namespace: crossplane-system
|
||||
name: admin-key
|
||||
key: admin-secret-key
|
||||
```
|
||||
|
||||
Apply the ProviderConfig when creating a managed resource.
|
||||
|
||||
This creates an AWS {{<hover label="user-bucket" line="2" >}}Bucket{{< /hover >}}
|
||||
resource using the
|
||||
{{<hover label="user-bucket" line="9" >}}user-keys{{< /hover >}} ProviderConfig.
|
||||
|
||||
```yaml {label="user-bucket"}
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: user-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
region: us-east-2
|
||||
providerConfigRef:
|
||||
name: user-keys
|
||||
```
|
||||
|
||||
This creates a second {{<hover label="admin-bucket" line="2" >}}Bucket{{< /hover >}}
|
||||
resource using the
|
||||
{{<hover label="admin-bucket" line="9" >}}admin-keys{{< /hover >}} ProviderConfig.
|
||||
|
||||
```yaml {label="admin-bucket"}
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: user-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
region: us-east-2
|
||||
providerConfigRef:
|
||||
name: admin-keys
|
||||
```
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
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.
|
|
@ -0,0 +1,488 @@
|
|||
---
|
||||
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 crds
|
||||
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
|
||||
locks.pkg.crossplane.io
|
||||
providerrevisions.pkg.crossplane.io
|
||||
providers.pkg.crossplane.io
|
||||
storeconfigs.secrets.crossplane.io
|
||||
```
|
||||
{{< /expand >}}
|
||||
|
||||
The following sections describe the functions of some of these CRDs.
|
||||
|
||||
## Providers
|
||||
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://marketplace.upbound.io/providers/upbound/provider-aws),
|
||||
[Azure](https://marketplace.upbound.io/providers/upbound/provider-azure)
|
||||
and [GCP](https://marketplace.upbound.io/providers/upbound/provider-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, the
|
||||
[Upbound Provider AWS](https://marketplace.upbound.io/providers/upbound/provider-aws/)
|
||||
defines a
|
||||
[`bucket`](https://marketplace.upbound.io/providers/upbound/provider-aws/v0.25.0/resources/s3.aws.upbound.io/Bucket/v1beta1)
|
||||
resource for creating and managing AWS S3 storage buckets.
|
||||
|
||||
Within the `bucket` CRD is a
|
||||
[`spec.forProvider.region`](https://marketplace.upbound.io/providers/upbound/provider-aws/v0.25.0/resources/s3.aws.upbound.io/Bucket/v1beta1#doc:spec-forProvider-region)
|
||||
value that defines which AWS region to deploy the bucket in.
|
||||
|
||||
The Upbound Marketplace contains a large
|
||||
[collection of Crossplane Providers](https://marketplace.upbound.io/providers).
|
||||
|
||||
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: myResource
|
||||
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: myResource
|
||||
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: myResource
|
||||
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" >}})
|
|
@ -0,0 +1,930 @@
|
|||
---
|
||||
title: AWS Quickstart Part 2
|
||||
weight: 120
|
||||
tocHidden: true
|
||||
---
|
||||
|
||||
{{< hint "important" >}}
|
||||
This guide is part 2 of a series. Follow [**part 1**]({{<ref "provider-aws" >}})**
|
||||
to install Crossplane and connect your Kubernetes cluster to AWS.
|
||||
|
||||
[**Part 3**]({{<ref "provider-aws-part-3">}})** covers patching _composite resources_
|
||||
and using Crossplane _packages_.
|
||||
{{< /hint >}}
|
||||
|
||||
<!-- vale gitlab.SentenceLength = NO -->
|
||||
This section creates a _[Composition](#create-a-composition)_,
|
||||
_[Composite Resource Definition](#define-a-composite-resource)_ and a
|
||||
_[Claim](#create-a-claim)_
|
||||
to create a custom Kubernetes API to create AWS resources.
|
||||
<!-- vale gitlab.SentenceLength = YES -->
|
||||
|
||||
## 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: upbound-provider-aws
|
||||
spec:
|
||||
package: xpkg.upbound.io/upbound/provider-aws:v0.27.0
|
||||
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 >}}
|
||||
|
||||
## Create a composition
|
||||
[Part 1]({{<ref "provider-aws" >}}) created a single _managed resource_.
|
||||
A _Composition_ is a template to create multiple _managed resources_ at the same time.
|
||||
|
||||
This sample _composition_ creates an DynamoDB instance and associated S3 storage
|
||||
bucket.
|
||||
|
||||
{{< hint "note" >}}
|
||||
This example comes from the AWS recommendation for
|
||||
[storing large DynamoDB attributes in S3](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-use-s3-too.html#bp-use-s3-too-large-values).
|
||||
{{< /hint >}}
|
||||
|
||||
To create a _composition_, first define each individual managed resource.
|
||||
|
||||
### Create an S3 bucket object
|
||||
Define a `bucket` resource using the configuration from the previous section:
|
||||
|
||||
```yaml
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: crossplane-quickstart-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
providerConfigRef:
|
||||
name: default
|
||||
```
|
||||
|
||||
### Create a DynamoDB table resource
|
||||
Next, define a DynamoDB `table` resource.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
The [Upbound Marketplace](https://marketplace.upbound.io/) provides
|
||||
[schema documentation](https://marketplace.upbound.io/providers/upbound/provider-aws/v0.27.0/resources/dynamodb.aws.upbound.io/Table/v1beta1) for a `Table` resource.
|
||||
{{< /hint >}}
|
||||
|
||||
The _AWS Provider_ defines the
|
||||
{{<hover line="1" label="dynamoMR">}}apiVersion{{</hover>}}
|
||||
and
|
||||
{{<hover line="2" label="dynamoMR">}}kind{{</hover>}}.
|
||||
|
||||
DynamoDB instances require a
|
||||
{{<hover line="7" label="dynamoMR">}}region{{</hover>}},
|
||||
{{<hover line="8" label="dynamoMR">}}writeCapacity{{</hover>}}
|
||||
and
|
||||
{{<hover line="9" label="dynamoMR">}}readCapacity{{</hover>}}
|
||||
parameters.
|
||||
|
||||
The {{<hover line="10" label="dynamoMR">}}attribute{{</hover>}} section creates
|
||||
the database "Partition key" and "Hash key."
|
||||
|
||||
This example creates a single key named
|
||||
{{<hover line="11" label="dynamoMR">}}S3ID{{</hover>}} of type
|
||||
{{<hover line="12" label="dynamoMR">}}S{{</hover>}} for "string"
|
||||
```yaml {label="dynamoMR"}
|
||||
apiVersion: dynamodb.aws.upbound.io/v1beta1
|
||||
kind: Table
|
||||
metadata:
|
||||
name: crossplane-quickstart-database
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
writeCapacity: 1
|
||||
readCapacity: 1
|
||||
attribute:
|
||||
- name: S3ID
|
||||
type: S
|
||||
hashKey: S3ID
|
||||
```
|
||||
|
||||
{{< hint "note" >}}
|
||||
DynamoDB specifics are beyond the scope of this guide. Read the
|
||||
[DynamoDB Developer Guide](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Introduction.html)
|
||||
for more information.
|
||||
{{</hint >}}
|
||||
|
||||
### Create the composition object
|
||||
The _composition_ combines the two resource definitions.
|
||||
|
||||
A
|
||||
{{<hover label="compName" line="2">}}Composition{{</ hover>}} comes from the
|
||||
{{<hover label="compName" line="1">}}Crossplane{{</ hover>}}
|
||||
API resources.
|
||||
|
||||
Create any {{<hover label="compName" line="4">}}name{{</ hover>}} for this _composition_.
|
||||
|
||||
```yaml {label="compName"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: dynamoDBWithS3
|
||||
```
|
||||
|
||||
Add the resources to the
|
||||
{{<hover label="specResources" line="5">}}spec.resources{{</ hover>}}
|
||||
section of the _composition_.
|
||||
|
||||
Give each resource a
|
||||
{{<hover label="specResources" line="7">}}name{{</ hover>}}
|
||||
and put the resource definition under the
|
||||
{{<hover label="specResources" line="8">}}base{{</ hover>}}
|
||||
key.
|
||||
|
||||
```yaml {label="specResources"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: dynamoDBWithS3
|
||||
spec:
|
||||
resources:
|
||||
- name: s3Bucket
|
||||
base:
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: crossplane-quickstart-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
providerConfigRef:
|
||||
name: default
|
||||
- name: dynamoDB
|
||||
base:
|
||||
apiVersion: dynamodb.aws.upbound.io/v1beta1
|
||||
kind: Table
|
||||
metadata:
|
||||
name: crossplane-quickstart-database
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
writeCapacity: 1
|
||||
readCapacity: 1
|
||||
attribute:
|
||||
- name: S3ID
|
||||
type: S
|
||||
hashKey: S3ID
|
||||
```
|
||||
|
||||
Put the entire resource definition including the
|
||||
{{<hover label="specResources" line="20">}}apiVersion{{</ hover>}} and resource
|
||||
settings under the
|
||||
{{<hover label="specResources" line="19">}}base{{</ hover>}}.
|
||||
|
||||
_Compositions_ are only a template for generating resources. A _composite
|
||||
resource_ actually creates the resources.
|
||||
|
||||
A _composition_ defines what _composite resources_ can use this
|
||||
template.
|
||||
|
||||
_Compositions_ do this with the
|
||||
{{<hover label="compRef" line="6">}}spec.compositeTypeRef{{</ hover>}}
|
||||
definition.
|
||||
|
||||
```yaml {label="compRef"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: dynamodb-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: database
|
||||
resources:
|
||||
# Removed for Brevity
|
||||
```
|
||||
|
||||
A _composite resource_ is actually a custom Kubernetes API type you define. The
|
||||
platform team controls the kind, API endpoint and version.
|
||||
|
||||
<!-- vale gitlab.SentenceLength = NO -->
|
||||
<!-- Lenght is because of shortcodes, ignore -->
|
||||
With this {{<hover label="compRef" line="6">}}spec.compositeTypeRef{{</ hover>}}
|
||||
Crossplane only allows _composite resources_ from the API group
|
||||
{{<hover label="compRef" line="7">}}custom-api.example.org{{</ hover>}}
|
||||
that are of
|
||||
{{<hover label="compRef" line="8">}}kind: database{{</ hover>}}
|
||||
to use this template to create resources.
|
||||
<!-- vale gitlab.SentenceLength = YES -->
|
||||
|
||||
### Apply the composition
|
||||
Apply the full _Composition_ to your Kubernetes cluster.
|
||||
|
||||
```yaml
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: dynamo-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: database
|
||||
resources:
|
||||
- name: s3Bucket
|
||||
base:
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: crossplane-quickstart-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
region: us-east-2
|
||||
providerConfigRef:
|
||||
name: default
|
||||
- name: dynamoDB
|
||||
base:
|
||||
apiVersion: dynamodb.aws.upbound.io/v1beta1
|
||||
kind: Table
|
||||
metadata:
|
||||
name: crossplane-quickstart-database
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
writeCapacity: 1
|
||||
readCapacity: 1
|
||||
attribute:
|
||||
- name: S3ID
|
||||
type: S
|
||||
hashKey: S3ID
|
||||
EOF
|
||||
```
|
||||
|
||||
Confirm the _composition_ exists with `kubectl get composition`
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get composition
|
||||
NAME AGE
|
||||
dynamo-with-bucket 22s
|
||||
```
|
||||
|
||||
## Define a composite resource
|
||||
|
||||
The _composition_ that was just created limited which _composite resources_ can
|
||||
use that template.
|
||||
|
||||
A _composite resource_ is a custom API defined by the platform teams.
|
||||
A _composite resource definition_ defines the schema for a _composite resource_.
|
||||
|
||||
|
||||
A _composite resource definition_ installs the custom API type into Kubernetes
|
||||
and defines what `spec` keys and values are valid when calling this new custom API.
|
||||
|
||||
Before creating a _composite resource_ Crossplane requires a _composite resource definition_.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
_Composite resource definitions_ are also called `XRDs` for short.
|
||||
{{< /hint >}}
|
||||
|
||||
Just like a _composition_ the
|
||||
{{<hover label="xrdName" line="2" >}}composite resource definition{{</hover>}}
|
||||
is part of the
|
||||
{{<hover label="xrdName" line="1" >}}Crossplane{{</hover>}}
|
||||
API group.
|
||||
|
||||
The _XRD_ {{<hover label="xrdName" line="4" >}}name{{</hover>}} is the new
|
||||
API endpoint.
|
||||
|
||||
```yaml {label="xrdName"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: databases.custom-api.example.org
|
||||
```
|
||||
|
||||
The _XRD's_
|
||||
{{<hover label="xrdGroup" line="5" >}}spec{{</hover>}} defines the new custom
|
||||
API.
|
||||
|
||||
### Define the API endpoint and kind
|
||||
First, define the new API
|
||||
{{<hover label="xrdGroup" line="6" >}}group{{</hover>}}.
|
||||
Next, create the API {{<hover label="xrdGroup" line="8" >}}kind{{</hover>}} and
|
||||
{{<hover label="xrdGroup" line="9" >}}plural{{</hover>}}.
|
||||
|
||||
```yaml {label="xrdGroup"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: databases.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: database
|
||||
plural: databases
|
||||
```
|
||||
|
||||
{{<hint "note" >}}
|
||||
The _XRD_ {{<hover label="xrdGroup" line="6" >}}group{{</hover>}} matches the _composition_ {{<hover label="noteComp"
|
||||
line="5">}}apiVersion{{</hover>}} and the
|
||||
_XRD_ {{<hover label="xrdGroup" line="8" >}}kind{{</hover>}} matches the _composition_
|
||||
{{<hover label="noteComp" line="6">}}kind{{</hover>}} under the {{<hover label="noteComp" line="4">}}compositeTypeRef{{</hover>}}.
|
||||
|
||||
```yaml {label="noteComp"}
|
||||
kind: Composition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: database
|
||||
```
|
||||
{{< /hint >}}
|
||||
|
||||
### Set the API version
|
||||
In Kubernetes, all API endpoints have a version to tell the stability of the API
|
||||
and track revisions.
|
||||
|
||||
Apply a version to the _XRD_ with a
|
||||
{{<hover label="xrdVersion" line="11">}}versions.name{{</hover>}}.
|
||||
This matches the {{<hover label="noteComp"
|
||||
line="5">}}apiVersion{{</hover>}} used in the _composition's_
|
||||
{{<hover label="noteComp" line="4">}}compositeTypeRef{{</hover>}}.
|
||||
|
||||
_XRDs_ require both
|
||||
{{<hover label="xrdVersion" line="12">}}versions.served{{</hover>}}
|
||||
and
|
||||
{{<hover label="xrdVersion" line="13">}}versions.referenceable{{</hover>}}.
|
||||
|
||||
```yaml {label="xrdVersion"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: custom-api-definition
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: database
|
||||
plural: databases
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
```
|
||||
|
||||
{{<hint "note" >}}
|
||||
For more information on defining versions in Kubernetes read the
|
||||
[API versioning](https://kubernetes.io/docs/reference/using-api/#api-versioning) section of the Kubernetes documentation.
|
||||
{{< /hint >}}
|
||||
|
||||
### Create the API schema
|
||||
With an API endpoint named, now define the API schema, or what's allowed
|
||||
inside the `spec` of the new Kubernetes object.
|
||||
|
||||
{{< hint "note" >}}
|
||||
_XRDs_ follow the Kubernetes
|
||||
[_custom resource definition_ rules for schemas](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema).
|
||||
{{</hint >}}
|
||||
|
||||
Place the API
|
||||
{{< hover label="xrdSchema" line="8" >}}schema{{</hover>}}
|
||||
under the
|
||||
{{< hover label="xrdSchema" line="7" >}}version.name{{</hover>}}
|
||||
|
||||
The _XRD_ type defines the next lines. They're always the same.
|
||||
|
||||
<!-- vale write-good.TooWordy = NO -->
|
||||
<!-- allow "validate" -->
|
||||
{{< hover label="xrdSchema" line="9" >}}openAPIV3Schema{{</hover>}} specifies
|
||||
how the schema gets validated.
|
||||
<!-- vale write-good.TooWordy = YES -->
|
||||
|
||||
Next, the entire API is an
|
||||
{{< hover label="xrdSchema" line="10" >}}object{{</hover>}}
|
||||
with a
|
||||
{{< hover label="xrdSchema" line="11" >}}property{{</hover>}} of
|
||||
{{< hover label="xrdSchema" line="12" >}}spec{{</hover>}}.
|
||||
|
||||
The
|
||||
{{< hover label="xrdSchema" line="12" >}}spec{{</hover>}} is also an
|
||||
{{< hover label="xrdSchema" line="13" >}}object{{</hover>}} with
|
||||
{{< hover label="xrdSchema" line="14" >}}properties{{</hover>}}.
|
||||
|
||||
```yaml {label="xrdSchema"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
# Removed for brevity
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
```
|
||||
|
||||
{{< hint "tip" >}}
|
||||
An _XRD_ is a Kubernetes _custom resource definition_.
|
||||
For more information on the values allowed in the _XRD_ view the _XRD_ object with
|
||||
`kubectl describe crd compositeresourcedefinitions`
|
||||
{{< /hint >}}
|
||||
|
||||
Now, define the custom API. Your custom API continues under the last
|
||||
{{<hover label="xrdSchema" line="14">}}properties{{</hover>}} definition in the
|
||||
previous example.
|
||||
|
||||
This custom API has only one setting:
|
||||
<!-- vale Google.We = NO -->
|
||||
* {{<hover label="customAPI" line="4" >}}region{{</hover >}} - where to deploy
|
||||
the resources, a choice of "EU" or "US"
|
||||
|
||||
|
||||
Users can't change any other settings of the S3 bucket or DynamoDB instance.
|
||||
|
||||
The{{<hover label="customAPI" line="4" >}}region{{</hover >}}
|
||||
is a {{<hover label="customAPI" line="5" >}}string{{</hover >}}
|
||||
and can match the regular expression that's
|
||||
{{<hover label="customAPI" line="6" >}}oneOf{{</hover >}}
|
||||
{{<hover label="customAPI" line="7" >}}EU{{</hover >}}
|
||||
or
|
||||
{{<hover label="customAPI" line="8" >}}US{{</hover >}}.
|
||||
|
||||
This API requires the setting
|
||||
{{<hover label="customAPI" line="10" >}}region{{</hover >}}.
|
||||
|
||||
|
||||
```yaml {label="customAPI"}
|
||||
# Removed for brevity
|
||||
# schema.openAPIV3Schema.type.properties.spec
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- region
|
||||
```
|
||||
|
||||
### Enable claims to the API
|
||||
Allow a _claim_ to use this _XRD_ by defining the _claim_ API endpoint under the _XRD_
|
||||
{{<hover label="XRDclaim" line="4">}}spec{{< /hover >}}.
|
||||
|
||||
```yaml {label="XRDclaim"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
# Removed for brevity
|
||||
claimNames:
|
||||
kind: customDatabase
|
||||
plural: customDatabases
|
||||
```
|
||||
|
||||
{{<hint "note" >}}
|
||||
The [Claims](#create-a-claim) section later in this guide discusses _claims_.
|
||||
{{< /hint >}}
|
||||
|
||||
### Apply the composite resource definition
|
||||
Apply the complete _XRD_ to your Kubernetes cluster.
|
||||
|
||||
|
||||
```yaml
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: databases.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: database
|
||||
plural: databases
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- region
|
||||
claimNames:
|
||||
kind: custom-database
|
||||
plural: custom-databases
|
||||
EOF
|
||||
```
|
||||
|
||||
Verify Kubernetes created the XRD with `kubectl get xrd`
|
||||
|
||||
```shell {copy-lines="1",label="getXRD"}
|
||||
kubectl get xrd
|
||||
NAME ESTABLISHED OFFERED AGE
|
||||
databases.custom-api.example.org True True 9s
|
||||
```
|
||||
|
||||
|
||||
## Create a composite resource
|
||||
Creating an _XRD_ allows the creation _composite resources_.
|
||||
|
||||
_Composite resources_ are a convenient way to create multiple resources with a standard template.
|
||||
|
||||
A _composite resource_ uses the custom API created in the _XRD_.
|
||||
|
||||
Looking at part of the _XRD_:
|
||||
|
||||
```yaml {label="xrdSnip"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: database
|
||||
# Removed for brevity
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
```
|
||||
|
||||
The _XRD_ {{<hover label="xrdSnip" line="5">}}group{{</hover>}}
|
||||
becomes the _composite resource_
|
||||
{{<hover label="xr" line="2">}}apiVersion{{</hover>}}.
|
||||
|
||||
The _XRD_ {{<hover label="xrdSnip" line="7">}}kind{{</hover>}}
|
||||
is the _composite resource_
|
||||
{{<hover label="xr" line="3">}}kind{{</hover>}}
|
||||
|
||||
The _XRD_ API {{<hover label="xrdSnip" line="9">}}spec{{</hover>}} defines the
|
||||
_composite resource_ {{<hover label="xr" line="6">}}spec{{</hover>}}.
|
||||
|
||||
The _XRD_ {{<hover label="xrdSnip" line="11">}}properties{{</hover>}} section
|
||||
defines the options for the _composite resource_
|
||||
{{<hover label="xr" line="6">}}spec{{</hover>}}.
|
||||
|
||||
The one option is {{<hover label="xrdSnip" line="12">}}region{{</hover>}} and it
|
||||
can be either {{<hover label="xrdSnip" line="15">}}EU{{</hover>}} or
|
||||
{{<hover label="xrdSnip" line="16">}}US{{</hover>}}.
|
||||
|
||||
This _composite resource_ uses
|
||||
{{<hover label="xr" line="7">}}region: US{{</hover>}}.
|
||||
<!-- vale Google.We = YES -->
|
||||
### Apply the composite resource
|
||||
|
||||
Apply the composite resource to the Kubernetes cluster.
|
||||
|
||||
```yaml {label="xr"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: database
|
||||
metadata:
|
||||
name: my-composite-resource
|
||||
spec:
|
||||
region: "US"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Verify the composite resource
|
||||
Verify Crossplane created the _composite resource_ with `kubectl get composite`
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get composite
|
||||
NAME SYNCED READY COMPOSITION AGE
|
||||
my-composite-resource True True dynamo-with-bucket 31s
|
||||
```
|
||||
|
||||
The output mentions the _composite_ template that the _composite resource_ used.
|
||||
|
||||
Now look at the S3 `bucket` and DynmoDB `table` _managed resources_ with
|
||||
`kubectl get bucket` and `kubectl get table`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get bucket
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-8b6tx True True my-composite-resource-8b6tx 56s
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get table
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-m6vk6 True True my-composite-resource-m6vk6 59s
|
||||
```
|
||||
|
||||
The _composite resource_ automatically generated both _managed resources_.
|
||||
|
||||
Using `kubectl describe` on a _managed resource_ shows the `Owner References` is
|
||||
the _composite resource_.
|
||||
|
||||
```yaml {copy-lines="1"}
|
||||
kubectl describe bucket | grep "Owner References" -A5
|
||||
Owner References:
|
||||
API Version: custom-api.example.org/v1alpha1
|
||||
Block Owner Deletion: true
|
||||
Controller: true
|
||||
Kind: database
|
||||
Name: my-composite-resource
|
||||
```
|
||||
|
||||
Each _composite resource_ creates and owns a unique set of _managed resources_.
|
||||
If you create a second _composite resource_ Crossplane creates a new S3 `bucket`
|
||||
and DynamoDB `table`.
|
||||
|
||||
```yaml {label="xr"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: database
|
||||
metadata:
|
||||
name: my-second-composite-resource
|
||||
spec:
|
||||
region: "US"
|
||||
EOF
|
||||
```
|
||||
|
||||
Again, use `kubectl get composite` to view both _composite resources_.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get composite
|
||||
NAME SYNCED READY COMPOSITION AGE
|
||||
my-composite-resource True True dynamo-with-bucket 2m21s
|
||||
my-second-composite-resource True True dynamo-with-bucket 42s
|
||||
```
|
||||
|
||||
And see there are two `bucket` and two `table` _managed resources_.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get bucket
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-8b6tx True True my-composite-resource-8b6tx 2m57s
|
||||
my-second-composite-resource-z22lc True True my-second-composite-resource-z22lc 78s
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get table
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-m6vk6 True True my-composite-resource-m6vk6 3m
|
||||
my-second-composite-resource-nsz6j True True my-second-composite-resource-nsz6j 81s
|
||||
```
|
||||
|
||||
### Delete the composite resources
|
||||
Because the _composite resource_ is the `Owner` of the _managed resources_, when
|
||||
Crossplane deletes the _composite resource_, it also deletes the _managed resources_ automatically.
|
||||
|
||||
Delete the new _composite resource_ with `kubectl delete composite`.
|
||||
|
||||
```shell
|
||||
kubectl delete composite my-second-composite-resource
|
||||
```
|
||||
|
||||
{{<hint "note">}}
|
||||
There may a delay in deleting the _managed resources_. Crossplane is making API
|
||||
calls to AWS and waits for AWS to confirm they deleted the resources before
|
||||
updating the state in Kubernetes.
|
||||
{{</hint >}}
|
||||
|
||||
Now only one bucket and table exist.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get bucket
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-8b6tx True True my-composite-resource-8b6tx 7m34s
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get table
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-m6vk6 True True my-composite-resource-m6vk6 7m37s
|
||||
```
|
||||
|
||||
Delete the second _composite resource_ to remove the last `bucket` and `table`
|
||||
_managed resources_.
|
||||
|
||||
```shell
|
||||
kubectl delete composite my-composite-resource
|
||||
```
|
||||
|
||||
_Composite resources_ are great for creating multiple related resources against
|
||||
a template, but all _composite resources_ exist at the Kubernetes "cluster
|
||||
level." There's no isolation between _composite resources_. Crossplane uses
|
||||
_claims_ to create resources with namespace isolation.
|
||||
|
||||
## Create a claim
|
||||
|
||||
_Claims_, just like _composite resources_ use the custom API defined in the
|
||||
_XRD_. Unlike a _composite resource_, Crossplane can create _claims_ in a
|
||||
namespace.
|
||||
|
||||
### Create a new Kubernetes namespace
|
||||
Create a new namespace with `kubectl create namespace`.
|
||||
|
||||
```shell
|
||||
kubectl create namespace test
|
||||
```
|
||||
|
||||
A _claim_ uses the same {{<hover label="XRDclaim2" line="7" >}}group{{</hover>}}
|
||||
a _composite resource_ uses but a different
|
||||
{{<hover label="XRDclaim2" line="8" >}}kind{{</hover>}}.
|
||||
|
||||
```yaml {label="XRDclaim2"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
# Removed for brevity
|
||||
group: custom-api.example.org
|
||||
claimNames:
|
||||
kind: custom-database
|
||||
plural: custom-databases
|
||||
```
|
||||
|
||||
Like the _composite resource_, create a new object with the
|
||||
{{<hover label="claim" line="2" >}}custom-api.example.org{{</hover>}} API
|
||||
endpoint.
|
||||
|
||||
The _XRD_
|
||||
{{<hover label="XRDclaim2" line="8" >}}ClaimNames.kind{{</hover>}} defines the
|
||||
{{<hover label="claim" line="3" >}}kind{{</hover>}}.
|
||||
|
||||
The {{<hover label="claim" line="7" >}}spec{{</hover>}} uses the same
|
||||
API options as the _composite resource_.
|
||||
|
||||
### Apply the claim
|
||||
Apply the _claim_ to your Kubernetes cluster.
|
||||
|
||||
```yaml {label="claim"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: custom-database
|
||||
metadata:
|
||||
name: claimed-database
|
||||
namespace: test
|
||||
spec:
|
||||
region: "US"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Verify the claim
|
||||
Verify Crossplane created the _claim_ with `kubectl get claim` in the `test`
|
||||
namespace.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get claim -n test
|
||||
NAME SYNCED READY CONNECTION-SECRET AGE
|
||||
claimed-database True True 35s
|
||||
```
|
||||
|
||||
When Crossplane creates a _claim_ a unique _composite resource_ is automatically
|
||||
created too. View the new _composite resource_ with `kubectl get composite`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get composite
|
||||
NAME SYNCED READY COMPOSITION AGE
|
||||
claimed-database-6xsgq True True dynamo-with-bucket 46s
|
||||
```
|
||||
|
||||
The _composite resource_ exists at the "cluster scope" while the _claim_ exists
|
||||
at the "namespace scope."
|
||||
|
||||
Create a second namespace and a second claim.
|
||||
|
||||
```shell
|
||||
kubectl create namespace test2
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: custom-database
|
||||
metadata:
|
||||
name: claimed-database
|
||||
namespace: test2
|
||||
spec:
|
||||
region: "US"
|
||||
EOF
|
||||
```
|
||||
|
||||
View the _claims_ in all namespaces with `kubectl get claim -A`
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get claim -A
|
||||
NAMESPACE NAME SYNCED READY CONNECTION-SECRET AGE
|
||||
test claimed-database True True 4m32s
|
||||
test2 claimed-database True True 43s
|
||||
```
|
||||
|
||||
Now look at the _composite resources_ at the cluster scope.
|
||||
|
||||
```shell
|
||||
kubectl get composite
|
||||
NAME SYNCED READY COMPOSITION AGE
|
||||
claimed-database-6xsgq True True dynamo-with-bucket 8m37s
|
||||
claimed-database-f54qv True True dynamo-with-bucket 4m47s
|
||||
```
|
||||
|
||||
Crossplane created a second _composite resource_ for the second _claim_.
|
||||
|
||||
Looking at the S3 `bucket` and DynamoDB `table` shows two of each resource, one
|
||||
for each claim.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get bucket
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
claimed-database-6xsgq-l9d8z True True claimed-database-6xsgq-l9d8z 9m18s
|
||||
claimed-database-f54qv-9542v True True claimed-database-f54qv-9542v 5m28s
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get table
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
claimed-database-6xsgq-nmxhs True True claimed-database-6xsgq-nmxhs 11m
|
||||
claimed-database-f54qv-qrsdj True True claimed-database-f54qv-qrsdj 7m24s
|
||||
```
|
||||
|
||||
### Delete the claims
|
||||
Removing the _claims_ removes the _composite resources_ and the associated
|
||||
_managed resources_.
|
||||
|
||||
```shell
|
||||
kubectl delete claim claimed-database -n test
|
||||
kubectl delete claim claimed-database -n test2
|
||||
```
|
||||
|
||||
Verify Crossplane removed all the _managed resources_.
|
||||
|
||||
```shell
|
||||
kubectl get bucket
|
||||
kubectl get table
|
||||
```
|
||||
|
||||
Claims are powerful tools to give users resources in their own isolated
|
||||
namespace. But these examples haven't shown how the custom API can change
|
||||
the settings defined in the _composition_. This _composition patching_ applies
|
||||
the API settings when creating resources.
|
||||
[Part 3]({{< ref "provider-aws-part-3">}}) of this guide covers _composition
|
||||
patches_ and making all this configuration portable in Crossplane _packages_.
|
||||
|
||||
## Next steps
|
||||
* [**Continue to part 3**]({{< ref "provider-aws-part-3">}}) to create a learn
|
||||
about _patching_ resources and creating Crossplane _packages_.
|
||||
* Explore AWS resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-aws/).
|
||||
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.
|
|
@ -0,0 +1,652 @@
|
|||
---
|
||||
title: AWS Quickstart Part 3
|
||||
weight: 120
|
||||
tocHidden: true
|
||||
---
|
||||
|
||||
{{< hint "important" >}}
|
||||
This guide is part 3 of a series.
|
||||
|
||||
Follow [**part 1**]({{<ref "provider-aws" >}})
|
||||
to install Crossplane and connect your Kubernetes cluster to AWS.
|
||||
|
||||
Follow [**part 2**]({{<ref "provider-aws-part-2" >}}) to create a _composition_,
|
||||
_custom resource definition_ and a _claim_.
|
||||
{{< /hint >}}
|
||||
|
||||
[Part 2]({{<ref "provider-aws-part-2" >}}) created a _composite resource
|
||||
definition_ to define the schema of the custom API. Users create a _claim_ to
|
||||
use the custom API and apply their options. Part 2 didn't show how the options
|
||||
set in a _claim_ change or get applied the associated _composite resources_.
|
||||
|
||||
## Prerequisites
|
||||
* Complete quickstart [part 1]({{<ref "provider-aws" >}}) and
|
||||
[Part 2]({{<ref "provider-aws-part-2" >}}) to install Crossplane and the quickstart
|
||||
configurations.
|
||||
|
||||
{{<expand "Skip parts 1 and 2 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: upbound-provider-aws
|
||||
spec:
|
||||
package: xpkg.upbound.io/upbound/provider-aws:v0.27.0
|
||||
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
|
||||
```
|
||||
|
||||
6. Create a _composition_
|
||||
```yaml
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: dynamo-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: database
|
||||
resources:
|
||||
- name: s3Bucket
|
||||
base:
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: crossplane-quickstart-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
- name: dynamoDB
|
||||
base:
|
||||
apiVersion: dynamodb.aws.upbound.io/v1beta1
|
||||
kind: Table
|
||||
metadata:
|
||||
name: crossplane-quickstart-database
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
writeCapacity: 1
|
||||
readCapacity: 1
|
||||
attribute:
|
||||
- name: S3ID
|
||||
type: S
|
||||
hashKey: S3ID
|
||||
EOF
|
||||
```
|
||||
|
||||
7. Create a _composite resource definition_
|
||||
```yaml
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: databases.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: database
|
||||
plural: databases
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- region
|
||||
claimNames:
|
||||
kind: custom-database
|
||||
plural: custom-databases
|
||||
EOF
|
||||
```
|
||||
|
||||
8. Create a new namespace
|
||||
```shell
|
||||
kubectl create namespace test
|
||||
```
|
||||
|
||||
{{</expand >}}
|
||||
|
||||
## Enable composition patches
|
||||
In a _composition_ `patches` map fields in the custom API to fields inside the
|
||||
_managed resources_.
|
||||
|
||||
The _composition_ has two _managed resources_, a
|
||||
{{<hover label="compResources" line="8">}}bucket{{</hover>}} and a
|
||||
{{<hover label="compResources" line="19">}}table{{</hover>}}.
|
||||
|
||||
```yaml {label="compResources"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
# Removed for Brevity
|
||||
resources:
|
||||
- name: s3Bucket
|
||||
base:
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: crossplane-quickstart-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
- name: dynamoDB
|
||||
base:
|
||||
apiVersion: dynamodb.aws.upbound.io/v1beta1
|
||||
kind: Table
|
||||
metadata:
|
||||
name: crossplane-quickstart-database
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
writeCapacity: 1
|
||||
readCapacity: 1
|
||||
attribute:
|
||||
- name: S3ID
|
||||
type: S
|
||||
hashKey: S3ID
|
||||
```
|
||||
<!-- vale Google.We = NO -->
|
||||
The custom API defined a single option,
|
||||
{{<hover label="xrdSnip" line="12">}}region{{</hover>}}. A
|
||||
{{<hover label="xrdSnip" line="12">}}region{{</hover>}} can be either
|
||||
{{<hover label="xrdSnip" line="15">}}EU{{</hover>}} or
|
||||
{{<hover label="xrdSnip" line="16">}}US{{</hover>}}.
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
```yaml {label="xrdSnip"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: database
|
||||
# Removed for brevity
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
```
|
||||
|
||||
Creating a _composition_ `patch` allows Crossplane to update the settings of the
|
||||
_composite resource_. Patches apply to the individual _managed resources_
|
||||
inside the _composition_.
|
||||
|
||||
A {{<hover label="patch" line="12">}}patch{{</hover>}} has a
|
||||
{{<hover label="patch" line="13">}}fromField{{</hover>}} and a
|
||||
{{<hover label="patch" line="14">}}toField{{</hover>}} specifying which value
|
||||
_from_ the custom API should apply _to_ the _managed resource_.
|
||||
Patches can create a
|
||||
{{<hover label="patch" line="15">}}transform{{</hover>}} to change the _from_
|
||||
field before it's applied.
|
||||
|
||||
The transform
|
||||
{{<hover label="patch" line="16">}}type{{</hover>}} is what kind of change to
|
||||
make on the _from_ field. Types of changes could include appending a string,
|
||||
preforming a math operation or mapping one value to another.
|
||||
|
||||
Applying a {{<hover label="patch" line="12">}}patch{{</hover>}} to the
|
||||
{{<hover label="patch" line="8">}}Bucket{{</hover>}} uses the custom API
|
||||
{{<hover label="patch" line="13">}}region{{</hover>}} to use as the _managed resource_
|
||||
{{<hover label="patch" line="11">}}region{{</hover>}}.
|
||||
|
||||
<!-- vale Google.We = NO -->
|
||||
The custom API value "EU" is
|
||||
{{<hover label="patch" line="18">}}mapped{{</hover>}} to the value "eu-north-1"
|
||||
and "US" is {{<hover label="patch" line="19">}}mapped{{</hover>}} to the value
|
||||
"us-east-2."
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
|
||||
```yaml {label="patch"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
# Removed for Brevity
|
||||
resources:
|
||||
- name: s3Bucket
|
||||
base:
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
spec:
|
||||
forProvider:
|
||||
region: "us-east-2"
|
||||
patches:
|
||||
- fromFieldPath: "region"
|
||||
toFieldPath: "spec.forProvider.region"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "eu-north-1"
|
||||
US: "us-east-2"
|
||||
```
|
||||
<!-- vale Google.We = NO -->
|
||||
Patching is a powerful tool enabling simpler or abstracted APIs. A developer
|
||||
isn't required to know the specific AWS region identifier, only the abstracted
|
||||
option of "EU" or "US."
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
### Apply the updated composition
|
||||
Apply the same `patch` to the `Table` _managed resource_ and apply the updated
|
||||
_composition_.
|
||||
|
||||
```yaml
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: dynamo-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: database
|
||||
resources:
|
||||
- name: s3Bucket
|
||||
base:
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: crossplane-quickstart-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
name: default
|
||||
region: "us-east-2"
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
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
|
||||
metadata:
|
||||
name: crossplane-quickstart-database
|
||||
spec:
|
||||
forProvider:
|
||||
writeCapacity: 1
|
||||
readCapacity: 1
|
||||
attribute:
|
||||
- name: S3ID
|
||||
type: S
|
||||
hashKey: S3ID
|
||||
region: "us-east-2"
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
toFieldPath: "spec.forProvider.region"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "eu-north-1"
|
||||
US: "us-east-2"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Create a claim
|
||||
Create a new _claim_ and set the
|
||||
{{<hover label="claim" line="8" >}}region{{</hover >}} to "EU."
|
||||
|
||||
```yaml {label="claim"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: custom-database
|
||||
metadata:
|
||||
name: claimed-eu-database
|
||||
namespace: test
|
||||
spec:
|
||||
region: "EU"
|
||||
EOF
|
||||
```
|
||||
|
||||
View the _claim_ with `kubectl get claim`
|
||||
|
||||
```shell
|
||||
kubectl get claim -n test
|
||||
NAME SYNCED READY CONNECTION-SECRET AGE
|
||||
claimed-eu-database True True 18m
|
||||
```
|
||||
|
||||
The claim reports `SYNCED` and `READY` as `True` after Crossplane creates
|
||||
all the _managed resources_.
|
||||
|
||||
Describe the `Table` resource to see the AWS region is `eu-north-1`.
|
||||
|
||||
```shell
|
||||
kubectl describe table | grep arn:aws
|
||||
Arn: arn:aws:dynamodb:eu-north-1:622343227358:table/claimed-eu-database-2sh9w-dhvw6
|
||||
```
|
||||
|
||||
<!-- vale Google.We = NO -->
|
||||
Using {{<hover label="claim" line="8" >}}region: "EU"{{</hover >}} patches the
|
||||
_composite resource_, updating the AWS region from `us-east-2` to `eu-north-1`.
|
||||
The developer creating the claim isn't required to know which specific AWS
|
||||
region or the naming conventions. Using the abstract API options of "EU" or "US"
|
||||
the developer places their resources in the desired location.
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
Deleting the claim removes the _managed resources_.
|
||||
|
||||
{{<hint "note" >}}
|
||||
The _managed resources_ take up to 5 minutes to delete.
|
||||
{{< /hint >}}
|
||||
|
||||
```shell
|
||||
kubectl delete claim claimed-eu-database -n test
|
||||
```
|
||||
|
||||
## Create a Crossplane configuration package
|
||||
|
||||
Crossplane _configuration packages_ allow users to combine their _custom
|
||||
resource definition_ and _composition_ files into an OCI image.
|
||||
|
||||
{{< hint "note" >}}
|
||||
The [Open Container Initiative](https://opencontainers.org/faq/)
|
||||
defines the OCI image standard.
|
||||
An OCI images is a standard way to package data.
|
||||
{{< /hint >}}
|
||||
|
||||
You can host configuration packages in image registries like
|
||||
[Docker Hub](https://hub.docker.com/) or the
|
||||
[Upbound Marketplace](https://marketplace.upbound.io/).
|
||||
|
||||
Crossplane can download and install configuration packages into a Kubernetes
|
||||
cluster.
|
||||
|
||||
Creating a configuration package makes your Crossplane custom APIs portable
|
||||
and versioned.
|
||||
|
||||
Building and installing configuration packages requires an OCI image compatible
|
||||
tool.
|
||||
|
||||
{{< hint "note" >}}
|
||||
You can use any software that builds OCI images. This includes
|
||||
[Docker](https://www.docker.com/) or
|
||||
[Upbound's Up CLI)](https://github.com/upbound/up).
|
||||
{{< /hint >}}
|
||||
|
||||
A configuration package includes three files:
|
||||
* `crossplane.yaml` defines the metadata of the package.
|
||||
* `definition.yaml` is the _composite resource definition_ for the package.
|
||||
* `composition.yaml` is the _composition_ template for the package.
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a crossplane.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
Configuration packages describe their contents and requirements with a
|
||||
`crossplane.yaml` file.
|
||||
|
||||
The `crossplane.yaml` file lists the required Crossplane _providers_ and their
|
||||
compatible versions as well as the required Crossplane version.
|
||||
|
||||
The Crossplane
|
||||
{{<hover label="xpyaml" line="1" >}}meta.pkg{{</hover>}} API defines the schema
|
||||
for a
|
||||
{{<hover label="xpyaml" line="2" >}}Configuration{{</hover>}}.
|
||||
|
||||
Inside the {{<hover label="xpyaml" line="5" >}}spec{{</hover>}} define the
|
||||
required Crossplane
|
||||
{{<hover label="xpyaml" line="7" >}}version{{</hover>}}.
|
||||
|
||||
The {{<hover label="xpyaml" line="8" >}}dependsOn{{</hover>}} section lists the
|
||||
dependencies for a package.
|
||||
|
||||
This package lists the Upbound
|
||||
{{<hover label="xpyaml" line="9" >}}provider-aws{{</hover>}}
|
||||
version {{<hover label="xpyaml" line="10" >}}0.27.0{{</hover>}} or later as a
|
||||
dependency.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Crossplane automatically installs dependencies. Dependencies can include other
|
||||
configuration packages.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml {label="xpyaml"}
|
||||
apiVersion: meta.pkg.crossplane.io/v1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: crossplane-aws-quickstart
|
||||
spec:
|
||||
crossplane:
|
||||
version: ">=v1.11.0"
|
||||
dependsOn:
|
||||
- provider: xpkg.upbound.io/upbound/provider-aws
|
||||
version: ">=v0.27.0"
|
||||
```
|
||||
|
||||
Create a new directory and save the `crossplane.yaml` file.
|
||||
|
||||
```yaml
|
||||
mkdir crossplane-aws-quickstart
|
||||
cat <<EOF > crossplane-aws-quickstart/crossplane.yaml
|
||||
apiVersion: meta.pkg.crossplane.io/v1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: crossplane-aws-quickstart
|
||||
spec:
|
||||
crossplane:
|
||||
version: ">=v1.11.0"
|
||||
dependsOn:
|
||||
- provider: xpkg.upbound.io/upbound/provider-aws
|
||||
version: ">=v0.27.0"
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a definition.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
|
||||
A configuration package requires a _composite resource definition_ (XRD) to define the
|
||||
custom API.
|
||||
|
||||
Save the _XRD_ as `definition.yaml` in the same directory as the
|
||||
`crossplane.yaml` file.
|
||||
|
||||
```yaml
|
||||
cat <<EOF > crossplane-aws-quickstart/definition.yaml
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: databases.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: database
|
||||
plural: databases
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- region
|
||||
claimNames:
|
||||
kind: custom-database
|
||||
plural: custom-databases
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a composition.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
|
||||
The _composition_ template creates the _managed resources_ and allows _patches_
|
||||
to customize the _managed resources_.
|
||||
|
||||
Copy the _composition_ into the `composition.yaml` file in the same directory as
|
||||
`crossplane.yaml`.
|
||||
|
||||
```yaml
|
||||
cat <<EOF > crossplane-aws-quickstart/composition.yaml
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: dynamo-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: database
|
||||
resources:
|
||||
- name: s3Bucket
|
||||
base:
|
||||
apiVersion: s3.aws.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: crossplane-quickstart-bucket
|
||||
spec:
|
||||
providerConfigRef:
|
||||
name: default
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
toFieldPath: "spec.forProvider.region"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "eu-north-1"
|
||||
US: "us-east-1"
|
||||
- name: dynamoDB
|
||||
base:
|
||||
apiVersion: dynamodb.aws.upbound.io/v1beta1
|
||||
kind: Table
|
||||
metadata:
|
||||
name: crossplane-quickstart-database
|
||||
spec:
|
||||
forProvider:
|
||||
writeCapacity: 1
|
||||
readCapacity: 1
|
||||
attribute:
|
||||
- name: S3ID
|
||||
type: S
|
||||
hashKey: S3ID
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
toFieldPath: "spec.forProvider.region"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "eu-north-1"
|
||||
US: "us-east-1"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Install the Crossplane command-line
|
||||
To build a configuration package install the Crossplane Kubernetes command-line
|
||||
extension.
|
||||
|
||||
```shell
|
||||
curl "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh"
|
||||
./install.sh
|
||||
sudo mv kubectl-crossplane /usr/bin
|
||||
```
|
||||
|
||||
Verify the Crossplane command-line installed with `kubectl crossplane --help`
|
||||
|
||||
```shell
|
||||
kubectl crossplane --help
|
||||
Usage: kubectl crossplane <command>
|
||||
|
||||
A command line tool for interacting with Crossplane.
|
||||
|
||||
Flags:
|
||||
-h, --help Show context-sensitive help.
|
||||
-v, --version Print version and quit.
|
||||
--verbose Print verbose logging statements.
|
||||
# Ouptut removed for brevity
|
||||
```
|
||||
|
||||
### Build a configuration package
|
||||
|
||||
Use the `kubectl crossplane` command to create an `.xpkg` file containing the
|
||||
custom APIs and Crossplane configuration.
|
||||
|
||||
```shell
|
||||
kubectl crossplane build configuration -f crossplane-aws-quickstart/ --name="crossplane-aws-quickstart"
|
||||
```
|
||||
|
||||
Now an `.xpkg` OCI image is inside the `crossplane-aws-quickstart` directory.
|
||||
|
||||
```shell
|
||||
ls crossplane-aws-quickstart/
|
||||
composition.yaml crossplane-aws-quickstart.xpkg crossplane.yaml definition.yaml
|
||||
```
|
||||
|
||||
## Next steps
|
||||
* Explore AWS resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-aws/).
|
||||
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.
|
||||
* Read more about [Crossplane concepts]({{<ref "../concepts" >}})
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,810 @@
|
|||
---
|
||||
title: Azure Quickstart Part 3
|
||||
weight: 120
|
||||
tocHidden: true
|
||||
---
|
||||
|
||||
{{< hint "important" >}}
|
||||
This guide is part 3 of a series.
|
||||
|
||||
Follow [**part 1**]({{<ref "provider-azure" >}})
|
||||
to install Crossplane and connect your Kubernetes cluster to Azure.
|
||||
|
||||
Follow [**part 2**]({{<ref "provider-azure-part-2" >}}) to create a _composition_,
|
||||
_custom resource definition_ and a _claim_.
|
||||
{{< /hint >}}
|
||||
|
||||
[Part 2]({{<ref "provider-azure-part-2" >}}) created a
|
||||
_CompositeResourceDefinition_ to define the schema of the custom API.
|
||||
Users create a _Claim_ to use the custom API and apply their options.
|
||||
Part 2 didn't show how the options set in a _Claim_ change or get
|
||||
applied to the associated _composite resources_.
|
||||
|
||||
## Prerequisites
|
||||
* Complete quickstart [part 1]({{<ref "provider-azure" >}}) and
|
||||
[part 2]({{<ref "provider-azure-part-2" >}}) to install Crossplane and the quickstart
|
||||
configurations.
|
||||
|
||||
{{<expand "Skip parts 1 and 2 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
|
||||
```
|
||||
|
||||
1. 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: upbound-provider-azure
|
||||
spec:
|
||||
package: xpkg.upbound.io/upbound/provider-azure:v0.32.0
|
||||
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
|
||||
```
|
||||
|
||||
6. Create a _composition_
|
||||
{{< hint "tip" >}}
|
||||
Apply your
|
||||
{{<hover label="Composition" line="27">}}resourceGroupName{{</hover>}} to each resource.
|
||||
{{< /hint >}}
|
||||
|
||||
{{< editCode >}}
|
||||
```yaml {label="Composition"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: crossplane-quickstart-vm-with-network
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XVirtualMachine
|
||||
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
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
size: Standard_B1ms
|
||||
sourceImageReference:
|
||||
- offer: debian-11
|
||||
publisher: Debian
|
||||
sku: 11-backports-gen2
|
||||
version: latest
|
||||
networkInterfaceIdsSelector:
|
||||
matchControllerRef: true
|
||||
- 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"
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
- name: quickstart-subnet
|
||||
base:
|
||||
apiVersion: network.azure.upbound.io/v1beta1
|
||||
kind: Subnet
|
||||
spec:
|
||||
forProvider:
|
||||
addressPrefixes:
|
||||
- 10.0.1.0/24
|
||||
virtualNetworkNameSelector:
|
||||
matchControllerRef: true
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
- name: quickstart-network
|
||||
base:
|
||||
apiVersion: network.azure.upbound.io/v1beta1
|
||||
kind: VirtualNetwork
|
||||
spec:
|
||||
forProvider:
|
||||
addressSpace:
|
||||
- 10.0.0.0/16
|
||||
location: "Central US"
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
EOF
|
||||
```
|
||||
{{< /editCode >}}
|
||||
|
||||
7. Create a _CompositeResourceDefinition_
|
||||
```yaml
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xvirtualmachines.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XVirtualMachine
|
||||
plural: xvirtualmachines
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- region
|
||||
claimNames:
|
||||
kind: VirtualMachine
|
||||
plural: virtualmachines
|
||||
EOF
|
||||
```
|
||||
|
||||
8. Create a new namespace
|
||||
```shell
|
||||
kubectl create namespace test
|
||||
```
|
||||
|
||||
{{</expand >}}
|
||||
|
||||
## Enable composition patches
|
||||
In a _Composition_ `patches` map fields in the custom API to fields inside the
|
||||
_managed resources_.
|
||||
|
||||
The example _Composition_ has four _managed resources_. A {{<hover label="compResources" line="8" >}}LinuxVirtualMachine{{</hover>}},
|
||||
{{<hover label="compResources" line="12" >}}NetworkInterface{{</hover>}},
|
||||
{{<hover label="compResources" line="16" >}}Subnet{{</hover>}} and a
|
||||
{{<hover label="compResources" line="20" >}}VirtualNetwork{{</hover>}}.
|
||||
|
||||
|
||||
```yaml {label="compResources",copy-lines="none"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
# Removed for Brevity
|
||||
resources:
|
||||
- name: quickstart-vm
|
||||
base:
|
||||
apiVersion: compute.azure.upbound.io/v1beta1
|
||||
kind: LinuxVirtualMachine
|
||||
- name: quickstart-nic
|
||||
base:
|
||||
apiVersion: network.azure.upbound.io/v1beta1
|
||||
kind: NetworkInterface
|
||||
- name: quickstart-subnet
|
||||
base:
|
||||
apiVersion: network.azure.upbound.io/v1beta1
|
||||
kind: Subnet
|
||||
- name: quickstart-network
|
||||
base:
|
||||
apiVersion: network.azure.upbound.io/v1beta1
|
||||
kind: VirtualNetwork
|
||||
```
|
||||
<!-- vale Google.We = NO -->
|
||||
The custom API defined a single option,
|
||||
{{<hover label="xrdSnip" line="12">}}region{{</hover>}}. A
|
||||
{{<hover label="xrdSnip" line="12">}}region{{</hover>}} can be either
|
||||
{{<hover label="xrdSnip" line="15">}}EU{{</hover>}} or
|
||||
{{<hover label="xrdSnip" line="16">}}US{{</hover>}}.
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
```yaml {label="xrdSnip",copy-lines="none"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XVirtualMachine
|
||||
# Removed for brevity
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
```
|
||||
|
||||
Creating a _composition_ `patch` allows Crossplane to update the settings of the
|
||||
_composite resource_. Patches apply to the individual _managed resources_
|
||||
inside the _Composition_.
|
||||
|
||||
A {{<hover label="patch" line="13">}}patch{{</hover>}} has a
|
||||
{{<hover label="patch" line="14">}}fromField{{</hover>}} and a
|
||||
{{<hover label="patch" line="15">}}toField{{</hover>}} specifying which value
|
||||
_from_ the custom API should apply _to_ a field in the _managed resource_.
|
||||
Patches can create a
|
||||
{{<hover label="patch" line="16">}}transform{{</hover>}} to change the _from_
|
||||
field before it's applied.
|
||||
|
||||
The transform
|
||||
{{<hover label="patch" line="17">}}type{{</hover>}} is what kind of change to
|
||||
make on the _from_ field. Types of changes could include appending a string,
|
||||
preforming a math operation or mapping one value to another.
|
||||
|
||||
Applying a {{<hover label="patch" line="13">}}patch{{</hover>}} to the
|
||||
{{<hover label="patch" line="8">}}LinuxVirtualMachine{{</hover>}} uses the
|
||||
custom API
|
||||
{{<hover label="patch" line="14">}}region{{</hover>}} to use as the
|
||||
_managed resource_
|
||||
{{<hover label="patch" line="15">}}location{{</hover>}}.
|
||||
|
||||
<!-- vale Google.We = NO -->
|
||||
The custom API value "EU" is
|
||||
{{<hover label="patch" line="19">}}mapped{{</hover>}} to the value
|
||||
"Sweden Central"
|
||||
and "US" is {{<hover label="patch" line="20">}}mapped{{</hover>}} to the value
|
||||
"Central US."
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
|
||||
```yaml {label="patch",copy-lines="none"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
# Removed for Brevity
|
||||
resources:
|
||||
- name: quickstart-vm
|
||||
base:
|
||||
apiVersion: compute.azure.upbound.io/v1beta1
|
||||
kind: LinuxVirtualMachine
|
||||
spec:
|
||||
forProvider:
|
||||
location: "Central US"
|
||||
# Removed for Brevity
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
toFieldPath: "spec.forProvider.location"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "Sweden Central"
|
||||
US: "Central US"
|
||||
```
|
||||
<!-- vale Google.We = NO -->
|
||||
Patching is a powerful tool enabling simpler or abstracted APIs. A developer
|
||||
isn't required to know the specific Azure location names, only the abstracted
|
||||
option of "EU" or "US."
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
### Apply the updated composition
|
||||
Apply the same `patch` to all other _managed resource_
|
||||
and apply the updated _Composition_.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Update each `resourceGroupName` with your Azure Resource Group.
|
||||
{{< /hint >}}
|
||||
|
||||
{{< editCode >}}
|
||||
```yaml
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: crossplane-quickstart-vm-with-network
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XVirtualMachine
|
||||
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
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
size: Standard_B1ms
|
||||
sourceImageReference:
|
||||
- offer: debian-11
|
||||
publisher: Debian
|
||||
sku: 11-backports-gen2
|
||||
version: latest
|
||||
networkInterfaceIdsSelector:
|
||||
matchControllerRef: true
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
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"
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
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
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
toFieldPath: "spec.forProvider.location"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "Sweden Central"
|
||||
US: "Central US"
|
||||
- name: quickstart-network
|
||||
base:
|
||||
apiVersion: network.azure.upbound.io/v1beta1
|
||||
kind: VirtualNetwork
|
||||
spec:
|
||||
forProvider:
|
||||
addressSpace:
|
||||
- 10.0.0.0/16
|
||||
location: "Sweden Central"
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
toFieldPath: "spec.forProvider.location"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "Sweden Central"
|
||||
US: "Central US"
|
||||
EOF
|
||||
```
|
||||
{{< /editCode >}}
|
||||
|
||||
### Create a claim
|
||||
Create a new _claim_ and set the
|
||||
{{<hover label="claim" line="8" >}}region{{</hover >}} to "EU."
|
||||
|
||||
```yaml {label="claim"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: VirtualMachine
|
||||
metadata:
|
||||
name: claimed-eu-virtualmachine
|
||||
namespace: test
|
||||
spec:
|
||||
region: "EU"
|
||||
EOF
|
||||
```
|
||||
|
||||
View the _Claim_ with `kubectl get claim`
|
||||
|
||||
{{< hint "note" >}}
|
||||
It may take up to 10 minutes for the Claim to be `READY`.
|
||||
{{< /hint >}}
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get claim -n test
|
||||
NAME SYNCED READY CONNECTION-SECRET AGE
|
||||
claimed-eu-virtualmachine True True 6m2s
|
||||
```
|
||||
|
||||
The claim reports `SYNCED` and `READY` as `True` after Crossplane creates
|
||||
all the _managed resources_.
|
||||
|
||||
Describe the `LinuxVirtualMachine` resource to see the Azure location is `Sweden
|
||||
Central`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl describe linuxvirtualmachine | grep "At Provider\|Location"
|
||||
Location: Sweden Central
|
||||
At Provider:
|
||||
Location: swedencentral
|
||||
```
|
||||
|
||||
<!-- vale Google.We = NO -->
|
||||
Using {{<hover label="claim" line="8" >}}region: "EU"{{</hover >}} patches the
|
||||
_composite resource_, updating the Azure location from `Central US` to
|
||||
`Sweden Central`.
|
||||
The developer creating the claim isn't required to know which specific Azure
|
||||
location or the location naming conventions. Using the abstract API options of
|
||||
"EU" or "US" the developer places their resources in the desired location.
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
Deleting the claim removes the _managed resources_.
|
||||
|
||||
{{<hint "note" >}}
|
||||
The _managed resources_ take up to 5 minutes to delete.
|
||||
{{< /hint >}}
|
||||
|
||||
```shell
|
||||
kubectl delete virtualmachine claimed-eu-virtualmachine -n test
|
||||
```
|
||||
|
||||
## Create a Crossplane configuration package
|
||||
|
||||
Crossplane _configuration packages_ allow users to combine their
|
||||
_Custom Resource Definition_ and _Composition_ files into a single OCI image.
|
||||
|
||||
{{< hint "note" >}}
|
||||
The [Open Container Initiative](https://opencontainers.org/faq/)
|
||||
defines the OCI image standard.
|
||||
An OCI images is a standard way to package data.
|
||||
{{< /hint >}}
|
||||
|
||||
You can host configuration packages in image registries like
|
||||
[Docker Hub](https://hub.docker.com/) or the
|
||||
[Upbound Marketplace](https://marketplace.upbound.io/).
|
||||
|
||||
Crossplane can download and install configuration packages into a Kubernetes
|
||||
cluster.
|
||||
|
||||
Creating a configuration package makes your Crossplane custom APIs portable
|
||||
and versioned.
|
||||
|
||||
Building and installing configuration packages requires an OCI image compatible
|
||||
tool.
|
||||
|
||||
{{< hint "note" >}}
|
||||
You can use any software that builds OCI images. This includes
|
||||
[Docker](https://www.docker.com/) or
|
||||
[Upbound's Up CLI](https://github.com/upbound/up).
|
||||
{{< /hint >}}
|
||||
|
||||
A configuration package includes at least three files:
|
||||
* `crossplane.yaml` defines the metadata of the package.
|
||||
* `definition.yaml` is the _CompositeResourceDefinition_ for the package.
|
||||
* `composition.yaml` is the _Composition_ template for the package.
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a crossplane.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
Configuration packages describe their contents and requirements with a
|
||||
`crossplane.yaml` file.
|
||||
|
||||
The `crossplane.yaml` file lists the required Crossplane _Providers_ and their
|
||||
compatible versions as well as the required Crossplane version.
|
||||
|
||||
The Crossplane
|
||||
{{<hover label="xpyaml" line="3" >}}meta.pkg{{</hover>}} API defines the schema
|
||||
for a
|
||||
{{<hover label="xpyaml" line="4" >}}Configuration{{</hover>}}.
|
||||
|
||||
Inside the {{<hover label="xpyaml" line="7" >}}spec{{</hover>}} define the
|
||||
required Crossplane
|
||||
{{<hover label="xpyaml" line="9" >}}version{{</hover>}}.
|
||||
|
||||
The {{<hover label="xpyaml" line="10" >}}dependsOn{{</hover>}} section lists the
|
||||
dependencies for a package.
|
||||
|
||||
This package lists the Upbound
|
||||
{{<hover label="xpyaml" line="11" >}}provider-azure{{</hover>}}
|
||||
version {{<hover label="xpyaml" line="12" >}}0.32.0{{</hover>}} or later as a
|
||||
dependency.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Crossplane automatically installs dependencies. Dependencies can include other
|
||||
configuration packages.
|
||||
{{< /hint >}}
|
||||
|
||||
Create a new directory and save the `crossplane.yaml` file.
|
||||
|
||||
```yaml {label="xpyaml"}
|
||||
mkdir crossplane-azure-quickstart
|
||||
cat <<EOF > crossplane-azure-quickstart/crossplane.yaml
|
||||
apiVersion: meta.pkg.crossplane.io/v1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: crossplane-azure-quickstart
|
||||
spec:
|
||||
crossplane:
|
||||
version: ">=v1.12.0"
|
||||
dependsOn:
|
||||
- provider: xpkg.upbound.io/upbound/provider-azure
|
||||
version: ">=v0.32.0"
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a definition.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
|
||||
A configuration package requires a _CompositeResourceDefinition_ (XRD) to
|
||||
define the custom API.
|
||||
|
||||
Save the _XRD_ as `definition.yaml` in the same directory as the
|
||||
`crossplane.yaml` file.
|
||||
|
||||
```yaml
|
||||
cat <<EOF > crossplane-azure-quickstart/definition.yaml
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xvirtualmachines.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XVirtualMachine
|
||||
plural: xvirtualmachines
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
region:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- region
|
||||
claimNames:
|
||||
kind: VirtualMachine
|
||||
plural: virtualmachines
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a composition.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
|
||||
The _Composition_ template creates the _managed resources_ and allows _patches_
|
||||
to customize the _managed resources_.
|
||||
|
||||
Copy the _Composition_ into the `composition.yaml` file in the same directory as
|
||||
`crossplane.yaml`.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Update each `resourceGroupName` with your Azure Resource Group.
|
||||
{{< /hint >}}
|
||||
|
||||
{{< editCode >}}
|
||||
```yaml
|
||||
cat <<EOF > crossplane-azure-quickstart/composition.yaml
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: crossplane-quickstart-vm-with-network
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XVirtualMachine
|
||||
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
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
size: Standard_B1ms
|
||||
sourceImageReference:
|
||||
- offer: debian-11
|
||||
publisher: Debian
|
||||
sku: 11-backports-gen2
|
||||
version: latest
|
||||
networkInterfaceIdsSelector:
|
||||
matchControllerRef: true
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
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"
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
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
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
toFieldPath: "spec.forProvider.location"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "Sweden Central"
|
||||
US: "Central US"
|
||||
- name: quickstart-network
|
||||
base:
|
||||
apiVersion: network.azure.upbound.io/v1beta1
|
||||
kind: VirtualNetwork
|
||||
spec:
|
||||
forProvider:
|
||||
addressSpace:
|
||||
- 10.0.0.0/16
|
||||
location: "Sweden Central"
|
||||
resourceGroupName: $$<resource_group_name>$$
|
||||
patches:
|
||||
- fromFieldPath: "spec.region"
|
||||
toFieldPath: "spec.forProvider.location"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "Sweden Central"
|
||||
US: "Central US"
|
||||
EOF
|
||||
```
|
||||
{{< /editCode >}}
|
||||
|
||||
### Install the Crossplane command-line
|
||||
To build a configuration package install the Crossplane Kubernetes command-line
|
||||
extension.
|
||||
|
||||
```shell
|
||||
wget "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh"
|
||||
chmod +x install.sh
|
||||
./install.sh
|
||||
```
|
||||
|
||||
Follow the directions and move the `kubectl-crossplane` binary to the correct
|
||||
directory.
|
||||
|
||||
Verify the Crossplane command-line installed with `kubectl crossplane --help`
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl crossplane --help
|
||||
Usage: kubectl crossplane <command>
|
||||
|
||||
A command line tool for interacting with Crossplane.
|
||||
|
||||
Flags:
|
||||
-h, --help Show context-sensitive help.
|
||||
-v, --version Print version and quit.
|
||||
--verbose Print verbose logging statements.
|
||||
# Ouptut removed for brevity
|
||||
```
|
||||
|
||||
### Build a configuration package
|
||||
|
||||
Use the `kubectl crossplane` command to create an `.xpkg` file containing the
|
||||
custom APIs and Crossplane configuration.
|
||||
|
||||
```shell
|
||||
kubectl crossplane build configuration -f crossplane-azure-quickstart/ --name="crossplane-azure-quickstart"
|
||||
```
|
||||
|
||||
Now an `.xpkg` OCI image is inside the `crossplane-azure-quickstart` directory.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
ls crossplane-azure-quickstart/
|
||||
composition.yaml crossplane-azure-quickstart.xpkg crossplane.yaml definition.yaml
|
||||
```
|
||||
|
||||
## Next steps
|
||||
* Explore Azure resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-azure/).
|
||||
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.
|
||||
* Read more about [Crossplane concepts]({{<ref "../concepts" >}})
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,967 @@
|
|||
---
|
||||
title: GCP Quickstart Part 2
|
||||
weight: 120
|
||||
tocHidden: true
|
||||
---
|
||||
|
||||
{{< hint "important" >}}
|
||||
This guide is part 2 of a series. Follow [**part 1**]({{<ref "provider-gcp" >}})
|
||||
to install Crossplane and connect your Kubernetes cluster to GCP.
|
||||
|
||||
[**Part 3**]({{<ref "provider-gcp-part-3">}})** covers patching
|
||||
_composite resources_ and using Crossplane _packages_.
|
||||
{{< /hint >}}
|
||||
|
||||
This section creates a _[Composition](#create-a-composition)_,
|
||||
_[Composite Resource Definition](#define-a-composite-resource)_ and a
|
||||
_[Claim](#create-a-claim)_
|
||||
to create a custom Kubernetes API to create GCP resources. This custom API is a
|
||||
_Composite Resource_ (XR) API.
|
||||
|
||||
## 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: upbound-provider-gcp
|
||||
spec:
|
||||
package: xpkg.upbound.io/upbound/provider-gcp:v0.28.0
|
||||
EOF
|
||||
```
|
||||
|
||||
3. Create a file called `gcp-credentials.json` with your GCP service account
|
||||
JSON file.
|
||||
|
||||
{{< hint type="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="warning" >}}
|
||||
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 >}}
|
||||
|
||||
## Create a composition
|
||||
[Part 1]({{<ref "provider-gcp" >}}) created a single _managed resource_.
|
||||
A _Composition_ is a template to create one or more _managed resources_ at the
|
||||
same time.
|
||||
|
||||
This sample _composition_ creates a Pub/Sub instance and associated GCP storage
|
||||
bucket.
|
||||
|
||||
{{< hint "note" >}}
|
||||
This example comes from part of the GCP
|
||||
[Stream messages from Pub/Sub by using Dataflow](https://cloud.google.com/pubsub/docs/stream-messages-dataflow)
|
||||
guide.
|
||||
{{< /hint >}}
|
||||
|
||||
To create a _composition_, first define each individual managed resource.
|
||||
|
||||
### Create a storage bucket object
|
||||
Define a `bucket` resource using the configuration from the previous section:
|
||||
|
||||
{{< hint "note" >}}
|
||||
Don't apply this configuration. This YAML is part of a larger
|
||||
definition.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml
|
||||
apiVersion: storage.gcp.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
metadata:
|
||||
name: crossplane-quickstart-bucket
|
||||
spec:
|
||||
forProvider:
|
||||
location: US
|
||||
providerConfigRef:
|
||||
name: default
|
||||
```
|
||||
|
||||
### Create a Pub/Sub topic resource
|
||||
Next, define a Pub/Sub `topic` resource.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
The [Upbound Marketplace](https://marketplace.upbound.io/) provides
|
||||
[schema documentation](https://marketplace.upbound.io/providers/upbound/provider-gcp/v0.28.0/resources/pubsub.gcp.upbound.io/Topic/v1beta1)
|
||||
for a `topic` resource.
|
||||
{{< /hint >}}
|
||||
|
||||
The _GCP Provider_ defines the
|
||||
{{<hover line="1" label="topicMR">}}apiVersion{{</hover>}}
|
||||
and
|
||||
{{<hover line="2" label="topicMR">}}kind{{</hover>}}.
|
||||
|
||||
A Pub/Sub topic doesn't have requirements but using
|
||||
{{<hover line="8" label="topicMR">}}messageStoragePolicy.allowedPersistenceRegions{{< /hover >}}
|
||||
can keep messages stored in the same location as the storage bucket.
|
||||
|
||||
```yaml {label="topicMR"}
|
||||
apiVersion: pubsub.gcp.upbound.io/v1beta1
|
||||
kind: Topic
|
||||
metadata:
|
||||
name: crossplane-quickstart-topic
|
||||
spec:
|
||||
forProvider:
|
||||
messageStoragePolicy:
|
||||
- allowedPersistenceRegions:
|
||||
- "us-central1"
|
||||
```
|
||||
|
||||
{{< hint "note" >}}
|
||||
Pub/Sub topic specifics are beyond the scope of this guide. Read the GCP
|
||||
[Pub/Sub API reference](https://cloud.google.com/compute/docs/apis)
|
||||
for more information.
|
||||
{{</hint >}}
|
||||
|
||||
### Create the composition object
|
||||
The _composition_ combines the two resource definitions.
|
||||
|
||||
A
|
||||
{{<hover label="compName" line="2">}}Composition{{</ hover>}} comes from the
|
||||
{{<hover label="compName" line="1">}}Crossplane{{</ hover>}}
|
||||
API resources.
|
||||
|
||||
Create any {{<hover label="compName" line="4">}}name{{</ hover>}} for this _composition_.
|
||||
|
||||
```yaml {label="compName"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: topic-with-bucket
|
||||
```
|
||||
|
||||
Add the resources to the
|
||||
{{<hover label="specResources" line="5">}}spec.resources{{</ hover>}}
|
||||
section of the _composition_.
|
||||
|
||||
Give each resource a
|
||||
{{<hover label="specResources" line="7">}}name{{</ hover>}}
|
||||
and put the resource definition under the
|
||||
{{<hover label="specResources" line="8">}}base{{</ hover>}}
|
||||
key.
|
||||
|
||||
{{< hint "note" >}}
|
||||
Don't include resource `metadata` under the
|
||||
{{<hover label="specResources" line="8">}}base{{</ hover>}} key.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml {label="specResources"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: topic-with-bucket
|
||||
spec:
|
||||
resources:
|
||||
- name: crossplane-quickstart-bucket
|
||||
base:
|
||||
apiVersion: storage.gcp.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
spec:
|
||||
forProvider:
|
||||
location: US
|
||||
- name: crossplane-quickstart-topic
|
||||
base:
|
||||
apiVersion: pubsub.gcp.upbound.io/v1beta1
|
||||
kind: Topic
|
||||
spec:
|
||||
forProvider:
|
||||
messageStoragePolicy:
|
||||
- allowedPersistenceRegions:
|
||||
- "us-central1"
|
||||
```
|
||||
|
||||
_Compositions_ are a template for generating resources. A
|
||||
_composite resource_ actually creates the resources.
|
||||
|
||||
A _composition_ defines which _composite resources_ can use this
|
||||
template.
|
||||
|
||||
_Compositions_ do this with the
|
||||
{{<hover label="compRef" line="6">}}spec.compositeTypeRef{{</ hover>}}
|
||||
definition.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Crossplane recommends prefacing the `kind` with an `X` to show it's a
|
||||
Composition.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml {label="compRef"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: topic-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XTopicBucket
|
||||
resources:
|
||||
# Removed for Brevity
|
||||
```
|
||||
|
||||
A _composite resource_ is actually a custom Kubernetes API type you define. The
|
||||
platform team controls the kind, API endpoint and version.
|
||||
|
||||
<!-- vale gitlab.SentenceLength = NO -->
|
||||
<!-- Length is because of shortcodes, ignore -->
|
||||
With this {{<hover label="compRef" line="6">}}spec.compositeTypeRef{{</ hover>}}
|
||||
Crossplane allows _composite resources_ from the API group
|
||||
{{<hover label="compRef" line="7">}}custom-api.example.org{{</ hover>}}
|
||||
that are of
|
||||
{{<hover label="compRef" line="8">}}kind: XTopicBucket{{</ hover>}}
|
||||
to use this template to create resources. No other API group or kind can use
|
||||
this template.
|
||||
<!-- vale gitlab.SentenceLength = YES -->
|
||||
|
||||
### Apply the composition
|
||||
Apply the full _Composition_ to your Kubernetes cluster.
|
||||
|
||||
```yaml {copy-lines="all"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: topic-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XTopicBucket
|
||||
resources:
|
||||
- name: crossplane-quickstart-bucket
|
||||
base:
|
||||
apiVersion: storage.gcp.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
spec:
|
||||
forProvider:
|
||||
location: US
|
||||
- name: crossplane-quickstart-topic
|
||||
base:
|
||||
apiVersion: pubsub.gcp.upbound.io/v1beta1
|
||||
kind: Topic
|
||||
spec:
|
||||
forProvider:
|
||||
messageStoragePolicy:
|
||||
- allowedPersistenceRegions:
|
||||
- "us-central1"
|
||||
EOF
|
||||
```
|
||||
|
||||
Confirm the _composition_ exists with `kubectl get composition`
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get composition
|
||||
NAME AGE
|
||||
topic-with-bucket 8s
|
||||
```
|
||||
|
||||
## Define a composite resource
|
||||
|
||||
The _composition_ that was just created limited which _composite resources_ can
|
||||
use that template.
|
||||
|
||||
A _composite resource_ is a custom API defined by the platform team.
|
||||
A _composite resource definition_ defines the schema for a _composite resource_.
|
||||
|
||||
|
||||
A _composite resource definition_ installs the custom API type into Kubernetes
|
||||
and defines what `spec` keys and values are valid when calling this new custom API.
|
||||
|
||||
Before creating a _composite resource_ Crossplane requires a _composite resource definition_.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
_Composite resource definitions_ are also called `XRDs` for short.
|
||||
{{< /hint >}}
|
||||
|
||||
Just like a _composition_ the
|
||||
{{<hover label="xrdName" line="2" >}}composite resource definition{{</hover>}}
|
||||
is part of the
|
||||
{{<hover label="xrdName" line="1" >}}Crossplane{{</hover>}}
|
||||
API group.
|
||||
|
||||
The _XRD_ {{<hover label="xrdName" line="4" >}}name{{</hover>}} is the new
|
||||
API endpoint.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Crossplane recommends using a plural name for the _XRD_
|
||||
{{<hover label="xrdName" line="4" >}}name{{</hover>}}.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml {label="xrdName"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xtopicbuckets.custom-api.example.org
|
||||
```
|
||||
|
||||
The _XRD's_
|
||||
{{<hover label="xrdGroup" line="5" >}}spec{{</hover>}} defines the new custom
|
||||
API.
|
||||
|
||||
### Define the API endpoint and kind
|
||||
First, define the new API
|
||||
{{<hover label="xrdGroup" line="6" >}}group{{</hover>}}.
|
||||
Next, create the API {{<hover label="xrdGroup" line="8" >}}kind{{</hover>}} and
|
||||
{{<hover label="xrdGroup" line="9" >}}plural{{</hover>}}.
|
||||
|
||||
```yaml {label="xrdGroup"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xtopicbuckets.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XTopicBucket
|
||||
plural: xtopicbuckets
|
||||
```
|
||||
|
||||
{{<hint "note" >}}
|
||||
The _XRD_ {{<hover label="xrdGroup" line="6" >}}group{{</hover>}} matches the _composition_ {{<hover label="noteComp"
|
||||
line="5">}}apiVersion{{</hover>}} and the
|
||||
_XRD_ {{<hover label="xrdGroup" line="8" >}}kind{{</hover>}} matches the _composition_
|
||||
{{<hover label="noteComp" line="6">}}compositeTypeRef.kind{{</hover>}}.
|
||||
|
||||
```yaml {label="noteComp"}
|
||||
kind: Composition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XTopicBucket
|
||||
```
|
||||
{{< /hint >}}
|
||||
|
||||
### Set the API version
|
||||
In Kubernetes, all API endpoints have a version to show the stability of the API
|
||||
and track revisions.
|
||||
|
||||
Apply a version to the _XRD_ with a
|
||||
{{<hover label="xrdVersion" line="11">}}versions.name{{</hover>}}.
|
||||
This matches the
|
||||
{{<hover label="noteComp"line="5">}}compositeTypeRef.apiVersion{{</hover>}}
|
||||
|
||||
_XRDs_ require both
|
||||
{{<hover label="xrdVersion" line="12">}}versions.served{{</hover>}}
|
||||
and
|
||||
{{<hover label="xrdVersion" line="13">}}versions.referenceable{{</hover>}}.
|
||||
|
||||
```yaml {label="xrdVersion"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xtopicbuckets.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XTopicBucket
|
||||
plural: xtopicbuckets
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
```
|
||||
|
||||
{{<hint "note" >}}
|
||||
For more information on defining versions in Kubernetes read the
|
||||
[API versioning](https://kubernetes.io/docs/reference/using-api/#api-versioning)
|
||||
section of the Kubernetes documentation.
|
||||
{{< /hint >}}
|
||||
|
||||
### Create the API schema
|
||||
With an API endpoint named, now define the API schema, or what's allowed
|
||||
inside the `spec` of the new Kubernetes object.
|
||||
|
||||
{{< hint "note" >}}
|
||||
_XRDs_ follow the Kubernetes
|
||||
[_custom resource definition_ rules for schemas](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema).
|
||||
{{</hint >}}
|
||||
|
||||
Place the API
|
||||
{{< hover label="xrdSchema" line="8" >}}schema{{</hover>}}
|
||||
under the
|
||||
{{< hover label="xrdSchema" line="7" >}}version.name{{</hover>}}
|
||||
|
||||
The _XRD_ type defines the next lines. They're always the same.
|
||||
|
||||
<!-- vale write-good.TooWordy = NO -->
|
||||
<!-- allow "validate" -->
|
||||
{{< hover label="xrdSchema" line="9" >}}openAPIV3Schema{{</hover>}} specifies
|
||||
how the schema gets validated.
|
||||
<!-- vale write-good.TooWordy = YES -->
|
||||
|
||||
Next, the entire API is an
|
||||
{{< hover label="xrdSchema" line="10" >}}object{{</hover>}}
|
||||
with a
|
||||
{{< hover label="xrdSchema" line="11" >}}property{{</hover>}} of
|
||||
{{< hover label="xrdSchema" line="12" >}}spec{{</hover>}}.
|
||||
|
||||
The
|
||||
{{< hover label="xrdSchema" line="12" >}}spec{{</hover>}} is also an
|
||||
{{< hover label="xrdSchema" line="13" >}}object{{</hover>}} with
|
||||
{{< hover label="xrdSchema" line="14" >}}properties{{</hover>}}.
|
||||
|
||||
```yaml {label="xrdSchema"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
# Removed for brevity
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
```
|
||||
|
||||
{{< hint "tip" >}}
|
||||
For more information on the values allowed in a _composite resource definition_ view its schema with
|
||||
`kubectl explain xrd`
|
||||
{{< /hint >}}
|
||||
|
||||
Now, define the custom API. Your custom API continues under the last
|
||||
{{<hover label="xrdSchema" line="14">}}properties{{</hover>}} definition in the
|
||||
previous example.
|
||||
|
||||
This custom API has one setting:
|
||||
<!-- vale Google.We = NO -->
|
||||
* {{<hover label="customAPI" line="4" >}}location{{</hover >}} - where to deploy
|
||||
the resources, a choice of "EU" or "US."
|
||||
|
||||
|
||||
Users can't change any other settings of the storage bucket or Pub/Sub topic.
|
||||
|
||||
The{{<hover label="customAPI" line="4" >}}location{{</hover >}}
|
||||
is a {{<hover label="customAPI" line="5" >}}string{{</hover >}}
|
||||
and matches the regular expression that's
|
||||
{{<hover label="customAPI" line="6" >}}oneOf{{</hover >}}
|
||||
{{<hover label="customAPI" line="7" >}}EU{{</hover >}}
|
||||
or
|
||||
{{<hover label="customAPI" line="8" >}}US{{</hover >}}.
|
||||
|
||||
This API requires the setting
|
||||
{{<hover label="customAPI" line="10" >}}location{{</hover >}}.
|
||||
|
||||
|
||||
```yaml {label="customAPI"}
|
||||
# Removed for brevity
|
||||
# schema.openAPIV3Schema.type.properties.spec
|
||||
properties:
|
||||
location:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- location
|
||||
```
|
||||
|
||||
### Enable claims to the API
|
||||
Tell this _XRD_ to offer a _claim_ by defining the _claim_ API endpoint under
|
||||
the _XRD_ {{<hover label="XRDclaim" line="4">}}spec{{< /hover >}}.
|
||||
|
||||
{{< hint "tip" >}}
|
||||
Crossplane recommends a _Claim_
|
||||
{{<hover label="XRDclaim" line="10" >}}kind{{</hover>}} match the
|
||||
_Composite Resource Definition_ (XRD)
|
||||
{{<hover label="XRDclaim" line="7" >}}kind{{</ hover>}},
|
||||
without the preceding `X`.
|
||||
{{< /hint >}}
|
||||
|
||||
|
||||
```yaml {label="XRDclaim"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
# Removed for brevity
|
||||
names:
|
||||
kind: XTopicBucket
|
||||
plural: xtopicbuckets
|
||||
claimNames:
|
||||
kind: TopicBucket
|
||||
plural: topicbuckets
|
||||
```
|
||||
|
||||
{{<hint "note" >}}
|
||||
The [Claims](#create-a-claim) section later in this guide discusses _claims_.
|
||||
{{< /hint >}}
|
||||
|
||||
### Apply the composite resource definition
|
||||
Apply the complete _XRD_ to your Kubernetes cluster.
|
||||
|
||||
|
||||
```yaml {copy-lines="all"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xtopicbuckets.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XTopicBucket
|
||||
plural: xtopicbuckets
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
location:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- location
|
||||
claimNames:
|
||||
kind: TopicBucket
|
||||
plural: topicbuckets
|
||||
EOF
|
||||
```
|
||||
|
||||
Verify Kubernetes created the XRD with `kubectl get xrd`
|
||||
|
||||
```shell {copy-lines="1",label="getXRD"}
|
||||
kubectl get xrd
|
||||
NAME ESTABLISHED OFFERED AGE
|
||||
xtopicbuckets.custom-api.example.org True True 9s
|
||||
```
|
||||
|
||||
## Create a composite resource
|
||||
Creating an _XRD_ allows the creation _composite resources_.
|
||||
|
||||
A _composite resource_ uses the custom API created in the _XRD_.
|
||||
|
||||
The _XRD_ maps the _composite resource_ values to the _composition_ template and
|
||||
creates new _managed resources_.
|
||||
|
||||
Looking at part of the _XRD_:
|
||||
|
||||
```yaml {label="xrdSnip"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XTopicBucket
|
||||
# Removed for brevity
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
location:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
```
|
||||
|
||||
The _XRD_ {{<hover label="xrdSnip" line="5">}}group{{</hover>}}
|
||||
becomes the _composite resource_
|
||||
{{<hover label="xr" line="2">}}apiVersion{{</hover>}}.
|
||||
|
||||
The _XRD_ {{<hover label="xrdSnip" line="7">}}kind{{</hover>}}
|
||||
is the _composite resource_
|
||||
{{<hover label="xr" line="3">}}kind{{</hover>}}
|
||||
|
||||
The _XRD_ API {{<hover label="xrdSnip" line="9">}}spec{{</hover>}} defines the
|
||||
_composite resource_ {{<hover label="xr" line="6">}}spec{{</hover>}}.
|
||||
|
||||
The _XRD_ {{<hover label="xrdSnip" line="11">}}properties{{</hover>}} section
|
||||
defines the options for the _composite resource_
|
||||
{{<hover label="xr" line="6">}}spec{{</hover>}}.
|
||||
|
||||
The one option is {{<hover label="xrdSnip" line="12">}}location{{</hover>}}
|
||||
and it can be either {{<hover label="xrdSnip" line="15">}}EU{{</hover>}} or
|
||||
{{<hover label="xrdSnip" line="16">}}US{{</hover>}}.
|
||||
|
||||
This _composite resource_ uses
|
||||
{{<hover label="xr" line="7">}}location: US{{</hover>}}.
|
||||
<!-- vale Google.We = YES -->
|
||||
### Apply the composite resource
|
||||
|
||||
Apply the composite resource to the Kubernetes cluster.
|
||||
|
||||
```yaml {label="xr", copy-lines="all"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XTopicBucket
|
||||
metadata:
|
||||
name: my-composite-resource
|
||||
spec:
|
||||
location: "US"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Verify the composite resource
|
||||
Verify Crossplane created the _composite resource_ with `kubectl get xdatasetwithbucket`
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Use `kubectl get <composite resource kind>` to view a specific `kind` of _composite resource_.
|
||||
View all _composite resources_ with `kubectl get composite`.
|
||||
{{< /hint >}}
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get XTopicBucket
|
||||
NAME SYNCED READY COMPOSITION AGE
|
||||
my-composite-resource True True topic-with-bucket 2m3s
|
||||
```
|
||||
|
||||
Both `SYNCED` and `READY` are `True` when Crossplane created the GCP resources.
|
||||
|
||||
Now look at the GCP storage `bucket` and Pub/Sub `topic` _managed resources_
|
||||
with `kubectl get bucket` and `kubectl get topic`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get bucket
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-m6lbx True True my-composite-resource-m6lbx 4m34s
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get topics
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-88vzp True True my-composite-resource-88vzp 4m48s
|
||||
```
|
||||
|
||||
The _composite resource_ automatically generated both _managed resources_.
|
||||
|
||||
Using `kubectl describe` on a _managed resource_ shows the `Owner References` is
|
||||
the _composite resource_.
|
||||
|
||||
```yaml {copy-lines="1"}
|
||||
kubectl describe bucket | grep "Owner References" -A5
|
||||
Owner References:
|
||||
API Version: custom-api.example.org/v1alpha1
|
||||
Block Owner Deletion: true
|
||||
Controller: true
|
||||
Kind: XTopicBucket
|
||||
Name: my-composite-resource
|
||||
```
|
||||
|
||||
Each _composite resource_ creates and owns a unique set of _managed resources_.
|
||||
If you create a second _composite resource_ Crossplane creates a new storage
|
||||
`bucket` and Pub/Sub `topic`.
|
||||
|
||||
```yaml {label="xr", copy-lines="all"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XTopicBucket
|
||||
metadata:
|
||||
name: my-second-composite-resource
|
||||
spec:
|
||||
location: "US"
|
||||
EOF
|
||||
```
|
||||
|
||||
Again, use `kubectl get XTopicBucket` to view both _composite resources_.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get XTopicBucket
|
||||
NAME SYNCED READY COMPOSITION AGE
|
||||
my-composite-resource True True topic-with-bucket 8m41s
|
||||
my-second-composite-resource True True topic-with-bucket 2m4s
|
||||
```
|
||||
|
||||
And see there are two `bucket` and two `topic` _managed resources_.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get bucket
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-m6lbx True True my-composite-resource-m6lbx 9m18s
|
||||
my-second-composite-resource-rkhbd True True my-second-composite-resource-rkhbd 2m41s
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get topic
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-88vzp True True my-composite-resource-88vzp 9m31s
|
||||
my-second-composite-resource-4wv89 True True my-second-composite-resource-4wv89 2m54s
|
||||
```
|
||||
|
||||
### Delete the composite resources
|
||||
Because the _composite resource_ is the `Owner` of the _managed resources_, when
|
||||
Crossplane deletes the _composite resource_, it also deletes the _managed resources_ automatically.
|
||||
|
||||
Delete the new _composite resource_ with `kubectl delete XTopicBucket`.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Delete a specific _composite resource_ with
|
||||
`kubectl delete <composite kind> <name>` or
|
||||
`kubectl delete composite <name>`.
|
||||
{{< /hint >}}
|
||||
|
||||
Delete the second composition
|
||||
```shell
|
||||
kubectl delete XTopicBucket my-second-composite-resource
|
||||
```
|
||||
|
||||
{{<hint "note">}}
|
||||
There may a delay in deleting the _managed resources_. Crossplane is making API
|
||||
calls to GCP and waits for GCP to confirm they deleted the resources before
|
||||
updating the state in Kubernetes.
|
||||
{{</hint >}}
|
||||
|
||||
Now a single bucket and topic exist.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get bucket
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-m6lbx True True my-composite-resource-m6lbx 11m
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get topic
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
my-composite-resource-88vzp True True my-composite-resource-88vzp 11m
|
||||
```
|
||||
|
||||
Delete the other _composite resource_ to remove the last `bucket` and `table`
|
||||
_managed resources_.
|
||||
|
||||
```shell
|
||||
kubectl delete xtopicbucket my-composite-resource
|
||||
```
|
||||
|
||||
_Composite resources_ are great for creating one or more related resources against
|
||||
a template, but all _composite resources_ exist at the Kubernetes "cluster
|
||||
level." There's no isolation between _composite resources_. Crossplane uses
|
||||
_claims_ to create resources with namespace isolation.
|
||||
|
||||
## Create a claim
|
||||
|
||||
_Claims_, just like _composite resources_ use the custom API defined in the
|
||||
_XRD_. Unlike a _composite resource_, Crossplane can create _claims_ in a
|
||||
namespace.
|
||||
|
||||
### Create a new Kubernetes namespace
|
||||
Create a new namespace with `kubectl create namespace`.
|
||||
|
||||
```shell
|
||||
kubectl create namespace test
|
||||
```
|
||||
|
||||
Look at the _XRD_ to see the parameters for the _claim_.
|
||||
A _claim_ uses the same {{<hover label="XRDclaim2" line="6" >}}group{{</hover>}}
|
||||
a _composite resource_ uses but a different
|
||||
{{<hover label="XRDclaim2" line="8" >}}kind{{</hover>}}.
|
||||
|
||||
```yaml {label="XRDclaim2"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
# Removed for brevity
|
||||
group: custom-api.example.org
|
||||
claimNames:
|
||||
kind: TopicBucket
|
||||
plural: topicbuckets
|
||||
```
|
||||
|
||||
Like the _composite resource_, create a new object with the
|
||||
{{<hover label="claim" line="2" >}}custom-api.example.org{{</hover>}} API
|
||||
endpoint.
|
||||
|
||||
The _XRD_
|
||||
{{<hover label="XRDclaim2" line="8" >}}claimNames.kind{{</hover>}} defines the
|
||||
{{<hover label="claim" line="3" >}}kind{{</hover>}}.
|
||||
|
||||
The {{<hover label="claim" line="7" >}}spec{{</hover>}} uses the same
|
||||
API options as the _composite resource_.
|
||||
|
||||
### Apply the claim
|
||||
Apply the _claim_ to your Kubernetes cluster.
|
||||
|
||||
```yaml {label="claim", copy-lines="all"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: TopicBucket
|
||||
metadata:
|
||||
name: claimed-topic-with-bucket
|
||||
namespace: test
|
||||
spec:
|
||||
location: "US"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Verify the claim
|
||||
Verify Crossplane created the _claim_ with `kubectl get TopicBucket` in the `test`
|
||||
namespace.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
View claims with `kubectl get <kind>` or use `kubectl get claim` to view all
|
||||
_claims_.
|
||||
{{</hint >}}
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get TopicBucket -n test
|
||||
NAME SYNCED READY CONNECTION-SECRET AGE
|
||||
claimed-topic-with-bucket True True 4m37s
|
||||
```
|
||||
|
||||
When Crossplane creates a _claim_, a unique _composite resource_ is also
|
||||
created. View the new _composite resource_ with `kubectl get xtopicbucket`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get xtopicbucket
|
||||
NAME SYNCED READY COMPOSITION AGE
|
||||
claimed-topic-with-bucket-7k2lj True True topic-with-bucket 4m58s
|
||||
```
|
||||
|
||||
The _composite resource_ exists at the "cluster scope" while the _claim_ exists
|
||||
at the "namespace scope."
|
||||
|
||||
Create a second namespace and a second claim.
|
||||
|
||||
```shell {copy-lines="all"}
|
||||
kubectl create namespace test2
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: TopicBucket
|
||||
metadata:
|
||||
name: second-claimed-topic-with-bucket
|
||||
namespace: test2
|
||||
spec:
|
||||
location: "US"
|
||||
EOF
|
||||
```
|
||||
|
||||
View the _claims_ in all namespaces with `kubectl get topicbucket -A`
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get topicbucket -A
|
||||
NAMESPACE NAME SYNCED READY CONNECTION-SECRET AGE
|
||||
test claimed-topic-with-bucket True True 8m48s
|
||||
test2 second-claimed-topic-with-bucket True True 2m24s
|
||||
```
|
||||
|
||||
Now look at the _composite resources_ at the cluster scope.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get xtopicbucket
|
||||
NAME SYNCED READY COMPOSITION AGE
|
||||
claimed-topic-with-bucket-7k2lj True True topic-with-bucket 9m11s
|
||||
second-claimed-topic-with-bucket-d5x58 True True topic-with-bucket 2m47s
|
||||
```
|
||||
|
||||
Crossplane created a second _composite resource_ for the second _claim_.
|
||||
|
||||
Looking at the GCP storage `bucket` and Pub/Sub `topic` shows two of each
|
||||
resource, one for each claim.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get bucket
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
claimed-topic-with-bucket-7k2lj-qf2m6 True True claimed-topic-with-bucket-7k2lj-qf2m6 9m46s
|
||||
second-claimed-topic-with-bucket-d5x58-drlxr True True second-claimed-topic-with-bucket-d5x58-drlxr 3m22s
|
||||
```
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get topic
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
claimed-topic-with-bucket-7k2lj-8xn7t True True claimed-topic-with-bucket-7k2lj-8xn7t 9m59s
|
||||
second-claimed-topic-with-bucket-d5x58-ctkrp True True second-claimed-topic-with-bucket-d5x58-ctkrp 3m35s
|
||||
```
|
||||
|
||||
### Delete the claims
|
||||
Removing the _claims_ removes the _composite resources_ and the associated
|
||||
_managed resources_.
|
||||
|
||||
```shell
|
||||
kubectl delete topicbucket claimed-topic-with-bucket -n test
|
||||
kubectl delete topicbucket second-claimed-topic-with-bucket -n test2
|
||||
```
|
||||
|
||||
Verify Crossplane removed all the _managed resources_.
|
||||
|
||||
```shell
|
||||
kubectl get bucket
|
||||
No resources found
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl get table
|
||||
No resources found
|
||||
```
|
||||
|
||||
Claims are powerful tools to give users resources in their own isolated
|
||||
namespace. But these examples haven't shown how the custom API can change
|
||||
the settings defined in the _composition_. This _composition patching_ applies
|
||||
the API settings when creating resources.
|
||||
[Part 3]({{< ref "provider-gcp-part-3">}}) of this guide covers
|
||||
_composition patches_ and making all this configuration portable in Crossplane
|
||||
_packages_.
|
||||
|
||||
## Next steps
|
||||
* [**Continue to part 3**]({{< ref "provider-gcp-part-3">}})** to create a learn
|
||||
about _patching_ resources and creating Crossplane _packages_.
|
||||
* Explore GCP resources that Crossplane can configure in the
|
||||
[Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-gcp/).
|
||||
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.
|
|
@ -0,0 +1,659 @@
|
|||
---
|
||||
title: GCP Quickstart Part 3
|
||||
weight: 120
|
||||
tocHidden: true
|
||||
---
|
||||
|
||||
{{< hint "important" >}}
|
||||
This guide is part 3 of a series.
|
||||
|
||||
Follow [**part 1**]({{<ref "provider-gcp" >}})
|
||||
to install Crossplane and connect your Kubernetes cluster to GCP.
|
||||
|
||||
Follow [**part 2**]({{<ref "provider-gcp-part-2" >}})** to create a _composition_,
|
||||
_custom resource definition_ and a _claim_.
|
||||
{{< /hint >}}
|
||||
|
||||
[Part 2]({{<ref "provider-gcp-part-2" >}}) created a _composite resource
|
||||
definition_ to define the schema of the custom API. Users create a _claim_ to
|
||||
use the custom API and apply their options. Part 2 didn't show how the options
|
||||
set in a _claim_ change or get applied the associated _composite resources_.
|
||||
|
||||
## Prerequisites
|
||||
* Complete quickstart [part 1]({{<ref "provider-gcp" >}}) and
|
||||
[Part 2]({{<ref "provider-gcp-part-2" >}}) to install Crossplane and the quickstart
|
||||
configurations.
|
||||
|
||||
{{<expand "Skip parts 1 and 2 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: upbound-provider-gcp
|
||||
spec:
|
||||
package: xpkg.upbound.io/upbound/provider-gcp:v0.28.0
|
||||
EOF
|
||||
```
|
||||
|
||||
3. Create a file called `gcp-credentials.json` with your GCP service account
|
||||
JSON file.
|
||||
|
||||
{{< hint type="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="warning" >}}
|
||||
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 >}}
|
||||
|
||||
|
||||
6. Create a _composition_
|
||||
```yaml {copy-lines="all"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: topic-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XTopicBucket
|
||||
resources:
|
||||
- name: crossplane-quickstart-bucket
|
||||
base:
|
||||
apiVersion: storage.gcp.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
spec:
|
||||
forProvider:
|
||||
location: US
|
||||
- name: crossplane-quickstart-topic
|
||||
base:
|
||||
apiVersion: pubsub.gcp.upbound.io/v1beta1
|
||||
kind: Topic
|
||||
spec:
|
||||
forProvider:
|
||||
messageStoragePolicy:
|
||||
- allowedPersistenceRegions:
|
||||
- "us-central1"
|
||||
EOF
|
||||
```
|
||||
|
||||
7. Create a _composite resource definition_
|
||||
```yaml {copy-lines="all"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xtopicbuckets.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XTopicBucket
|
||||
plural: xtopicbuckets
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
location:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- location
|
||||
claimNames:
|
||||
kind: TopicBucket
|
||||
plural: topicbuckets
|
||||
EOF
|
||||
```
|
||||
|
||||
8. Create a new namespace
|
||||
```shell
|
||||
kubectl create namespace test
|
||||
```
|
||||
|
||||
{{</expand >}}
|
||||
|
||||
## Enable composition patches
|
||||
In a _composition_, `patches` map fields in the custom API to fields inside the
|
||||
_managed resources_.
|
||||
|
||||
The example _composition_ has two _managed resources_, a
|
||||
{{<hover label="compResources" line="8">}}bucket{{</hover>}} and a
|
||||
{{<hover label="compResources" line="15">}}topic{{</hover>}}.
|
||||
|
||||
```yaml {label="compResources"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
# Removed for Brevity
|
||||
resources:
|
||||
- name: crossplane-quickstart-bucket
|
||||
base:
|
||||
apiVersion: storage.gcp.upbound.io/v1beta1
|
||||
kind: Bucket
|
||||
spec:
|
||||
forProvider:
|
||||
location: US
|
||||
- name: crossplane-quickstart-topic
|
||||
base:
|
||||
apiVersion: pubsub.gcp.upbound.io/v1beta1
|
||||
kind: Topic
|
||||
spec:
|
||||
forProvider:
|
||||
messageStoragePolicy:
|
||||
- allowedPersistenceRegions:
|
||||
- "us-central1"
|
||||
```
|
||||
<!-- vale Google.We = NO -->
|
||||
The custom API defined a single option,
|
||||
{{<hover label="xrdSnip" line="12">}}location{{</hover>}}. A
|
||||
{{<hover label="xrdSnip" line="12">}}location{{</hover>}} can be either
|
||||
{{<hover label="xrdSnip" line="15">}}EU{{</hover>}} or
|
||||
{{<hover label="xrdSnip" line="16">}}US{{</hover>}}.
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
```yaml {label="xrdSnip"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
# Removed for brevity
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XDatabase
|
||||
# Removed for brevity
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
location:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
```
|
||||
|
||||
Creating a _composition_ `patch` allows Crossplane to update the settings of a
|
||||
_composite resource_. Patches apply to an individual _managed resource_
|
||||
inside the _composition_.
|
||||
|
||||
A {{<hover label="patch" line="14">}}patch{{</hover>}} has a
|
||||
{{<hover label="patch" line="15">}}fromField{{</hover>}} and a
|
||||
{{<hover label="patch" line="16">}}toField{{</hover>}} specifying which value
|
||||
_from_ the custom API should apply _to_ a field in the _managed resource_.
|
||||
Patches can create a
|
||||
{{<hover label="patch" line="17">}}transform{{</hover>}} to change the _from_
|
||||
field before it's applied.
|
||||
|
||||
The transform
|
||||
{{<hover label="patch" line="18">}}type{{</hover>}} is what kind of change to
|
||||
make on the _from_ field. Types of changes could include appending a string,
|
||||
preforming a math operation or mapping one value to another.
|
||||
|
||||
Applying a {{<hover label="patch" line="14">}}patch{{</hover>}} to the
|
||||
{{<hover label="patch" line="8">}}Topic{{</hover>}} uses the custom API
|
||||
{{<hover label="patch" line="15">}}spec.location{{</hover>}} field to use as the
|
||||
_managed resource_
|
||||
{{<hover label="patch" line="12">}}allowedPersistenceRegions{{</hover>}} value.
|
||||
|
||||
<!-- vale Google.We = NO -->
|
||||
The custom API value "EU" is
|
||||
{{<hover label="patch" line="20">}}mapped{{</hover>}} to the value
|
||||
"europe-central2" and "US" is
|
||||
{{<hover label="patch" line="21">}}mapped{{</hover>}} to the value
|
||||
"us-central1."
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
|
||||
```yaml {label="patch"}
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
# Removed for Brevity
|
||||
resources:
|
||||
- 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[*].allowedPersistenceRegions[*]"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "europe-central2"
|
||||
US: "us-central1"
|
||||
```
|
||||
<!-- vale Google.We = NO -->
|
||||
Patching is a powerful tool enabling simpler or abstracted APIs. Developers
|
||||
aren't required to know the specific GCP region, just the abstracted
|
||||
option of "EU" or "US."
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
### Apply the updated composition
|
||||
Apply a similar `patch` to the `Bucket` _managed resource_ and apply the updated
|
||||
_composition_.
|
||||
|
||||
```yaml
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: topic-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XTopicBucket
|
||||
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[*].allowedPersistenceRegions[*]"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "europe-central2"
|
||||
US: "us-central1"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Create a claim
|
||||
Create a new _claim_ and set the
|
||||
{{<hover label="claim" line="8" >}}location{{</hover >}} to "EU."
|
||||
|
||||
```yaml {label="claim"}
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: TopicBucket
|
||||
metadata:
|
||||
name: claimed-eu-topic-with-bucket
|
||||
namespace: test
|
||||
spec:
|
||||
location: "EU"
|
||||
EOF
|
||||
```
|
||||
|
||||
View the _claim_ with `kubectl get claim`
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get TopicBucket -n test
|
||||
NAME SYNCED READY CONNECTION-SECRET AGE
|
||||
claimed-eu-topic-with-bucket True True 2m26s
|
||||
```
|
||||
|
||||
The claim reports `SYNCED` and `READY` as `True` after Crossplane creates
|
||||
all the _managed resources_.
|
||||
|
||||
Describe the `Topic` resource to see the GCP location is
|
||||
{{< hover label="topicLocation" line="5">}}europe-central2{{< /hover >}}.
|
||||
|
||||
```shell {copy-lines="1",label="topicLocation"}
|
||||
kubectl describe topic | grep "For Provider" -A3
|
||||
For Provider:
|
||||
Message Storage Policy:
|
||||
Allowed Persistence Regions:
|
||||
europe-central2
|
||||
```
|
||||
|
||||
Describe the `Bucket` resource to see the GCP location is also set to
|
||||
{{<hover label="bucketLocation" line="3">}}EU{{</hover>}}.
|
||||
|
||||
```shell {copy-lines="1",label="bucketLocation"}
|
||||
kubectl describe bucket | grep "For Provider" -A1
|
||||
For Provider:
|
||||
Location: EU
|
||||
```
|
||||
|
||||
<!-- vale Google.We = NO -->
|
||||
Using {{<hover label="claim" line="8" >}}location: "EU"{{</hover >}} in the
|
||||
claim patches the _composite resource_, updating the `Topic` GCP region from
|
||||
`us-central1` to `europe-central-2` and the `Bucket` from GCP region `US` to GCP
|
||||
region `EU`.
|
||||
The developer creating the claim isn't required to know which specific GCP
|
||||
region or the naming conventions. Using the abstract API options of "EU" or "US"
|
||||
the developer places their resources in the desired location.
|
||||
|
||||
In this example, patching also allows platform teams to ensure all resources are
|
||||
in the same location.
|
||||
<!-- vale Google.We = YES -->
|
||||
|
||||
Deleting the claim removes the _managed resources_.
|
||||
|
||||
{{<hint "note" >}}
|
||||
The _managed resources_ take up to 5 minutes to delete.
|
||||
{{< /hint >}}
|
||||
|
||||
```shell
|
||||
kubectl delete TopicBucket claimed-eu-topic-with-bucket -n test
|
||||
```
|
||||
|
||||
## Create a Crossplane configuration package
|
||||
|
||||
Creating a configuration package makes your Crossplane custom APIs portable
|
||||
and versioned.
|
||||
|
||||
Crossplane _configuration packages_ allow users to combine their _custom
|
||||
resource definition_ and _composition_ files into an OCI image.
|
||||
|
||||
{{< hint "note" >}}
|
||||
The [Open Container Initiative](https://opencontainers.org/faq/)
|
||||
defines the OCI image standard.
|
||||
An OCI images is a standard way to package data.
|
||||
{{< /hint >}}
|
||||
|
||||
You can host configuration packages in image registries like
|
||||
[Docker Hub](https://hub.docker.com/) or the
|
||||
[Upbound Marketplace](https://marketplace.upbound.io/).
|
||||
|
||||
Crossplane can download and install configuration packages into a Kubernetes
|
||||
cluster.
|
||||
|
||||
Building and installing configuration packages requires an OCI image compatible
|
||||
tool.
|
||||
|
||||
{{< hint "note" >}}
|
||||
You can use any software that builds OCI images. This includes
|
||||
[Docker](https://www.docker.com/) or
|
||||
[Upbound's Up command-line tool](https://github.com/upbound/up)
|
||||
{{< /hint >}}
|
||||
|
||||
A configuration package includes three files:
|
||||
* `crossplane.yaml` defines the metadata of the package.
|
||||
* `definition.yaml` is the _composite resource definition_ for the package.
|
||||
* `composition.yaml` is the _composition_ template for the package.
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a crossplane.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
Configuration packages describe their contents and requirements with a
|
||||
`crossplane.yaml` file.
|
||||
|
||||
The `crossplane.yaml` file lists the required Crossplane _providers_ and their
|
||||
compatible versions as well as the required Crossplane version.
|
||||
|
||||
The Crossplane
|
||||
{{<hover label="xpyaml" line="1" >}}meta.pkg{{</hover>}} API defines the schema
|
||||
for a
|
||||
{{<hover label="xpyaml" line="2" >}}Configuration{{</hover>}}.
|
||||
|
||||
Inside the {{<hover label="xpyaml" line="5" >}}spec{{</hover>}} define the
|
||||
required Crossplane
|
||||
{{<hover label="xpyaml" line="7" >}}version{{</hover>}}.
|
||||
|
||||
The {{<hover label="xpyaml" line="8" >}}dependsOn{{</hover>}} section lists the
|
||||
dependencies for a package.
|
||||
|
||||
This package lists the Upbound
|
||||
{{<hover label="xpyaml" line="9" >}}provider-gcp{{</hover>}}
|
||||
version {{<hover label="xpyaml" line="10" >}}0.28.0{{</hover>}} or later as a
|
||||
dependency.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Crossplane automatically installs dependencies. Dependencies can include other
|
||||
configuration packages.
|
||||
{{< /hint >}}
|
||||
|
||||
```yaml {label="xpyaml"}
|
||||
apiVersion: meta.pkg.crossplane.io/v1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: crossplane-gcp-quickstart
|
||||
spec:
|
||||
crossplane:
|
||||
version: ">=v1.11.0"
|
||||
dependsOn:
|
||||
- provider: xpkg.upbound.io/upbound/provider-gcp
|
||||
version: ">=v0.28.0"
|
||||
```
|
||||
|
||||
Create a new directory and save the `crossplane.yaml` file.
|
||||
|
||||
```yaml {copy-lines="all"}
|
||||
mkdir crossplane-gcp-quickstart
|
||||
cat <<EOF > crossplane-gcp-quickstart/crossplane.yaml
|
||||
apiVersion: meta.pkg.crossplane.io/v1
|
||||
kind: Configuration
|
||||
metadata:
|
||||
name: crossplane-gcp-quickstart
|
||||
spec:
|
||||
crossplane:
|
||||
version: ">=v1.12.0"
|
||||
dependsOn:
|
||||
- provider: xpkg.upbound.io/upbound/provider-gcp
|
||||
version: ">=v0.28.0"
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a definition.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
|
||||
A configuration package requires a _composite resource definition_ (XRD) to define the
|
||||
custom API.
|
||||
|
||||
Save the _XRD_ as `definition.yaml` in the same directory as the
|
||||
`crossplane.yaml` file.
|
||||
|
||||
```yaml {copy-lines="all"}
|
||||
cat <<EOF > crossplane-gcp-quickstart/definition.yaml
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: CompositeResourceDefinition
|
||||
metadata:
|
||||
name: xtopicbuckets.custom-api.example.org
|
||||
spec:
|
||||
group: custom-api.example.org
|
||||
names:
|
||||
kind: XTopicBucket
|
||||
plural: xtopicbuckets
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
referenceable: true
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
type: object
|
||||
properties:
|
||||
spec:
|
||||
type: object
|
||||
properties:
|
||||
location:
|
||||
type: string
|
||||
oneOf:
|
||||
- pattern: '^EU$'
|
||||
- pattern: '^US$'
|
||||
required:
|
||||
- location
|
||||
claimNames:
|
||||
kind: TopicBucket
|
||||
plural: topicbuckets
|
||||
EOF
|
||||
```
|
||||
|
||||
<!-- vale gitlab.Substitutions = NO -->
|
||||
<!-- yaml is in the filename -->
|
||||
### Create a composition.yaml file
|
||||
<!-- vale gitlab.Substitutions = YES -->
|
||||
|
||||
The _composition_ template creates the _managed resources_ and allows _patches_
|
||||
to customize the _managed resources_.
|
||||
|
||||
Copy the _composition_ into the `composition.yaml` file in the same directory as
|
||||
`crossplane.yaml`.
|
||||
|
||||
```yaml
|
||||
cat <<EOF > crossplane-gcp-quickstart/composition.yaml
|
||||
apiVersion: apiextensions.crossplane.io/v1
|
||||
kind: Composition
|
||||
metadata:
|
||||
name: topic-with-bucket
|
||||
spec:
|
||||
compositeTypeRef:
|
||||
apiVersion: custom-api.example.org/v1alpha1
|
||||
kind: XTopicBucket
|
||||
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[*].allowedPersistenceRegions[*]"
|
||||
transforms:
|
||||
- type: map
|
||||
map:
|
||||
EU: "europe-central2"
|
||||
US: "us-central1"
|
||||
EOF
|
||||
```
|
||||
|
||||
### Install the Crossplane command-line
|
||||
To build a configuration package install the Crossplane Kubernetes command-line
|
||||
extension.
|
||||
|
||||
```shell
|
||||
wget "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh"
|
||||
chmod +x install.sh
|
||||
./install.sh
|
||||
sudo mv kubectl-crossplane /usr/bin
|
||||
```
|
||||
|
||||
Verify the Crossplane command-line installed with `kubectl crossplane --help`
|
||||
|
||||
```shell
|
||||
kubectl crossplane --help
|
||||
Usage: kubectl crossplane <command>
|
||||
|
||||
A command line tool for interacting with Crossplane.
|
||||
|
||||
Flags:
|
||||
-h, --help Show context-sensitive help.
|
||||
-v, --version Print version and quit.
|
||||
--verbose Print verbose logging statements.
|
||||
# Ouptut removed for brevity
|
||||
```
|
||||
|
||||
### Build a configuration package
|
||||
|
||||
Use the `kubectl crossplane` command to create an `.xpkg` file containing the
|
||||
custom APIs and Crossplane configuration.
|
||||
|
||||
```shell
|
||||
kubectl crossplane build configuration -f crossplane-gcp-quickstart/ --name="crossplane-gcp-quickstart"
|
||||
```
|
||||
|
||||
Now an `.xpkg` OCI image is inside the `crossplane-gcp-quickstart` directory.
|
||||
|
||||
```shell
|
||||
ls crossplane-gcp-quickstart/
|
||||
composition.yaml crossplane-gcp-quickstart.xpkg crossplane.yaml definition.yaml
|
||||
```
|
||||
|
||||
## Next steps
|
||||
* Explore GCP resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-gcp/).
|
||||
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.
|
||||
* Read more about [Crossplane concepts]({{<ref "../concepts" >}})
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
title: Install, Uninstall and Upgrade
|
||||
weight: 300
|
||||
description: Manage Crossplane installations
|
||||
---
|
||||
|
||||
## [Install Crossplane](./install/)
|
||||
How to install and customize Crossplane in an existing Kubernetes cluster.
|
||||
|
||||
## [Uninstall Crossplane](./uninstall/)
|
||||
How to remove Crossplane from a Kubernetes cluster.
|
|
@ -0,0 +1,342 @@
|
|||
---
|
||||
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 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 Manger design document](https://github.com/crossplane/crossplane/blob/master/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.
|
||||
|
||||
<!-- 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"` |
|
||||
| `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`. | `{}` |
|
||||
| `extraVolumeMountsCrossplane` | Add custom `volumeMounts` to the Crossplane pod. | `{}` |
|
||||
| `extraVolumesCrossplane` | Add custom `volumes` to the Crossplane pod. | `{}` |
|
||||
| `hostNetwork` | Enable `hostNetwork` for the Crossplane deployment. Caution: enabling `hostNetwork`` grants the Crossplane Pod access to the host network namespace. | `false` |
|
||||
| `image.pullPolicy` | The image pull policy used for Crossplane and RBAC Manager pods. | `"IfNotPresent"` |
|
||||
| `image.repository` | Repository for the Crossplane pod image. | `"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` |
|
||||
| `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.managementPolicy` | Defines the Roles and ClusterRoles the RBAC Manager creates and manages. - A policy of `Basic` creates and binds Roles only for the Crossplane ServiceAccount, Provider ServiceAccounts and creates Crossplane ClusterRoles. - A policy of `All` includes all the `Basic` settings and also creates Crossplane Roles in all namespaces. - Read the Crossplane docs for more information on the [RBAC Roles and ClusterRoles](https://docs.crossplane.io/latest/concepts/pods/#crossplane-clusterroles) | `"Basic"` |
|
||||
| `rbacManager.nodeSelector` | Add `nodeSelectors` to the RBAC Manager pod deployment. | `{}` |
|
||||
| `rbacManager.replicas` | The number of RBAC Manager pod `replicas` to deploy. | `1` |
|
||||
| `rbacManager.skipAggregatedClusterRoles` | Don't install aggregated Crossplane ClusterRoles. | `false` |
|
||||
| `rbacManager.tolerations` | Add `tolerations` to the RBAC Manager pod deployment. | `[]` |
|
||||
| `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. | `"100m"` |
|
||||
| `resourcesCrossplane.limits.memory` | Memory resource limits for the Crossplane pod. | `"512Mi"` |
|
||||
| `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"` |
|
||||
| `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` |
|
||||
| `serviceAccount.customAnnotations` | Add custom `annotations` to the Crossplane ServiceAccount. | `{}` |
|
||||
| `tolerations` | Add `tolerations` to the Crossplane pod deployment. | `[]` |
|
||||
| `webhooks.enabled` | Enable webhooks for Crossplane and installed Provider packages. | `true` |
|
||||
| `xfn.args` | Add custom arguments to the Composite functions runner container. | `[]` |
|
||||
| `xfn.cache.configMap` | The name of a ConfigMap to use as the Composite function runner package cache. Disables the default Composite function runner package cache `emptyDir` Volume. | `""` |
|
||||
| `xfn.cache.medium` | Set to `Memory` to hold the Composite function runner package cache in a RAM-backed file system. Useful for Crossplane development. | `""` |
|
||||
| `xfn.cache.pvc` | The name of a PersistentVolumeClaim to use as the Composite function runner package cache. Disables the default Composite function runner package cache `emptyDir` Volume. | `""` |
|
||||
| `xfn.cache.sizeLimit` | The size limit for the Composite function runner package cache. If medium is `Memory` the `sizeLimit` can't exceed Node memory. | `"1Gi"` |
|
||||
| `xfn.enabled` | Enable the alpha Composition functions (`xfn`) sidecar container. Also requires Crossplane `args` value `--enable-composition-functions` set. | `false` |
|
||||
| `xfn.extraEnvVars` | Add custom environmental variables to the Composite function runner container. Replaces any `.` in a variable name with `_`. For example, `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`. | `{}` |
|
||||
| `xfn.image.pullPolicy` | Composite function runner container image pull policy. | `"IfNotPresent"` |
|
||||
| `xfn.image.repository` | Composite function runner container image. | `"crossplane/xfn"` |
|
||||
| `xfn.image.tag` | Composite function runner container image tag. Defaults to the value of `appVersion` in Chart.yaml. | `""` |
|
||||
| `xfn.resources.limits.cpu` | CPU resource limits for the Composite function runner container. | `"2000m"` |
|
||||
| `xfn.resources.limits.memory` | Memory resource limits for the Composite function runner container. | `"2Gi"` |
|
||||
| `xfn.resources.requests.cpu` | CPU resource requests for the Composite function runner container. | `"1000m"` |
|
||||
| `xfn.resources.requests.memory` | Memory resource requests for the Composite function runner container. | `"1Gi"` |
|
||||
| `xfn.securityContext.allowPrivilegeEscalation` | Enable `allowPrivilegeEscalation` for the Composite function runner container. | `false` |
|
||||
| `xfn.securityContext.capabilities.add` | Set Linux capabilities for the Composite function runner container. The default values allow the container to create an unprivileged user namespace for running Composite function containers. | `["SETUID","SETGID"]` |
|
||||
| `xfn.securityContext.readOnlyRootFilesystem` | Set the Composite function runner container root file system as read-only. | `true` |
|
||||
| `xfn.securityContext.runAsGroup` | The group ID used by the Composite function runner container. | `65532` |
|
||||
| `xfn.securityContext.runAsUser` | The user ID used by the Composite function runner container. | `65532` |
|
||||
| `xfn.securityContext.seccompProfile.type` | Apply a `seccompProfile` to the Composite function runner container. The default value allows the Composite function runner container permissions to use the `unshare` syscall. | `"Unconfined"` |
|
||||
{{< /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-seperated 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-revisions` |Enable support for CompositionRevisions |
|
||||
| Alpha | `--enable-composition-functions` | Enable support for Composition Functions. |
|
||||
| Alpha | `--enable-composition-webhook-schema-validation` | Enable Composition validation using schemas. |
|
||||
| Alpha | `--enable-environment-configs` | Enable support for EnvironmentConfigs. |
|
||||
| Alpha | `--enable-external-secret-stores` | Enable support for External Secret Stores. |
|
||||
{{< /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"]`.
|
||||
|
||||
### 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.
|
||||
|
||||
### Vendors
|
||||
Below are vendors providing conformant Crossplane distributions.
|
||||
|
||||
#### Upbound
|
||||
Upbound, the founders of Crossplane, maintains a free and open source
|
||||
distribution of Crossplane called
|
||||
[Universal Crossplane](https://www.upbound.io/products/universal-crossplane)
|
||||
(`UXP`).
|
||||
|
||||
Find information on UXP in the
|
||||
[Upbound UXP documentation](https://docs.upbound.io/uxp/install/).
|
|
@ -0,0 +1,183 @@
|
|||
---
|
||||
title: Uninstall Crossplane
|
||||
weight: 300
|
||||
---
|
||||
|
||||
{{<hint "warning" >}}
|
||||
Resources created by Crossplane aren't deleted if Crossplane isn't uninstalled
|
||||
in order.
|
||||
|
||||
This can leave cloud resources running, requiring manual deletion.
|
||||
{{< /hint >}}
|
||||
|
||||
## Ordered Crossplane uninstall
|
||||
Most Crossplane resources have dependencies on other Crossplane resources.
|
||||
|
||||
For example, a _managed resource_ is dependent on the _provider_.
|
||||
|
||||
Failure to delete Crossplane resources in order may prevent Crossplane from
|
||||
deleting provisioned external resources.
|
||||
|
||||
Removing Crossplane resources should happen in the following order:
|
||||
1. Remove all _composite resource definitions_
|
||||
2. Remove all remaining _managed resources_
|
||||
3. Remove all _providers_
|
||||
|
||||
Deleting the Crossplane pod removes remaining Crossplane components like _claims_.
|
||||
|
||||
{{<hint "tip" >}}
|
||||
Collect an inventory of all external resources with `kubectl get managed`.
|
||||
|
||||
Depending on the size of the Kubernetes API server and number of resources, this
|
||||
command may take minutes to return.
|
||||
|
||||
{{<expand "An example kubectl get managed" >}}
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get managed
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
securitygroup.ec2.aws.upbound.io/my-db-7mc7h-j84h8 True True sg-0da6e9c29113596b6 3m1s
|
||||
securitygroup.ec2.aws.upbound.io/my-db-8bhr2-9wsx9 True True sg-02695166f010ec05b 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
route.ec2.aws.upbound.io/my-db-7mc7h-vw985 True True r-rtb-05822b8df433e4e2b1080289494 3m1s
|
||||
route.ec2.aws.upbound.io/my-db-8bhr2-7m2wq False True 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
securitygrouprule.ec2.aws.upbound.io/my-db-7mc7h-mkd9s True True sgrule-778063708 3m1s
|
||||
securitygrouprule.ec2.aws.upbound.io/my-db-8bhr2-lzr89 False True 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
routetable.ec2.aws.upbound.io/my-db-7mc7h-mnqvm True True rtb-05822b8df433e4e2b 3m1s
|
||||
routetable.ec2.aws.upbound.io/my-db-8bhr2-dfhj6 True True rtb-02e875abd25658254 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
subnet.ec2.aws.upbound.io/my-db-7mc7h-7m49d True True subnet-0c1ab32c5ec129dd1 3m2s
|
||||
subnet.ec2.aws.upbound.io/my-db-7mc7h-9t64t True True subnet-07075c17c7a72f79e 3m2s
|
||||
subnet.ec2.aws.upbound.io/my-db-7mc7h-rs8t8 True True subnet-08e88e826a42e55b4 3m2s
|
||||
subnet.ec2.aws.upbound.io/my-db-8bhr2-9sjpx True True subnet-05d21c7b52f7ac8ca 2m26s
|
||||
subnet.ec2.aws.upbound.io/my-db-8bhr2-dvrxf True True subnet-0432310376b5d09de 2m26s
|
||||
subnet.ec2.aws.upbound.io/my-db-8bhr2-t7dpr True True subnet-0080fdcb6e9b70632 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
vpc.ec2.aws.upbound.io/my-db-7mc7h-ktbbh True True vpc-08d7dd84e0c12f33e 3m3s
|
||||
vpc.ec2.aws.upbound.io/my-db-8bhr2-mrh2x True True vpc-06994bf323fc1daea 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
internetgateway.ec2.aws.upbound.io/my-db-7mc7h-s2x4v True True igw-0189c4da07a3142dc 3m1s
|
||||
internetgateway.ec2.aws.upbound.io/my-db-8bhr2-q7dzl True True igw-01bf2a1dbbebf6a27 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
routetableassociation.ec2.aws.upbound.io/my-db-7mc7h-28qb4 True True rtbassoc-0718d680b5a0e68fe 3m1s
|
||||
routetableassociation.ec2.aws.upbound.io/my-db-7mc7h-9hdlr True True rtbassoc-0faaedb88c6e1518c 3m1s
|
||||
routetableassociation.ec2.aws.upbound.io/my-db-7mc7h-txhmz True True rtbassoc-0e5010724ca027864 3m1s
|
||||
routetableassociation.ec2.aws.upbound.io/my-db-8bhr2-bvgkt False True 2m26s
|
||||
routetableassociation.ec2.aws.upbound.io/my-db-8bhr2-d9gbg False True 2m26s
|
||||
routetableassociation.ec2.aws.upbound.io/my-db-8bhr2-k6k8m False True 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
instance.rds.aws.upbound.io/my-db-7mc7h-5d6w4 False True my-db-7mc7h-5d6w4 3m1s
|
||||
instance.rds.aws.upbound.io/my-db-8bhr2-tx9kf False True my-db-8bhr2-tx9kf 2m26s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
subnetgroup.rds.aws.upbound.io/my-db-7mc7h-8c8n9 True True my-db-7mc7h-8c8n9 3m2s
|
||||
subnetgroup.rds.aws.upbound.io/my-db-8bhr2-mc5ps True True my-db-8bhr2-mc5ps 2m27s
|
||||
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
bucket.s3.aws.upbound.io/crossplane-bucket-867737b10 True True
|
||||
crossplane-bucket-867737b10 5m26s
|
||||
```
|
||||
|
||||
{{</expand >}}
|
||||
{{< /hint >}}
|
||||
|
||||
### Remove composite resource definitions
|
||||
Removing installed _composite resource definitions_ removes any
|
||||
_composite resources_ defined by the _composite resource definition_ and the
|
||||
_managed resourced_ they created.
|
||||
|
||||
View the installed _composite resource definitions_ with `kubectl get xrd`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get xrd
|
||||
NAME ESTABLISHED OFFERED AGE
|
||||
compositepostgresqlinstances.database.example.org True True 40s
|
||||
```
|
||||
|
||||
Delete the _composite resource definitions_ with `kubectl delete xrd`.
|
||||
|
||||
```shell
|
||||
kubectl delete xrd compositepostgresqlinstances.database.example.org
|
||||
```
|
||||
|
||||
### Remove managed resources
|
||||
|
||||
Manually delete any _managed resources_ manually created.
|
||||
|
||||
Use `kubectl get managed` to view remaining _managed resources_.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get managed
|
||||
NAME READY SYNCED EXTERNAL-NAME AGE
|
||||
bucket.s3.aws.upbound.io/crossplane-bucket-867737b10 True True crossplane-bucket-867737b10 8h
|
||||
```
|
||||
|
||||
Use `kubectl delete` to remove the resources.
|
||||
|
||||
```shell
|
||||
kubectl delete bucket.s3.aws.upbound.io/crossplane-bucket-867737b10
|
||||
```
|
||||
|
||||
### Remove Crossplane providers
|
||||
|
||||
List the installed _providers_ with `kubectl get providers`.
|
||||
|
||||
```shell {copy-lines="1"}
|
||||
kubectl get providers
|
||||
NAME INSTALLED HEALTHY PACKAGE AGE
|
||||
upbound-provider-aws True True xpkg.upbound.io/upbound/provider-aws:v0.27.0 8h
|
||||
```
|
||||
|
||||
Remove the installed _providers_ with `kubectl delete provider`.
|
||||
|
||||
```shell
|
||||
kubectl delete provider upbound-provider-aws
|
||||
```
|
||||
|
||||
## Uninstall the Crossplane deployment
|
||||
|
||||
Uninstall Crossplane using Helm with `helm uninstall`
|
||||
|
||||
```shell
|
||||
helm uninstall crossplane --namespace crossplane-system
|
||||
```
|
||||
|
||||
Verify Helm removed the Crossplane pods with `kubectl get pods`
|
||||
|
||||
```shell
|
||||
kubectl get pods -n crossplane-system
|
||||
No resources found in crossplane-system namespace.
|
||||
```
|
||||
|
||||
## Delete the Crossplane namespace
|
||||
|
||||
When Helm installs Crossplane it creates the `crossplane-system` namespace. Helm
|
||||
doesn't uninstall this namespace with `helm uninstall`.
|
||||
|
||||
Manually delete the Crossplane namespace with `kubectl delete namespace`.
|
||||
|
||||
```shell
|
||||
kubectl delete namespace crossplane-system
|
||||
```
|
||||
|
||||
Verify Kubernetes removed the namespace with `kubectl get namespaces`
|
||||
|
||||
```shell
|
||||
kubectl get namespace
|
||||
NAME STATUS AGE
|
||||
default Active 2m45s
|
||||
kube-flannel Active 2m42s
|
||||
kube-node-lease Active 2m47s
|
||||
kube-public Active 2m47s
|
||||
kube-system Active 2m47s
|
||||
```
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
title: Upgrade Crossplane
|
||||
weight: 200
|
||||
draft: true
|
||||
---
|
||||
|
||||
Install, Uninstall, Upgrade
|
Loading…
Reference in New Issue