v1.12 Docs Release (#414)

This commit is contained in:
Pete Lumbis 2023-04-25 13:33:38 -04:00 committed by GitHub
parent b203b5dc7d
commit 7864da34b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 4870 additions and 7560 deletions

View File

@ -7,5 +7,6 @@ labels: release
- [ ] Update the `/latest` redirect in [netlify.toml](https://github.com/crossplane/docs/blob/master/netlify.toml#L9)
- [ ] Update `params.latest` in [config.yaml](https://github.com/crossplane/docs/blob/master/config.yaml#L48)
- [ ] Update `version` in the `_index.md` file of `/content/<new latest>`
- [ ] Create a [new release/tag](https://github.com/crossplane/docs/releases/new) named "v<EOL version>-archive" to snapshot EOL'd docs.
- [ ] Remove EOL'd docs version from "/content" directory and run `hugo` locally to check for broken links.

View File

@ -51,7 +51,7 @@ security:
- ^REVIEW_ID
params:
latest: "1.11"
latest: "1.12"
upboundLink: "https://www.upbound.io/"
slackLink: "https://slack.crossplane.io/"
githubLink: "https://github.com/crossplane/crossplane"

49
content/v1.12/_index.md Normal file
View File

@ -0,0 +1,49 @@
---
title: "Overview"
weight: -1
cascade:
version: "1.12"
---
{{< 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.

View File

@ -1,6 +1,7 @@
---
title: Concepts
weight: 100
description: Understand Crossplane's core components
---
Crossplane introduces multiple building blocks that enable you to provision,

View File

@ -1,8 +1,245 @@
---
title: Composition
weight: 304
title: Composite Resources
weight: 103
---
Crossplane Composite Resources are opinionated Kubernetes Custom Resources that
are _composed_ of [Managed Resources][managed-resources]. We often call them XRs
for short.
![Diagram of claims, XRs, and Managed Resources][xrs-and-mrs]
Composite Resources are designed to let you build your own platform with your
own opinionated concepts and APIs without needing to write a Kubernetes
controller from scratch. Instead, you define the schema of your XR and teach
Crossplane which Managed Resources it should compose (i.e. create) when someone
creates the XR you defined.
If you're already familiar with Composite Resources and looking for a detailed
configuration reference or some tips, tricks, and troubleshooting information,
try the [Composition Reference][xr-ref].
Below is an example of a Composite Resource:
```yaml
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
metadata:
name: my-db
spec:
parameters:
storageGB: 20
compositionRef:
name: production
writeConnectionSecretToRef:
namespace: crossplane-system
name: my-db-connection-details
```
You define your own XRs, so they can be of whatever API version and kind you
like, and contain whatever spec and status fields you need.
## How It Works
The first step towards using Composite Resources is configuring Crossplane so
that it knows what XRs you'd like to exist, and what to do when someone creates
one of those XRs. This is done using a `CompositeResourceDefinition` (XRD)
resource and one or more `Composition` resources.
Once you've configured Crossplane with the details of your new XR you can either
create one directly, or use a _claim_. Typically only the folks responsible for
configuring Crossplane (often a platform or SRE team) have permission to create
XRs directly. Everyone else manages XRs via a lightweight proxy resource called
a Composite Resource Claim (or claim for short). More on that later.
![Diagram combining all Composition concepts][how-it-works]
> If you're coming from the Terraform world you can think of an XRD as similar
> to the `variable` blocks of a Terraform module, while the `Composition` is
> the rest of the module's HCL code that describes how to use those variables to
> create a bunch of resources. In this analogy the XR or claim is a little like
> a `tfvars` file providing inputs to the module.
### Defining Composite Resources
A `CompositeResourceDefinition` (or XRD) defines the type and schema of your XR.
It lets Crossplane know that you want a particular kind of XR to exist, and what
fields that XR should have. An XRD is a little like a `CustomResourceDefinition`
(CRD), but slightly more opinionated. Writing an XRD is mostly a matter of
specifying an OpenAPI ["structural schema"][crd-docs].
The XRD that defines the `XPostgreSQLInstance` XR above would look like this:
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
required:
- parameters
```
You might notice that the `XPostgreSQLInstance` example above has some fields
that don't appear in the XRD, like the `writeConnectionSecretToRef` and
`compositionRef` fields. This is because Crossplane automatically injects some
standard Crossplane Resource Model (XRM) fields into all XRs.
### Configuring Composition
A `Composition` lets Crossplane know what to do when someone creates a Composite
Resource. Each `Composition` creates a link between an XR and a set of one or
more Managed Resources - when the XR is created, updated, or deleted the set of
Managed Resources are created, updated or deleted accordingly.
You can add multiple Compositions for each XRD, and choose which should be used
when XRs are created. This allows a Composition to act like a class of service -
for example you could configure one Composition for each environment you
support, such as production, staging, and development.
A basic `Composition` for the above `XPostgreSQLInstance` might look like this:
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example
labels:
crossplane.io/xrd: xpostgresqlinstances.database.example.org
provider: gcp
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: cloudsqlinstance
base:
apiVersion: database.gcp.crossplane.io/v1beta1
kind: CloudSQLInstance
spec:
forProvider:
databaseVersion: POSTGRES_12
region: us-central1
settings:
tier: db-custom-1-3840
dataDiskType: PD_SSD
ipConfiguration:
ipv4Enabled: true
authorizedNetworks:
- value: "0.0.0.0/0"
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.storageGB
toFieldPath: spec.forProvider.settings.dataDiskSizeGb
```
The above `Composition` tells Crossplane that when someone creates an
`XPostgreSQLInstance` XR Crossplane should create a `CloudSQLInstance` in
response. The `storageGB` field of the `XPostgreSQLInstance` should be used to
configure the `dataDiskSizeGb` field of the `CloudSQLInstance`. This is only a
small subset of the functionality a `Composition` enables - take a look at the
[reference page][xr-ref] to learn more.
> We almost always talk about XRs composing Managed Resources, but actually an
> XR can also compose other XRs to allow nested layers of abstraction. XRs don't
> support composing arbitrary Kubernetes resources (e.g. Deployments, operators,
> etc) directly but you can do so using our [Kubernetes][provider-kubernetes]
> and [Helm][provider-helm] providers.
### Claiming Composite Resources
Crossplane uses Composite Resource Claims (or just claims, for short) to allow
application operators to provision and manage XRs. When we talk about using XRs
it's typically implied that the XR is being used via a claim. Claims are almost
identical to their corresponding XRs. It helps to think of a claim as an
application teams interface to an XR. You could also think of claims as the
public (app team) facing part of the opinionated platform API, while XRs are the
private (platform team) facing part.
A claim for the `XPostgreSQLInstance` XR above would look like this:
```yaml
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
namespace: default
name: my-db
spec:
parameters:
storageGB: 20
compositionRef:
name: production
writeConnectionSecretToRef:
name: my-db-connection-details
```
There are three key differences between an XR and a claim:
1. Claims are namespaced, while XRs (and Managed Resources) are cluster scoped.
1. Claims are of a different `kind` than the XR - by convention the XR's `kind`
without the proceeding `X`. For example a `PostgreSQLInstance` claims an
`XPostgreSQLInstance`.
1. An active claim contains a reference to its corresponding XR, while an XR
contains both a reference to the claim an array of references to the managed
resources it composes.
Not all XRs offer a claim - doing so is optional. See the XRD section of the
[Composition reference][xr-ref] to learn how to offer a claim.
![Diagram showing the relationship between claims and XRs][claims-and-xrs]
Claims may seem a little superfluous at first, but they enable some handy
scenarios, including:
- **Private XRs.** Sometimes a platform team might not want a type of XR to be
directly consumed by their application teams. For example because the XR
represents 'supporting' infrastructure - consider the above VPC `XNetwork` XR. App
teams might create `PostgreSQLInstance` claims that _reference_ (i.e. consume)
an `XNetwork`, but they shouldn't be _creating their own_. Similarly, some
kinds of XR might be intended only for 'nested' use - intended only to be
composed by other XRs.
- **Global XRs**. Not all infrastructure is conceptually namespaced. Say your
organisation uses team scoped namespaces. A `PostgreSQLInstance` that belongs
to Team A should probably be part of the `team-a` namespace - you'd represent
this by creating a `PostgreSQLInstance` claim in that namespace. On the other
hand the `XNetwork` XR we mentioned previously could be referenced (i.e. used)
by XRs from many different namespaces - it doesn't exist to serve a particular
team.
- **Pre-provisioned XRs**. Finally, separating claims from XRs allows a platform
team to pre-provision certain kinds of XR. Typically an XR is created
on-demand in response to the creation of a claim, but it's also possible for a
claim to instead request an existing XR. This can allow application teams to
instantly claim infrastructure like database instances that would otherwise
take minutes to provision on-demand.
This reference provides detailed examples of defining, configuring, and using
Composite Resources in Crossplane. You can also refer to Crossplane's [API
@ -37,6 +274,17 @@ spec:
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
name: my-db
# The compositeDeletePolicy specifies the propagation policy that will be used by Crossplane
# when deleting the Composite Resource that is associated with the Claim. The default
# value is Background, which causes the Composite resource to be deleted using
# the kubernetes default propagation policy of Background, and all associated
# resources will be deleted simultaneously. The other value for this field is Foreground,
# which will cause the Composite resource to be deleted using Foreground Cascading Deletion.
# Kubernetes will add a foregroundDeletion finalizer to all of the resources in the
# dependency graph, and they will be deleted starting with the edge or leaf nodes and
# working back towards the root Composite. See https://kubernetes.io/docs/concepts/architecture/garbage-collection/#cascading-deletion
# for more information on cascading deletion.
compositeDeletePolicy: Background
# The compositionRef specifies which Composition this XR will use to compose
# resources when it is created, updated, or deleted. This can be omitted and
# will be set automatically if the XRD has a default or enforced composition
@ -51,6 +299,27 @@ spec:
environment: production
region: us-east
provider: gcp
# The environment is an in-memory object that can be patched from / to during
# rendering.
# The environment is composed by merging the 'data' of all EnvironmentConfigs
# referenced below. It is disposed after every reconcile.
# NOTE: EnvironmentConfigs are an alpha feature and need to be enabled with
# the '--enable-environment-configs' flag on startup.
environment:
# EnvironmentConfigs is a list of object references that is made up of
# name references and label selectors
environmentConfigs:
- type: Reference # this is the default
ref:
name: example-environment
- type: Selector
selector:
- key: stage
type: FromCompositeFieldPath # this is the default
valueFromFieldPath: spec.parameters.stage
- key: provider
type: Value
value: "gcp"
# The resourceRefs array contains references to all of the resources of which
# this XR is composed. Despite being in spec this field isn't intended to be
# configured by humans - Crossplane will take care of keeping it updated.
@ -167,12 +436,21 @@ spec:
# be written to the connection secret of the XR.
connectionSecretKeys:
- hostname
# Each type of XR may specify a default Composite Delete Policy to be used
# when the Claim has no compositeDeletePolicy. The valid values are Background
# and Foreground, and the default is Background. See the description of the
# compositeDeletePolicy parameter for more information.
defaultCompositeDeletePolicy: Background
# Each type of XR may specify a default Composition to be used when none is
# specified (e.g. when the XR has no compositionRef or selector). A similar
# enforceCompositionRef field also exists to allow XRs to enforce a specific
# Composition that should always be used.
defaultCompositionRef:
name: example
# Each type of XR may specify a default Composition Update Policy to be used
# when the Claim has no compositionUpdatePolicy. The valid values are Automatic
# and Manual and the default is Automatic.
defaultCompositionUpdatePolicy: Automatic
# Each type of XR may be served at different versions - e.g. v1alpha1, v1beta1
# and v1 - simultaneously. Currently Crossplane requires that all versions
# have an identical schema, so this is mostly useful to 'promote' a type of XR
@ -373,6 +651,45 @@ spec:
fromFieldPath: metadata.labels[some-important-label]
```
### Pause Annotation
There is an annotation named `crossplane.io/paused` that you can use on
Composite Resources and Composite Resource Claims to temporarily pause
reconciliations of their respective controllers on them. An example
for a Composite Resource Claim is as follows:
```yaml
apiVersion: test.com/v1alpha1
kind: MyResource
metadata:
annotations:
crossplane.io/paused: "true"
namespace: upbound-system
name: my-resource
spec:
parameters:
tagValue: demo-test
compositionRef:
name: example
```
where `MyResource` is a Composite Resource Claim kind.
When a Composite Resource or a Claim has the `crossplane.io/paused` annotation
with its value set to `true`, the Composite Resource controller or the Claim
controller pauses reconciliations on the resource until
the annotation is removed or its value set to something other than `true`.
Before temporarily pausing reconciliations, an event with the type `Synced`,
the status `False`, and the reason `ReconcilePaused` is emitted
on the resource.
Please also note that annotations on a Composite Resource Claim are propagated
to the associated Composite Resource but when the
`crossplane.io/paused: "true"` annotation is added to a Claim, because
reconciliations on the Claim are now paused, this newly added annotation
will not be propagated. However, whenever the annotation's value is set to a
non-`true` value, reconciliations on the Claim will now resume, and thus the
annotation will now be propagated to the associated Composite Resource
with a non-`true` value. An implication of the described behavior is that
pausing reconciliations on the Claim will not inherently pause reconciliations
on the associated Composite Resource.
### Patch Types
You can use the following types of patch in a `Composition`:
@ -428,6 +745,35 @@ resources:
toFieldPath: spec.forProvider.firewallRules[*].CIDRBlock
```
`FromEnvironmentFieldPath`. This type patches from a field within the in-memory
environment to a field within the composed resource. It's commonly used to
expose a composed resource spec field as an XR spec field.
Note that EnvironmentConfigs are an alpha feature and need to be enabled with
the `--enable-environment-configs` flag on startup.
```yaml
# Patch from the environment's tier.name field to the composed resource's
# spec.forProvider.settings.tier field.
- type: FromEnvironmentFieldPath
fromFieldPath: tier.name
toF/ieldPath: spec.forProvider.settings.tier
```
`ToEnvironmentFieldPath`. This type patches from a composed field to the
in-memory environment. Note that, unlike `ToCompositeFieldPath` patches, this
is executed before the composed resource is applied on the cluster which means
that the `status` is not available.
Note that EnvironmentConfigs are an alpha feature and need to be enabled with
the `--enable-environment-configs` flag on startup.
```yaml
# Patch from the environment's tier.name field to the composed resource's
# spec.forProvider.settings.tier field.
- type: ToEnvironmentFieldPath
fromFieldPath: spec.forProvider.settings.tier
toFieldPath: tier.name
```
Note that the field to be patched requires some initial value to be set.
`CombineFromComposite`. Combines multiple fields from the XR to produce one
@ -454,6 +800,26 @@ composed resource field.
fromFieldPath: Required
```
`CombineFromEnvironment`. Combines multiple fields from the in-memory
environment to produce one composed resource field.
Note that EnvironmentConfigs are an alpha feature and need to be enabled with
the `--enable-environment-configs` flag on startup.
```yaml
# Patch from the environments's location field and region to the composed
# resource's spec.forProvider.administratorLogin field.
- type: CombineFromEnvironment
combine:
# The patch will only be applied when all variables have non-zero values.
variables:
- fromFieldPath: location
- fromFieldPath: region
strategy: string
string:
fmt: "%s-%s"
toFieldPath: spec.forProvider.administratorLogin
```
At the time of writing only the `string` combine strategy is supported. It uses
[Go string formatting][pkg/fmt] to combine values, so if the XR's location was
`us-west` and its claim name was `db` the composed resource's administratorLogin
@ -478,6 +844,26 @@ would be set to `us-west-db`.
toFieldPath: status.adminDSN
```
`CombineToEnvironment` is the inverse of `CombineFromEnvironment`.
Note that EnvironmentConfigs are an alpha feature and need to be enabled with
the `--enable-environment-configs` flag on startup.
```yaml
# Patch from the composed resource's spec.parameters.administratorLogin and
# spec.forProvider.domainName fields back to the environment's adminDSN field.
- type: CombineToEnvironment
combine:
variables:
- fromFieldPath: spec.parameters.administratorLogin
- fromFieldPath: spec.forProvider.domainName
strategy: string
# Here, our administratorLogin parameter and fullyQualifiedDomainName
# status are formatted to a single output string representing a DSN.
string:
fmt: "mysql://%s@%s:3306/my-database-name"
toFieldPath: adminDSN
```
`PatchSet`. References a named set of patches defined in the `spec.patchSets`
array of a `Composition`.
@ -507,20 +893,88 @@ You can use the following types of transform on a value being patched:
au-east: Australia East
```
`math`. Transforms values using math. The input value must be an integer.
Currently only `multiply` is supported.
`match`. A more complex version of `map` that can match different kinds of
patterns. It should be used if more advanced pattern matchings than a simple
string equality check are required.
The result of the first matching pattern is used as the output of this
transform.
If no pattern matches, you can either fallback to a given `fallbackValue` or
fallback to the input value by setting the `fallbackTo` field to `Input`.
```yaml
# In the example below, if the value in the 'from' field is 'us-west', the
# value in the 'to' field will be set to 'West US'.
# If the value in the 'from' field is 'eu-west', the value in the 'to' field
# will be set to 'Unknown' because no pattern matches.
- type: match
match:
patterns:
- type: literal # Not needed. This is the default.
literal: us-west
result: West US
- type: regexp
regexp: '^af-.*'
result: Somewhere in Africa
fallbackTo: Value # Not needed. This is the default.
fallbackValue: Unknown
# If fallbackTo is set to Input, the output will be the input value if no
# pattern matches.
# In the example below, if the value in the 'from' field is 'us-west', the
# value in the 'to' field will be set to 'West US'.
# If the value in the 'from' field is 'eu-west', the value in the 'to' field
# will be set to 'eu-west' because no pattern matches.
- type: match
match:
patterns:
- type: literal
literal: us-west
result: West US
- type: regexp
regexp: '^af-.*'
result: Somewhere in Africa
fallbackTo: Input
```
`math`. Transforms values using math. The input value must be an integer.
* math transform type `Multiply`, multiplies the input by the given value.
* math transform type `ClampMin`, sets a minimum value for the output.
* math transform type `ClampMax`, sets a maximum value for the output.
```yaml
# If you omit the field type, by default type is set to `Multiply`
# If the value of the 'from' field is 2, the value of the 'to' field will be set
# to 4.
- type: math
math:
multiply: 2
# This is the same as above
# If the value of the 'from' field is 2, the value of the 'to' field will be set
# to 4.
- type: math
math:
type: Multiply
multiply: 2
# If the value of the 'from' field is 3, the value of the 'to' field will
# be set to 4.
- type: math
math:
type: ClampMin
clampMin: 4
# If the value of the 'from' field is 3, the value of the 'to' field will
# be set to 2.
- type: math
math:
type: ClampMax
clampMax: 2
```
`string`. Transforms string values.
* string transform type `Format`, Currently only Go style fmt is supported. [Go style `fmt`][pkg/fmt] is supported.
* string transform type `Convert`, accepts one of `ToUpper`, `ToLower`, `ToBase64`, `FromBase64`.
* string transform type `Convert`, accepts one of `ToUpper`, `ToLower`, `ToBase64`, `FromBase64`, `ToJson`, `ToSha1`, `ToSha256`, `ToSha512`.
* string transform type `TrimPrefix`, accepts a string to be trimmed from the beginning of the input.
* string transform type `TrimSuffix`, accepts a string to be trimmed from the end of the input.
* string transform type `Regexp`, accepts a string for regexp to be applied to.
@ -568,6 +1022,19 @@ Currently only `multiply` is supported.
type: Convert
convert: FromBase64
# If the value of the 'from' field is not nil, the value of the 'to' field will be
# set to raw JSON representation of the 'from' field.
- type: string
string:
type: Convert
convert: ToJson
# The output will be the hash of the JSON representation of the 'from' field.
- type: string
string:
type: Convert
convert: ToSha1 # alternatives: 'ToSha256' or 'ToSha512'
# If the value of the 'from' field is https://crossplane.io, the value of the 'to' field will
# be set to crossplane.io
- type: string
@ -614,6 +1081,17 @@ true converts to integer 1 and float 1.0, while false converts to 0 and 0.0.
toType: int
```
Converting `string` to `float64` additionally supports parsing string in
[K8s quantity format](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity),
such as `1000m` or `500 Mi`:
```yaml
- type: convert
convert:
toType: float64
format: quantity
```
### Connection Details
Connection details secret of XR is an aggregated sum of the connection details
@ -706,6 +1184,38 @@ not considered to be 'empty', and thus will pass the readiness check.
`None`. Considers the composed resource to be ready as soon as it exists.
### Composition validation
Crossplane uses a `Validating Webhook` to inform users of any potential
errors in a `Composition`. By default webhooks only perform
`logical checks`. `logical checks` enforce requirements that
aren't explicitly defined in the schema but Crossplane assumes to hold at runtime.
#### Experimental validation with schemas
Enable experimental schema-aware validation in Crossplane
through the `--enable-composition-webhook-schema-validation` feature flag. This
enables Composition validation against available schemas in the cluster.
For example, ensuring that `fieldPaths` are valid and source and destination
types match taking into account provided transforms too.
The `crossplane.io/composition-validation-mode` annotation on the Composition
allows setting one of two modes for schema validation:
- `loose` (default): Validates Compositions against required schemas. If a
required schema is missing, schema validation stops, emits a warning and
falls back to `logical checks` only.
- `strict`: Validates Compositions against required schemas, and rejects them
when finding errors. Rejects any Compositions missing required schemas.
See the [Composition Validating Webhook design document][validation-design-doc]
for more information about future development around schema-aware validation.
#### Disabling webhooks
Crossplane enables webhooks by default. Turn off webhooks by
`webhooks.enabled` to `false` in the provided Helm Chart.
### Missing Functionality
You might find while reading through this reference that Crossplane is missing
@ -716,7 +1226,7 @@ understand that the Crossplane maintainers are growing the feature set of the
community, but we also feel it's critical to avoid bloat and complexity. We
therefore wish to carefully consider each new addition. We feel some features
may be better suited for a real, expressive programming language and intend to
build an alternative to the `Composition` type as it is documented here per
build an alternative to the `Composition` type as it's documented here per
[this proposal][issue-2524].
## Tips, Tricks, and Troubleshooting
@ -826,14 +1336,19 @@ so:
1. Use a `FromCompositeFieldPath` patch to patch from the 'intermediary' field
you patched to in step 1 to a field on the destination composed resource.
[api-docs]: {{<ref "../api-docs/crossplane" >}}
[xr-concepts]: {{<ref "../concepts/composition" >}}
[crd-docs]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
[raise an issue]: https://github.com/crossplane/crossplane/issues/new?assignees=&labels=enhancement&template=feature_request.md
[issue-2524]: https://github.com/crossplane/crossplane/issues/2524
[field-paths]: https://github.com/kubernetes/community/blob/61f3d0/contributors/devel/sig-architecture/api-conventions.md#selecting-fields
[pkg/fmt]: https://pkg.go.dev/fmt
[trouble-ref]: {{<ref "troubleshoot" >}}
[upbound-marketplace]: https://marketplace.upbound.io
[helm-and-gcp]: https://github.com/crossplane-contrib/provider-helm/blob/2dcbdd0/examples/in-composition/composition.yaml
[issue-2024]: https://github.com/crossplane/crossplane/issues/2024
[xrs-and-mrs]: /media/composition-xrs-and-mrs.svg
[how-it-works]: /media/composition-how-it-works.svg
[provider-kubernetes]: https://marketplace.upbound.io/providers/crossplane-contrib/provider-kubernetes
[provider-helm]: https://marketplace.upbound.io/providers/crossplane-contrib/provider-helm/
[claims-and-xrs]: /media/composition-claims-and-xrs.svg
[xr-ref]: {{<ref "#compositions" >}}
[managed-resources]: {{<ref "managed-resources" >}}
[validation-design-doc]: https://github.com/crossplane/crossplane/blob/master/design/design-doc-composition-validating-webhook.md

View File

@ -5,20 +5,19 @@ weight: 102
A Managed Resource (MR) is Crossplane's representation of a resource in an
external system - most commonly a cloud provider. Managed Resources are
opinionated, Crossplane Resource Model ([XRM][term-xrm]) compliant Kubernetes
Custom Resources that are installed by a Crossplane [provider].
opinionated, Crossplane Resource Model ([XRM]({{<ref "../concepts/terminology">}})) compliant Kubernetes
Custom Resources that are installed by a Crossplane [provider]({{<ref "providers" >}}).
For example, `RDSInstance` in the AWS Provider corresponds to an actual RDS
Instance in AWS. There is a one-to-one relationship and the changes on managed
resources are reflected directly on the corresponding resource in the provider.
Similarly, the `Database` types in the SQL provider represent a PostgreSQL or
MySQL database. You can browse [API Reference][api-reference] to discover all
available managed resources.
MySQL database.
Managed Resources are the building blocks of Crossplane. They're designed to be
_composed_ into higher level, opinionated Custom Resources that Crossplane calls
Composite Resources or XRs - not used directly. See the
[Composition][composition] documentation for more information.
[Composition]({{<ref "composition" >}}) documentation for more information.
## Syntax
@ -51,7 +50,7 @@ spec:
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/provision/aws.yaml
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.10/docs/snippets/provision/aws.yaml
```
Creating the above instance will cause Crossplane to provision an RDS instance
@ -100,7 +99,7 @@ spec:
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/provision/gcp.yaml
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.10/docs/snippets/provision/gcp.yaml
```
Creating the above instance will cause Crossplane to provision a CloudSQL
@ -167,7 +166,7 @@ spec:
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/provision/azure.yaml
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.10/docs/snippets/provision/azure.yaml
```
Creating the above instance will cause Crossplane to provision a PostgreSQL
@ -304,6 +303,25 @@ never deletes the external resource in the provider.
> means Crossplane will allow immutable fields to be changed, but will not
> actually make the desired change. This is tracked in [this issue][issue-727].
#### Pausing Reconciliations
If a managed resource being reconciled by the [managed reconciler], has the
`crossplane.io/paused` annotation with its value set to `true` as in the
following example, then further reconciliations are paused on that resource
after emitting an event with the type `Synced`, the status `False`,
and the reason `ReconcilePaused`:
```yaml
apiVersion: ec2.aws.upbound.io/v1beta1
kind: VPC
metadata:
name: paused-vpc
annotations:
crossplane.io/paused: "true"
...
```
Reconciliations on the managed resource will resume once the
`crossplane.io/paused` annotation is removed or its value is set
to anything other than `true`.
### External Name
By default the name of the managed resource is used as the name of the external
@ -429,8 +447,7 @@ the values that are fetched from the provider.
Note that if a resource has required fields, you must fill those fields or the
creation of the managed resource will be rejected. So, in those cases, you will
need to enter the name of the resource as well as the required fields as
indicated in the [API Reference][api-reference] documentation.
need to enter the name of the resource as well as the required fields.
## Backup and Restore
@ -445,14 +462,11 @@ fields are there and those are enough to import a resource. The tool you're
using needs to store `annotations` and `spec` fields, which most tools do
including Velero.
[term-xrm]: {{<ref "terminology" >}}#crossplane-resource-model
[rds]: https://aws.amazon.com/rds/
[cloudsql]: https://cloud.google.com/sql
[composition]: {{<ref "composition" >}}
[api-versioning]: https://kubernetes.io/docs/reference/using-api/#api-versioning#api-versioning
[velero]: https://velero.io/
[api-reference]: {{<ref "../api-docs" >}}
[provider]: {{<ref "providers" >}}
[issue-727]: https://github.com/crossplane/crossplane/issues/727
[issue-1143]: https://github.com/crossplane/crossplane/issues/1143
[managed-api-patterns]: https://github.com/crossplane/crossplane/blob/master/design/one-pager-managed-resource-api-design.md
[managed-api-patterns]: https://github.com/crossplane/crossplane/blob/release-1.10/design/one-pager-managed-resource-api-design.md
[managed reconciler]: https://github.com/crossplane/crossplane-runtime/blob/84e629b9589852df1322ff1eae4c6e7639cf6e99/pkg/reconciler/managed/reconciler.go#L637

View File

@ -177,7 +177,7 @@ 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].
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:
@ -379,8 +379,10 @@ package without considering the version of Crossplane that is installed.
### spec.controllerConfigRef
> This field is only available when installing a `Provider` and is an `alpha`
> feature that depends on the `v1alpha1` [`ControllerConfig` API][controller-config-docs].
{{< 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
@ -491,7 +493,6 @@ by [pre-pulling images] onto nodes in the cluster.
[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
[getting-started-with-gcp]: https://github.com/crossplane/crossplane/tree/release-1.9/docs/snippets/package/gcp
[specification]: https://github.com/Masterminds/semver#basic-comparisons
[composition]: {{<ref "composition" >}}
[IAM Roles for Service Accounts]: https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html

View File

@ -3,8 +3,8 @@ title: Providers
weight: 101
---
Providers are Crossplane packages that bundle a set of [Managed
Resources][managed-resources] and their respective controllers to allow
Providers are Crossplane packages that bundle a set of
[Managed Resources]({{<ref "managed-resources" >}}) and their respective controllers to allow
Crossplane to provision the respective infrastructure resource.
## Installing Providers
@ -65,8 +65,7 @@ spec:
You can see that there is a reference to a key in a specific `Secret`. The value
of that key should contain the credentials that the controller will use. The
documentation of each provider should give you an idea of how that credentials
blob should look like. See [Getting Started][getting-started] guide for more
details.
blob should look like.
The following is an example usage of AWS `ProviderConfig`, referenced by a
`RDSInstance`:
@ -90,8 +89,7 @@ will attempt to use a `ProviderConfig` named `default`.
<!-- Named Links -->
[getting-started]: {{<ref "../getting-started/install-configure" >}}
[Google Cloud Platform (GCP) Service Account]: {{<ref "../cloud-providers/gcp/gcp-provider" >}}
[Microsoft Azure Service Principal]: {{<ref "../cloud-providers/azure/azure-provider" >}}
[Amazon Web Services (AWS) IAM User]: {{<ref "../cloud-providers/aws/aws-provider" >}}
[managed-resources]: {{<ref "managed-resources" >}}
[Google Cloud Platform (GCP) Service Account]: "../cloud-providers/gcp/gcp-provider"
[Microsoft Azure Service Principal]: "../cloud-providers/azure/azure-provider"
[Amazon Web Services (AWS) IAM User]: "../cloud-providers/aws/aws-provider"

View File

@ -2,7 +2,6 @@
title: Terminology
weight: 110
---
## A Note on Style
Each type of Kubernetes resource has a Pascal case name - i.e. a title case

View File

@ -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.

View File

@ -0,0 +1,464 @@
---
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.
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.
Crossplane also acts as a
[Kubernetes Controller](https://kubernetes.io/docs/concepts/architecture/controller/)
to monitor 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. |
| [Composite Resource Definitions]({{<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 _Custom Resource_
{{< hover label="xr2" line="3" >}}kind{{</hover>}}.
* A {{< hover label="specGroup" line="8" >}}versions.schema{{</hover>}} section
to define the _Custom 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 settings.
The following _Composite Resource Definition_ defines a {{<hover label="specVersions" line="17" >}}storage{{< /hover >}}
parameter. The size 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:
- size
```
A _Custom Resource Definition_ can define a wide variety of settings and options.
Creating a _Custom Resource Definition_ enables the creation of _Custom
Resources_ but can also create a _Claim_.
_Custom 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"}
# Custom 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 _Custom
Resource Definition_.
_Claims_ look like _Custom Resources_, but they're namespace scoped,
while _Custom 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 _Custom 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"}
# Custom 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
_Custom Resource Definition_.
The _Claim_ {{<hover label="claim" line="3">}}kind{{< /hover >}} matches the
_Custom 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 define a {{<hover label="claim" line="6">}}namespace{{</hover >}}.
The _Custom Resource Definition_ defines the
{{<hover label="claim" line="7">}}spec{{< /hover >}} like a _Custom Resource_.
_Claims_ are namespace scoped.
View all available Claims with the command `kubectl get claim`.
## Next steps
Build your own Crossplane platform using one of the quickstart guides.
* [Azure Quickstart]({{<ref "provider-azure" >}})
* [AWS Quickstart]({{<ref "provider-aws" >}})
* [GCP Quickstart]({{<ref "provider-gcp" >}})

View File

@ -0,0 +1,928 @@
---
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 >}}
This section creates a _[Composition](#create-a-composition)_,
_[Custom Resource Definition](#define-a-composite-resource)_ and a
_[Claim](#create-a-claim)_
to create a custom Kubernetes API to create AWS resources.
## 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-aws/latest/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.

View File

@ -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
doesn't need 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 doesn't need 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 Universal Crossplane (UXP)](https://github.com/upbound/universal-crossplane)
{{< /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-aws/latest/crds).
* 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

View File

@ -0,0 +1,218 @@
---
title: Azure Quickstart
weight: 110
---
Connect Crossplane to Microsoft Azure to create and manage cloud resources from Kubernetes with the [Upbound Azure Provider](https://marketplace.upbound.io/providers/upbound/provider-azure).
This guide walks you through the steps required to get started with the Upbound Azure Provider. This includes installing Crossplane, configuring the provider to authenticate to Azure and creating a _Managed Resource_ in Azure directly from your Kubernetes cluster.
- [Prerequisites](#prerequisites)
- [Install the Azure provider](#install-the-azure-provider)
- [Create a Kubernetes secret for Azure](#create-a-kubernetes-secret-for-azure)
- [Install the Azure command-line](#install-the-azure-command-line)
- [Create an Azure service principal](#create-an-azure-service-principal)
- [Create a Kubernetes secret with the Azure credentials](#create-a-kubernetes-secret-with-the-azure-credentials)
- [Create a ProviderConfig](#create-a-providerconfig)
- [Create a managed resource](#create-a-managed-resource)
- [Delete the managed resource](#delete-the-managed-resource)
- [Next steps](#next-steps)
## Prerequisites
This quickstart requires:
* a Kubernetes cluster with at least 3 GB of RAM
* permissions to create pods and secrets in the Kubernetes cluster
* [Helm] version `v3.2.0` or later
* an Azure account with permissions to create an Azure [service principal](https://learn.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals#service-principal-object) and an [Azure Resource Group](https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal)
{{< hint type="tip" >}}
If you don't have a Kubernetes cluster create one locally with [minikube](https://minikube.sigs.k8s.io/docs/start/) or [kind](https://kind.sigs.k8s.io/).
{{< /hint >}}
{{< hint type="note" >}}
All commands use the current `kubeconfig` context and configuration.
{{< /hint >}}
## Install the Azure provider
Install the provider into the Kubernetes cluster with a Kubernetes configuration file.
```shell {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: upbound-provider-azure
spec:
package: xpkg.upbound.io/upbound/provider-azure:v0.29.0
EOF
```
The {{< hover label="provider" line="3">}}kind: Provider{{< /hover >}} uses the Crossplane `Provider` _Custom Resource Definition_ to connect your Kubernetes cluster to your cloud provider.
Verify the provider installed with `kubectl get providers`.
{{< hint type="note" >}}
It may take up to five minutes for the provider to list `HEALTHY` as `True`.
{{< /hint >}}
```shell
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
upbound-provider-azure True True xpkg.upbound.io/upbound/provider-azure:v0.29.0 3m3s
```
A provider installs their own Kubernetes _Custom Resource Definitions_ (CRDs). These CRDs allow you to create Azure resources directly inside Kubernetes.
You can view the new CRDs with `kubectl get crds`. Every CRD maps to a unique Azure service Crossplane can provision and manage.
{{< hint type="tip" >}}
All the supported CRDs are also available in the [Upbound Marketplace](https://marketplace.upbound.io/providers/upbound/provider-azure/latest/crds).
{{< /hint >}}
## Create a Kubernetes secret for Azure
The provider requires credentials to create and manage Azure resources. Providers use a Kubernetes _Secret_ to connect the credentials to the provider.
{{< hint type="note" >}}
Other authentication methods exist and are beyond the scope of this guide. The [Provider documentation](https://marketplace.upbound.io/providers/upbound/provider-azure/latest/docs/configuration) contains information on alternative authentication methods.
{{< /hint >}}
First generate a Kubernetes _Secret_ from your Azure JSON file and then configure the Provider to use it.
### Install the Azure command-line
Generating an [authentication file](https://docs.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-file-based-authentication) requires the Azure command-line.
Follow the documentation from Microsoft to [Download and install the Azure command-line](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli).
Log in to the Azure command-line.
```command
az login
```
### Create an Azure service principal
Follow the Azure documentation to [find your Subscription ID](https://docs.microsoft.com/en-us/azure/azure-portal/get-subscription-tenant-id) from the Azure Portal.
Using the Azure command-line and provide your Subscription ID create a service principal and authentication file.
```shell {copy-lines="all"}
az ad sp create-for-rbac \
--sdk-auth \
--role Owner \
--scopes /subscriptions/<Subscription ID>
```
Save your Azure JSON output as `azure-credentials.json`.
{{< hint type="note" >}}
The [Configuration](https://marketplace.upbound.io/providers/upbound/provider-azure/latest/docs/configuration) section of the Provider documentation describes other authentication methods.
{{< /hint >}}
### Create a Kubernetes secret with the Azure credentials
A Kubernetes generic secret has a name and contents. Use {{< hover label="kube-create-secret" line="1">}}kubectl create secret{{< /hover >}} to generate the secret object named {{< hover label="kube-create-secret" line="2">}}azure-secret{{< /hover >}} in the {{< hover label="kube-create-secret" line="3">}}crossplane-system{{</ hover >}} namespace.
<!-- vale gitlab.Substitutions = NO -->
<!-- ignore .json file name -->
Use the {{< hover label="kube-create-secret" line="4">}}--from-file={{</hover>}} argument to set the value to the contents of the {{< hover label="kube-create-secret" line="4">}}azure-credentials.json{{< /hover >}} file.
<!-- vale gitlab.Substitutions = YES -->
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret \
generic azure-secret \
-n crossplane-system \
--from-file=creds=./azure-credentials.json
```
View the secret with `kubectl describe secret`
{{< hint type="note" >}}
The size may be larger if there are extra blank spaces in your text file.
{{< /hint >}}
```shell
kubectl describe secret azure-secret -n crossplane-system
Name: azure-secret
Namespace: crossplane-system
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
creds: 629 bytes
```
## Create a ProviderConfig
A `ProviderConfig` customizes the settings of the Azure Provider.
Apply the {{< hover label="providerconfig" line="2">}}ProviderConfig{{</ hover >}} with the command:
```yaml {label="providerconfig",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: azure.upbound.io/v1beta1
metadata:
name: default
kind: ProviderConfig
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: azure-secret
key: creds
EOF
```
This attaches the Azure credentials, saved as a Kubernetes secret, as a {{< hover label="providerconfig" line="9">}}secretRef{{</ hover>}}.
The {{< hover label="providerconfig" line="11">}}spec.credentials.secretRef.name{{< /hover >}} value is the name of the Kubernetes secret containing the Azure credentials in the {{< hover label="providerconfig" line="10">}}spec.credentials.secretRef.namespace{{< /hover >}}.
## Create a managed resource
A _managed resource_ is anything Crossplane creates and manages outside of the Kubernetes cluster. This creates an Azure Resource group with Crossplane. The Resource group is a _managed resource_.
{{< hint type="tip" >}}
A resource group is one of the fastest Azure resources to provision.
{{< /hint >}}
```yaml {label="xr",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: azure.upbound.io/v1beta1
kind: ResourceGroup
metadata:
name: example-rg
spec:
forProvider:
location: "East US"
providerConfigRef:
name: default
EOF
```
Notice the {{< hover label="xr" line="2">}}apiVersion{{< /hover >}} and {{< hover label="xr" line="3">}}kind{{</hover >}} are from the `Provider's` CRDs.
The {{< hover label="xr" line="5">}}metadata.name{{< /hover >}} value is the name of the created resource group in Azure.
This example uses the name `example-rg`.
The {{< hover label="xr" line="8">}}spec.forProvider.location{{< /hover >}} tells Azure which Azure region to use when deploying resources. The region can be any [Azure geography](https://azure.microsoft.com/en-us/explore/global-infrastructure/geographies/) code.
Use `kubectl get resourcegroup` to verify Crossplane created the resource group.
```shell
kubectl get ResourceGroup
NAME READY SYNCED EXTERNAL-NAME AGE
example-rg True True example-rg 4m58s
```
## Delete the managed resource
Before shutting down your Kubernetes cluster, delete the resource group just created.
Use `kubectl delete resource-group` to remove the bucket.
```shell
kubectl delete resourcegroup example-rg
resourcegroup.azure.upbound.io "example-rg" deleted
```
## Next steps
* Explore Azure resources that can Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-azure/latest/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.

View File

@ -0,0 +1,224 @@
---
title: GCP Quickstart
weight: 140
---
Connect Crossplane to Google GCP to create and manage cloud resources from Kubernetes with the [Upbound GCP Provider](https://marketplace.upbound.io/providers/upbound/provider-gcp/).
This guide walks you through the steps required to get started with the Upbound GCP Provider. This includes installing Crossplane, configuring the provider to authenticate to GCP and creating a _Managed Resource_ in GCP directly from your Kubernetes cluster.
- [Prerequisites](#prerequisites)
- [Install the GCP provider](#install-the-gcp-provider)
- [Create a Kubernetes secret for GCP](#create-a-kubernetes-secret-for-gcp)
- [Generate a GCP service account JSON file](#generate-a-gcp-service-account-json-file)
- [Create a Kubernetes secret with the GCP credentials](#create-a-kubernetes-secret-with-the-gcp-credentials)
- [Create a ProviderConfig](#create-a-providerconfig)
- [Create a managed resource](#create-a-managed-resource)
- [Delete the managed resource](#delete-the-managed-resource)
- [Next steps](#next-steps)
## Prerequisites
This quickstart requires:
* a Kubernetes cluster with at least 3 GB of RAM
* permissions to create pods and secrets in the Kubernetes cluster
* [Helm](https://helm.sh/) version `v3.2.0` or later
* a GCP account with permissions to create a storage bucket
* GCP [account keys](https://cloud.google.com/iam/docs/creating-managing-service-account-keys)
* GCP [Project ID](https://support.google.com/googleapi/answer/7014113?hl=en)
{{< hint type="tip" >}}
If you don't have a Kubernetes cluster create one locally with [minikube](https://minikube.sigs.k8s.io/docs/start/) or [kind](https://kind.sigs.k8s.io/).
{{< /hint >}}
{{< hint type="note" >}}
All commands use the current `kubeconfig` context and configuration.
{{< /hint >}}
## Install the GCP provider
Install the provider into the Kubernetes cluster with a Kubernetes configuration file.
```shell {label="provider",copy-lines="all"}
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: upbound-provider-gcp
spec:
package: xpkg.upbound.io/upbound/provider-gcp:v0.15.0
EOF
```
The {{< hover label="provider" line="3">}}kind: Provider{{< /hover >}} uses the Crossplane `Provider` _Custom Resource Definition_ to connect your Kubernetes cluster to your cloud provider.
Verify the provider installed with `kubectl get providers`.
{{< hint type="note" >}}
It may take up to five minutes for the provider to list `HEALTHY` as `True`.
{{< /hint >}}
```shell
kubectl get providers
NAME INSTALLED HEALTHY PACKAGE AGE
upbound-provider-gcp True False xpkg.upbound.io/upbound/provider-gcp:v0.15.0 8s
```
A provider installs their own Kubernetes _Custom Resource Definitions_ (CRDs). These CRDs allow you to create GCP resources directly inside Kubernetes.
You can view the new CRDs with `kubectl get crds`. Every CRD maps to a unique GCP service Crossplane can provision and manage.
{{< hint type="tip" >}}
All the supported CRDs are also available in the [Upbound Marketplace](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/crds).
{{< /hint >}}
## Create a Kubernetes secret for GCP
The provider requires credentials to create and manage GCP resources. Providers use a Kubernetes _Secret_ to connect the credentials to the provider.
First generate a Kubernetes _Secret_ from a Google Cloud service account JSON file and then configure the Provider to use it.
{{< hint type="note" >}}
Other authentication methods exist and are beyond the scope of this guide. The [Provider documentation](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/docs/configuration) contains information on alternative authentication methods.
{{< /hint >}}
### Generate a GCP service account JSON file
For basic user authentication, use a Google Cloud 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 >}}
Save this JSON file as `gcp-credentials.json`
{{< hint type="note" >}}
The [Configuration](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/docs/configuration) section of the Provider documentation describes other authentication methods.
{{< /hint >}}
### Create a Kubernetes secret with the GCP credentials
<!-- vale gitlab.Substitutions = NO -->
<!-- ignore .json file name -->
A Kubernetes generic secret has a name and contents. Use {{< hover label="kube-create-secret" line="1">}}kubectl create secret{{< /hover >}} to generate the secret object named {{< hover label="kube-create-secret" line="2">}}gcp-secret{{< /hover >}} in the {{< hover label="kube-create-secret" line="3">}}crossplane-system{{</ hover >}} namespace.
Use the {{< hover label="kube-create-secret" line="4">}}--from-file={{</hover>}} argument to set the value to the contents of the {{< hover label="kube-create-secret" line="4">}}gcp-credentials.json{{< /hover >}} file.
<!-- vale gitlab.Substitutions = YES -->
```shell {label="kube-create-secret",copy-lines="all"}
kubectl create secret \
generic gcp-secret \
-n crossplane-system \
--from-file=creds=./gcp-credentials.json
```
View the secret with `kubectl describe secret`
{{< hint type="note" >}}
The size may be larger if there are extra blank spaces in your text file.
{{< /hint >}}
```shell
kubectl describe secret gcp-secret -n crossplane-system
Name: gcp-secret
Namespace: crossplane-system
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
creds: 2330 bytes
```
## Create a ProviderConfig
A `ProviderConfig` customizes the settings of the GCP Provider.
Apply the {{< hover label="providerconfig" line="2">}}ProviderConfig{{</ hover >}}. Include your {{< hover label="providerconfig" line="7" >}}GCP project ID{{< /hover >}}.
{{< hint type="warning" >}}
Add your GCP `project ID` into the output below.
{{< /hint >}}
```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
```
This attaches the GCP credentials, saved as a Kubernetes secret, as a {{< hover label="providerconfig" line="9">}}secretRef{{</ hover>}}.
The {{< hover label="providerconfig" line="12">}}spec.credentials.secretRef.name{{< /hover >}} value is the name of the Kubernetes secret containing the GCP credentials in the {{< hover label="providerconfig" line="11">}}spec.credentials.secretRef.namespace{{< /hover >}}.
## Create a managed resource
A _managed resource_ is anything Crossplane creates and manages outside of the Kubernetes cluster. This creates a GCP storage bucket with Crossplane. The storage bucket is a _managed resource_.
This generates a random name for the storage bucket starting with {{< hover label="xr" line="1" >}}crossplane-bucket{{< /hover >}}
```yaml {label="xr",copy-lines="all"}
bucket=$(echo "crossplane-bucket-"$(head -n 4096 /dev/urandom | openssl sha1 | tail -c 10))
cat <<EOF | kubectl apply -f -
apiVersion: storage.gcp.upbound.io/v1beta1
kind: Bucket
metadata:
name: $bucket
spec:
forProvider:
location: US
storageClass: MULTI_REGIONAL
providerConfigRef:
name: default
deletionPolicy: Delete
EOF
```
Notice the {{< hover label="xr" line="3">}}apiVersion{{< /hover >}} and {{< hover label="xr" line="4">}}kind{{</hover >}} are from the `Provider's` CRDs.
The {{< hover label="xr" line="6">}}metadata.name{{< /hover >}} value is the name of the created GCP storage bucket.
This example uses the generated name `crossplane-bucket-<hash>` in the {{< hover label="xr" line="6">}}$bucket{{</hover >}} variable.
{{< hover label="xr" line="10" >}}spec.storageClass{{< /hover >}} defines the GCP storage bucket is [single-region, dual-region or multi-region](https://cloud.google.com/storage/docs/locations#key-concepts).
{{< hover label="xr" line="9">}}spec.forProvider.location{{< /hover >}} is a [GCP location based](https://cloud.google.com/storage/docs/locations) on the {{< hover label="xr" line="10" >}}storageClass{{< /hover >}}.
Use `kubectl get buckets` to verify Crossplane created the bucket.
{{< hint type="tip" >}}
Crossplane created the bucket when the values `READY` and `SYNCED` are `True`.
This may take up to 5 minutes.
{{< /hint >}}
```shell
kubectl get bucket
NAME READY SYNCED EXTERNAL-NAME AGE
crossplane-bucket-cf2b6d853 True True crossplane-bucket-cf2b6d853 3m3s
```
Optionally, log into the [GCP Console](https://console.cloud.google.com/) and see the storage bucket inside GCP.
## Delete the managed resource
Before shutting down your Kubernetes cluster, delete the S3 bucket just created.
Use `kubectl delete bucket <bucketname>` to remove the bucket.
```shell
kubectl delete bucket $bucket
bucket.storage.gcp.upbound.io "crossplane-bucket-b7cf6b590" deleted
```
Look in the [GCP Console](https://console.cloud.google.com/) to confirm Crossplane deleted the bucket from GCP.
## Next steps
* Explore GCP resources that can Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-gcp/latest/crds).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.

View File

@ -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.

View File

@ -0,0 +1,337 @@
---
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
* [Kubernetes](https://kubernetes.io/releases/) version `v1.16.0` or later
* [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.
{{<expand "All Crossplane customization options" >}}
{{< table "table table-hover table-striped table-sm">}}
| Parameter | Description | Default |
| --- | --- | --- |
| `affinity` | Enable pod affinity for the Crossplane pods. | `{}` |
| `args` | Optional arguments passed to the Crossplane pods. | `{}` |
| `configuration.packages` | A list of Crossplane _Configuration_ packages to install together with Crossplane. | `[]` |
| `customAnnotations` | Add custom annotations to the Crossplane deployments and pods. | `{}` |
| `customLabels` | Add custom labels to the Crossplane deployments and pods. | `{}` |
| `deploymentStrategy` | The deployment strategy for the Crossplane and RBAC Manager pods. | `RollingUpdate` |
| `extraEnvVarsCrossplane` | List of extra environment variables to set in the Crossplane deployment. **Note**: Helm replaces all dot `.` values with underscores `_` (example: `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`). | `{}` |
| `extraEnvVarsRBACManager` | List of extra environment variables to set in the Crossplane RBAC Manager deployment. **Note**: Helm replaces all dot `.` values with underscores `_` (example: `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`). | `{}` |
| `image.pullPolicy` | Image pull policy used in all Crossplane containers. | `IfNotPresent` |
| `image.repository` | Image repository for the Crossplane pods. | `crossplane/crossplane` |
| `image.tag` | Image tag used to install the Crossplane pod image. | `master` |
| `imagePullSecrets` | Names of image pull secrets to use. | `{}` |
| `leaderElection` | Enable leader election for the Crossplane Manager pods. | `true` |
| `metrics.enabled` | Expose Crossplane and RBAC Manager pod metrics endpoints. | `false` |
| `nodeSelector` | Enable a node selector for the Crossplane pods. | `{}` |
| `packageCache.configMap` | A [Kubernetes `configMap`](https://kubernetes.io/docs/concepts/storage/volumes/#configmap) to define the Crossplane _Configuration_ package cache. Configuring `packageCache.configMap` disables the [Kubernetes `emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir). Crossplane ignores the `packageCache.configMap` when using `packageCache.pvc`. | `""` |
| `packageCache.medium` | The [Kubernetes `emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) medium used for the Crossplane _Configuration_ package cache. Unused with `packageCache.pvc` or `packageCache.configMap` set. | `""` |
| `packageCache.pvc` | Name of the [Kubernetes `PersistentVolumeClaim`](https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim) used for the Crossplane _Configuration_ package cache. The `packageCache.pvc` takes precedence over `packageCache.configMap` and disables the [Kubernetes `emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir). | `""` |
| `packageCache.sizeLimit` | The size limit of the [Kubernetes `emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) used for the Crossplane _Configuration_ package cache. Unused with `packageCache.pvc` or `packageCache.configMap` set. | `5Mi` |
| `podSecurityContextCrossplane` | Configure a [Kubernetes `securityContext`](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for the Crossplane pods. | `{}` |
| `podSecurityContextCrossplane` | Configure a [Kubernetes `securityContext`](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) for the Crossplane RBAC Manager pod. | `{}` |
| `priorityClassName` | The priority class name for Crossplane and RBAC Manager pods. | `""` |
| `provider.packages` | A list of Crossplane _Provider_ packages to install together with Crossplane. | `[]` |
| `rbacManager.affinity` | Enable affinity for the Crossplane RBAC Manager pod. | `{}` |
| `rbacManager.deploy` | Deploy the Crossplane RBAC Manager pod and its required roles. | `true` |
| `rbacManager.leaderElection` | Enable the leader election for the Crossplane RBAC Managers pod. | `true` |
| `rbacManager.managementPolicy`| The extent to which the Crossplane RBAC manager manages permissions. Setting `rbacManager.managementPolicy` to `All` the Crossplane RBAC contoller manages all Crossplane controller and user roles. Setting `rbacManager.managementPolicy` to `Basic` the Crossplane RBAC controller only manages `crossplane-admin`, `crossplane-edit`, and `crossplane-view` user roles. | `All` |
| `rbacManager.nodeSelector` | Enable a node selector for the Crossplane RBAC Manager pod. | `{}` |
| `rbacManager.replicas` | The number of replicas to run for the Crossplane RBAC Manager pods. | `1` |
| `rbacManager.skipAggregatedClusterRoles` | Don't deploy RBAC aggregated ClusterRoles. | `false` |
| `rbacManager.tolerations` | Enable tolerations for Crossplane RBAC Managers pod. | `[]` |
| `registryCaBundleConfig.key` | Key to use from the _ConfigMap_ containing a CA bundle for fetching from package registries. | `{}` |
| `registryCaBundleConfig.name` | Name of _ConfigMap_ containing a CA bundle for fetching from package registries. | `{}` |
| `replicas` | The number of replicas to run for the Crossplane pods. | `1` |
| `resourcesCrossplane.limits.cpu` | CPU resource limits for the Crossplane pods. | `100m` |
| `resourcesCrossplane.limits.memory` | Memory resource limits for the Crossplane pods. | `512Mi` |
| `resourcesCrossplane.requests.cpu` | CPU resource requests for the Crossplane pods. | `100m` |
| `resourcesCrossplane.requests.memory` | Memory resource requests for the Crossplane pods. | `256Mi` |
| `resourcesRBACManager.limits.cpu` | CPU resource limits for the Crossplane RBAC Manager pod. | `100m` |
| `resourcesRBACManager.limits.memory` | Memory resource limits for the Crossplane RBAC Manager pod. | `512Mi` |
| `resourcesRBACManager.requests.cpu` | CPU resource requests for the Crossplane RBAC Manager pod. | `100m` |
| `resourcesRBACManager.requests.memory` | Memory resource requests value the Crossplane RBAC Manager pod. | `256Mi` |
| `securityContextCrossplane.allowPrivilegeEscalation` | Allow privilege escalation for the Crossplane pods. | `false` |
| `securityContextCrossplane.readOnlyRootFilesystem` | Set a read only root file system for the Crossplane pods. | `true` |
| `securityContextCrossplane.runAsGroup` | A _run as group_ for the Crossplane pods. | `65532` |
| `securityContextCrossplane.runAsUser` | A _run as user_ for the Crossplane pods. | `65532` |
| `securityContextRBACManager.allowPrivilegeEscalation` | Allow privilege escalation for the Crossplane RBAC Manager pod. | `false` |
| `securityContextRBACManager.readOnlyRootFilesystem` | Set a read only root file system for the Crossplane RBAC Manager pod. | `true` |
| `securityContextRBACManager.runAsGroup` | The _run as group_ for the Crossplane RBAC Manager pod. | `65532` |
| `securityContextRBACManager.runAsUser` | The _run as user_ for the Crossplane RBAC Manager pod. | `65532` |
| `serviceAccount.customAnnotations` | Add custom annotations to the Crossplane service account. | `{}` |
| `tolerations` | Enable tolerations for Crossplane pod. | `[]` |
| `webhooks.enabled` | Enable webhooks for Crossplane as well as packages installed by Crossplane. | `false` |
| `xfn.args` | Optional arguments passed to the _Composite Resource Functions_ sidecar container. | `{}` |
| `xfn.cache.medium` | The [Kubernetes `emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) medium used for the _Composite Resource Functions_ sidecar container cache. Unused with `xfn.cache.pvc` set. | `""` |
| `xfn.cache.pvc` | Name of the [Kubernetes `PersistentVolumeClaim`](https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim) used for the _Composite Resource Functions_ sidecar container cache. The `xfn.cache.pvc` disables the _Composite Resource Functions_ [Kubernetes `emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir). | `""` |
| `xfn.cache.sizeLimit` | The size limit of the [Kubernetes `emptyDir`](https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) used for the _Composite Resource Functions_ sidecar container cache. Unused with `xfn.cache.pvc` set. | `1Gi` |
| `xfn.enabled` | Enable Crossplane _Composite Resource Functions_. Enabling _Composite Resource Functions_ also requires `args` set with `--enable-composition-functions`. | `false` |
| `xfn.extraEnvVars` | List of extra environment variables to set in the _Composite Resource Functions_ sidecar container. **Note**: Helm replaces all dot `.` values with underscores `_` (example: `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`). | `{}` |
| `xfn.image.pullPolicy` | Image pull policy used in the _Composite Resource Functions_ sidecar container. | `IfNotPresent` |
| `xfn.image.repository` | Image repository for the _Composite Resource Functions_ sidecar container. | `crossplane/xfn` |
| `xfn.image.tag` | Image tag used to install the _Composite Resource Functions_ sidecar container. | The installed Crossplane version. |
| `xfn.imagePullSecrets` | Names of image pull secrets to use when installing the _Composite Resource Functions_ sidecar container. | `{}` |
| `xfn.limits.cpu` | CPU resource limits for the Crossplane RBAC Manager pod. | `2000m` |
| `xfn.limits.memory` | Memory resource limits for the Crossplane RBAC Manager pod. | `2Gi` |
| `xfn.requests.cpu` | CPU resource requests for the Crossplane RBAC Manager pod. | `1000m` |
| `xfn.requests.memory` | Memory resource requests value the Crossplane RBAC Manager pod. | `1Gi` |
| `xfn.securityContext.allowPrivilegeEscalation` | Allow privilege escalation for the Crossplane RBAC Manager pod. | `false` |
| `xfn.securityContext.readOnlyRootFilesystem` | Set a read only root file system for the Crossplane RBAC Manager pod. | `true` |
| `xfn.securityContext.runAsGroup` | The _run as group_ for the Crossplane RBAC Manager pod. | `65532` |
| `xfn.securityContext.runAsUser` | The _run as user_ for the Crossplane RBAC Manager pod. | `65532` |
{{< /table >}}
{{< /expand >}}
#### 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 multiple, 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 usually introduces new features behind feature flags. By default
alpha features are off, while beta features are enabled. 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/).

View File

@ -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
```

View File

@ -0,0 +1,7 @@
---
title: Upgrade Crossplane
weight: 200
draft: true
---
Install, Uninstall, Upgrade

View File

@ -1,27 +0,0 @@
---
title: "Overview"
weight: -1
cascade:
version: "1.9"
---
{{< img src="/media/banner.png" alt="Crossplane Popsicle Truck" size="large" >}}
Crossplane is an open source Kubernetes add-on that transforms your cluster into
a **universal control plane**. Crossplane enables platform teams to assemble
infrastructure from multiple vendors, and expose higher level self-service APIs
for application teams to consume, without having to write any code.
Crossplane extends your Kubernetes cluster to support orchestrating any
infrastructure or managed service. Compose Crossplane's granular resources into
higher level abstractions that can be versioned, managed, deployed and consumed
using your favorite tools and existing processes. [Install Crossplane]({{<ref "getting-started/install-configure" >}}) into any
Kubernetes cluster to get started.
Crossplane is a [Cloud Native Compute Foundation][cncf] project.
<!-- Named Links -->
[cncf]: https://www.cncf.io/

View File

@ -1,20 +0,0 @@
---
title: API Documentation
weight: 400
---
Crossplane packages offer API types in a cluster by installing CRDs or XRDs.
Packages that are pushed to `xpkg.upbound.io` have auto-generated documentation
for their API types on the [Upbound Marketplace]. You can access documentation
for the most recent release of any package by navigating to
`https://marketplace.upbound.io/{provider|configuration}/<org>/<repo>`.
Crossplane repositories that do not contain providers or configurations, but do
publish CRDs, are served on [doc.crds.dev]. For instance, the
[crossplane/crossplane] repository.
<!-- Named Links -->
[Upbound Marketplace]: https://marketplace.upbound.io
[doc.crds.dev]: https://doc.crds.dev/
[crossplane/crossplane]: https://doc.crds.dev/github.com/crossplane/crossplane

View File

@ -1,141 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: configurations.meta.pkg.crossplane.io
spec:
group: meta.pkg.crossplane.io
names:
kind: Configuration
listKind: ConfigurationList
plural: configurations
singular: configuration
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: A Configuration is the description of a Crossplane Configuration
package.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ConfigurationSpec specifies the configuration of a Configuration.
properties:
crossplane:
description: Semantic version constraints of Crossplane that package
is compatible with.
properties:
version:
description: Semantic version constraints of Crossplane that package
is compatible with.
type: string
required:
- version
type: object
dependsOn:
description: Dependencies on other packages.
items:
description: Dependency is a dependency on another package. One
of Provider or Configuration may be supplied.
properties:
configuration:
description: Configuration is the name of a Configuration package
image.
type: string
provider:
description: Provider is the name of a Provider package image.
type: string
version:
description: Version is the semantic version constraints of
the dependency image.
type: string
required:
- version
type: object
type: array
type: object
required:
- spec
type: object
served: true
storage: true
- name: v1alpha1
schema:
openAPIV3Schema:
description: A Configuration is the description of a Crossplane Configuration
package.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ConfigurationSpec specifies the configuration of a Configuration.
properties:
crossplane:
description: Semantic version constraints of Crossplane that package
is compatible with.
properties:
version:
description: Semantic version constraints of Crossplane that package
is compatible with.
type: string
required:
- version
type: object
dependsOn:
description: Dependencies on other packages.
items:
description: Dependency is a dependency on another package. One
of Provider or Configuration may be supplied.
properties:
configuration:
description: Configuration is the name of a Configuration package
image.
type: string
provider:
description: Provider is the name of a Provider package image.
type: string
version:
description: Version is the semantic version constraints of
the dependency image.
type: string
required:
- version
type: object
type: array
type: object
required:
- spec
type: object
served: true
storage: false
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -1,263 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: providers.meta.pkg.crossplane.io
spec:
group: meta.pkg.crossplane.io
names:
kind: Provider
listKind: ProviderList
plural: providers
singular: provider
scope: Namespaced
versions:
- name: v1
schema:
openAPIV3Schema:
description: A Provider is the description of a Crossplane Provider package.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ProviderSpec specifies the configuration of a Provider.
properties:
controller:
description: Configuration for the packaged Provider's controller.
properties:
image:
description: Image is the packaged Provider controller image.
type: string
permissionRequests:
description: PermissionRequests for RBAC rules required for this
provider's controller to function. The RBAC manager is responsible
for assessing the requested permissions.
items:
description: PolicyRule holds information that describes a policy
rule, but does not contain information about who the rule
applies to or which namespace the rule applies to.
properties:
apiGroups:
description: APIGroups is the name of the APIGroup that
contains the resources. If multiple API groups are specified,
any action requested against one of the enumerated resources
in any API group will be allowed.
items:
type: string
type: array
nonResourceURLs:
description: NonResourceURLs is a set of partial urls that
a user should have access to. *s are allowed, but only
as the full, final step in the path Since non-resource
URLs are not namespaced, this field is only applicable
for ClusterRoles referenced from a ClusterRoleBinding.
Rules can either apply to API resources (such as "pods"
or "secrets") or non-resource URL paths (such as "/api"), but
not both.
items:
type: string
type: array
resourceNames:
description: ResourceNames is an optional white list of
names that the rule applies to. An empty set means that
everything is allowed.
items:
type: string
type: array
resources:
description: Resources is a list of resources this rule
applies to. '*' represents all resources.
items:
type: string
type: array
verbs:
description: Verbs is a list of Verbs that apply to ALL
the ResourceKinds contained in this rule. '*' represents
all verbs.
items:
type: string
type: array
required:
- verbs
type: object
type: array
type: object
crossplane:
description: Semantic version constraints of Crossplane that package
is compatible with.
properties:
version:
description: Semantic version constraints of Crossplane that package
is compatible with.
type: string
required:
- version
type: object
dependsOn:
description: Dependencies on other packages.
items:
description: Dependency is a dependency on another package. One
of Provider or Configuration may be supplied.
properties:
configuration:
description: Configuration is the name of a Configuration package
image.
type: string
provider:
description: Provider is the name of a Provider package image.
type: string
version:
description: Version is the semantic version constraints of
the dependency image.
type: string
required:
- version
type: object
type: array
required:
- controller
type: object
required:
- spec
type: object
served: true
storage: true
- name: v1alpha1
schema:
openAPIV3Schema:
description: A Provider is the description of a Crossplane Provider package.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: ProviderSpec specifies the configuration of a Provider.
properties:
controller:
description: Configuration for the packaged Provider's controller.
properties:
image:
description: Image is the packaged Provider controller image.
type: string
permissionRequests:
description: PermissionRequests for RBAC rules required for this
provider's controller to function. The RBAC manager is responsible
for assessing the requested permissions.
items:
description: PolicyRule holds information that describes a policy
rule, but does not contain information about who the rule
applies to or which namespace the rule applies to.
properties:
apiGroups:
description: APIGroups is the name of the APIGroup that
contains the resources. If multiple API groups are specified,
any action requested against one of the enumerated resources
in any API group will be allowed.
items:
type: string
type: array
nonResourceURLs:
description: NonResourceURLs is a set of partial urls that
a user should have access to. *s are allowed, but only
as the full, final step in the path Since non-resource
URLs are not namespaced, this field is only applicable
for ClusterRoles referenced from a ClusterRoleBinding.
Rules can either apply to API resources (such as "pods"
or "secrets") or non-resource URL paths (such as "/api"), but
not both.
items:
type: string
type: array
resourceNames:
description: ResourceNames is an optional white list of
names that the rule applies to. An empty set means that
everything is allowed.
items:
type: string
type: array
resources:
description: Resources is a list of resources this rule
applies to. '*' represents all resources.
items:
type: string
type: array
verbs:
description: Verbs is a list of Verbs that apply to ALL
the ResourceKinds contained in this rule. '*' represents
all verbs.
items:
type: string
type: array
required:
- verbs
type: object
type: array
type: object
crossplane:
description: Semantic version constraints of Crossplane that package
is compatible with.
properties:
version:
description: Semantic version constraints of Crossplane that package
is compatible with.
type: string
required:
- version
type: object
dependsOn:
description: Dependencies on other packages.
items:
description: Dependency is a dependency on another package. One
of Provider or Configuration may be supplied.
properties:
configuration:
description: Configuration is the name of a Configuration package
image.
type: string
provider:
description: Provider is the name of a Provider package image.
type: string
version:
description: Version is the semantic version constraints of
the dependency image.
type: string
required:
- version
type: object
type: array
required:
- controller
type: object
required:
- spec
type: object
served: true
storage: false
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -1,6 +0,0 @@
---
title: crossplane
weight: 401
layout: redirect
to: https://doc.crds.dev/github.com/crossplane/crossplane
---

View File

@ -1,147 +0,0 @@
---
title: Adding Amazon Web Services (AWS) to Crossplane
tocHidden: true
---
In this guide, we will walk through the steps necessary to configure your AWS
account to be ready for integration with Crossplane. This will be done by adding
an AWS `ProviderConfig` resource type, which enables Crossplane to communicate with an
AWS account.
## Requirements
Prior to adding AWS to Crossplane, following steps need to be taken
- Crossplane is installed in a k8s cluster
- `provider-aws` is installed in the same cluster
- `kubectl` is configured to communicate with the same cluster
## Step 1: Configure `aws` CLI
Crossplane uses [AWS security credentials], and stores them as a [secret] which
is managed by an AWS `ProviderConfig` instance. In addition, the AWS default region is
also used for targeting a specific region. Crossplane requires to have [`aws`
command line tool] [installed] and [configured]. Once installed, the credentials
and configuration will reside in `~/.aws/credentials` and `~/.aws/config`
respectively.
## Step 2: Setup `aws` ProviderConfig
Run `setup.sh` to read `aws` credentials and region, and create an `aws
provider` instance in Crossplane:
```bash
curl -O https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/configure/aws/providerconfig.yaml
curl -O https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/configure/aws/setup.sh
chmod +x setup.sh
./setup.sh [--profile aws_profile]
```
The `--profile` switch is optional and specifies the [aws named profile] that
was set in Step 1. If not provided, the `default` profile will be selected.
Once the script is successfully executed, Crossplane will use the specified aws
account and region in the given named profile to create subsequent AWS managed
resources.
You can confirm the existence of the AWS `ProviderConfig` by running:
```bash
kubectl get providerconfig default
```
## Optional: Setup AWS Provider Manually
An AWS [user][aws user] with `Administrative` privileges is needed to enable
Crossplane to create the required resources. Once the user is provisioned, an
[Access Key][] needs to be created so the user can have API access.
Using the set of [access key credentials][AWS security credentials] for the user
with the right access, we need to [install][install-aws] [`aws cli`][aws command
line tool], and then [configure][aws-cli-configure] it.
When the AWS cli is configured, the credentials and configuration will be in
`~/.aws/credentials` and `~/.aws/config` respectively. These will be consumed in
the next step.
When configuring the AWS cli, the user credentials could be configured under a
specific [AWS named profile][], or under `default`. Without loss of generality,
in this guide let's assume that the credentials are configured under the
`aws_profile` profile (which could also be `default`). We'll use this profile to
setup cloud provider in the next section.
Crossplane uses the AWS user credentials that were configured in the previous
step to create resources in AWS. These credentials will be stored as a
[secret][kubernetes secret] in Kubernetes, and will be used by an AWS
`ProviderConfig` instance. The default AWS region is also pulled from the cli
configuration, and added to the AWS provider.
To store the credentials as a secret, run:
```bash
# retrieve profile's credentials, save it under 'default' profile, and base64 encode it
BASE64ENCODED_AWS_ACCOUNT_CREDS=$(echo -e "[default]\naws_access_key_id = $(aws configure get aws_access_key_id --profile $aws_profile)\naws_secret_access_key = $(aws configure get aws_secret_access_key --profile $aws_profile)" | base64 | tr -d "\n")
```
Next, we'll need to create an AWS provider configuration:
```bash
cat > provider.yaml <<EOF
---
apiVersion: v1
kind: Secret
metadata:
name: aws-account-creds
namespace: crossplane-system
type: Opaque
data:
creds: ${BASE64ENCODED_AWS_ACCOUNT_CREDS}
---
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-account-creds
key: creds
EOF
# apply it to the cluster:
kubectl apply -f "provider.yaml"
# delete the credentials variable
unset BASE64ENCODED_AWS_ACCOUNT_CREDS
```
The output will look like the following:
```bash
secret/aws-user-creds created
provider.aws.crossplane.io/default created
```
Crossplane resources use the `ProviderConfig` named `default` if no specific
`ProviderConfig` is specified, so this `ProviderConfig` will be the default for
all AWS resources.
<!-- Named Links -->
[`aws` command line tool]: https://aws.amazon.com/cli/
[AWS SDK for GO]: https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/setting-up.html
[installed]: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
[configured]: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
[AWS security credentials]: https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html
[secret]:https://kubernetes.io/docs/concepts/configuration/secret/
[aws named profile]: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
[aws user]: https://docs.aws.amazon.com/mediapackage/latest/ug/setting-up-create-iam-user.html
[Access Key]: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html
[AWS security credentials]: https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html
[aws command line tool]: https://aws.amazon.com/cli/
[install-aws]: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
[aws-cli-configure]: https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html
[kubernetes secret]: https://kubernetes.io/docs/concepts/configuration/secret/
[AWS named profile]: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

View File

@ -1,132 +0,0 @@
---
title: Adding Microsoft Azure to Crossplane
tocHidden: true
---
In this guide, we will walk through the steps necessary to configure your Azure
account to be ready for integration with Crossplane. The general steps we will
take are summarized below:
* Create a new service principal (account) that Crossplane will use to create
and manage Azure resources
* Add the required permissions to the account
* Consent to the permissions using an administrator account
## Preparing your Microsoft Azure Account
In order to manage resources in Azure, you must provide credentials for a Azure
service principal that Crossplane can use to authenticate. This assumes that you
have already [set up the Azure CLI
client](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli?view=azure-cli-latest)
with your credentials.
Create a JSON file that contains all the information needed to connect and
authenticate to Azure:
```bash
# create service principal with Owner role
az ad sp create-for-rbac --sdk-auth --role Owner > crossplane-azure-provider-key.json
```
Take note of the `clientID` value from the JSON file that we just created, and
save it to an environment variable:
```bash
export AZURE_CLIENT_ID=<clientId value from json file>
```
Now add the required permissions to the service principal that will allow it to
manage the necessary resources in Azure:
```bash
# add required Azure Active Directory permissions
az ad app permission add --id ${AZURE_CLIENT_ID} --api 00000002-0000-0000-c000-000000000000 --api-permissions 1cda74f2-2616-4834-b122-5cb1b07f8a59=Role 78c8a3c8-a07e-4b9e-af1b-b5ccab50a175=Role
# grant (activate) the permissions
az ad app permission grant --id ${AZURE_CLIENT_ID} --api 00000002-0000-0000-c000-000000000000 --expires never
```
You might see an error similar to the following, but that is OK, the permissions
should have gone through still:
```console
Operation failed with status: 'Conflict'. Details: 409 Client Error: Conflict for url: https://graph.windows.net/e7985bc4-a3b3-4f37-b9d2-fa256023b1ae/oauth2PermissionGrants?api-version=1.6
```
Finally, you need to grant admin permissions on the Azure Active Directory to
the service principal because it will need to create other service principals
for your `AKSCluster`:
```bash
# grant admin consent to the service princinpal you created
az ad app permission admin-consent --id "${AZURE_CLIENT_ID}"
```
Note: You might need `Global Administrator` role to `Grant admin consent for
Default Directory`. Please contact the administrator of your Azure subscription.
To check your role, go to `Azure Active Directory` -> `Roles and
administrators`. You can find your role(s) by clicking on `Your Role (Preview)`
After these steps are completed, you should have the following file on your
local filesystem:
* `crossplane-azure-provider-key.json`
## Setup Azure ProviderConfig
Before creating any resources, we need to create and configure an Azure cloud
provider resource in Crossplane, which stores the cloud account information in
it. All the requests from Crossplane to Azure Cloud will use the credentials
attached to this provider resource. The following command assumes that you have
a `crossplane-azure-provider-key.json` file that belongs to the account youd
like Crossplane to use.
```bash
BASE64ENCODED_AZURE_ACCOUNT_CREDS=$(base64 crossplane-azure-provider-key.json | tr -d "\n")
```
Now well create our `Secret` that contains the credential and `ProviderConfig`
resource that refers to that secret:
```bash
cat > provider.yaml <<EOF
---
apiVersion: v1
kind: Secret
metadata:
name: azure-account-creds
namespace: crossplane-system
type: Opaque
data:
credentials: ${BASE64ENCODED_AZURE_ACCOUNT_CREDS}
---
apiVersion: azure.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: azure-account-creds
key: credentials
EOF
# apply it to the cluster:
kubectl apply -f "provider.yaml"
# delete the credentials variable
unset BASE64ENCODED_AZURE_ACCOUNT_CREDS
```
The output will look like the following:
```bash
secret/azure-user-creds created
provider.azure.crossplane.io/default created
```
Crossplane resources use the `ProviderConfig` named `default` if no specific
`ProviderConfig` is specified, so this `ProviderConfig` will be the default for
all Azure resources.

View File

@ -1,268 +0,0 @@
---
title: Adding Google Cloud Platform (GCP) to Crossplane
tocHidden: true
---
In this guide, we will walk through the steps necessary to configure your GCP
account to be ready for integration with Crossplane. The general steps we will
take are summarized below:
* Create a new example project that all resources will be deployed to
* Enable required APIs such as Kubernetes and CloudSQL
* Create a service account that will be used to perform GCP operations from
Crossplane
* Assign necessary roles to the service account
* Enable billing
For your convenience, the specific steps to accomplish those tasks are provided
for you below using either the `gcloud` command line tool, or the GCP console in
a web browser. You can choose whichever you are more comfortable with.
## Option 1: gcloud Command Line Tool
If you have the `gcloud` tool installed, you can run the commands below from the
crossplane directory.
Instructions for installing `gcloud` can be found in the [Google
docs](https://cloud.google.com/sdk/install).
### Using `gcp-credentials.sh`
Crossplane provides a helper script for configuring GCP credentials. This script
will prompt you for the organization, project, and billing account that will be
used by `gcloud` when creating a project, service account, and credentials file
(`crossplane-gcp-provider-key.json`). The chosen project and created service
account will have access to the services and roles sufficient to run the
Crossplane GCP examples.
```bash
curl -O https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/configure/gcp/credentials.sh
./credentials.sh
# ... EXAMPLE OUTPUT ONLY
# export ORGANIZATION_ID=987654321
# export PROJECT_ID=crossplane-example-1234
# export EXAMPLE_SA=example-1234@crossplane-example-1234.iam.gserviceaccount.com
# export BASE64ENCODED_GCP_PROVIDER_CREDS=$(base64 crossplane-gcp-provider-key.json | tr -d "\n")
```
After running `gcp-credentials.sh`, a series of `export` commands will be shown.
Copy and paste the `export` commands that are provided. These variable names
will be referenced throughout the Crossplane examples, generally with a `sed`
command.
You will also find a `crossplane-gcp-provider-key.json` file in the current
working directory. Be sure to remove this file when you are done with the
example projects.
### Running `gcloud` by hand
```bash
# list your organizations (if applicable), take note of the specific organization ID you want to use
# if you have more than one organization (not common)
gcloud organizations list
# create a new project (project id must be <=30 characters)
export EXAMPLE_PROJECT_ID=crossplane-example-123
gcloud projects create $EXAMPLE_PROJECT_ID --enable-cloud-apis # [--organization $ORGANIZATION_ID]
# or, record the PROJECT_ID value of an existing project
# export EXAMPLE_PROJECT_ID=$(gcloud projects list --filter NAME=$EXAMPLE_PROJECT_NAME --format="value(PROJECT_ID)")
# link billing to the new project
gcloud beta billing accounts list
gcloud beta billing projects link $EXAMPLE_PROJECT_ID --billing-account=$ACCOUNT_ID
# enable Kubernetes API
gcloud --project $EXAMPLE_PROJECT_ID services enable container.googleapis.com
# enable CloudSQL API
gcloud --project $EXAMPLE_PROJECT_ID services enable sqladmin.googleapis.com
# enable Redis API
gcloud --project $EXAMPLE_PROJECT_ID services enable redis.googleapis.com
# enable Compute API
gcloud --project $EXAMPLE_PROJECT_ID services enable compute.googleapis.com
# enable Service Networking API
gcloud --project $EXAMPLE_PROJECT_ID services enable servicenetworking.googleapis.com
# enable Additional APIs needed for the example or project
# See `gcloud services list` for a complete list
# create service account
gcloud --project $EXAMPLE_PROJECT_ID iam service-accounts create example-123 --display-name "Crossplane Example"
# export service account email
export EXAMPLE_SA="example-123@$EXAMPLE_PROJECT_ID.iam.gserviceaccount.com"
# create service account key (this will create a `crossplane-gcp-provider-key.json` file in your current working directory)
gcloud --project $EXAMPLE_PROJECT_ID iam service-accounts keys create --iam-account $EXAMPLE_SA crossplane-gcp-provider-key.json
# assign roles
gcloud projects add-iam-policy-binding $EXAMPLE_PROJECT_ID --member "serviceAccount:$EXAMPLE_SA" --role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding $EXAMPLE_PROJECT_ID --member "serviceAccount:$EXAMPLE_SA" --role="roles/cloudsql.admin"
gcloud projects add-iam-policy-binding $EXAMPLE_PROJECT_ID --member "serviceAccount:$EXAMPLE_SA" --role="roles/container.admin"
gcloud projects add-iam-policy-binding $EXAMPLE_PROJECT_ID --member "serviceAccount:$EXAMPLE_SA" --role="roles/redis.admin"
gcloud projects add-iam-policy-binding $EXAMPLE_PROJECT_ID --member "serviceAccount:$EXAMPLE_SA" --role="roles/compute.networkAdmin"
gcloud projects add-iam-policy-binding $EXAMPLE_PROJECT_ID --member "serviceAccount:$EXAMPLE_SA" --role="roles/storage.admin"
```
## Option 2: GCP Console in a Web Browser
If you chose to use the `gcloud` tool, you can skip this section entirely.
Create a GCP example project which we will use to host our example GKE cluster,
as well as our example CloudSQL instance.
- Login into [GCP Console](https://console.cloud.google.com)
- Create a [new
project](https://console.cloud.google.com/flows/enableapi?apiid=container.googleapis.com,sqladmin.googleapis.com,redis.googleapis.com)
(either stand alone or under existing organization)
- Create Example Service Account
- Navigate to: [Create Service
Account](https://console.cloud.google.com/iam-admin/serviceaccounts)
- `Service Account Name`: type "example"
- `Service Account ID`: leave auto assigned
- `Service Account Description`: type "Crossplane example"
- Click `Create and Continue` button
- This should advance to the next section `2 Grant this service account to
project (optional)`
- We will assign this account 4 roles:
- `Service Account User`
- `Cloud SQL Admin`
- `Kubernetes Engine Admin`
- `Compute Network Admin`
- Click `Continue` button
- This should advance to the next section `3 Grant users access to this
service account (optional)`
- We don't need to assign any user or admin roles to this account for the
example purposes, so you can leave following two fields blank:
- `Service account users role`
- `Service account admins role`
- Next, we will create and export service account key
- Click `+ Create Key` button.
- This should open a `Create Key` side panel
- Select `json` for the Key type (should be selected by default)
- Click `Create`
- This should show `Private key saved to your computer` confirmation
dialog
- You also should see `crossplane-example-1234-[suffix].json` file in your
browser's Download directory
- Save (copy or move) this file into example (this) directory, with new
name `crossplane-gcp-provider-key.json`
- Enable `Cloud SQL API`
- Navigate to [Cloud SQL Admin
API](https://console.developers.google.com/apis/api/sqladmin.googleapis.com/overview)
- Click `Enable`
- Enable `Kubernetes Engine API`
- Navigate to [Kubernetes Engine
API](https://console.developers.google.com/apis/api/container.googleapis.com/overview)
- Click `Enable`
- Enable `Cloud Memorystore for Redis`
- Navigate to [Cloud Memorystore for
Redis](https://console.developers.google.com/apis/api/redis.googleapis.com/overview)
- Click `Enable`
- Enable `Compute Engine API`
- Navigate to [Compute Engine
API](https://console.developers.google.com/apis/api/compute.googleapis.com/overview)
- Click `Enable`
- Enable `Service Networking API`
- Navigate to [Service Networking
API](https://console.developers.google.com/apis/api/servicenetworking.googleapis.com/overview)
- Click `Enable`
### Enable Billing
You will need to enable billing for your account in order to create and use
Kubernetes clusters with GKE.
- Go to [GCP Console](https://console.cloud.google.com)
- Select example project
- Click `Enable Billing`
- Go to [Kubernetes Clusters](https://console.cloud.google.com/kubernetes/list)
- Click `Enable Billing`
## Setup GCP ProviderConfig
Before creating any resources, we need to create and configure a GCP cloud
`ProviderConfig` resource in Crossplane, which stores the cloud account
information in it. All the requests from Crossplane to GCP will use the
credentials attached to this `ProviderConfig` resource. The following command
assumes that you have a `crossplane-gcp-provider-key.json` file that belongs to
the account that will be used by Crossplane, which has GCP project id. You
should be able to get the project id from the JSON credentials file or from the
GCP console. Without loss of generality, let's assume the project id is
`my-cool-gcp-project` in this guide.
First, let's encode the credential file contents and put it in a variable:
```bash
# base64 encode the GCP credentials
BASE64ENCODED_GCP_PROVIDER_CREDS=$(base64 crossplane-gcp-provider-key.json | tr -d "\n")
```
Next, store the project ID of the GCP project in which you would like to
provision infrastructure as a variable:
```bash
# replace this with your own gcp project id
PROJECT_ID=my-cool-gcp-project
```
Finally, store the namespace in which you want to save the provider's secret as
a variable:
```bash
# change this namespace value if you want to use a different namespace (e.g. gitlab-managed-apps)
PROVIDER_SECRET_NAMESPACE=crossplane-system
```
Now well create the `Secret` resource that contains the credential, and
`ProviderConfig` resource which refers to that secret:
```bash
cat > provider.yaml <<EOF
---
apiVersion: v1
kind: Secret
metadata:
name: gcp-account-creds
namespace: ${PROVIDER_SECRET_NAMESPACE}
type: Opaque
data:
creds: ${BASE64ENCODED_GCP_PROVIDER_CREDS}
---
apiVersion: gcp.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
# replace this with your own gcp project id
projectID: ${PROJECT_ID}
credentials:
source: Secret
secretRef:
namespace: ${PROVIDER_SECRET_NAMESPACE}
name: gcp-account-creds
key: creds
EOF
# apply it to the cluster:
kubectl apply -f "provider.yaml"
# delete the credentials
unset BASE64ENCODED_GCP_PROVIDER_CREDS
```
The output will look like the following:
```bash
secret/gcp-account-creds created
provider.gcp.crossplane.io/default created
```
Crossplane resources use the `ProviderConfig` named `default` if no specific
`ProviderConfig` is specified, so this `ProviderConfig` will be the default for
all GCP resources.

View File

@ -1,250 +0,0 @@
---
title: Composite Resources
weight: 103
---
Crossplane Composite Resources are opinionated Kubernetes Custom Resources that
are _composed_ of [Managed Resources][managed-resources]. We often call them XRs
for short.
![Diagram of claims, XRs, and Managed Resources][xrs-and-mrs]
Composite Resources are designed to let you build your own platform with your
own opinionated concepts and APIs without needing to write a Kubernetes
controller from scratch. Instead, you define the schema of your XR and teach
Crossplane which Managed Resources it should compose (i.e. create) when someone
creates the XR you defined.
If you're already familiar with Composite Resources and looking for a detailed
configuration reference or some tips, tricks, and troubleshooting information,
try the [Composition Reference][xr-ref].
Below is an example of a Composite Resource:
```yaml
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
metadata:
name: my-db
spec:
parameters:
storageGB: 20
compositionRef:
name: production
writeConnectionSecretToRef:
namespace: crossplane-system
name: my-db-connection-details
```
You define your own XRs, so they can be of whatever API version and kind you
like, and contain whatever spec and status fields you need.
## How It Works
The first step towards using Composite Resources is configuring Crossplane so
that it knows what XRs you'd like to exist, and what to do when someone creates
one of those XRs. This is done using a `CompositeResourceDefinition` (XRD)
resource and one or more `Composition` resources.
Once you've configured Crossplane with the details of your new XR you can either
create one directly, or use a _claim_. Typically only the folks responsible for
configuring Crossplane (often a platform or SRE team) have permission to create
XRs directly. Everyone else manages XRs via a lightweight proxy resource called
a Composite Resource Claim (or claim for short). More on that later.
![Diagram combining all Composition concepts][how-it-works]
> If you're coming from the Terraform world you can think of an XRD as similar
> to the `variable` blocks of a Terraform module, while the `Composition` is
> the rest of the module's HCL code that describes how to use those variables to
> create a bunch of resources. In this analogy the XR or claim is a little like
> a `tfvars` file providing inputs to the module.
### Defining Composite Resources
A `CompositeResourceDefinition` (or XRD) defines the type and schema of your XR.
It lets Crossplane know that you want a particular kind of XR to exist, and what
fields that XR should have. An XRD is a little like a `CustomResourceDefinition`
(CRD), but slightly more opinionated. Writing an XRD is mostly a matter of
specifying an OpenAPI ["structural schema"][crd-docs].
The XRD that defines the `XPostgreSQLInstance` XR above would look like this:
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
required:
- parameters
```
You might notice that the `XPostgreSQLInstance` example above has some fields
that don't appear in the XRD, like the `writeConnectionSecretToRef` and
`compositionRef` fields. This is because Crossplane automatically injects some
standard Crossplane Resource Model (XRM) fields into all XRs.
### Configuring Composition
A `Composition` lets Crossplane know what to do when someone creates a Composite
Resource. Each `Composition` creates a link between an XR and a set of one or
more Managed Resources - when the XR is created, updated, or deleted the set of
Managed Resources are created, updated or deleted accordingly.
You can add multiple Compositions for each XRD, and choose which should be used
when XRs are created. This allows a Composition to act like a class of service -
for example you could configure one Composition for each environment you
support, such as production, staging, and development.
A basic `Composition` for the above `XPostgreSQLInstance` might look like this:
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example
labels:
crossplane.io/xrd: xpostgresqlinstances.database.example.org
provider: gcp
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: cloudsqlinstance
base:
apiVersion: database.gcp.crossplane.io/v1beta1
kind: CloudSQLInstance
spec:
forProvider:
databaseVersion: POSTGRES_12
region: us-central1
settings:
tier: db-custom-1-3840
dataDiskType: PD_SSD
ipConfiguration:
ipv4Enabled: true
authorizedNetworks:
- value: "0.0.0.0/0"
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.storageGB
toFieldPath: spec.forProvider.settings.dataDiskSizeGb
```
The above `Composition` tells Crossplane that when someone creates an
`XPostgreSQLInstance` XR Crossplane should create a `CloudSQLInstance` in
response. The `storageGB` field of the `XPostgreSQLInstance` should be used to
configure the `dataDiskSizeGb` field of the `CloudSQLInstance`. This is only a
small subset of the functionality a `Composition` enables - take a look at the
[reference page][xr-ref] to learn more.
> We almost always talk about XRs composing Managed Resources, but actually an
> XR can also compose other XRs to allow nested layers of abstraction. XRs don't
> support composing arbitrary Kubernetes resources (e.g. Deployments, operators,
> etc) directly but you can do so using our [Kubernetes][provider-kubernetes]
> and [Helm][provider-helm] providers.
### Claiming Composite Resources
Crossplane uses Composite Resource Claims (or just claims, for short) to allow
application operators to provision and manage XRs. When we talk about using XRs
it's typically implied that the XR is being used via a claim. Claims are almost
identical to their corresponding XRs. It helps to think of a claim as an
application teams interface to an XR. You could also think of claims as the
public (app team) facing part of the opinionated platform API, while XRs are the
private (platform team) facing part.
A claim for the `XPostgreSQLInstance` XR above would look like this:
```yaml
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
namespace: default
name: my-db
spec:
parameters:
storageGB: 20
compositionRef:
name: production
writeConnectionSecretToRef:
name: my-db-connection-details
```
There are three key differences between an XR and a claim:
1. Claims are namespaced, while XRs (and Managed Resources) are cluster scoped.
1. Claims are of a different `kind` than the XR - by convention the XR's `kind`
without the proceeding `X`. For example a `PostgreSQLInstance` claims an
`XPostgreSQLInstance`.
1. An active claim contains a reference to its corresponding XR, while an XR
contains both a reference to the claim an array of references to the managed
resources it composes.
Not all XRs offer a claim - doing so is optional. See the XRD section of the
[Composition reference][xr-ref] to learn how to offer a claim.
![Diagram showing the relationship between claims and XRs][claims-and-xrs]
Claims may seem a little superfluous at first, but they enable some handy
scenarios, including:
- **Private XRs.** Sometimes a platform team might not want a type of XR to be
directly consumed by their application teams. For example because the XR
represents 'supporting' infrastructure - consider the above VPC `XNetwork` XR. App
teams might create `PostgreSQLInstance` claims that _reference_ (i.e. consume)
an `XNetwork`, but they shouldn't be _creating their own_. Similarly, some
kinds of XR might be intended only for 'nested' use - intended only to be
composed by other XRs.
- **Global XRs**. Not all infrastructure is conceptually namespaced. Say your
organisation uses team scoped namespaces. A `PostgreSQLInstance` that belongs
to Team A should probably be part of the `team-a` namespace - you'd represent
this by creating a `PostgreSQLInstance` claim in that namespace. On the other
hand the `XNetwork` XR we mentioned previously could be referenced (i.e. used)
by XRs from many different namespaces - it doesn't exist to serve a particular
team.
- **Pre-provisioned XRs**. Finally, separating claims from XRs allows a platform
team to pre-provision certain kinds of XR. Typically an XR is created
on-demand in response to the creation of a claim, but it's also possible for a
claim to instead request an existing XR. This can allow application teams to
instantly claim infrastructure like database instances that would otherwise
take minutes to provision on-demand.
[managed-resources]: {{<ref "managed-resources" >}}
[xrs-and-mrs]: /media/composition-xrs-and-mrs.svg
[xr-ref]: {{<ref "../reference/composition" >}}
[how-it-works]: /media/composition-how-it-works.svg
[crd-docs]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
[provider-kubernetes]: https://marketplace.upbound.io/providers/crossplane-contrib/provider-kubernetes
[provider-helm]: https://marketplace.upbound.io/providers/crossplane-contrib/provider-helm/
[claims-and-xrs]: /media/composition-claims-and-xrs.svg

View File

@ -1,17 +0,0 @@
---
title: Contributing
weight: 1000
---
The best place to start if you're thinking about contributing to Crossplane is
our [`CONTRIBUTING.md`] file. The following documents supplement that guide.
1. [Provider Development Guide]
2. [Observability Developer Guide]
3. [Release Process]
[`CONTRIBUTING.md`]: https://github.com/crossplane/crossplane/blob/master/CONTRIBUTING.md
[Provider Development Guide]: {{<ref "provider_development_guide" >}}
[Observability Developer Guide]: {{<ref "observability_developer_guide" >}}
[Release Process]: {{<ref "release-process" >}}

View File

@ -1,135 +0,0 @@
---
title: Adding Secret Store Support
weight: 1004
---
To add support for [External Secret Stores] in a provider, we need the following
changes at a high level:
1. Bump Crossplane Runtime and Crossplane Tools to latest and generate existing
resources to include `PublishConnectionDetails` API.
2. Add a new Type and CRD for Secret StoreConfig.
3. Add feature flag for enabling External Secret Store support.
4. Add Secret Store Connection Details Manager as a `ConnectionPublisher` if
feature enabled.
In this document, we will go through each step in details. You can check
[this PR as a complete example].
> If your provider is a Terrajet based provider, then please check
> [this PR instead].
## Steps
**1. Bump Crossplane Runtime and Crossplane Tools to latest and generate
existing resources to include `PublishConnectionDetails` API.**
We need a workaround for code generation since latest runtime both adds new API
but also adds a new interface to managed.resourceSpec. Without this workaround,
expect errors similar to below:
```console
16:40:56 [ .. ] go generate darwin_amd64
angryjet: error: error loading packages using pattern ./...: /Users/hasanturken/ Workspace/crossplane/provider-gcp/apis/cache/v1beta1/zz_ generated.managedlist.go:27:14: cannot use &l.Items[i] (value of type * CloudMemorystoreInstance) as "github.com/crossplane/crossplane-runtime/pkg/ resource".Managed value in assignment: missing method GetPublishConnectionDetailsTo
exit status 1
apis/generate.go:30: running "go": exit status 1
16:41:04 [FAIL]
make[1]: *** [go.generate] Error 1
make: *** [generate] Error 2
```
First, we need to consume a temporary runtime version together with the latest
Crossplane Tools:
```shell
go mod edit -replace=github.com/crossplane/crossplane-runtime=github.com/turkenh/crossplane-runtime@v0.0.0-20220314141040-6f74175d3c1f
go get github.com/crossplane/crossplane-tools@master
go mod tidy
```
Then, remove `trivialVersions=true` in the file `api/generate.go`:
```diff
-//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./... crd:trivialVersions=true,crdVersions=v1 output:artifacts:config=../package/crds
+//go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./... crd:crdVersions=v1 output:artifacts:config=../package/crds
```
Now, we can generate CRDs with `PublishConnectionDetailsTo` API:
```shell
make generate
```
Finally, we can revert our workaround by consuming the latest Crossplane
Runtime:
```shell
go mod edit -dropreplace=github.com/crossplane/crossplane-runtime
go get github.com/crossplane/crossplane-runtime@master
go mod tidy
make generate
```
**2. Add a new Type and CRD for Secret StoreConfig.**
See [this commit as an example on how to add the type]. It is expected to be
almost same for all providers except groupName which includes the name short
name of the provider (e.g. `gcp.crossplane.io`)
Generate the CRD with:
```shell
make generate
```
**3. Add feature flag for enabling External Secret Store support.**
We will add a feature flag to enable the feature which would be off by default.
As part of this step, we will also create a `default` `StoreConfig` during
provider start up, which stores connection secrets into the same Kubernetes
cluster.
To be consistent across all providers, please define
`--enable-external-secret-stores` as a boolean which is false by default.
See [this commit as an example for adding the feature flag].
**4. Add Secret Store Connection Details Manager as a `ConnectionPublisher` if
feature enabled.**
Add the following to the Setup function controller. Unfortunately this step
requires some dirty work as we need to this for all types:
```diff
func SetupServiceAccountKey(mgr ctrl.Manager, o controller.Options) error {
name := managed.ControllerName(v1alpha1.ServiceAccountKeyGroupKind)
+ cps := []managed.ConnectionPublisher{managed.NewAPISecretPublisher(mgr.GetClient(), mgr.GetScheme())}
+ if o.Features.Enabled(features.EnableAlphaExternalSecretStores) {
+ cps = append(cps, connection.NewDetailsManager(mgr.GetClient(), scv1alpha1.StoreConfigGroupVersionKind))
+ }
+
r := managed.NewReconciler(mgr,
resource.ManagedKind(v1alpha1.ServiceAccountKeyGroupVersionKind),
managed.WithInitializers(),
managed.WithExternalConnecter(&serviceAccountKeyServiceConnector{client: mgr.GetClient()}),
managed.WithPollInterval(o.PollInterval),
managed.WithLogger(o.Logger.WithValues("controller", name)),
- managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))
+ managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))),
+ managed.WithConnectionPublishers(cps...))
return ctrl.NewControllerManagedBy(mgr).
Named(name).
```
You can check [this commit as an example for changes in Setup functions] as an
example.
[External Secret Stores]: https://github.com/crossplane/crossplane/blob/master/design/design-doc-external-secret-stores.md
[this PR as a complete example]: https://github.com/crossplane/provider-gcp/pull/421
[this PR instead]: https://github.com/crossplane-contrib/provider-jet-template/pull/23/commits
[this commit as an example on how to add the type]: https://github.com/crossplane-contrib/provider-aws/pull/1242/commits/d8a2df323fa2489d82bf1843d2fe338de033c61d
[this commit as an example for adding the feature flag]: https://github.com/crossplane/provider-gcp/pull/421/commits/b5898c62dc6668d9918496de8aa9bc365c371f82
[this commit as an example for changes in Setup functions]: https://github.com/crossplane/provider-gcp/pull/421/commits/9700d0c4fdb7e1fba8805afa309c1b1c7aa167a6

View File

@ -1,194 +0,0 @@
---
title: Observability Developer Guide
weight: 1002
---
## Introduction
Observability is crucial to Crossplane users; both those operating Crossplane
and those using Crossplane to operate their infrastructure. Crossplane currently
approaches observability via Kubernetes events and structured logs.
## Goals
In short, a non-admin user and an admin user should both be able to debug any
issues only by inspecting logs and events. There should be no need to rebuild
the Crossplane binary or to reach out to a Crossplane developer.
A user should be able to:
* Debug an issue without rebuilding the Crossplane binary
* Understand an issue without contacting a cluster admin
* Ask a cluster admin to check the logs for more details about the reason the
issue happened, if the details are not part of the error message
A cluster admin should be able to:
* Debug an issue without rebuilding the Crossplane binary
* Debug an issue only by looking at the logs
* Debug an issue without needing to contact a Crossplane developer
## Error reporting in the logs
Error reporting in the logs is mostly intended for consumption by Crossplane
cluster admins. A cluster admin should be able to debug any issue by inspecting
the logs, without needing to add more logs themselves or contact a Crossplane
developer. This means that logs should contain:
* Error messages, at either the info or debug level as contextually appropriate
* Any context leading up to an error, typically at debug level, so that the
errors can be debugged
## Error reporting as events
Error reporting as Kubernetes events is primarily aimed toward end-users of
Crossplane who are not cluster admins. Crossplane typically runs as a Kubernetes
pod, and thus it is unlikely that most users of Crossplane will have access to
its logs. [Events], on the other hand, are available as top-level Kubernetes
objects, and show up the objects they relate to when running `kubectl describe`.
Events should be recorded in the following cases:
* A significant operation is taken on a resource
* The state of a resource is changed
* An error occurs
The events recorded in these cases can be thought of as forming an event log of
things that happen for the resources that Crossplane manages. Each event should
refer back to the relevant controller and resource, and use other fields of the
Event kind as appropriate.
More details about examples of how to interact with events can be found in the
guide to [debugging an application cluster].
## Choosing between methods of error reporting
There are many ways to report errors, such as:
* Metrics
* Events
* Logging
* Tracing
It can be confusing to figure out which one is appropriate in a given situation.
This section will try to offer advice and a mindset that can be used to help
make this decision.
Let's set the context by listing the different user scenarios where error
reporting may be consumed. Here are the typical scenarios as we imagine them:
1. A person **using** a system needs to figure out why things aren't working as
expected, and whether they made a mistake that they can correct.
2. A person **operating** a service needs to monitor the service's **health**,
both now and historically.
3. A person **debugging** a problem which happened in a **live environment**
(often an **operator** of the system) needs information to figure out what
happened.
4. A person **developing** the software wants to **observe** what is happening.
5. A person **debugging** the software in a **development environment**
(typically a **developer** of the system) wants to debug a problem (there is
a lot of overlap between this and the live environment debugging scenario).
The goal is to satisfy the users in all of the scenarios. We'll refer to the
scenarios by number.
The short version is: we should do whatever satisfies all of the scenarios.
Logging and events are the recommendations for satisfying the scenarios,
although they don't cover scenario 2.
The longer version is:
* Scenario 1 is best served by events in the context of Crossplane, since the
users may not have access to read logs or metrics, and even if they did, it
would be hard to relate them back to the event the user is trying to
understand.
* Scenario 2 is best served by metrics, because they can be aggregated and
understood as a whole. And because they can be used to track things over time.
* Scenario 3 is best served by either logging that contains all the information
about and leading up to the event. Request-tracing systems are also useful for
this scenario.
* Scenario 4 is usually logs, maybe at a more verbose level than normal. But it
could be an attached debugger or some other type of tool. It could also be a
test suite.
* Scenario 5 is usually either logs, up to the highest imaginable verbosity, or
an attached debugging session. If there's a gap in reporting, it could involve
adding some print statements to get more logging.
As for the question of how to decide whether to log or not, we believe it helps
to try to visualize which of the scenarios the error or information in question
will be used for. We recommend starting with reporting as much information as
possible, but with configurable runtime behavior so that, for example, debugging
logs don't show up in production normally.
For the question of what constitutes an error, errors should be actionable by a
human. See the [Dave Cheney article] on this topic for some more discussion.
## In Practice
Crossplane provides two observability libraries as part of crossplane-runtime:
* [`event`] emits Kubernetes events.
* [`logging`] produces structured logs. Refer to its package documentation for
additional context on its API choices.
Keep the following in mind when using the above libraries:
* [Do] [not] use package level loggers or event recorders. Instantiate them in
`main()` and plumb them down to where they're needed.
* Each [`Reconciler`] implementation should use its own `logging.Logger` and
`event.Recorder`. Implementations are strongly encouraged to default to using
`logging.NewNopLogger()` and `event.NewNopRecorder()`, and accept a functional
loggers and recorder via variadic options. See for example the [managed
resource reconciler].
* Each controller should use its name as its event recorder's name, and include
its name under the `controller` structured logging key. The controllers name
should be of the form `controllertype/resourcekind`, for example
`managed/cloudsqlinstance` or `stacks/stackdefinition`. Controller names
should always be lowercase.
* Logs and events should typically be emitted by the `Reconcile` method of the
`Reconciler` implementation; not by functions called by `Reconcile`. Author
the methods orchestrated by `Reconcile` as if they were a library; prefer
surfacing useful information for the `Reconciler` to log (for example by
[wrapping errors]) over plumbing loggers and event recorders down to
increasingly deeper layers of code.
* Almost nothing is worth logging at info level. When deciding which logging
level to use, consider a production deployment of Crossplane reconciling tens
or hundreds of managed resources. If in doubt, pick debug. You can easily
increase the log level later if it proves warranted.
* The above is true even for errors; consider the audience. Is this an error
only the Crossplane cluster operator can fix? Does it indicate a significant
degradation of Crossplane's functionality? If so, log it at info. If the error
pertains to a single Crossplane resource emit an event instead.
* Always log errors under the structured logging key `error` (e.g.
`log.Debug("boom!, "error", err)`). Many logging implementations (including
Crossplane's) add context like stack traces for this key.
* Emit events liberally; they're rate limited and deduplicated.
* Follow [API conventions] when emitting events; ensure event reasons are unique
and `CamelCase`.
* Consider emitting events and logs when a terminal condition is encountered
(e.g. `Reconcile` returns) over logging logic flow. i.e. Prefer one log line
that reads "encountered an error fooing the bar" over two log lines that read
"about to foo the bar" and "encountered an error". Recall that if the audience
is a developer debugging Crossplane they will be provided a stack trace with
file and line context when an error is logged.
* Consider including the `reconcile.Request`, and the resource's UID and
resource version (not API version) under the keys `request`, `uid`, and
`version`. Doing so allows log readers to determine what specific version of a
resource the log pertains to.
Finally, when in doubt, aim for consistency with existing Crossplane controller
implementations.
<!-- Named Links -->
[Events]: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.21/#event-v1-core
[debugging an application cluster]: https://kubernetes.io/docs/tasks/debug-application-cluster/
[Dave Cheney article]: https://dave.cheney.net/2015/11/05/lets-talk-about-logging
[`event`]: https://godoc.org/github.com/crossplane/crossplane-runtime/pkg/event
[`logging`]: https://godoc.org/github.com/crossplane/crossplane-runtime/pkg/logging
[Do]: https://peter.bourgon.org/go-best-practices-2016/#logging-and-instrumentation
[not]: https://dave.cheney.net/2017/01/23/the-package-level-logger-anti-pattern
[`Reconciler`]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/reconcile#Reconciler
[managed resource reconciler]: https://github.com/crossplane/crossplane-runtime/blob/a6bb0/pkg/reconciler/managed/reconciler.go#L436
[wrapping errors]: https://godoc.org/github.com/pkg/errors#Wrap
[API conventions]: https://github.com/kubernetes/community/blob/09f55c6/contributors/devel/sig-architecture/api-conventions.md#events

View File

@ -1,657 +0,0 @@
---
title: Provider Development Guide
weight: 1001
---
Crossplane allows you to manage infrastructure directly from Kubernetes. Each
infrastructure API resource that Crossplane orchestrates is known as a "managed
resource". This guide will walk through the process of adding support for a new
kind of managed resource to a Crossplane Provider.
> You can watch [TBS Episode 18] to follow along the live implementation of GCP PubSub
managed resource.
> If there is a corresponding Terraform Provider, please consider generating
a Crossplane Provider with [Terrajet] by following the
[Generating a Crossplane Provider guide].
> If you plan to implement a managed resource for AWS, please see the
[code generation guide].
## What Makes a Crossplane Infrastructure Resource
Crossplane builds atop Kubernetes's powerful architecture in which declarative
configuration, known as resources, are continually 'reconciled' with reality by
one or more controllers. A controller is an endless loop that:
1. Observes the desired state (the declarative configuration resource).
1. Observes the actual state (the thing said configuration resource represents).
1. Tries to make the actual state match the desired state.
Typical Crossplane managed infrastructure consists of two configuration
resources and one controller. The GCP Provider's support for Google Cloud
Memorystore illustrates this. First, the configuration resources:
1. A [managed resource]. Managed resources are cluster scoped, high-fidelity
representations of a resource in an external system such as a cloud
provider's API. Managed resources are _non-portable_ across external systems
(i.e. cloud providers); they're tightly coupled to the implementation details
of the external resource they represent. Managed resources are defined by a
Provider. The GCP Provider's [`CloudMemorystoreInstance`] resource is an
example of a managed resource.
1. A provider. Providers enable access to an external system, typically by
indicating a Kubernetes Secret containing any credentials required to
authenticate to the system, as well as any other metadata required to
connect. Providers are cluster scoped, like managed resources and classes.
The GCP [`ProviderConfig`] is an example of a provider. Note that provider is a
somewhat overloaded term in the Crossplane ecosystem - it's also used to
refer to the controller manager for a particular cloud, for example
`provider-gcp`.
A managed resource is powered by a controller. This controller is responsible
for taking instances of the aforementioned high-fidelity managed resource kind
and reconciling them with an external system. The `CloudMemorystoreInstance`
controller watches for changes to `CloudMemorystoreInstance` resources and calls
Google's Cloud Memorystore API to create, update, or delete an instance as
necessary.
Crossplane does not require controllers to be written in any particular
language. The Kubernetes API server is our API boundary, so any process capable
of [watching the API server] and updating resources can be a Crossplane
controller.
## Getting Started
At the time of writing all Crossplane Services controllers are written in Go,
and built using [crossplane-runtime]. While it is possible to write a controller
using any language and tooling with a Kubernetes client this set of tools are
the "[golden path]". They're well supported, broadly used, and provide a shared
language with the Crossplane community. This guide targets [crossplane-runtime
v0.9.0]. It assumes the reader is familiar with the Kubernetes [API Conventions]
and the [kubebuilder book].
> If you are building a new provider from scratch, instead of adding new
resources to an already existing one, please use [provider-template] repository
as a template by hitting the `Use this template` button in GitHub UI. It
codifies most of the best practices used by the Crossplane community so far and
is the easiest way to start a new provider.
## Defining Resource Kinds
Let's assume we want to add Crossplane support for your favourite cloud's
database-as-a-service. Your favourite cloud brands these instances as "Favourite
DB instances". Under the hood they're powered by the open source FancySQL
engine. We'll name the new managed resource kind `FavouriteDBInstance`.
The first step toward implementing a new managed service is to define the code
level schema of its configuration resources. These are referred to as
[resources], (resource) [kinds], and [objects] interchangeably. The kubebuilder
scaffolding is a good starting point for any new Crossplane API kind.
> Note that while Crossplane was originally derived from kubebuilder scaffolds
> its patterns have diverged somewhat. It is _possible_ to use kubebuilder to
> scaffold a resource, but the author must be careful to adapt said resource to
> Crossplane patterns. It may often be quicker to copy and modify a v1beta1 or
> above resource from the same provider repository, rather than using
> kubebuilder.
```console
kubebuilder create api \
--group example --version v1alpha1 --kind FavouriteDBInstance \
--resource=true --controller=false --namespaced=false
```
The above command should produce a scaffold similar to the below example:
```go
type FavouriteDBInstanceSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of infrastructure
// Important: Run "make" to regenerate code after modifying this file
}
// FavouriteDBInstanceStatus defines the observed state of FavouriteDBInstance
type FavouriteDBInstanceStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of infrastructure
// Important: Run "make" to regenerate code after modifying this file
}
// +kubebuilder:object:root=true
// FavouriteDBInstance is the Schema for the favouritedbinstance API
// +kubebuilder:resource:scope=Cluster
type FavouriteDBInstance struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec FavouriteDBInstanceeSpec `json:"spec,omitempty"`
Status FavouriteDBInstanceStatus `json:"status,omitempty"`
}
```
Crossplane requires that these newly generated API type scaffolds be extended
with a set of struct fields, getters, and setters that are standard to all
Crossplane resource kinds. The getters and setter methods required to satisfy
crossplane-runtime interfaces are omitted from the below examples for brevity.
They can be added by hand, but new services are encouraged to use [`angryjet`]
to generate them automatically using a `//go:generate` comment per the
[`angryjet` documentation].
Note that in many cases a suitable provider will already exist. Frequently
adding support for a new managed service requires only the definition of the
managed resource itself.
### Managed Resource Kinds
Managed resources must:
* Satisfy crossplane-runtime's [`resource.Managed`] interface.
* Embed a [`ResourceStatus`] struct in their `Status` struct.
* Embed a [`ResourceSpec`] struct in their `Spec` struct.
* Embed a `Parameters` struct in their `Spec` struct.
* Use the `+kubebuilder:subresource:status` [comment marker].
* Use the `+kubebuilder:resource:scope=Cluster` [comment marker].
The `Parameters` struct should be a _high fidelity_ representation of the
writeable fields of the external resource's API. Put otherwise, if your
favourite cloud represents Favourite DB instances as a JSON object then
`FavouriteDBParameters` should marshal to a something as close to that JSON
object as possible while still complying with Kubernetes API conventions.
For example, assume the external API object for Favourite DB instance was:
```json
{
"id": 42,
"name": "mycoolinstance",
"fanciness_level": 100,
"version": "2.3",
"status": "ONLINE",
"hostname": "cool.fcp.example.org"
}
```
Further assume the `id`, `status`, and `hostname` fields were output only, and
the `version` field was optional. The `FavouriteDBInstance` managed resource
should look as follows:
```go
// FavouriteDBInstanceParameters define the desired state of an FavouriteDB
// instance. Most fields map directly to an Instance:
// https://favourite.example.org/api/v1/db#Instance
type FavouriteDBInstanceParameters struct {
// We're still working on a standard for naming external resources. See
// https://github.com/crossplane/crossplane/issues/624 for context.
// Name of this instance.
Name string `json:"name"`
// Note that fanciness_level becomes fancinessLevel below. Kubernetes API
// conventions trump cloud provider fidelity.
// FancinessLevel specifies exactly how fancy this instance is.
FancinessLevel int `json:"fancinessLevel"`
// Version specifies what version of FancySQL this instance will run.
// +optional
Version *string `json:"version,omitempty"`
}
// A FavouriteDBInstanceSpec defines the desired state of a FavouriteDBInstance.
type FavouriteDBInstanceSpec struct {
xpv1.ResourceSpec `json:",inline"`
ForProvider FavouriteDBInstanceParameters `json:"forProvider"`
}
// A FavouriteDBInstanceStatus represents the observed state of a
// FavouriteDBInstance.
type FavouriteDBInstanceStatus struct {
xpv1.ResourceStatus `json:",inline"`
// Note that we add the three "output only" fields here in the status,
// instead of the parameters. We want this representation to be high
// fidelity just like the parameters.
// ID of this instance.
ID int `json:"id,omitempty"`
// Status of this instance.
Status string `json:"status,omitempty"`
// Hostname of this instance.
Hostname string `json:"hostname,omitempty"`
}
// A FavouriteDBInstance is a managed resource that represents a Favourite DB
// instance.
// +kubebuilder:subresource:status
type FavouriteDBInstance struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec FavouriteDBInstanceSpec `json:"spec"`
Status FavouriteDBInstanceStatus `json:"status,omitempty"`
}
```
Note that Crossplane uses the GoDoc strings of API kinds to generate user facing
API documentation. __Document all fields__ and prefer GoDoc that assumes the
reader is running `kubectl explain`, or reading an API reference, not reading
the code. Refer to the [Managed Resource API Patterns] one pager for more detail
on authoring high fidelity managed resources.
### Provider Kinds
You'll typically only need to add a new Provider kind if you're creating an
infrastructure provider that adds support for a new infrastructure provider.
Providers must:
* Be named exactly `ProviderConfig`.
* Embed a [`ProviderSpec`] struct in their `Spec` struct.
* Use the `+kubebuilder:resource:scope=Cluster` [comment marker].
The Favourite Cloud `ProviderConfig` would look as follows. Note that the cloud to
which it belongs should be indicated by its API group, i.e. its API Version
would be `favouritecloud.crossplane.io/v1alpha1` or similar.
```go
// A ProviderSpec defines the desired state of a Provider.
type ProviderSpec struct {
xpv1.ProviderSpec `json:",inline"`
// Information required outside of the Secret referenced in the embedded
// xpv1.ProviderSpec that is required to authenticate to the provider.
// ProjectID is used as an example here.
ProjectID string `json:"projectID"`
}
// A Provider configures a Favourite Cloud 'provider', i.e. a connection to a
// particular Favourite Cloud project using a particular Favourite Cloud service
// account.
type Provider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ProviderSpec `json:"spec"`
}
```
### Finishing Touches
At this point we've defined the managed resource necessary to start
building controllers. Before moving on to the controllers:
* Add any kubebuilder [comment markers] that may be useful for your resource.
Comment markers can be used to validate input, or add additional columns to
the standard `kubectl get` output, among other things.
* Run `make reviewable` to generate Custom Resource Definitions and additional
helper methods for your new resource kinds.
* Make sure any package documentation (i.e. `// Package v1alpha1...` GoDoc,
including package level comment markers) are in a file named `doc.go`.
kubebuilder adds them to `groupversion_info.go`, but several code generation
tools only check `doc.go`.
Finally, add convenience [`GroupVersionKind`] variables for each new resource
kind. These are typically added to either `register.go` or
`groupversion_info.go` depending on which version of kubebuilder scaffolded the
API type:
```go
// FavouriteDBInstance type metadata.
var (
FavouriteDBInstanceKind = reflect.TypeOf(FavouriteDBInstance{}).Name()
FavouriteDBInstanceKindAPIVersion = FavouriteDBInstanceKind + "." + GroupVersion.String()
FavouriteDBInstanceGroupVersionKind = GroupVersion.WithKind(FavouriteDBInstanceKind)
)
```
Consider opening a draft pull request and asking a Crossplane maintainer for
review before you start work on the controller!
## Adding Controllers
Crossplane controllers, like those scaffolded by kubebuilder, are built around
the [controller-runtime] library. controller-runtime flavoured controllers
encapsulate most of their domain-specific logic in a [`reconcile.Reconciler`]
implementation. Most Crossplane controllers are one of the three kinds mentioned
under [What Makes a Crossplane Infrastructure Resource]. Each of these controller kinds
are similar enough across implementations that [crossplane-runtime] provides
'default' reconcilers. These reconcilers encode what the Crossplane community
has learned about managing external systems and narrow the problem space from
reconciling a Kubernetes resource kind with an arbitrary system down to
Crossplane-specific tasks.
crossplane-runtime provides the following `reconcile.Reconcilers`:
* The [`managed.Reconciler`] reconciles managed resources with external systems
by instantiating a client of the external API and using it to create, update,
or delete the external resource as necessary.
Crossplane controllers typically differ sufficiently from those scaffolded by
kubebuilder that there is little value in using kubebuilder to generate a
controller scaffold.
### Managed Resource Controllers
Managed resource controllers should use [`managed.NewReconciler`] to wrap a
managed-resource specific implementation of [`managed.ExternalConnecter`]. Parts
of `managed.Reconciler`'s behaviour is customisable; refer to the
[`managed.NewReconciler`] GoDoc for a list of options. The following is an
example controller for the `FavouriteDBInstance` managed resource we defined
earlier:
```go
import (
"context"
"fmt"
"strings"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
// An API client of the hypothetical FavouriteDB service.
"github.com/fcp-sdk/v1/services/database"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
"github.com/crossplane/crossplane-runtime/pkg/meta"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
"github.com/crossplane/provider-fcp/apis/database/v1alpha3"
fcpv1alpha3 "github.com/crossplane/provider-fcp/apis/v1alpha3"
)
type FavouriteDBInstanceController struct{}
// SetupWithManager instantiates a new controller using a managed.Reconciler
// configured to reconcile FavouriteDBInstances using an ExternalClient produced by
// connecter, which satisfies the ExternalConnecter interface.
func (c *FavouriteDBInstanceController) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
Named(strings.ToLower(fmt.Sprintf("%s.%s", v1alpha3.FavouriteDBInstanceKind, v1alpha3.Group))).
For(&v1alpha3.FavouriteDBInstance{}).
Complete(managed.NewReconciler(mgr,
resource.ManagedKind(v1alpha3.FavouriteDBInstanceGroupVersionKind),
managed.WithExternalConnecter(&connecter{client: mgr.GetClient()})))
}
// Connecter satisfies the resource.ExternalConnecter interface.
type connecter struct{ client client.Client }
// Connect to the supplied resource.Managed (presumed to be a
// FavouriteDBInstance) by using the Provider it references to create a new
// database client.
func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
// Assert that resource.Managed we were passed in fact contains a
// FavouriteDBInstance. We told NewControllerManagedBy that this was a
// controller For FavouriteDBInstance, so something would have to go
// horribly wrong for us to encounter another type.
i, ok := mg.(*v1alpha3.FavouriteDBInstance)
if !ok {
return nil, errors.New("managed resource is not a FavouriteDBInstance")
}
// Get the Provider referenced by the FavouriteDBInstance.
p := &fcpv1alpha3.Provider{}
if err := c.client.Get(ctx, meta.NamespacedNameOf(i.Spec.ProviderReference), p); err != nil {
return nil, errors.Wrap(err, "cannot get Provider")
}
// Get the Secret referenced by the Provider.
s := &corev1.Secret{}
n := types.NamespacedName{Namespace: p.Namespace, Name: p.Spec.Secret.Name}
if err := c.client.Get(ctx, n, s); err != nil {
return nil, errors.Wrap(err, "cannot get Provider secret")
}
// Create and return a new database client using the credentials read from
// our Provider's Secret.
client, err := database.NewClient(ctx, s.Data[p.Spec.Secret.Key])
return &external{client: client}, errors.Wrap(err, "cannot create client")
}
// External satisfies the resource.ExternalClient interface.
type external struct{ client database.Client }
// Observe the existing external resource, if any. The managed.Reconciler
// calls Observe in order to determine whether an external resource needs to be
// created, updated, or deleted.
func (e *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) {
i, ok := mg.(*v1alpha3.FavouriteDBInstance)
if !ok {
return managed.ExternalObservation{}, errors.New("managed resource is not a FavouriteDBInstance")
}
// Use our FavouriteDB API client to get an up to date view of the external
// resource.
existing, err := e.client.GetInstance(ctx, i.Spec.Name)
// If we encounter an error indicating the external resource does not exist
// we want to let the managed.Reconciler know so it can create it.
if database.IsNotFound(err) {
return managed.ExternalObservation{ResourceExists: false}, nil
}
// Any other errors are wrapped (as is good Go practice) and returned to the
// managed.Reconciler. It will update the "Synced" status condition
// of the managed resource to reflect that the most recent reconcile failed
// and ensure the reconcile is reattempted after a brief wait.
if err != nil {
return managed.ExternalObservation{}, errors.Wrap(err, "cannot get instance")
}
// The external resource exists. Copy any output-only fields to their
// corresponding entries in our status field.
i.Status.Status = existing.GetStatus()
i.Status.Hostname = existing.GetHostname()
i.Status.ID = existing.GetID()
// Update our "Ready" status condition to reflect the status of the external
// resource. Most managed resources use the below well known reasons that
// the "Ready" status may be true or false, but managed resource authors
// are welcome to define and use their own.
switch i.Status.Status {
case database.StatusOnline:
resource.SetBindable(i)
i.SetConditions(xpv1.Available())
case database.StatusCreating:
i.SetConditions(xpv1.Creating())
case database.StatusDeleting:
i.SetConditions(xpv1.Deleting())
}
// Finally, we report what we know about the external resource. In this
// hypothetical case FancinessLevel is the only field that can be updated
// after creation time, so the resource does not need to be updated if
// the actual fanciness level matches our desired fanciness level. Any
// ConnectionDetails we return will be published to the managed resource's
// connection secret if it specified one.
o := managed.ExternalObservation{
ResourceExists: true,
ResourceUpToDate: existing.GetFancinessLevel == i.Spec.FancinessLevel,
ConnectionDetails: managed.ConnectionDetails{
xpv1.ResourceCredentialsSecretUserKey: []byte(existing.GetUsername()),
xpv1.ResourceCredentialsSecretEndpointKey: []byte(existing.GetHostname()),
},
}
return o, nil
}
// Create a new external resource based on the specification of our managed
// resource. managed.Reconciler only calls Create if Observe reported
// that the external resource did not exist.
func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) {
i, ok := mg.(*v1alpha3.FavouriteDBInstance)
if !ok {
return managed.ExternalCreation{}, errors.New("managed resource is not a FavouriteDBInstance")
}
// Indicate that we're about to create the instance. Remember ExternalClient
// authors can use a bespoke condition reason here in cases where Creating
// doesn't make sense.
i.SetConditions(xpv1.Creating())
// Create must return any connection details that are set or returned only
// at creation time. The managed.Reconciler will merge any details
// with those returned during the Observe phase.
password := database.GeneratePassword()
cd := managed.ConnectionDetails{xpv1.ResourceCredentialsSecretPasswordKey: []byte(password)}
// Create a new instance.
new := database.Instance{Name: i.Name, FancinessLevel: i.FancinessLevel, Version: i.Version}
err := e.client.CreateInstance(ctx, new, password)
// Note that we use resource.Ignore to squash any error that indicates the
// external resource already exists. Create implementations must not return
// an error if asked to create a resource that already exists. Real managed
// resource controllers are advised to avoid unintentially 'adoptign' an
// existing, unrelated external resource, per
// https://github.com/crossplane/crossplane-runtime/issues/27
return managed.ExternalCreation{ConnectionDetails: cd}, errors.Wrap(resource.Ignore(database.IsExists, err), "cannot create instance")
}
// Update the existing external resource to match the specifications of our
// managed resource. managed.Reconciler only calls Update if Observe
// reported that the external resource was not up to date.
func (e *external) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) {
i, ok := mg.(*v1alpha3.FavouriteDBInstance)
if !ok {
return managed.ExternalUpdate{}, errors.New("managed resource is not a FavouriteDBInstance")
}
// Recall that FancinessLevel is the only field that we _can_ update.
new := database.Instance{Name: i.Name, FancinessLevel: i.FancinessLevel}
err := e.client.UpdateInstance(ctx, new)
return managed.ExternalUpdate{}, errors.Wrap(err, "cannot update instance")
}
// Delete the external resource. managed.Reconciler only calls Delete
// when a managed resource with the 'Delete' deletion policy (the default) has
// been deleted.
func (e *external) Delete(ctx context.Context, mg resource.Managed) error {
i, ok := mg.(*v1alpha3.FavouriteDBInstance)
if !ok {
return errors.New("managed resource is not a FavouriteDBInstance")
}
// Indicate that we're about to delete the instance.
i.SetConditions(xpv1.Deleting())
// Delete the instance.
err := e.client.DeleteInstance(ctx, i.Spec.Name)
// Note that we use resource.Ignore to squash any error that indicates the
// external resource does not exist. Delete implementations must not return
// an error when asked to delete a non-existent external resource.
return errors.Wrap(resource.Ignore(database.IsNotFound, err), "cannot delete instance")
}
```
### Wrapping Up
Once all your controllers are in place you'll want to test them. Note that most
projects under the [crossplane org] [favor] table driven tests that use Go's
standard library `testing` package over kubebuilder's Gingko based tests. Please
do not add or proliferate Gingko based tests.
Finally, don't forget to plumb any newly added resource kinds and controllers up
to your controller manager. Simple providers may do this for each type within
within `main()`, but most more complicated providers take an approach in which
each package exposes an `AddToScheme` (for resource kinds) or `SetupWithManager`
(for controllers) function that invokes the same function within its child
packages, resulting in a `main.go` like:
```go
import (
"time"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/manager/signals"
crossplaneapis "github.com/crossplane/crossplane/apis"
fcpapis "github.com/crossplane/provider-fcp/apis"
"github.com/crossplane/provider-fcp/pkg/controller"
)
func main() {
cfg, err := config.GetConfig()
if err != nil {
panic(err)
}
mgr, err := manager.New(cfg, manager.Options{SyncPeriod: 1 * time.Hour})
if err != nil {
panic(err)
}
if err := crossplaneapis.AddToScheme(mgr.GetScheme()); err != nil {
panic(err)
}
if err := fcpapis.AddToScheme(mgr.GetScheme()); err != nil {
panic(err)
}
if err := controller.SetupWithManager(mgr); err != nil {
panic(err)
}
panic(mgr.Start(signals.SetupSignalHandler()))
}
```
## In Review
In this guide we walked through the process of defining the resource kinds and
controllers necessary to build support for new managed infrastructure; possibly
even a completely new infrastructure provider. Please do not hesitate to [reach
out] to the Crossplane maintainers and community for help designing and
implementing support for new managed services. We would highly value any
feedback you may have about the development process!
<!-- Named Links -->
[crossplane-runtime v0.9.0]: https://github.com/crossplane/crossplane-runtime/releases/tag/v0.9.0
[TBS Episode 18]: https://www.youtube.com/watch?v=rvQ8N0u3rkE&t=7s
[What Makes a Crossplane Infrastructure Resource]: #what-makes-a-crossplane-infrastructure-resource
[managed resource]: {{<ref "../concepts/managed-resources" >}}
[`CloudMemorystoreInstance`]: https://github.com/crossplane/provider-gcp/blob/85a6ed3c669a021f1d61be51b2cbe2714b0bc70b/apis/cache/v1beta1/cloudmemorystore_instance_types.go#L184
[`ProviderConfig`]: https://github.com/crossplane/provider-gcp/blob/be5aaf6/apis/v1beta1/providerconfig_types.go#L39
[watching the API server]: https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes
[controller-runtime]: https://github.com/kubernetes-sigs/controller-runtime
[crossplane-runtime]: https://github.com/crossplane/crossplane-runtime/
[golden path]: https://charity.wtf/2018/12/02/software-sprawl-the-golden-path-and-scaling-teams-with-agency/
[API Conventions]: https://github.com/kubernetes/community/blob/c6e1e89a/contributors/devel/sig-architecture/api-conventions.md
[kubebuilder book]: https://book.kubebuilder.io/
[resources]: https://kubebuilder.io/cronjob-tutorial/gvks.html#kinds-and-resources
[kinds]: https://kubebuilder.io/cronjob-tutorial/gvks.html#kinds-and-resources
[objects]: https://kubernetes.io/docs/concepts/#kubernetes-objects
[comment marker]: https://kubebuilder.io/reference/markers.html
[comment markers]: https://kubebuilder.io/reference/markers.html
[`resource.Managed`]: https://godoc.org/github.com/crossplane/crossplane-runtime/pkg/resource#Managed
[`managed.Reconciler`]: https://godoc.org/github.com/crossplane/crossplane-runtime/pkg/reconciler/managed#Reconciler
[`managed.NewReconciler`]: https://godoc.org/github.com/crossplane/crossplane-runtime/pkg/reconciler/managed#NewReconciler
[`managed.ExternalConnecter`]: https://godoc.org/github.com/crossplane/crossplane-runtime/pkg/reconciler/managed#ExternalConnecter
[`managed.ExternalClient`]: https://godoc.org/github.com/crossplane/crossplane-runtime/pkg/reconciler/managed#ExternalClient
[`ResourceSpec`]: https://godoc.org/github.com/crossplane/crossplane-runtime/apis/common/v1#ResourceSpec
[`ResourceStatus`]: https://godoc.org/github.com/crossplane/crossplane-runtime/apis/common/v1#ResourceStatus
[`ProviderSpec`]: https://godoc.org/github.com/crossplane/crossplane-runtime/apis/common/v1#ProviderSpec
['managed.ExternalConnecter`]: https://godoc.org/github.com/crossplane/crossplane-runtime/pkg/reconciler/managed#ExternalConnecter
[opening a Crossplane issue]: https://github.com/crossplane/crossplane/issues/new/choose
[`GroupVersionKind`]: https://godoc.org/k8s.io/apimachinery/pkg/runtime/schema#GroupVersionKind
[`reconcile.Reconciler`]: https://godoc.org/sigs.k8s.io/controller-runtime/pkg/reconcile#Reconciler
[favor]: https://github.com/crossplane/crossplane/issues/452
[reach out]: https://github.com/crossplane/crossplane#get-involved
[crossplane org]: https://github.com/crossplane
[`angryjet`]: https://github.com/crossplane/crossplane-tools
[Managed Resource API Patterns]: https://github.com/crossplane/crossplane/blob/master/design/one-pager-managed-resource-api-design.md
[Crossplane CLI]: https://github.com/crossplane/crossplane-cli#quick-start-stacks
[`angryjet` documentation]: https://github.com/crossplane/crossplane-tools/blob/master/README.md
[code generation guide]: https://github.com/crossplane-contrib/provider-aws/blob/master/CODE_GENERATION.md
[Terrajet]: https://github.com/crossplane/terrajet
[Generating a Crossplane Provider guide]: https://github.com/crossplane/terrajet/blob/main/docs/generating-a-provider.md
[provider-template]: https://github.com/crossplane/provider-template

View File

@ -1,266 +0,0 @@
---
title: Release Process
weight: 1003
---
This document is meant to be a complete end-to-end guide for how to release new
versions of software for Crossplane and its related projects.
## tl;dr Process Overview
All the details are available in the sections below, but we'll start this guide
with a very high level sequential overview for how to run the release process.
These steps apply to all Crossplane projects, all of which utilize [Github
Actions](https://github.com/features/actions) for pipelines.
1. **feature freeze**: Merge all completed features into main development branch
of all repos to begin "feature freeze" period.
1. **pin dependencies**: Update the go module on main development branch to
depend on stable versions of dependencies if needed.
1. **branch repo**: Create a new release branch using the GitHub UI for the
repo.
1. **release branch prep**: Make any release-specific updates on the release
branch (typically documentation).
1. **tag release**: Run the `Tag` action on the _release branch_ with the
desired version (e.g. `v0.14.0`).
1. **build/publish**: Run the `CI` and `Configurations` action on the release
branch with the version that was just tagged.
1. **tag next pre-release**: Run the `tag` action on the main development branch
with the `rc.0` for the next release (e.g. `v0.15.0-rc.0`).
1. **verify**: Verify all artifacts have been published successfully, perform
sanity testing.
1. **promote**: Run the `Promote` action to promote release to desired
channel(s).
1. **release notes**: Publish well authored and complete release notes on
GitHub.
1. **announce**: Announce the release on Twitter, Slack, etc.
## Detailed Process
This section will walk through the release process in more fine grained and
prescriptive detail.
### Feature Freeze
Feature freeze should be performed on all repos. In order to start the feature
freeze period, the following conditions should be met:
* All issues in the
[milestone](https://github.com/crossplane/crossplane/milestones) should be
closed
* Sanity testing has been performed on main development branch
### Pin Dependencies
It is a best practice to release Crossplane projects with "pinned" dependencies
to specific stable versions. For example, after crossplane-runtime has been
released, we want to update the main Crossplane repo to use that specific
released version.
To update a dependency to a specific version, simply edit the `go.mod` file to
point to the desired version, then run `go mod tidy`.
### Create Release Branch
Creating the release branch can be done within the [GitHub
UI](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-and-deleting-branches-within-your-repository).
Basically, you just use the branch selector drop down and type in the name of
the new release branch, e.g. `release-0.5`. Release branch names always follow
the convention of `release-[minor-semver]`.
If this is the first ever release branch being created in a repo (uncommon), you
should also set up branch protection rules for the `release-*` pattern. You can
find existing examples in the
<a href="https://github.com/crossplane/crossplane/settings/branches" data-proofer-ignore>Crossplane repo
settings</a>.
{{<hint "important">}}
Only maintainers can view the repo settings.
{{< /hint >}}
At this point, the `HEAD` commit in the release branch will be our release
candidate. The build pipeline will automatically be started due to the create
branch event, so we can start to perform testing on this build. Note that it
should be the exact same as what is currently in main development branch since
they are using the same commit and have the same tag. Also note that this is not
the official release build since we have not made the official release tag yet
(e.g. `v0.5.0`).
### Release Branch Prep
Some repos may not require any release branch prep. This is desirable as it
reduces the burden of running a new release. If this is the case for the repo
being released, you may skip this step.
In the core Crossplane repository, we need to update the release branch docs and
examples to point to the new versions that we will be releasing soon.
* Documentation, such as pinning
[snippet](https://github.com/crossplane/crossplane/blob/release-0.14/docs/snippets)
links to the current release branch.
* searching for `:v` will help a lot here
#### Bug Fixes in Release Branch
During our testing of the release candidate, we may find issues or bugs that we
triage and decide we want to fix before the release goes out. In order to fix a
bug in the release branch, the following process is recommended:
1. Make the bug fix into main development branch first through the normal PR
process
1. If the applicable code has already been removed from the main development
branch then simply fix the bug directly in the release branch by opening
a PR directly against the release branch
1. Backport the fix by performing a cherry-pick of the fix's commit hash
(**not** the merge commit) from main development branch into the release
branch. For example, to backport a fix from the main development branch to
`v0.5.0`, something like the following should be used:
```console
git fetch --all
git checkout -b release-0.5 upstream/release-0.5
git cherry-pick -x <fix commit hash>
```
1. Open a PR with the cherry-pick commit targeting the release-branch
After all bugs have been fixed and backported to the release branch, we can move
on to tagging the final release commit.
### Tag Release
Now it's time to run the `Tag` action on the release branch.
Run the tag action by going to the repo's "Actions" tab in the Github UI. You
will be prompted for the desired branch and the version you are tagging. The
latest commit on the selected branch will be the commit that is tagged.
### Draft Release Notes
We're getting close to starting the official release, so you should take this
opportunity to draft up the release notes. You can create a [new release draft
here](https://github.com/crossplane/crossplane/releases/new). Make sure you
select "This is a pre-release" and hit "Save draft" when you are ready to share
and collect feedback. Do **not** hit "Publish release" yet.
You can see and follow the template and structure from [previous
releases](https://github.com/crossplane/crossplane/releases).
### Build and Publish
Run the `CI` action on the release branch. This will build and publish the
official release with the correct version tag and all of its release artifacts
will be published.
If there are any `Configuration` packages that are built in the repo, you must
also run the `Configurations` action on the release branch. This will build,
tag, and publish the `Configuration` packages to the configured OCI image
registry.
After the pipeline runs successfully, you should verify that all artifacts have
been published to:
For all repos:
* [Docker Hub](https://hub.docker.com/repository/docker/crossplane)
For all repos with Helm charts:
* [S3 releases bucket](https://releases.crossplane.io/)
* [Helm chart repository](https://charts.crossplane.io/)
For crossplane/crossplane:
* [Docs website](https://docs.crossplane.io)
* [Configuration Packages](https://marketplace.upbound.io)
### Tag Next Pre-release
The next step is to create the pre-release tag for the `HEAD` commit in main
development branch. This tag serves as an indication of when the release was
branched from the main development branch and is also important for generating
future versions of the main development branch builds since that [versioning
process](https://github.com/upbound/build/blob/master/makelib/common.mk#L182-L196)
is based on `git describe --tags`.
> NOTE: the `build` submodule uses the latest tag by timestamp on the branch
> which the commit it is building resides on. If there were no prep commits made
> on the release branch, then its `HEAD` is even with the main development
> branch (i.e. the stable tag and the next pre-release tag will be on the same
> commit). This means that we must tag the pre-release version _after_ the
> stable version to ensure subsequent builds use the next pre-release tag as
> their base. If there are additional commits on the release branch before the
> stable tag is created, then the pre-release tag could be created first.
To accomplish this, run the `Tag` action for the repo on the main development
branch branch. You will be prompted to enter the `version` for the tag. Since
this tag will essentially be the start of pre-releases working towards the
**next** version, the `version` should be the **next** release number, plus a
trailing tag to indicate it is a pre-release. The current convention is to use
`*-rc.0`. For example, when we are releasing the `v0.9.0` release and we are
ready for the main development branch to start working towards the **next**
release of `v0.10.0`, we would make the tag `v0.10.0-rc.0`
After the tag action has succeeded, verify in the [GitHub
UI](https://github.com/crossplane/crossplane/tags) that the tag was successfully
applied to the correct commit.
The main development branch can now be opened for new features since we have a
safe release branch to continue bug fixes and improvements for the release
itself. Essentially, the main development branch is free to now diverge from the
release branch.
### Promote
If everything looks good with the official versioned release that we just
published, we can go ahead and run the `Promote` action on the release branch.
This is a very quick pipeline that doesn't rebuild anything, it simply makes
metadata changes to the published release to also include the release in the
channel of your choice.
Run the `Promote` action on the release branch and input the version you would
like to promote (e.g. `v0.5.0`) and the channel you'd like to promote it to.
After the `Promote` actions have succeeded, verify on DockerHub and the Helm
chart repository that the release has been promoted to the right channels.
### Publish Release Notes
Now that the release has been published and verified, you can publish the
[release notes](https://github.com/crossplane/crossplane/releases) that you
drafted earlier. After incorporating all feedback, you can now click on the
"Publish release" button.
This will send an email notification with the release notes to all watchers of
the repo.
### Announce Release
We have completed the entire release, so it's now time to announce it to the
world. Using the [@crossplane_io](https://twitter.com/crossplane_io) Twitter
account, tweet about the new release and blog. You'll see examples from the
previous releases, such as this tweet for
[v0.4](https://twitter.com/crossplane_io/status/1189307636350705664).
Post a link to this tweet on the Slack #announcements channel, then copy a link
to that and post it in the #general channel.
### Patch Releases
We also have the ability to run patch releases to update previous releases that
have already been published. These patch releases are always run from the last
release branch, we do **not** create a new release branch for a patch release.
The basic flow is **very** similar to a normal release, but with a few less
steps. Please refer to details for each step in the sections above.
* Fix any bugs in the main development branch first and then `cherry-pick -x` to
the release branch
* If main development branch has already removed the relevant code then make
your fix directly in the release branch
* After all testing on the release branch look good and any docs/tests have been
updated with the new version number, run the `Tag` action on the release
branch with the new patch version (e.g. `v0.5.1`)
* Run the normal `CI` action on the release branch to build and publish the
release
* Publish release notes
* Run `Promote` action to promote the patch release to the appropriate channels

View File

@ -1,20 +0,0 @@
---
title: FAQ
weight: 1200
---
### Where did the name Crossplane come from?
Crossplane is the fusing of cross-cloud control plane. We wanted to use a noun
that refers to the entity responsible for connecting different cloud providers
and acts as control plane across them. Cross implies “cross-cloud” and “plane”
brings in “control plane”.
### What's up with popsicle?
We believe in a multi-flavor cloud.
### Related Projects
See [Related Projects].
[Related Projects]: {{<ref "related_projects" >}}

View File

@ -1,83 +0,0 @@
---
title: Related Projects
weight: 1201
---
While there are many projects that address similar issues, none of them
encapsulate the full use case that Crossplane addresses. This list is not
exhaustive and is not meant to provide a deep analysis of the following
projects, but instead to motivate why Crossplane was created.
## Open Service Broker and Service Catalog
The [Open Service Broker] and the [Kubernetes Service Catalog] are able to
dynamically provision cloud services from Kubernetes. As a result it shares
similar goals with Crossplane. However, service broker does not have the
ability to define, compose, and publish your own infrastructure resources to
the Kubernetes API in a no-code way. Crossplane goes further by enabling
infrastructure operators to hide infrastructure complexity and include policy
guardrails, with a team-centric approach and a strong separation of concerns,
so applications can easily and safely consume the infrastructure they need,
using any tool that works with the Kubernetes API. Solutions like the [GCP
implementation of Open Service Broker][GCP OSB] have been deprecated in favor
of a more Kubernetes-native solution, but one that is Google-specific.
## GCP Config Connector
The [GCP Config Connector] is the GCP replacement for Open Service Broker, and
implements a set of Kubernetes controllers that are able to provision managed
services in GCP. It defines a set of CRDs for managed services like CloudSQL,
and controllers that can provision them via their cloud APIs. It is similar to
Crossplane in that it can provision managed services in GCP. Crossplane goes
further by enabling you to provision managed services from any cloud
provider and the ability to define, compose, and publish your own
infrastructure resources in a no-code way. Crossplane supports a team-centric
approach with a strong separation of concerns, that enables applications to
easily and safely consume the infrastructure they need, using any tool that
works with the Kubernetes API. GCP Config Connector is open source as of May
12, 2022.
## AWS Controllers for Kubernetes
The [AWS Controllers for Kubernetes] is a recent project that implements a set of
Kubernetes controllers that are able to provision managed services in AWS. It
defines a set of CRDs for managed services like DynamoDB, and controllers that
can provision them. It is similar to Crossplane in that
it can provision managed services in AWS. Crossplane goes further by
enabling you to provision managed services from any cloud provider and the
ability to define, compose, and publish your own infrastructure API types in
Kubernetes in a no-code way. Crossplane supports a team-centric approach with a
strong separation of concerns, that enables applications to easily and safely
consume the infrastructure they need, using any tool that works with the
Kubernetes API.
## AWS CloudFormation, GCP Deployment Manager, and Others
These products offer a declarative model for deploying and provisioning
infrastructure in each of the respective cloud providers. They only work for
one cloud provider, are generally closed source, and offer little or no
extensibility points, let alone being able to extend the Kubernetes API to
provide your own infrastructure abstractions in a no-code way. We have
considered using some of these products as a way to implement resource
controllers in Crossplane. These projects use an Infrastructure as Code
approach to management, while Crossplane offers an API-driven control plane.
## Terraform and Pulumi
[Terraform] and [Pulumi] are tools for provisioning infrastructure across cloud
providers that offer a declarative configuration language with support for
templating, composability, referential integrity and dependency management.
Terraform can declaratively manage any compatible API and perform changes when
the tool is run by a human or in a deployment pipeline. Terraform is an
Infrastructure as Code tool, while Crossplane offers an API-driven control
plane.
<!-- Named Links -->
[Open Service Broker]: https://www.openservicebrokerapi.org/
[Kubernetes Service Catalog]: https://github.com/kubernetes-retired/service-catalog
[GCP OSB]: https://cloud.google.com/kubernetes-engine/docs/concepts/google-cloud-platform-service-broker
[GCP Config Connector]: https://github.com/GoogleCloudPlatform/k8s-config-connector
[AWS Controllers for Kubernetes]: https://github.com/aws-controllers-k8s/community
[Terraform]: https://www.terraform.io/
[Pulumi]: https://www.pulumi.com/

View File

@ -1,25 +0,0 @@
---
title: "Getting Started"
weight: 1
---
{{< img src="/media/banner.png" alt="Crossplane Popsicle Truck" size="large" >}}
Crossplane is an open source Kubernetes add-on that transforms your cluster into
a **universal control plane**. Crossplane enables platform teams to assemble
infrastructure from multiple vendors, and expose higher level self-service APIs
for application teams to consume, without having to write any code.
Crossplane extends your Kubernetes cluster to support orchestrating any
infrastructure or managed service. Compose Crossplane's granular resources into
higher level abstractions that can be versioned, managed, deployed and consumed
using your favorite tools and existing processes. [Install Crossplane]({{<ref "install-configure" >}}) into any
Kubernetes cluster to get started.
Crossplane is a [Cloud Native Compute Foundation][cncf] project.
<!-- Named Links -->
[cncf]: https://www.cncf.io/

View File

@ -1,673 +0,0 @@
---
title: Create a Configuration
weight: 4
---
In the [previous section] we were able to create a PostgreSQL database because
we had installed a configuration package that defined the `PostgreSQLInstance`
type and a `Composition` of managed resources that mapped to it. Crossplane
allows you to define your own composite resources (XRs) and compositions, then
package them up to be easily distributed as OCI images. This allows you to
construct a reproducible platform that exposes infrastructure APIs at your
desired level of abstraction, and can be installed into any Crossplane cluster.
## Create a Configuration Directory
We are going to build the same configuration package that we previously
installed. It will consist of three files:
* `crossplane.yaml` - Metadata about the configuration.
* `definition.yaml` - The XRD.
* `composition.yaml` - The Composition.
Crossplane can create a configuration from any directory with a valid
`crossplane.yaml` metadata file at its root, and one or more XRDs or
Compositions. The directory structure does not matter, as long as the
`crossplane.yaml` file is at the root. Note that a configuration need not
contain one XRD and one composition - it could include only an XRD, only a
composition, several compositions, or any combination thereof.
Before we go any further, we must create a directory in which to build our
configuration:
```console
mkdir crossplane-config
cd crossplane-config
```
We'll create the aforementioned three files in this directory, then build them
into a package.
> Note that `definition.yaml` and `composition.yaml` could be created directly
> in the Crossplane cluster without packaging them into a configuration. This
> can be useful for testing compositions before pushing them to a registry.
## Create CompositeResourceDefinition
First we'll create a `CompositeResourceDefinition` (XRD) to define the schema of
our `XPostgreSQLInstance` and its `PostgreSQLInstance` resource claim.
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
required:
- parameters
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/package/definition.yaml
```
> You might notice that the XRD we created specifies both "names" and "claim
> names". This is because the composite resource it defines offers a composite
> resource claim (XRC).
## Create Compositions
Now we'll specify which managed resources our `XPostgreSQLInstance` XR
and its claim could be composed of, and how they should be configured. We do
this by defining a `Composition` that can satisfy the XR we defined above. In
this case, our `Composition` will specify how to provision a public PostgreSQL
instance on the chosen provider.
{{< tabs >}}
{{< tab "AWS (Default VPC)" >}}
> Note that this Composition will create an RDS instance using your default VPC,
> which may or may not allow connections from the internet depending on how it
> is configured. Select the AWS (New VPC) Composition if you wish to create an
> RDS instance that will allow traffic from the internet.
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgresqlinstances.aws.database.example.org
labels:
provider: aws
guide: quickstart
vpc: default
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: rdsinstance
base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
spec:
forProvider:
region: us-east-1
dbInstanceClass: db.t2.small
masterUsername: masteruser
engine: postgres
engineVersion: "12"
skipFinalSnapshotBeforeDeletion: true
publiclyAccessible: true
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.allocatedStorage"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- fromConnectionSecretKey: port
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/package/aws/composition.yaml
```
{{< /tab >}}
{{< tab "AWS (New VPC)" >}}
> Note: this `Composition` for AWS also includes several networking managed
> resources that are required to provision a publicly available PostgreSQL
> instance. Composition enables scenarios such as this, as well as far more
> complex ones. See the [composition] documentation for more information.
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: vpcpostgresqlinstances.aws.database.example.org
labels:
provider: aws
guide: quickstart
vpc: new
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: vpc
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: VPC
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.0.0/16
enableDnsSupport: true
enableDnsHostNames: true
- name: subnet-a
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1a
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.64.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1a
- name: subnet-b
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1b
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.128.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1b
- name: subnet-c
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1c
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.192.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1c
- name: dbsubnetgroup
base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: DBSubnetGroup
spec:
forProvider:
region: us-east-1
description: An excellent formation of subnetworks.
subnetIdSelector:
matchControllerRef: true
- name: internetgateway
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: InternetGateway
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
- name: routetable
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: RouteTable
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
routes:
- destinationCidrBlock: 0.0.0.0/0
gatewayIdSelector:
matchControllerRef: true
associations:
- subnetIdSelector:
matchLabels:
zone: us-east-1a
- subnetIdSelector:
matchLabels:
zone: us-east-1b
- subnetIdSelector:
matchLabels:
zone: us-east-1c
- name: securitygroup
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: SecurityGroup
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
groupName: crossplane-getting-started
description: Allow access to PostgreSQL
ingress:
- fromPort: 5432
toPort: 5432
ipProtocol: tcp
ipRanges:
- cidrIp: 0.0.0.0/0
description: Everywhere
- name: rdsinstance
base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
spec:
forProvider:
region: us-east-1
dbSubnetGroupNameSelector:
matchControllerRef: true
vpcSecurityGroupIDSelector:
matchControllerRef: true
dbInstanceClass: db.t2.small
masterUsername: masteruser
engine: postgres
engineVersion: "12"
skipFinalSnapshotBeforeDeletion: true
publiclyAccessible: true
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.allocatedStorage"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- fromConnectionSecretKey: port
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/package/aws-with-vpc/composition.yaml
```
{{< /tab >}}
{{< tab "GCP" >}}
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgresqlinstances.gcp.database.example.org
labels:
provider: gcp
guide: quickstart
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: cloudsqlinstance
base:
apiVersion: database.gcp.crossplane.io/v1beta1
kind: CloudSQLInstance
spec:
forProvider:
databaseVersion: POSTGRES_12
region: us-central1
settings:
tier: db-custom-1-3840
dataDiskType: PD_SSD
ipConfiguration:
ipv4Enabled: true
authorizedNetworks:
- value: "0.0.0.0/0"
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.settings.dataDiskSizeGb"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- type: FromValue
name: port
value: "5432"
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/docs/master/content/v1.9/snippets/package/gcp/composition.yaml
```
{{< /tab >}}
{{< tab "Azure" >}}
> Note: the `Composition` for Azure also includes a `ResourceGroup` and
> `PostgreSQLServerFirewallRule` that are required to provision a publicly
> available PostgreSQL instance on Azure. Composition enables scenarios such as
> this, as well as far more complex ones. See the [composition] documentation
> for more information.
```yaml
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgresqlinstances.azure.database.example.org
labels:
provider: azure
guide: quickstart
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: resourcegroup
base:
apiVersion: azure.crossplane.io/v1alpha3
kind: ResourceGroup
spec:
location: West US 2
- name: postgresqlserver
base:
apiVersion: database.azure.crossplane.io/v1beta1
kind: PostgreSQLServer
spec:
forProvider:
administratorLogin: myadmin
resourceGroupNameSelector:
matchControllerRef: true
location: West US 2
sslEnforcement: Disabled
version: "9.6"
sku:
tier: GeneralPurpose
capacity: 2
family: Gen5
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.storageProfile.storageMB"
transforms:
- type: math
math:
multiply: 1024
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- type: FromValue
name: port
value: "5432"
- name: firewallrule
base:
apiVersion: database.azure.crossplane.io/v1alpha3
kind: PostgreSQLServerFirewallRule
spec:
forProvider:
serverNameSelector:
matchControllerRef: true
resourceGroupNameSelector:
matchControllerRef: true
properties:
startIpAddress: 0.0.0.0
endIpAddress: 255.255.255.254
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/package/azure/composition.yaml
```
{{< /tab >}}
{{< /tabs >}}
## Build and Push The Configuration
Finally, we'll author our metadata file then build and push our configuration
so that Crossplane users may install it.
> Note that Crossplane pushes packages to an OCI registry - currently [Docker
> Hub] by default. You may need to run `docker login` before you are able to
> push a package.
{{< tabs >}}
{{< tab "AWS (Default VPC)" >}}
```yaml
apiVersion: meta.pkg.crossplane.io/v1
kind: Configuration
metadata:
name: getting-started-with-aws
annotations:
guide: quickstart
provider: aws
vpc: default
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-aws
version: ">=v0.18.2"
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/package/aws/crossplane.yaml
kubectl crossplane build configuration
```
You should see a file in your working directory with a `.xpkg` extension. The
Crossplane CLI will automatically tag and push it to the registry of your
choosing in the next step if it is the only `.xpkg` in the directory. Otherwise
you may specify a specific package by using the `-f` flag.
```console
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane push configuration ${REG}/getting-started-with-aws:v1.9.1
```
> Note that the Crossplane CLI will not follow symbolic links for files in the
> root package directory.
{{< /tab >}}
{{< tab "AWS (Default VPC)" >}}
```yaml
apiVersion: meta.pkg.crossplane.io/v1
kind: Configuration
metadata:
name: getting-started-with-aws-with-vpc
annotations:
guide: quickstart
provider: aws
vpc: new
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-aws
version: ">=v0.18.2"
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/package/aws-with-vpc/crossplane.yaml
kubectl crossplane build configuration
```
You should see a file in your working directory with a `.xpkg` extension. The
Crossplane CLI will automatically tag and push it to the registry of your
choosing in the next step if it is the only `.xpkg` in the directory. Otherwise
you may specify a specific package by using the `-f` flag.
```console
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane push configuration ${REG}/getting-started-with-aws-with-vpc:v1.9.1
```
> Note that the Crossplane CLI will not follow symbolic links for files in the
> root package directory.
{{< /tab >}}
{{< tab "GCP" >}}
```yaml
apiVersion: meta.pkg.crossplane.io/v1
kind: Configuration
metadata:
name: getting-started-with-gcp
annotations:
guide: quickstart
provider: gcp
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-gcp
version: ">=v0.13.0"
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/docs/master/content/v1.9/snippets/package/gcp/crossplane.yaml
kubectl crossplane build configuration
```
You should see a file in your working directory with a `.xpkg` extension. The
Crossplane CLI will automatically tag and push it to the registry of your
choosing in the next step if it is the only `.xpkg` in the directory. Otherwise
you may specify a specific package by using the `-f` flag.
```console
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane push configuration ${REG}/getting-started-with-gcp:v1.9.1
```
> Note that the Crossplane CLI will not follow symbolic links for files in the
> root package directory.
{{< /tab >}}
{{< tab "Azure" >}}
```yaml
apiVersion: meta.pkg.crossplane.io/v1
kind: Configuration
metadata:
name: getting-started-with-azure
annotations:
guide: quickstart
provider: azure
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-azure
version: ">=v0.13.0"
```
```console
curl -OL https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/package/azure/crossplane.yaml
kubectl crossplane build configuration
```
You should see a file in your working directory with a `.xpkg` extension. The
Crossplane CLI will automatically tag and push it to the registry of your
choosing in the next step if it is the only `.xpkg` in the directory. Otherwise
you may specify a specific package by using the `-f` flag.
```console
# Set this to the Docker Hub username or OCI registry you wish to use.
REG=my-package-repo
kubectl crossplane push configuration ${REG}/getting-started-with-azure:v1.9.1
```
> Note that the Crossplane CLI will not follow symbolic links for files in the
> root package directory.
{{< /tab >}}
{{< /tabs >}}
That's it! You've now built and pushed your package. Take a look at the
Crossplane [packages] documentation for more information about installing and
working with packages, or read about other Crossplane [concepts].
## Clean Up
To clean up, you can simply delete your package directory:
```console
cd ..
rm -rf crossplane-config
```
<!-- Named Links -->
[previous section]: {{<ref "provision-infrastructure" >}}
[composed]: {{<ref "../concepts/composition" >}}
[composition]: {{<ref "../concepts/composition" >}}
[Docker Hub]: https://hub.docker.com/
[packages]: {{<ref "../concepts/packages" >}}
[concepts]: {{<ref "../concepts" >}}

View File

@ -1,483 +0,0 @@
---
title: Install & Configure
weight: 2
---
## Choosing Your Crossplane Distribution
Users looking to use Crossplane for the first time have two options available to
them today. The first way is to use the version of Crossplane which is
maintained and released by the community and found on the [Crossplane GitHub].
The second option is to use a vendor supported Crossplane distribution. These
distributions are [certified by the CNCF] to be conformant with Crossplane, but
may include additional features or tooling around it that makes it easier to use
in production environments.
{{% tabs "Crossplane Distros" %}}
{{% tab "Crossplane (upstream)" %}}
## Start with Upstream Crossplane
Installing Crossplane into an existing Kubernetes cluster will require a bit
more setup, but can provide more flexibility for users who need it.
### Get a Kubernetes Cluster
<!-- inside Crossplane (upstream) -->
{{% tabs "Kubernetes Clusters" %}}
{{% tab "macOS via Homebrew" %}}
For macOS via Homebrew use the following:
```bash
brew upgrade
brew install kind
brew install kubectl
brew install helm
kind create cluster --image kindest/node:v1.23.0 --wait 5m
```
<!-- close "macOS via Homebrew" -->
{{% /tab %}}
{{% tab "macOS / Linux" %}}
For macOS / Linux use the following:
* [Kubernetes cluster]
* [Kind]
* [Minikube], minimum version `v0.28+`
* etc.
* [Helm], minimum version `v3.0.0+`.
<!-- close "macOS / Linux" -->
{{% /tab %}}
{{% tab "Windows" %}}
For Windows use the following:
* [Kubernetes cluster]
* [Kind]
* [Minikube], minimum version `v0.28+`
* etc.
* [Helm], minimum version `v3.0.0+`.
<!-- close "Windows" -->
{{% /tab %}}
<!-- close "Kubernetes Clusters" -->
{{% /tabs %}}
### Install Crossplane
{{% tabs "install with helm" %}}
{{% tab "Helm 3 (stable)" %}}
Use Helm 3 to install the latest official `stable` release of Crossplane, suitable for community use and testing:
```bash
kubectl create namespace crossplane-system
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane --namespace crossplane-system crossplane-stable/crossplane
```
<!-- close "Helm 3 (stable)" -->
{{% /tab %}}
{{% tab "Helm 3 (latest)" %}}
<!-- fold start -->
Use Helm 3 to install the latest pre-release version of Crossplane:
```bash
kubectl create namespace crossplane-system
helm repo add crossplane-master https://charts.crossplane.io/master/
helm repo update
helm search repo crossplane-master --devel
helm install crossplane --namespace crossplane-system crossplane-master/crossplane \
--devel --version <version>
```
For example:
```bash
helm install crossplane --namespace crossplane-system crossplane-master/crossplane \
--version 0.11.0-rc.100.gbc5d311 --devel
```
<!-- close "Helm 3 (latest)" -->
{{% /tab %}}
<!-- close "install with helm" -->
{{% /tabs %}}
### Check Crossplane Status
```bash
helm list -n crossplane-system
kubectl get all -n crossplane-system
```
## Install Crossplane CLI
The Crossplane CLI extends `kubectl` with functionality to build, push, and
install [Crossplane packages]:
{{% tabs "crossplane CLI" %}}
{{% tab "Stable" %}}
```bash
curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | sh
```
<!-- close "Stable" -->
{{% /tab %}}
{{% tab "Latest" %}}
```bash
curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | XP_CHANNEL=master sh
```
You may also specify `XP_VERSION` for download if you would like to select a
specific version from the given release channel. If a version is not specified
the latest version from the release channel will be used.
```bash
curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | XP_CHANNEL=master XP_VERSION=v1.0.0-rc.0.130.g94f34fd3 sh
```
<!-- close "Latest" -->
{{% /tab %}}
<!-- close "crossplane CLI" -->
{{% /tabs %}}
## Select a Getting Started Configuration
Crossplane goes beyond simply modelling infrastructure primitives as custom
resources - it enables you to define new custom resources with schemas of your
choosing. We call these "composite resources" (XRs). Composite resources compose
managed resources -- Kubernetes custom resources that offer a high fidelity
representation of an infrastructure primitive, like an SQL instance or a
firewall rule.
We use two special Crossplane resources to define and configure these new custom
resources:
- A `CompositeResourceDefinition` (XRD) _defines_ a new kind of composite
resource, including its schema. An XRD may optionally _offer_ a claim (XRC).
- A `Composition` specifies which resources a composite resource will be
composed of, and how they should be configured. You can create multiple
`Composition` options for each composite resource.
XRDs and Compositions may be packaged and installed as a _configuration_. A
configuration is a [package] of composition configuration that can easily be
installed to Crossplane by creating a declarative `Configuration` resource, or
by using `kubectl crossplane install configuration`.
In the examples below we will install a configuration that defines a new
`XPostgreSQLInstance` XR and `PostgreSQLInstance` XRC that takes a
single `storageGB` parameter, and creates a connection `Secret` with keys for
`username`, `password`, and `endpoint`. A `Configuration` exists for each
provider that can satisfy a `PostgreSQLInstance`. Let's get started!
{{% tabs "getting started" %}}
{{% tab "AWS (Default VPC)" %}}
### Install Configuration Package
> If you prefer to see the contents of this configuration package and how it is
> constructed prior to install, skip ahead to the [create a configuration]
> section.
```bash
kubectl crossplane install configuration registry.upbound.io/xp/getting-started-with-aws:v1.9.1
```
Wait until all packages become healthy:
```bash
watch kubectl get pkg
```
### Get AWS Account Keyfile
Using an AWS account with permissions to manage RDS databases:
```bash
AWS_PROFILE=default && echo -e "[default]\naws_access_key_id = $(aws configure get aws_access_key_id --profile $AWS_PROFILE)\naws_secret_access_key = $(aws configure get aws_secret_access_key --profile $AWS_PROFILE)" > creds.conf
```
### Create a Provider Secret
```bash
kubectl create secret generic aws-creds -n crossplane-system --from-file=creds=./creds.conf
```
### Configure the Provider
We will create the following `ProviderConfig` object to configure credentials
for AWS Provider:
```yaml
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds
key: creds
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/configure/aws/providerconfig.yaml
```
<!-- close "AWS (Default VPC)" -->
{{% /tab %}}
{{% tab "AWS (New VPC)" %}}
### Install Configuration Package
> If you prefer to see the contents of this configuration package and how it is
> constructed prior to install, skip ahead to the [create a configuration]
> section.
```bash
kubectl crossplane install configuration registry.upbound.io/xp/getting-started-with-aws-with-vpc:v1.9.1
```
Wait until all packages become healthy:
```bash
watch kubectl get pkg
```
### Get AWS Account Keyfile
Using an AWS account with permissions to manage RDS databases:
```bash
AWS_PROFILE=default && echo -e "[default]\naws_access_key_id = $(aws configure get aws_access_key_id --profile $AWS_PROFILE)\naws_secret_access_key = $(aws configure get aws_secret_access_key --profile $AWS_PROFILE)" > creds.conf
```
### Create a Provider Secret
```bash
kubectl create secret generic aws-creds -n crossplane-system --from-file=creds=./creds.conf
```
### Configure the Provider
We will create the following `ProviderConfig` object to configure credentials
for AWS Provider:
```yaml
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds
key: creds
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/configure/aws/providerconfig.yaml
```
<!-- close "AWS (New VPC)" -->
{{% /tab %}}
{{% tab "GCP" %}}
### Install Configuration Package
> If you prefer to see the contents of this configuration package and how it is
> constructed prior to install, skip ahead to the [create a configuration]
> section.
```bash
kubectl crossplane install configuration registry.upbound.io/xp/getting-started-with-gcp:v1.9.1
```
Wait until all packages become healthy:
```
watch kubectl get pkg
```
### Get GCP Account Keyfile
```bash
# replace this with your own gcp project id and the name of the service account
# that will be created.
PROJECT_ID=my-project
NEW_SA_NAME=test-service-account-name
# create service account
SA="${NEW_SA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
gcloud iam service-accounts create $NEW_SA_NAME --project $PROJECT_ID
# enable cloud API
SERVICE="sqladmin.googleapis.com"
gcloud services enable $SERVICE --project $PROJECT_ID
# grant access to cloud API
ROLE="roles/cloudsql.admin"
gcloud projects add-iam-policy-binding --role="$ROLE" $PROJECT_ID --member "serviceAccount:$SA"
# create service account keyfile
gcloud iam service-accounts keys create creds.json --project $PROJECT_ID --iam-account $SA
```
### Create a Provider Secret
```bash
kubectl create secret generic gcp-creds -n crossplane-system --from-file=creds=./creds.json
```
### Configure the Provider
We will create the following `ProviderConfig` object to configure credentials
for GCP Provider:
```bash
# replace this with your own gcp project id
PROJECT_ID=my-project
echo "apiVersion: gcp.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
projectID: ${PROJECT_ID}
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: gcp-creds
key: creds" | kubectl apply -f -
```
<!-- close "GCP" -->
{{% /tab %}}
{{% tab "Azure" %}}
### Install Configuration Package
> If you prefer to see the contents of this configuration package and how it is
> constructed prior to install, skip ahead to the [create a configuration]
> section.
```bash
kubectl crossplane install configuration registry.upbound.io/xp/getting-started-with-azure:v1.9.1
```
Wait until all packages become healthy:
```
watch kubectl get pkg
```
### Get Azure Principal Keyfile
```bash
# create service principal with Owner role
az ad sp create-for-rbac --role Contributor --scopes /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx > "creds.json"
```
### Create a Provider Secret
```bash
kubectl create secret generic azure-creds -n crossplane-system --from-file=creds=./creds.json
```
### Configure the Provider
We will create the following `ProviderConfig` object to configure credentials
for Azure Provider:
```yaml
apiVersion: azure.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: azure-creds
key: creds
```
```bash
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/configure/azure/providerconfig.yaml
```
<!-- close "Azure" -->
{{% /tab %}}
{{% /tabs %}}
## Next Steps
Now that you have configured Crossplane with support for `PostgreSQLInstance`,
you can [provision infrastructure].
<!-- close "Crossplane (upstream)" -->
{{% /tab %}}
{{% tab "Downstream Distribution" %}}
## Start with a Downstream Distribution
Upbound, the founders of Crossplane, maintains a free and open source downstream
distribution of Crossplane which makes getting started with Crossplane easy.
Universal Crossplane, or UXP for short, connects to Upbound's hosted management
console and Registry to make it easier to develop, debug, and manage Provider
and Configuration packages.
[Get started with Universal Crossplane] on the Upbound Documentation site.
<i>Want see another hosted Crossplane service listed? Please [reach out on
Slack][Slack] and our community will highlight it here!</i>
<!-- close "Downstream Distribution" -->
{{% /tab %}}
<!-- close "Crossplane Distros" -->
{{% /tabs %}}
## More Info
* See [Install] and [Configure] docs for installing alternate versions and more
detailed instructions.
* See [Uninstall] docs for cleaning up resources, packages, and Crossplane
itself.
* See [Providers] for installing and using different providers beyond AWS, GCP
and Azure mentionded in this guide.
<!-- Named Links -->
[package]: {{<ref "../concepts/packages" >}}
[provision infrastructure]: {{<ref "provision-infrastructure" >}}
[create a configuration]: {{<ref "create-configuration" >}}
[Install]: {{<ref "../reference/install" >}}
[Configure]: {{<ref "../reference/configure" >}}
[Uninstall]: {{<ref "../reference/uninstall" >}}
[Kubernetes cluster]: https://kubernetes.io/docs/setup/
[Minikube]: https://minikube.sigs.k8s.io/docs/start/
[Helm]:https://helm.sh/docs/intro/using_helm/
[Kind]: https://kind.sigs.k8s.io/docs/user/quick-start/
[Crossplane packages]: {{<ref "../concepts/packages" >}}
[Slack]: http://slack.crossplane.io/
[up]: https://github.com/upbound/up
[Upbound documentation]: https://https://docs.upbound.io//docs
[Providers]: {{<ref "../concepts/providers" >}}
[Universal Crossplane]: https://https://docs.upbound.io/uxp/
[Get started with Universal Crossplane]: https://docs.upbound.io/uxp/install
[certified by the CNCF]: https://github.com/cncf/crossplane-conformance
[Crossplane GitHub]: https://github.com/crossplane/crossplane

View File

@ -1,273 +0,0 @@
---
title: Provision Infrastructure
weight: 3
---
Composite resources (XRs) are always cluster scoped - they exist outside of any
namespace. This allows an XR to represent infrastructure that might be consumed
from several different namespaces. This is often true for VPC networks - an
infrastructure operator may wish to define a VPC network XR and an SQL instance
XR, only the latter of which may be managed by application operators. The
application operators are restricted to their team's namespace, but their SQL
instances should all be attached to the VPC network that the infrastructure
operator manages. Crossplane enables scenarios like this by allowing the
infrastructure operator to offer their application operators a _composite
resource claim_ (XRC). An XRC is a namespaced proxy for an XR; the schema of an
XRC is identical to that of its corresponding XR. When an application operator
creates an XRC, a corresponding backing XR is created automatically. This model
has similarities to [Persistent Volumes (PV) and Persistent Volume Claims (PVC)]
in Kubernetes.
## Claim Your Infrastructure
The `Configuration` package we installed in the last section:
- Defines a `XPostgreSQLInstance` XR.
- Offers a `PostgreSQLInstance` claim (XRC) for said XR.
- Creates a `Composition` that can satisfy our XR.
This means that we can create a `PostgreSQLInstance` XRC in the `default`
namespace to provision a PostgreSQL instance and all the supporting
infrastructure (VPCs, firewall rules, resource groups, etc) that it may need!
{{< tabs >}}
{{< tab "AWS (Default VPC)" >}}
> Note that this resource will create an RDS instance using your default VPC,
> which may or may not allow connections from the internet depending on how it
> is configured.
```yaml
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
name: my-db
namespace: default
spec:
parameters:
storageGB: 20
compositionSelector:
matchLabels:
provider: aws
vpc: default
writeConnectionSecretToRef:
name: db-conn
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/compose/claim-aws.yaml
```
{{< /tab >}}
{{< tab "AWS (New VPC)" >}}
> Note that this resource also includes several networking managed resources
> that are required to provision a publicly available PostgreSQL instance.
> Composition enables scenarios such as this, as well as far more complex ones.
> See the [composition] documentation for more information.
```yaml
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
name: my-db
namespace: default
spec:
parameters:
storageGB: 20
compositionSelector:
matchLabels:
provider: aws
vpc: new
writeConnectionSecretToRef:
name: db-conn
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/compose/claim-aws.yaml
```
{{< /tab >}}
{{< tab "GCP" >}}
```yaml
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
name: my-db
namespace: default
spec:
parameters:
storageGB: 20
compositionSelector:
matchLabels:
provider: gcp
writeConnectionSecretToRef:
name: db-conn
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/compose/claim-gcp.yaml
```
{{< /tab >}}
{{< tab "Azure" >}}
```yaml
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
name: my-db
namespace: default
spec:
parameters:
storageGB: 20
compositionSelector:
matchLabels:
provider: azure
writeConnectionSecretToRef:
name: db-conn
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/compose/claim-azure.yaml
```
{{< /tab >}}
{{< /tabs >}}
After creating the `PostgreSQLInstance` Crossplane will begin provisioning a
database instance on your provider of choice. Once provisioning is complete, you
should see `READY: True` in the output when you run:
```console
kubectl get postgresqlinstance my-db
```
> Note: while waiting for the `PostgreSQLInstance` to become ready, you
> may want to look at other resources in your cluster. The following commands
> will allow you to view groups of Crossplane resources:
>
> - `kubectl get claim`: get all resources of all claim kinds, like `PostgreSQLInstance`.
> - `kubectl get composite`: get all resources that are of composite kind, like `XPostgreSQLInstance`.
> - `kubectl get managed`: get all resources that represent a unit of external
> infrastructure.
> - `kubectl get <name-of-provider>`: get all resources related to `<provider>`.
> - `kubectl get crossplane`: get all resources related to Crossplane.
Try the following command to watch your provisioned resources become ready:
```console
kubectl get crossplane -l crossplane.io/claim-name=my-db
```
Once your `PostgreSQLInstance` is ready, you should see a `Secret` in the `default`
namespace named `db-conn` that contains keys that we defined in XRD. If they were
filled by the composition, then they should appear:
```console
$ kubectl describe secrets db-conn
Name: db-conn
Namespace: default
...
Type: connection.crossplane.io/v1alpha1
Data
====
password: 27 bytes
port: 4 bytes
username: 25 bytes
endpoint: 45 bytes
```
## Consume Your Infrastructure
Because connection secrets are written as a Kubernetes `Secret` they can easily
be consumed by Kubernetes primitives. The most basic building block in
Kubernetes is the `Pod`. Let's define a `Pod` that will show that we are able to
connect to our newly provisioned database.
> Note that if you're using a hosted Crossplane you'll need to copy the db-conn
> connection secret over to your own Kubernetes cluster and run this pod there.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: see-db
namespace: default
spec:
containers:
- name: see-db
image: postgres:12
command: ['psql']
args: ['-c', 'SELECT current_database();']
env:
- name: PGDATABASE
value: postgres
- name: PGHOST
valueFrom:
secretKeyRef:
name: db-conn
key: endpoint
- name: PGUSER
valueFrom:
secretKeyRef:
name: db-conn
key: username
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: db-conn
key: password
- name: PGPORT
valueFrom:
secretKeyRef:
name: db-conn
key: port
```
```console
kubectl apply -f https://raw.githubusercontent.com/crossplane/crossplane/release-1.9/docs/snippets/compose/pod.yaml
```
This `Pod` simply connects to a PostgreSQL database and prints its name, so you
should see the following output (or similar) after creating it if you run
`kubectl logs see-db`:
```SQL
current_database
------------------
postgres
(1 row)
```
## Clean Up
To clean up the `Pod`, run:
```console
kubectl delete pod see-db
```
To clean up the infrastructure that was provisioned, you can delete the
`PostgreSQLInstance` XRC:
```console
kubectl delete postgresqlinstance my-db
```
## Next Steps
Now you have seen how to provision and consume complex infrastructure via
composition. In the [next section] you will learn how compose and package your
own infrastructure APIs.
<!-- Named Links -->
[Persistent Volumes (PV) and Persistent Volume Claims (PVC)]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/
[composition]: {{<ref "../concepts/composition" >}}
[setup]: {{<ref "install-configure" >}}
[next section]: {{<ref "create-configuration" >}}

View File

@ -1,28 +0,0 @@
---
title: Guides
weight: 200
---
This section contains guides for using Crossplane in specific scenarios or
alongside other technologies. If you are interested in writing and
maintaining a guide for your own use-case please feel free to [open an issue] to
add it! Also check out the [The Binding Status], a biweekly livestream show
where Crossplane maintainers welcome guests from the cloud-native community and
show off [demos] integrating with the projects they work on.
- [Upgrading to v0.14]
- [Upgrading to v1.x]
- [Vault Provider Credential Injection]
-
<!-- Named Links -->
[open an issue]: https://github.com/crossplane/crossplane/issues/new
[The Binding Status]: https://youtube.com/playlist?list=PL510POnNVaaYFuK-B_SIUrpIonCtLVOzT
[demos]: https://github.com/crossplane/tbs
[Upgrading to v0.14]: {{<ref "upgrading-to-v0.14.md" >}}
[Upgrading to v1.x]: {{<ref "upgrading-to-v1.x.md" >}}
[Vault Provider Credential Injection]: {{<ref "vault-injection" >}}

View File

@ -1,154 +0,0 @@
---
title: Composition Revisions
weight: 260
---
This guide discusses the use of "Composition Revisions" to safely make and roll
back changes to a Crossplane [`Composition`][composition-type]. It assumes
familiarity with Crossplane, and particularly with
[Composition][composition-term].
> Composition Revisions are an __alpha feature__. They are not yet recommended
> for production use, and are disabled by default.
A `Composition` configures how Crossplane should reconcile a Composite Resource
(XR). Put otherwise, when you create an XR the selected `Composition` determines
what managed resources Crossplane will create in response. Let's say for example
that you define a `PlatformDB` XR, which represents your organisation's common
database configuration of an Azure MySQL Server and a few firewall rules. The
`Composition` contains the 'base' configuration for the MySQL server and the
firewall rules that is extended by the configuration for the `PlatformDB`.
There is a one-to-many relationship between a `Composition` and the XRs that use
it. You might define a `Composition` named `big-platform-db` that is used by ten
different `PlatformDB` XRs. Usually, in the interest of self-service, the
`Composition` is managed by a different team from the actual `PlatformDB` XRs.
For example the `Composition` may be written and maintained by a platform team
member, while individual application teams create `PlatformDB` XRs that use said
`Composition`.
Each `Composition` is mutable - you can update it as your organisation's needs
change. However, without Composition Revisions updating a `Composition` can be a
risky process. Crossplane constantly uses the `Composition` to ensure that your
actual infrastructure - your MySQL Servers and firewall rules - match your
desired state. If you have 10 `PlatformDB` XRs all using the `big-platform-db`
`Composition`, all 10 of those XRs will be instantly updated in accordance with
any updates you make to the `big-platform-db` `Composition`.
Composition Revisions allow XRs to opt out of automatic updates. Instead you can
update your XRs to leverage the latest `Composition` settings at your own pace.
This enables you to [canary] changes to your infrastructure, or to roll back
some XRs to previous `Composition` settings without rolling back all XRs.
## Enabling Composition Revisions
Composition Revisions are an alpha feature. They are not yet recommended for
production use, and are disabled by default. Start Crossplane with the
`--enable-composition-revisions` flag to enable Composition Revision support.
```console
kubectl create namespace crossplane-system
helm install crossplane --namespace crossplane-system crossplane-stable/crossplane --set args='{--enable-composition-revisions}'
```
See the [getting started guide][install-guide] for more information on
installing Crossplane.
## Using Composition Revisions
When you enable Composition Revisions three things happen:
1. Crossplane creates a `CompositionRevision` for each `Composition` update.
1. Composite Resources gain a `spec.compositionRevisionRef` field that specifies
which `CompositionRevision` they use.
1. Composite Resources gain a `spec.compositionUpdatePolicy` field that
specifies how they should be updated to new Composition Revisions.
Each time you edit a `Composition` Crossplane will automatically create a
`CompositionRevision` that represents that 'revision' of the `Composition` -
that unique state. Each revision is allocated an increasing revision number.
This gives `CompositionRevision` consumers an idea about which revision is
'newest'.
Crossplane distinguishes between the 'newest' and the 'current' revision of a
`Composition`. That is, if you revert a `Composition` to a previous state that
corresponds to an existing `CompositionRevision` that revision will become
'current' even if it is not the 'newest' revision (i.e. the most latest _unique_
`Composition` configuration).
You can discover which revisions exist using `kubectl`:
```console
# Find all revisions of the Composition named 'example'
kubectl get compositionrevision -l crossplane.io/composition-name=example
```
This should produce output something like:
```console
NAME REVISION CURRENT AGE
example-18pdg 1 False 4m36s
example-2bgdr 2 True 73s
example-xjrdm 3 False 61s
```
> A `Composition` is a mutable resource that you can update as your needs
> change over time. Each `CompositionRevision` is an immutable snapshot of those
> needs at a particular point in time.
Crossplane behaves the same way by default whether Composition Revisions are
enabled or not. This is because when you enable Composition Revisions all XRs
default to the `Automatic` `compositionUpdatePolicy`. XRs support two update
policies:
* `Automatic`: Automatically use the current `CompositionRevision`. (Default)
* `Manual`: Require manual intervention to change `CompositionRevision`.
The below XR uses the `Manual` policy. When this policy is used the XR will
select the current `CompositionRevision` when it is first created, but must
manually be updated when you wish it to use another `CompositionRevision`.
```yaml
apiVersion: example.org/v1alpha1
kind: PlatformDB
metadata:
name: example
spec:
parameters:
storageGB: 20
# The Manual policy specifies that you do not want this XR to update to the
# current CompositionRevision automatically.
compositionUpdatePolicy: Manual
compositionRef:
name: example
writeConnectionSecretToRef:
name: db-conn
```
Crossplane sets an XR's `compositionRevisionRef` automatically at creation time
regardless of your chosen `compositionUpdatePolicy`. If you choose the `Manual`
policy you must edit the `compositionRevisionRef` field when you want your XR to
use a different `CompositionRevision`.
```yaml
apiVersion: example.org/v1alpha1
kind: PlatformDB
metadata:
name: example
spec:
parameters:
storageGB: 20
compositionUpdatePolicy: Manual
compositionRef:
name: example
# Update the referenced CompositionRevision if and when you are ready.
compositionRevisionRef:
name: example-18pdg
writeConnectionSecretToRef:
name: db-conn
```
[composition-type]: {{<ref "../concepts/composition" >}}
[composition-term]: {{<ref "../concepts/terminology" >}}#composition
[canary]: https://martinfowler.com/bliki/CanaryRelease.html
[install-guide]: {{<ref "../getting-started/install-configure" >}}

View File

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

View File

@ -1,52 +0,0 @@
---
title: Self-Signed CA Certs
toc: true
weight: 270
indent: true
---
> Using self-signed certificates is not advised in production, it is
recommended to only use self-signed certificates for testing.
When Crossplane loads Configuration and Provider Packages from private
registries, it must be configured to trust the CA and Intermediate certs.
Crossplane needs to be installed via the Helm chart with the
`registryCaBundleConfig.name` and `registryCaBundleConfig.key` parameters
defined. See [Install Crossplane]({{< ref "../getting-started/install-configure" >}}).
## Configure
1. Create a CA Bundle (A file containing your Root and Intermediate
certificates in a specific order). This can be done with any text editor or
from the command line, so long as the resulting file contains all required crt
files in the proper order. In many cases, this will be either a single
self-signed Root CA crt file, or an Intermediate crt and Root crt file. The
order of the crt files should be from lowest to highest in signing order.
For example, if you have a chain of two certificates below your Root
certificate, you place the bottom level Intermediate cert at the beginning of
the file, then the Intermediate cert that singed that cert, then the Root cert
that signed that cert.
2. Save the files as `[yourdomain].ca-bundle`.
3. Create a Kubernetes ConfigMap in your Crossplane system namespace:
```
kubectl -n [Crossplane system namespace] create cm ca-bundle-config \
--from-file=ca-bundle=./[yourdomain].ca-bundle
```
4. Set the `registryCaBundleConfig.name` Helm chart parameter to
`ca-bundle-config` and the `registryCaBundleConfig.key` parameter to
`ca-bundle`.
> Providing Helm with parameter values is convered in the Helm docs,
[Helm install](https://helm.sh/docs/helm/helm_install/). An example block
in an `override.yaml` file would look like this:
```
registryCaBundleConfig:
name: ca-bundle-config
key: ca-bundle
```

View File

@ -1,162 +0,0 @@
---
title: Upgrading to v0.14
weight: 210
---
Crossplane made a small handful of breaking changes in v0.14. The most broadly
impactful change was updating the `CompositeResourceDefinition` (XRD) schema to
support defining multiple versions of a composite resource (XR) at once. This
guide covers how to upgrade from v0.13 of Crossplane to v0.14.
- [Updating CompositeResourceDefinitions](#updating-compositeresourcedefinitions)
- [Updating Packages](#updating-packages)
## Updating CompositeResourceDefinitions
In v0.14 the schema of XRD was updated to support defining multiple versions of
an XR. This update requires manual update steps. To upgrade from v0.13 to v0.14
you must:
1. Ensure you have up-to-date YAML representations of all of your XRDs.
1. `helm upgrade` your Crossplane release.
1. Update and apply all of your XRDs.
Note that Crossplane will not actively reconcile your XRs between steps 2 and 3,
and you will see some errors in the events and logs, but your managed resources
(and thus infrastructure) will continue to run. Follow the below steps in order
to update your XRDs for v0.14:
1. Rename `spec.crdSpecTemplate` to `spec.versions`.
1. Move `spec.versions.group` to `spec.group`.
1. Move `spec.versions.names` to `spec.names`.
1. Rename `spec.versions.version` to `spec.versions.name`
1. Rename `spec.versions.validation` (if set) to `spec.versions.schema`.
1. Rename `spec.versions.additionalPrinterColumns[].JSONPath` (if set) to
`spec.versions.additionalPrinterColumns[].jsonPath`.
1. Set `spec.versions.served` to `true`.
1. Set `spec.versions.referenceable` to `true`.
1. Make `spec.versions` a single element array.
For example, the below XRD:
```yaml
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
crdSpecTemplate:
group: database.example.org
version: v1alpha1
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
validation:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
required:
- parameters
```
Would become:
```yaml
apiVersion: apiextensions.crossplane.io/v1alpha1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
required:
- parameters
```
## Updating Packages
A minor breaking change was made to on-disk package types
(`meta.pkg.crossplane.io`). In v0.13, the `spec.crossplane` field was present to
specify a compatible Crossplane version range, but it was not honored by the
package manager when packages were installed. The field was refactored to
`spec.crossplane.version` meaning that packages that previously specified
`spec.crossplane` will fail to parse when building with the Crossplane CLI or
installing into a Crossplane Kubernetes cluster. If `spec.crossplane` was not
specified, packages compatible with Crossplane v0.13 will continue to be
compatible in v0.14. This is true for both `Provider` and `Configuration`
packages.
The following example shows how a `Configuration` package that specified
`spec.crossplane` can be updated to specify Crossplane version constraints that
will be honored by the package manager in v0.14:
```yaml
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: my-configuration
spec:
crossplane: ">=v0.13.0"
```
Would become:
```yaml
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: my-configuration
spec:
crossplane:
version: ">=v0.13.0"
```
Please note that while `spec.dependsOn` is also a valid field in on-disk package
types, it is not yet honored by the package manager and will be ignored at
installation time.

View File

@ -1,46 +0,0 @@
---
title: Upgrading to v1.x
weight: 220
---
Crossplane versions post v1.0 do not introduce any breaking changes, but may
make some backward compatible changes to the core Crossplane CRDs. Helm [does
not currently touch CRDs](https://github.com/helm/helm/issues/6581) when a chart
is upgraded, so Crossplane has moved to [managing its own
CRDs](https://github.com/crossplane/crossplane/pull/2160) as of v1.2.0. However,
for versions prior to v1.2.0, you must manually apply the appropriate CRDs
before upgrading.
## Upgrading to v1.0.x or v1.1.x
To upgrade from the currently installed version, run:
```console
# Update to the latest CRDs.
kubectl apply -k https://github.com/crossplane/crossplane//cluster?ref=<release-branch>
# Update to the latest stable Helm chart for the desired version
helm --namespace crossplane-system upgrade crossplane crossplane-stable/crossplane --version <version>
```
## Upgrading to v1.2.x and Subsequent Versions
Since `v1.2.0`, we do not include any custom resource instances in our Helm chart.
This means the `Lock` object and `Provider`s and `Configuration`s you might have
possibly installed via Helm values will get deleted when you upgrade to `v1.2.x`.
The following commands will instruct Helm not to delete any instances of those
types:
```console
for name in $(kubectl get locks.pkg.crossplane.io -o name); do kubectl annotate $name 'helm.sh/resource-policy=keep'; done
for name in $(kubectl get providers.pkg.crossplane.io -o name); do kubectl annotate $name 'helm.sh/resource-policy=keep'; done
for name in $(kubectl get configurations.pkg.crossplane.io -o name); do kubectl annotate $name 'helm.sh/resource-policy=keep'; done
```
After annotations are in place you can upgrade from the currently installed version
by running:
```console
# Update to the latest stable Helm chart for the desired version
helm --namespace crossplane-system upgrade crossplane crossplane-stable/crossplane --version <version>
```

View File

@ -1,478 +0,0 @@
---
title: Vault as an External Secret Store
weight: 230
---
This guide walks through the steps required to configure Crossplane and
its Providers to use [Vault] as an [External Secret Store]. For the sake of
completeness, we will also include steps for Vault installation and setup,
however, you can skip those and use your existing Vault.
> External Secret Stores are an alpha feature. They are not yet recommended for
> production use, and are disabled by default.
Crossplane consumes and also produces sensitive information to operate which
could be categorized as follows:
1. **Provider credentials:** These are the credentials required for Providers
to authenticate against external APIs. For example, AWS Access/Secret keys, GCP
service account json, etc.
2. **Connection Details:** Once an infrastructure provisioned, we usually
need some connection data to consume it. Most of the time, this
information includes sensitive information like usernames, passwords or access
keys.
3. **Sensitive Inputs to Managed Resources:** There are some Managed resources
which expect input parameters that could be sensitive. Initial password of a
managed database is a good example of this category.
It is already possible to use Vault for the 1st category (i.e. Provider
Credentials) as described in [the previous guide]. The 3rd use case is relatively
rare and being tracked with [this issue].
In this guide we will focus on the 2nd category, which is storing Connection
Details for managed resources in Vault.
## Steps
> Some steps in this guide duplicates [the previous guide] on Vault injection.
> However, for convenience, we put them here as well with minor
> changes/improvements.
At a high level we will run the following steps:
- Install and Unseal Vault.
- Configure Vault with Kubernetes Auth.
- Install and Configure Crossplane by enabling the feature.
- Install and Configure Provider GCP by enabling the feature.
- Deploy a Composition and CompositeResourceDefinition.
- Create a Claim.
- Verify all secrets land in Vault as expected.
For simplicity, we will deploy Vault into the same cluster as Crossplane,
however, this is not a requirement as long as Vault has Kubernetes auth enabled
for the cluster where Crossplane is running.
### Prepare Vault
1. Install Vault Helm Chart
```shell
kubectl create ns vault-system
helm repo add hashicorp https://helm.releases.hashicorp.com --force-update
helm -n vault-system upgrade --install vault hashicorp/vault
```
2. [Unseal] Vault
```shell
kubectl -n vault-system exec vault-0 -- vault operator init -key-shares=1 -key-threshold=1 -format=json > cluster-keys.json
VAULT_UNSEAL_KEY=$(cat cluster-keys.json | jq -r ".unseal_keys_b64[]")
kubectl -n vault-system exec vault-0 -- vault operator unseal $VAULT_UNSEAL_KEY
```
3. Configure Vault with Kubernetes Auth.
In order for Vault to be able to authenticate requests based on Kubernetes
service accounts, the [Kubernetes auth method] must be enabled.
This requires logging in to Vault and configuring it with a service account
token, API server address, and certificate. Because we are running Vault in
Kubernetes, these values are already available via the container filesystem and
environment variables.
Get Vault Root Token:
```shell
cat cluster-keys.json | jq -r ".root_token"
```
Login as root and enable/configure Kubernetes Auth:
```shell
kubectl -n vault-system exec -it vault-0 -- /bin/sh
vault login # use root token from above
vault auth enable kubernetes
vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
exit # exit vault container
```
4. Enable Vault Key Value Secret Engine
There are two different versions of [Vault KV Secrets Engine], `v1` and `v2`,
which you can find more details in the linked documentation page.
We will use `v2` in this guide as an example, however, both versions are
supported as an external secret store.
```shell
kubectl -n vault-system exec -it vault-0 -- vault secrets enable -path=secret kv-v2
```
5. Create a Vault Policy and Role for Crossplane
```shell
kubectl -n vault-system exec -i vault-0 -- vault policy write crossplane - <<EOF
path "secret/data/*" {
capabilities = ["create", "read", "update", "delete"]
}
path "secret/metadata/*" {
capabilities = ["create", "read", "update", "delete"]
}
EOF
kubectl -n vault-system exec -it vault-0 -- vault write auth/kubernetes/role/crossplane \
bound_service_account_names="*" \
bound_service_account_namespaces=crossplane-system \
policies=crossplane \
ttl=24h
```
### Install and Configure Crossplane
1. Install Crossplane by:
- Enabling `External Secret Stores` feature.
- Annotating for [Vault Agent Sidecar Injection]
```shell
kubectl create ns crossplane-system
helm repo add crossplane-stable https://charts.crossplane.io/stable --force-update
helm upgrade --install crossplane crossplane-stable/crossplane --namespace crossplane-system \
--set 'args={--enable-external-secret-stores}' \
--set-string customAnnotations."vault\.hashicorp\.com/agent-inject"=true \
--set-string customAnnotations."vault\.hashicorp\.com/agent-inject-token"=true \
--set-string customAnnotations."vault\.hashicorp\.com/role"=crossplane \
--set-string customAnnotations."vault\.hashicorp\.com/agent-run-as-user"=65532
```
2. Create a Secret `StoreConfig` for Crossplane to be used by
Composition types, i.e. `Composites` and `Claims`:
```shell
echo "apiVersion: secrets.crossplane.io/v1alpha1
kind: StoreConfig
metadata:
name: vault
spec:
type: Vault
defaultScope: crossplane-system
vault:
server: http://vault.vault-system:8200
mountPath: secret/
version: v2
auth:
method: Token
token:
source: Filesystem
fs:
path: /vault/secrets/token" | kubectl apply -f -
```
### Install and Configure Provider GCP
1. Similar to Crossplane, install Provider GCP by:
- Enabling `External Secret Stores` feature.
- Annotating for [Vault Agent Sidecar Injection]
```shell
echo "apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
name: vault-config
spec:
args:
- --enable-external-secret-stores
metadata:
annotations:
vault.hashicorp.com/agent-inject: \"true\"
vault.hashicorp.com/agent-inject-token: \"true\"
vault.hashicorp.com/role: crossplane
vault.hashicorp.com/agent-run-as-user: \"2000\"
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-gcp
spec:
package: xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0
controllerConfigRef:
name: vault-config" | kubectl apply -f -
```
2. Create a Secret `StoreConfig` for Provider GCP to be used by GCP Managed
Resources:
```shell
echo "apiVersion: gcp.crossplane.io/v1alpha1
kind: StoreConfig
metadata:
name: vault
spec:
type: Vault
defaultScope: crossplane-system
vault:
server: http://vault.vault-system:8200
mountPath: secret/
version: v2
auth:
method: Token
token:
source: Filesystem
fs:
path: /vault/secrets/token" | kubectl apply -f -
```
### Deploy and Test
> Prerequisite: You should have a working **default** `ProviderConfig` for
> GCP available.
1. Create a `Composition` and a `CompositeResourceDefinition`:
```shell
echo "apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: compositeessinstances.ess.example.org
annotations:
feature: ess
spec:
group: ess.example.org
names:
kind: CompositeESSInstance
plural: compositeessinstances
claimNames:
kind: ESSInstance
plural: essinstances
connectionSecretKeys:
- publicKey
- publicKeyType
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
serviceAccount:
type: string
required:
- serviceAccount
required:
- parameters" | kubectl apply -f -
echo "apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: essinstances.ess.example.org
labels:
feature: ess
spec:
publishConnectionDetailsWithStoreConfigRef:
name: vault
compositeTypeRef:
apiVersion: ess.example.org/v1alpha1
kind: CompositeESSInstance
resources:
- name: serviceaccount
base:
apiVersion: iam.gcp.crossplane.io/v1alpha1
kind: ServiceAccount
metadata:
name: ess-test-sa
spec:
forProvider:
displayName: a service account to test ess
- name: serviceaccountkey
base:
apiVersion: iam.gcp.crossplane.io/v1alpha1
kind: ServiceAccountKey
spec:
forProvider:
serviceAccountSelector:
matchControllerRef: true
publishConnectionDetailsTo:
name: ess-mr-conn
metadata:
labels:
environment: development
team: backend
configRef:
name: vault
connectionDetails:
- fromConnectionSecretKey: publicKey
- fromConnectionSecretKey: publicKeyType" | kubectl apply -f -
```
2. Create a `Claim`:
```shell
echo "apiVersion: ess.example.org/v1alpha1
kind: ESSInstance
metadata:
name: my-ess
namespace: default
spec:
parameters:
serviceAccount: ess-test-sa
compositionSelector:
matchLabels:
feature: ess
publishConnectionDetailsTo:
name: ess-claim-conn
metadata:
labels:
environment: development
team: backend
configRef:
name: vault" | kubectl apply -f -
```
3. Verify all resources SYNCED and READY:
```shell
kubectl get managed
# Example output:
# NAME READY SYNCED DISPLAYNAME EMAIL DISABLED
# serviceaccount.iam.gcp.crossplane.io/my-ess-zvmkz-vhklg True True a service account to test ess my-ess-zvmkz-vhklg@testingforbugbounty.iam.gserviceaccount.com
# NAME READY SYNCED KEY_ID CREATED_AT EXPIRES_AT
# serviceaccountkey.iam.gcp.crossplane.io/my-ess-zvmkz-bq8pz True True 5cda49b7c32393254b5abb121b4adc07e140502c 2022-03-23T10:54:50Z
kubectl -n default get claim
# Example output:
# NAME READY CONNECTION-SECRET AGE
# my-ess True 19s
kubectl get composite
# Example output:
# NAME READY COMPOSITION AGE
# my-ess-zvmkz True essinstances.ess.example.org 32s
```
### Verify the Connection Secrets landed to Vault
```shell
# Check connection secrets in the "default" scope (namespace).
kubectl -n vault-system exec -i vault-0 -- vault kv list /secret/default
# Example output:
# Keys
# ----
# ess-claim-conn
# Check connection secrets in the "crossplane-system" scope (namespace).
kubectl -n vault-system exec -i vault-0 -- vault kv list /secret/crossplane-system
# Example output:
# Keys
# ----
# d2408335-eb88-4146-927b-8025f405da86
# ess-mr-conn
# Check contents of claim connection secret
kubectl -n vault-system exec -i vault-0 -- vault kv get /secret/default/ess-claim-conn
# Example output:
# ======= Metadata =======
# Key Value
# --- -----
# created_time 2022-03-18T21:24:07.2085726Z
# custom_metadata map[environment:development secret.crossplane.io/owner-uid:881cd9a0-6cc6-418f-8e1d-b36062c1e108 team:backend]
# deletion_time n/a
# destroyed false
# version 1
#
# ======== Data ========
# Key Value
# --- -----
# publicKey -----BEGIN PUBLIC KEY-----
# MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsEYCokmYEsZJCc9QN/8
# Fm1M/kTPp7Gat/MXLTP3zFyCTBFVNLN79MbAKdinWi6ePXEb75vzB79IdZcWj8lo
# 8trnS64QjNB9Vs4Xk5UvDALwleFN/bZeperxivDPwVPvT9Aqy/U9kohoS/LHyE8w
# uWQb5AuMeVQ1gtCTnCqQZ4d2MSVhQXYVvAWax1spJ9LT7mHub5j95xDdYIcOV3VJ
# l9CIo4VrWIT8THFN2NnjTrGq9+0TzXY0bV674bjJkfBC6v6yXs5HTetG+Uekq/xf
# FCjrrDi1+2UR9Mu2WTuvl8qn50be+mbwdJO5wE32jewxdYrVVmj19+PkaEeAwGTc
# vwIDAQAB
# -----END PUBLIC KEY-----
# publicKeyType TYPE_RAW_PUBLIC_KEY
# Check contents of managed resource connection secret
kubectl -n vault-system exec -i vault-0 -- vault kv get /secret/crossplane-system/ess-mr-conn
# Example output:
# ======= Metadata =======
# Key Value
# --- -----
# created_time 2022-03-18T21:21:07.9298076Z
# custom_metadata map[environment:development secret.crossplane.io/owner-uid:4cd973f8-76fc-45d6-ad45-0b27b5e9252a team:backend]
# deletion_time n/a
# destroyed false
# version 2
#
# ========= Data =========
# Key Value
# --- -----
# privateKey {
# "type": "service_account",
# "project_id": "REDACTED",
# "private_key_id": "REDACTED",
# "private_key": "-----BEGIN PRIVATE KEY-----\nREDACTED\n-----END PRIVATE KEY-----\n",
# "client_email": "ess-test-sa@REDACTED.iam.gserviceaccount.com",
# "client_id": "REDACTED",
# "auth_uri": "https://accounts.google.com/o/oauth2/auth",
# "token_uri": "https://oauth2.googleapis.com/token",
# "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
# "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/ess-test-sa%40REDACTED.iam.gserviceaccount.com"
# }
# privateKeyType TYPE_GOOGLE_CREDENTIALS_FILE
# publicKey -----BEGIN PUBLIC KEY-----
# MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzsEYCokmYEsZJCc9QN/8
# Fm1M/kTPp7Gat/MXLTP3zFyCTBFVNLN79MbAKdinWi6ePXEb75vzB79IdZcWj8lo
# 8trnS64QjNB9Vs4Xk5UvDALwleFN/bZeperxivDPwVPvT9Aqy/U9kohoS/LHyE8w
# uWQb5AuMeVQ1gtCTnCqQZ4d2MSVhQXYVvAWax1spJ9LT7mHub5j95xDdYIcOV3VJ
# l9CIo4VrWIT8THFN2NnjTrGq9+0TzXY0bV674bjJkfBC6v6yXs5HTetG+Uekq/xf
# FCjrrDi1+2UR9Mu2WTuvl8qn50be+mbwdJO5wE32jewxdYrVVmj19+PkaEeAwGTc
# vwIDAQAB
# -----END PUBLIC KEY-----
# publicKeyType TYPE_RAW_PUBLIC_KEY
```
The commands above verifies using the cli, however, you can also connect to the
Vault UI and check secrets there.
```shell
kubectl -n vault-system port-forward vault-0 8200:8200
```
Now, you can open http://127.0.0.1:8200/ui in browser and login with the root token.
### Cleanup
Delete the claim which should clean up all the resources created.
```
kubectl -n default delete claim my-ess
```
<!-- named links -->
[Vault]: https://www.vaultproject.io/
[External Secret Store]: https://github.com/crossplane/crossplane/blob/master/design/design-doc-external-secret-stores.md
[the previous guide]: {{<ref "vault-injection" >}}
[this issue]: https://github.com/crossplane/crossplane/issues/2985
[Kubernetes Auth Method]: https://www.vaultproject.io/docs/auth/kubernetes
[Unseal]: https://www.vaultproject.io/docs/concepts/seal
[Vault KV Secrets Engine]: https://www.vaultproject.io/docs/secrets/kv
[Vault Agent Sidecar Injection]: https://www.vaultproject.io/docs/platform/k8s/injector

View File

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

View File

@ -1,24 +0,0 @@
---
title: Reference
weight: 300
---
The reference documentation includes answers to frequently asked questions,
information about similar projects, and links to resources that can help you
learn more about Crossplane and Kubernetes. If you have additional information
that you think would be valuable for the community, please feel free to [open a
pull request] and add it.
1. [Install]
1. [Configure]
1. [Uninstall]
1. [Troubleshoot]
1. [Learn More]
<!-- Named Links -->
[open a pull request]: https://github.com/crossplane/crossplane/compare
[Install]: {{<ref "install" >}}
[Configure]: {{<ref "configure" >}}
[Uninstall]: {{<ref "uninstall" >}}
[Troubleshoot]: {{<ref "troubleshoot" >}}
[Learn More]: {{<ref "learn_more" >}}

View File

@ -1,22 +0,0 @@
---
title: Configure Your Cloud Provider Account
weight: 302
---
In order for Crossplane to be able to manage resources in a specific cloud
provider, you will need to create an account for Crossplane to use. Use the
links below for cloud-specific instructions to create an account that can be
used throughout the guides:
* [Google Cloud Platform (GCP) Service Account]
* [Microsoft Azure Service Principal]
* [Amazon Web Services (AWS) IAM User]
Once you have configured your cloud provider account, you can get started
provisioning resources!
<!-- Named Links -->
[Google Cloud Platform (GCP) Service Account]: {{<ref "../cloud-providers/gcp/gcp-provider" >}}
[Microsoft Azure Service Principal]: {{<ref "../cloud-providers/azure/azure-provider" >}}
[Amazon Web Services (AWS) IAM User]: {{<ref "../cloud-providers/aws/aws-provider" >}}

View File

@ -1,169 +0,0 @@
---
title: Install Crossplane
weight: 301
---
# Install Crossplane
Crossplane can be easily installed into any existing Kubernetes cluster using
the regularly published Helm chart. The Helm chart contains all the custom
resources and controllers needed to deploy and configure Crossplane.
## Pre-requisites
* [Kubernetes cluster], minimum version `v1.16.0+`
* [Helm], minimum version `v3.0.0+`.
## Installation
Helm charts for Crossplane are currently published to the `stable` and `master`
channels.
### Stable
The stable channel is the most recent release of Crossplane that is considered
ready for the community.
```console
kubectl create namespace crossplane-system
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane --namespace crossplane-system crossplane-stable/crossplane
```
### Master
The `master` channel contains the latest commits, with all automated tests
passing. `master` is subject to instability, incompatibility, and features may
be added or removed without much prior notice. It is recommended to use one of
the more stable channels, but if you want the absolute newest Crossplane
installed, then you can use the `master` channel.
To install the Helm chart from master, you will need to pass the specific
version returned by the `search` command:
```console
kubectl create namespace crossplane-system
helm repo add crossplane-master https://charts.crossplane.io/master/
helm repo update
helm search repo crossplane-master --devel
helm install crossplane --namespace crossplane-system crossplane-master/crossplane --devel --version <version>
```
## Uninstalling the Chart
To uninstall/delete the `crossplane` deployment:
```console
helm delete crossplane --namespace crossplane-system
```
That command removes all Kubernetes components associated with Crossplane,
including all the custom resources and controllers.
## Configuration
The following tables lists the configurable parameters of the Crossplane chart
and their default values.
{{< expand "Select to view all configuration options" >}}
{{< table "table table-hover table-striped table-sm">}}
| Parameter | Description | Default |
| --- | --- | --- |
| `affinity` | Enable affinity for Crossplane pod | `{}` |
| `image.repository` | Image | `crossplane/crossplane` |
| `image.tag` | Image tag | `master` |
| `image.pullPolicy` | Image pull policy used in all containers | `IfNotPresent` |
| `imagePullSecrets` | Names of image pull secrets to use | `dockerhub` |
| `registryCaBundleConfig.name` | Name of ConfigMap containing additional CA bundle for fetching from package registries | `{}` |
| `registryCaBundleConfig.key` | Key to use from ConfigMap containing additional CA bundle for fetching from package registries | `{}` |
| `replicas` | The number of replicas to run for the Crossplane pods | `1` |
| `deploymentStrategy` | The deployment strategy for the Crossplane and RBAC Manager (if enabled) pods | `RollingUpdate` |
| `leaderElection` | Enable leader election for Crossplane Managers pod | `true` |
| `nodeSelector` | Enable nodeSelector for Crossplane pod | `{}` |
| `customLabels` | Custom labels to add into metadata | `{}` |
| `customAnnotations` | Custom annotations to add to the Crossplane deployment and pod | `{}` |
| `serviceAccount.customAnnotations` | Custom annotations to add to the serviceaccount of Crossplane | `{}` |
| `priorityClassName` | Priority class name for Crossplane and RBAC Manager (if enabled) pods | `""` |
| `resourcesCrossplane.limits.cpu` | CPU resource limits for Crossplane | `100m` |
| `resourcesCrossplane.limits.memory` | Memory resource limits for Crossplane | `512Mi` |
| `resourcesCrossplane.requests.cpu` | CPU resource requests for Crossplane | `100m` |
| `resourcesCrossplane.requests.memory` | Memory resource requests for Crossplane | `256Mi` |
| `securityContextCrossplane.runAsUser` | Run as user for Crossplane | `65532` |
| `securityContextCrossplane.runAsGroup` | Run as group for Crossplane | `65532` |
| `securityContextCrossplane.allowPrivilegeEscalation` | Allow privilege escalation for Crossplane | `false` |
| `securityContextCrossplane.readOnlyRootFilesystem` | ReadOnly root filesystem for Crossplane | `true` |
| `provider.packages` | The list of Provider packages to install together with Crossplane | `[]` |
| `configuration.packages` | The list of Configuration packages to install together with Crossplane | `[]` |
| `packageCache.medium` | Storage medium for package cache. `Memory` means volume will be backed by tmpfs, which can be useful for development. | `""` |
| `packageCache.sizeLimit` | Size limit for package cache. If medium is `Memory` then maximum usage would be the minimum of this value the sum of all memory limits on containers in the Crossplane pod. | `5Mi` |
| `packageCache.pvc` | Name of the PersistentVolumeClaim to be used as the package cache. Providing a value will cause the default emptyDir volume to not be mounted. | `""` |
| `tolerations` | Enable tolerations for Crossplane pod | `{}` |
| `resourcesRBACManager.limits.cpu` | CPU resource limits for RBAC Manager | `100m` |
| `resourcesRBACManager.limits.memory` | Memory resource limits for RBAC Manager | `512Mi` |
| `resourcesRBACManager.requests.cpu` | CPU resource requests for RBAC Manager | `100m` |
| `resourcesRBACManager.requests.memory` | Memory resource requests for RBAC Manager | `256Mi` |
| `securityContextRBACManager.runAsUser` | Run as user for RBAC Manager | `65532` |
| `securityContextRBACManager.runAsGroup` | Run as group for RBAC Manager | `65532` |
| `securityContextRBACManager.allowPrivilegeEscalation` | Allow privilege escalation for RBAC Manager | `false` |
| `securityContextRBACManager.readOnlyRootFilesystem` | ReadOnly root filesystem for RBAC Manager | `true` |
| `rbacManager.affinity` | Enable affinity for RBAC Managers pod | `{}` |
| `rbacManager.deploy` | Deploy RBAC Manager and its required roles | `true` |
| `rbacManager.nodeSelector` | Enable nodeSelector for RBAC Managers pod | `{}` |
| `rbacManager.replicas` | The number of replicas to run for the RBAC Manager pods | `1` |
| `rbacManager.leaderElection` | Enable leader election for RBAC Managers pod | `true` |
| `rbacManager.managementPolicy`| The extent to which the RBAC manager will manage permissions. `All` indicates to manage all Crossplane controller and user roles. `Basic` indicates to only manage Crossplane controller roles and the `crossplane-admin`, `crossplane-edit`, and `crossplane-view` user roles. | `All` |
| `rbacManager.tolerations` | Enable tolerations for RBAC Managers pod | `{}` |
| `rbacManager.skipAggregatedClusterRoles` | Opt out of deploying aggregated ClusterRoles | `false` |
| `metrics.enabled` | Expose Crossplane and RBAC Manager metrics endpoint | `false` |
| `extraEnvVarsCrossplane` | List of extra environment variables to set in the crossplane deployment. Any `.` in variable names will be replaced with `_` (example: `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`). | `{}` |
| `extraEnvVarsRBACManager` | List of extra environment variables to set in the crossplane rbac manager deployment. Any `.` in variable names will be replaced with `_` (example: `SAMPLE.KEY=value1` becomes `SAMPLE_KEY=value1`). | `{}` |
| `webhooks.enabled` | Enable webhook functionality for Crossplane as well as packages installed by Crossplane. | `false` |
{{< /table >}}
{{< /expand >}}
### Command Line
You can pass the settings with helm command line parameters. Specify each
parameter using the `--set key=value[,key=value]` argument to `helm install`.
For example, the following command will install Crossplane with an image pull
policy of `IfNotPresent`.
```console
helm install --namespace crossplane-system crossplane-stable/crossplane --set image.pullPolicy=IfNotPresent
```
### Settings File
Alternatively, a yaml file that specifies the values for the above parameters
(`values.yaml`) can be provided while installing the chart.
```console
helm install crossplane --namespace crossplane-system crossplane-stable/crossplane -f values.yaml
```
Here are the sample settings to get you started.
```yaml
replicas: 1
deploymentStrategy: RollingUpdate
image:
repository: crossplane/crossplane
tag: alpha
pullPolicy: Always
imagePullSecrets:
- dockerhub
```
<!-- Named Links -->
[Kubernetes cluster]: https://kubernetes.io/docs/setup/
[Minikube]: https://kubernetes.io/docs/tasks/tools/install-minikube/
[Helm]: https://docs.helm.sh/using_helm/

View File

@ -1,35 +0,0 @@
---
title: Learn More
weight: 307
---
If you have any questions, please drop us a note on [Crossplane Slack][join-crossplane-slack] or [contact us][contact-us]!
***Learn more about using Crossplane***
- [Latest Design Docs](https://github.com/crossplane/crossplane/tree/master/design)
- [Roadmap](https://github.com/crossplane/crossplane/blob/master/ROADMAP.md)
- [Crossplane Architecture](https://docs.google.com/document/d/1whncqdUeU2cATGEJhHvzXWC9xdK29Er45NJeoemxebo/edit?usp=sharing)
- [GitLab deploys into multiple clouds from kubectl using Crossplane](https://about.gitlab.com/2019/05/20/gitlab-first-deployed-kubernetes-api-to-multiple-clouds/)
- [CNCF Talks & Community Presentations](https://www.youtube.com/playlist?list=PL510POnNVaaZJj9OG6PbgsZvgYbhwJRyE)
- [Software Engineering Daily - Intro Podcast](https://softwareengineeringdaily.com/2019/01/02/crossplane-multicloud-control-plane-with-bassam-tabbara/)
***Writing Kubernetes controllers to extend Crossplane***
- [Keep the Space Shuttle Flying: Writing Robust Operators](https://www.youtube.com/watch?v=uf97lOApOv8)
- [Best practices for building Kubernetes Operators](https://cloud.google.com/blog/products/containers-kubernetes/best-practices-for-building-kubernetes-operators-and-stateful-apps)
- [Programming Kubernetes Book](https://www.oreilly.com/library/view/programming-kubernetes/9781492047094/)
- [Contributor Guide](https://github.com/crossplane/crossplane/blob/master/CONTRIBUTING.md)
***Join the growing Crossplane community and get involved!***
- Join our [Community Slack](https://slack.crossplane.io/)!
- Submit an issue on [GitHub](https://github.com/crossplane/crossplane)
- Attend our bi-weekly [Community Meeting](https://github.com/crossplane/crossplane#get-involved)
- Join our bi-weekly live stream: [The Binding Status](https://github.com/crossplane/tbs)
- Subscribe to our [YouTube Channel](https://www.youtube.com/channel/UC19FgzMBMqBro361HbE46Fw)
- Drop us a note on Twitter: [@crossplane_io](https://twitter.com/crossplane_io)
- Email us: [info@crossplane.io](mailto:info@crossplane.io)
<!-- Named links -->
[join-crossplane-slack]: https://slack.crossplane.io
[contact-us]: https://github.com/crossplane/crossplane#contact

View File

@ -1,91 +0,0 @@
---
title: Release Cycle
weight: 308
---
Starting with the v1.0.0 release, Crossplane is released on an eight week
cadence. A cycle is comprised of three general stages:
- Weeks 1-6: [Active Development]
- Week 7: [Feature Freeze]
- Week 8: [Code Freeze]
This results in six releases per year, with the most recent three releases being
maintained at any given time. When a new release is cut, the fourth most recent
release reaches end of life (EOL). Users can expect any given release to be
maintained for six months.
### Definition of Maintenance
The Crossplane community defines maintenance in that relevant bug fixes that are
merged to the main development branch will be eligible to be back-ported to the
release branch of any currently maintained version, and patch releases will be
cut appropriately. It is also possible that a fix may be merged directly to the
release branch if no longer applicable on the main development branch.
Maintenance does not indicate any SLA on response time for user support in the
form of Slack messages or issues, but problems will be addressed on a best
effort basis by maintainers and contributors for currently maintained releases.
### Patch Releases
_This policy is subject to change in the future._
Patch releases are cut for currently maintained minor versions on an as-needed
basis. Any critical back-ported fixes will be included in a patch release as
soon as possible after merge.
### Pre-Releases
_This policy is subject to change in the future._
Alpha, Beta, and RC releases are cut for an upcoming release on an as-needed
basis. As a policy, at least one pre-release will be cut prior to any minor
release. Pre-releases will not be made on release branches.
### Provider Releases
The Crossplane release cycle is not required to be adhered to by any other
Crossplane projects, but a similar cadence is encouraged. Maintainers listed in
each repository's `OWNERS.md` file are responsible for determining and
publishing the release cycle for their project.
## Release Stages
The following stages are the main milestones in a Crossplane release.
### Active Development
During active development, any code that meets the requisite criteria (i.e.
passing appropriate tests, approved by a maintainer, etc.) will be merged into
the main development branch. At present, there is no requirement to formally
submit an enhancement proposal prior to the start of the release cycle, but
contributors are encouraged to open an issue and gather feedback before starting
work on a major implementation (see [CONTRIBUTING.md] for more information).
### Feature Freeze
During feature freeze, no new functionality should be merged into the main
development branch. Bug fixes, documentation changes, and non-critical changes
may be made. In the case that a new feature is deemed absolutely necessary for a
release, the Crossplane maintainers will weigh the impact of the change and make
a decision on whether it should be included.
### Code Freeze
During code freeze, there should be no changes merged to the main development
branch with the following exceptions:
- Fixes to a failing test that is deemed to be incorrectly testing
functionality.
- Documentation only changes. It is possible that a documentation freeze will be
implemented in the future, but it is not currently enforced.
- Fixes to a critical bug that was not previously identified. Merging a bug fix
during code freeze requires application for and approval of an exception by
Crossplane maintainers. This process is currently informal, but may be
formalized in the future.
<!-- Named links -->
[Active Development]: #active-development
[Feature Freeze]: #feature-freeze
[Code Freeze]: #code-freeze
[CONTRIBUTING.md]: https://github.com/crossplane/crossplane/blob/master/CONTRIBUTING.md

View File

@ -1,292 +0,0 @@
---
title: Troubleshoot
weight: 306
---
* [Requested Resource Not Found]
* [Resource Status and Conditions]
* [Resource Events]
* [Crossplane Logs]
* [Provider Logs]
* [Pausing Crossplane]
* [Pausing Providers]
* [Deleting When a Resource Hangs]
* [Installing Crossplane Package]
* [Handling Crossplane Package Dependency]
## Requested Resource Not Found
If you use the kubectl Crossplane plugin to install a `Provider` or
`Configuration` (e.g. `kubectl crossplane install provider
xpkg.upbound.io/crossplane-contrib/provider-aws:v0.33.0`) and get `the server
could not find the requested resource` error, more often than not, that is an
indicator that the kubectl Crossplane you're using is outdated. In other words
some Crossplane API has been graduated from alpha to beta or stable and the old
plugin is not aware of this change.
You can follow the [install Crossplane CLI] instructions to upgrade the plugin.
## Resource Status and Conditions
Most Crossplane resources have a `status` section that can represent the current
state of that particular resource. Running `kubectl describe` against a
Crossplane resource will frequently give insightful information about its
condition. For example, to determine the status of a GCP `CloudSQLInstance`
managed resource, run:
```shell
kubectl describe cloudsqlinstance my-db
```
This should produce output that includes:
```console
Status:
Conditions:
Last Transition Time: 2019-09-16T13:46:42Z
Reason: Creating
Status: False
Type: Ready
```
Most Crossplane resources set the `Ready` condition. `Ready` represents the
availability of the resource - whether it is creating, deleting, available,
unavailable, binding, etc.
## Resource Events
Most Crossplane resources emit _events_ when something interesting happens. You
can see the events associated with a resource by running `kubectl describe` -
e.g. `kubectl describe cloudsqlinstance my-db`. You can also see all events in a
particular namespace by running `kubectl get events`.
```console
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning CannotConnectToProvider 16s (x4 over 46s) managed/postgresqlserver.database.azure.crossplane.io cannot get referenced ProviderConfig: ProviderConfig.azure.crossplane.io "default" not found
```
> Note that events are namespaced, while many Crossplane resources (XRs, etc)
> are cluster scoped. Crossplane emits events for cluster scoped resources to
> the 'default' namespace.
## Crossplane Logs
The next place to look to get more information or investigate a failure would be
in the Crossplane pod logs, which should be running in the `crossplane-system`
namespace. To get the current Crossplane logs, run the following:
```shell
kubectl -n crossplane-system logs -lapp=crossplane
```
> Note that Crossplane emits few logs by default - events are typically the best
> place to look for information about what Crossplane is doing. You may need to
> restart Crossplane with the `--debug` flag if you can't find what you're
> looking for.
## Provider Logs
Remember that much of Crossplane's functionality is provided by providers. You
can use `kubectl logs` to view provider logs too. By convention, they also emit
few logs by default.
```shell
kubectl -n crossplane-system logs <name-of-provider-pod>
```
All providers maintained by the Crossplane community mirror Crossplane's support
of the `--debug` flag. The easiest way to set flags on a provider is to create a
`ControllerConfig` and reference it from the `Provider`:
```yaml
apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
name: debug-config
spec:
args:
- --debug
---
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: debug-config
```
> Note that a reference to a `ControllerConfig` can be added to an already
> installed `Provider` and it will update its `Deployment` accordingly.
## Pausing Crossplane
Sometimes, for example when you encounter a bug, it can be useful to pause
Crossplane if you want to stop it from actively attempting to manage your
resources. To pause Crossplane without deleting all of its resources, run the
following command to simply scale down its deployment:
```bash
kubectl -n crossplane-system scale --replicas=0 deployment/crossplane
```
Once you have been able to rectify the problem or smooth things out, you can
unpause Crossplane simply by scaling its deployment back up:
```bash
kubectl -n crossplane-system scale --replicas=1 deployment/crossplane
```
## Pausing Providers
Providers can also be paused when troubleshooting an issue or orchestrating a
complex migration of resources. Creating and referencing a `ControllerConfig` is
the easiest way to scale down a provider, and the `ControllerConfig` can be
modified or the reference can be removed to scale it back up:
```yaml
apiVersion: pkg.crossplane.io/v1alpha1
kind: ControllerConfig
metadata:
name: scale-config
spec:
replicas: 0
---
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: scale-config
```
> Note that a reference to a `ControllerConfig` can be added to an already
> installed `Provider` and it will update its `Deployment` accordingly.
## Deleting When a Resource Hangs
The resources that Crossplane manages will automatically be cleaned up so as not
to leave anything running behind. This is accomplished by using finalizers, but
in certain scenarios the finalizer can prevent the Kubernetes object from
getting deleted.
To deal with this, we essentially want to patch the object to remove its
finalizer, which will then allow it to be deleted completely. Note that this
won't necessarily delete the external resource that Crossplane was managing, so
you will want to go to your cloud provider's console and look there for any
lingering resources to clean up.
In general, a finalizer can be removed from an object with this command:
```console
kubectl patch <resource-type> <resource-name> -p '{"metadata":{"finalizers": []}}' --type=merge
```
For example, for a `CloudSQLInstance` managed resource (`database.gcp.crossplane.io`) named
`my-db`, you can remove its finalizer with:
```console
kubectl patch cloudsqlinstance my-db -p '{"metadata":{"finalizers": []}}' --type=merge
```
## Installing Crossplane Package
After installing [Crossplane package], to verify the install results or
troubleshoot any issue spotted during the installation, there are a few things
you can do.
Run below command to list all Crossplane resources available on your cluster:
```console
kubectl get crossplane
```
If you installed a Provider package, pay attention to the `Provider` and
`ProviderRevision` resource. Especially the `INSTALLED` and `HEALTHY` column.
They all need to be `TRUE`. Otherwise, there must be some errors that occurred
during the installation.
If you installed a Configuration package, pay attention to the `Configuration`
and `ConfigurationRevision` resource. Again, the `INSTALLED` and `HEALTHY`
column for these resources need to be `TRUE`. Besides that, you should also see
the `CompositeResourceDefinition` and `Composition` resources included in this
package are listed if the package is installed successfully.
If you only care about the installed packages, you can also run below command
which will show you all installed Configuration and Provider packages:
```console
kubectl get pkg
```
When there are errors, you can run below command to check detailed information
for the packages that are getting installed.
```console
kubectl get lock -o yaml
```
To inspect a particular package for troubleshooting, you can run
`kubectl describe` against the corresponding resources, e.g. the `Provider` and
`ProviderRevision` resource for Provider package, or the `Configuration` and
`ConfigurationRevision` resource for Configuration package. Usually, you should
be able to know the error reason by checking the `Status` and `Events` field for
these resources.
## Handling Crossplane Package Dependency
When using `crossplane.yaml` to define a Crossplane Configuration package, you
can specify packages that it depends on by including `spec.dependsOn`. You can
also specify version constraints for dependency packages.
When you define a dependency package, please make sure you provide the fully
qualified address to the dependency package, but do not append the package
version (i.e. the OCI image tag) after the package name. This may lead to the
missing dependency error when Crossplane tries to install the dependency.
When specifying the version constraint, you should strictly follow the
[semver spec]. Otherwise, it may not be able to find the appropriate version for
the dependency package even it says the dependency is found. This may lead to an
incompatible dependency error during the installation.
Below is an example where a Configuration package depends on a provider pulled
from `xpkg.upbound.io/crossplane-contrib/provider-aws`. It defines `">=v0.18.2`
as the version constraint which means all versions after `v0.16.0` including all
prerelease versions, in the form of `-xyz` after the normal version string, will
be considered when Crossplane tries to find the best match.
```yaml
apiVersion: meta.pkg.crossplane.io/v1
kind: Configuration
metadata:
name: test-configuration
annotations:
provider: aws
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-aws
version: ">=v0.18.2"
```
<!-- Named Links -->
[Requested Resource Not Found]: #requested-resource-not-found
[install Crossplane CLI]: {{<ref "../getting-started/install-configure" >}}#install-crossplane-cli
[Resource Status and Conditions]: #resource-status-and-conditions
[Resource Events]: #resource-events
[Crossplane Logs]: #crossplane-logs
[Provider Logs]: #provider-logs
[Pausing Crossplane]: #pausing-crossplane
[Pausing Providers]: #pausing-providers
[Deleting When a Resource Hangs]: #deleting-when-a-resource-hangs
[Installing Crossplane Package]: #installing-crossplane-package
[Crossplane package]: {{<ref "../concepts/packages" >}}
[Handling Crossplane Package Dependency]: #handling-crossplane-package-dependency
[semver spec]: https://github.com/Masterminds/semver#basic-comparisons

View File

@ -1,87 +0,0 @@
---
title: Uninstall
weight: 303
---
Crossplane has a number of components that must be cleaned up in order to
guarantee proper removal from the cluster. When deleting objects, it is best to
consider parent-child relationships and clean up the children first to ensure
the proper action is taken externally. For instance, cleaning up `provider-aws`
before deleting an `RDSInstance` will result in the RDS instance remaining
provisioned on AWS as the controller responsible for cleaning it up will have
already been deleted. It will also result in the `RDSInstance` CRD remaining in
the cluster, which could make it difficult to re-install the same provider at a
future time.
## Deleting Resources
If you wish for all claims (XRC), composite resources (XR), and managed
resources to have deletion handled properly both in the cluster in externally,
they should be deleted and no longer exist in cluster before the package that
extended the Kubernetes API to include them is uninstalled. You can use the
following logic to clean up resources effectively:
- If an XRC exists for a given XR and set of managed resources, delete the XRC
and both the XR and managed resources will be cleaned up.
- If only an XR exists for a given set of managed resources, delete the XR and
each of the managed resources will be cleaned up.
- If a managed resource was provisioned directly, delete it directly.
The following commands can be used to identify existing XRC, XR, and managed
resources:
- XRC: `kubectl get claim`
- XR: `kubectl get composite`
- Managed Resources: `kubectl get managed`
Crossplane controllers add [finalizers] to resources to ensure they are handled
externally before they are fully removed from the cluster. If resource deletion
hangs it is likely due to a delay in the resource being handled externally,
causing the controller to wait to remove the finalizer. If this persists for a
long period of time, use the [troubleshooting guide] to fix the issue.
## Uninstall Packages
Once all resources are cleaned up, it is safe to uninstall packages.
`Configuration` packages can typically be deleted safely with the following
command:
```console
kubectl delete configuration.pkg <configuration-name>
```
Before deleting `Provider` packages, you will want to make sure you have deleted
all `ProviderConfig`s you created. An example command if you used AWS Provider:
```console
kubectl delete providerconfig.aws --all
```
Now you are safe to delete the `Provider` package:
```console
kubectl delete provider.pkg <provider-name>
```
## Uninstall Crossplane
When all resources and packages have been cleaned up, you are safe to uninstall
Crossplane:
```console
helm delete crossplane --namespace crossplane-system
kubectl delete namespace crossplane-system
```
Helm does not delete CRD objects. You can delete the ones Crossplane created
with the following commands:
```console
kubectl get crd -o name | grep crossplane.io | xargs kubectl delete
```
<!-- Named Links -->
[finalizers]: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#finalizers
[troubleshooting guide]: {{<ref "troubleshoot" >}}

View File

@ -1,211 +0,0 @@
---
title: xpkg Specification
weight: 305
---
Crossplane supports two types of [packages]: Providers and Configurations. These
packages are distributed as generic [OCI images], which contain [YAML] content
informing the Crossplane package manager how to alter the state of a cluster by
installing objects that configure new resource types, and starting controllers
to reconcile them. An OCI image that contains valid Crossplane package content
is commonly referred to as an `xpkg` ("ex-package"). This document provides the
specification for a valid `xpkg`, which can be considered a superset of the
requirements detailed in the [OCI image specification]. It is divided into two
broad sections: requirements related to OCI image format and requirements
related to Crossplane `package.yaml` contents.
- [OCI Image Format](#oci-image-format)
- [Indexes](#indexes)
- [Manifests](#manifests)
- [Configuration](#configuration)
- [Layers](#layers)
- [package.yaml Contents](#packageyaml-contents)
- [Configuration Package Requirements](#configuration-package-requirements)
- [Provider Package Requirements](#provider-package-requirements)
- [Object Annotations](#object-annotations)
## OCI Image Format
OCI images are comprised of [manifests], [configuration], and [layers].
Additionally, an image reference could refer to an image [index], which may
reference multiple image manifests and is frequently used for multi-platform
images. A valid Crossplane `xpkg` imposes various requirements on the components
of an OCI, each of which are described in the following sections.
### Indexes
The components of an `xpkg` that Crossplane interacts with do not contain any
platform-specific information, so Crossplane is broadly agnostic to the
formatting of an image index. Crossplane does impose the following requirements
on an image index:
- At least one (1) manifest MUST be referenced in the manifest descriptor array
for a package to be successfully fetched and processed.
> The OCI image specification allows for zero-length manifest descriptor arrays
> in an index.
The following default behavior when interacting with image indexes is
implemented in the Crossplane package manager:
- If one manifest is referenced in the image index, the image it points to will
be used.
- If multiple manifests are referenced in the image index, Crossplane will use
the `linux/amd64` variant by default.
> It is important to note that the platform of the package image that is used by
> Crossplane does not necessarily mean that the same platform will be used for
> the controller if the package is a Provider. The decision of selecting a
> platform for a Provider controller image is deferred to the configured
> container runtime.
### Manifests
A manifest defines the layers and configuration of a specific image. Crossplane
is only concerned with the layer descriptors array in an image manifest and does
not impose additional requirements on any other portions of the manifest. The
following requirements are imposed on the layer descriptors array:
- One (1) layer descriptor in the array MAY have an [annotation] with key
`io.crossplane.xpkg` and value `base`.
- Any number of layer descriptors in the array MAY have an annotation with key
`io.crossplane.xpkg` and arbitrary value. Whether multiple layer descriptors
may have the same value is left to the specification of the consumer of those
layers.
> As evidenced by the fact that annotations are provided as a map of
> _string-string_, no single descriptor will contain multiple
> `io.crossplane.xpkg` annotations.
Crossplane is only concerned with the layer with the `base` annotation, and any
other layers with the `io.crossplane.xpkg` key are used to signify to
third-party consumers that a layer contains content related to the `xpkg` that
may be specific to a given consumer.
If no layer descriptors have an annotation in the form `io.crossplane.xpkg:
base`, the resultant filesystem from [applying changesets] from all layers will
be used. It is preferred to use layer descriptor annotations.
**Motivation**
Crossplane prefers the usage of annotated layer descriptors because it allows
for fetching and processing individual layers, rather than all layers in the
image. In the event that the image contains a single layer, this overhead is
minimal. However, larger images with many layers, whether they contain
third-party `xpkg` content or unrelated data, will result in multiple network
calls and more data to process.
Crossplane also prefers the usage of annotated layer descriptors to define
additive package content (i.e. third-party `xpkg` content) as it provides a
clean mechanism to build an `xpkg` through a series of stages. A valid `xpkg`
can be produced and later modified while verifying that the integrity of the
existing content is not violated, which ensures that Crossplane's package
manager will process the resulting `xpkg` in the same manner as the it would
prior to modification.
While not explicitly forbidden, modifying content from a preceding layer with
the `io.crossplane.xpkg` annotation in any subsequent layers is discouraged, as
it may lead to confusion if a third-party is consuming content from the
flattened filesystem.
### Configuration
Crossplane imposes no additional requirements on image configuration and does
not consider its contents when processing a package.
### Layers
As described above, Crossplane is only concerned with the single layer
referenced by the descriptor containing `io.crossplane.xpkg: base` if
distinguished. Crossplane imposes no additional restrictions on any other
layers, including those with a `io.crossplane.xpkg` annotation but a value other
than `base`, but does require the following of the `xpkg` base layer:
- A single file with name `package.yaml` MUST exist in the root directory of the
`xpkg` base layer if distinguished, or in the root of the image filesystem
after all layer changesets are applied.
- The `package.yaml` file MUST contain a valid [YAML stream].
- All other content in either the `xpkg` base layer, or the full image
filesystem is ignored by Crossplane.
> The ability to use the image's flattened filesystem is primarily for backwards
> compatibility and is not encouraged, especially in the event that an image
> contains more than just `xpkg` related content, due to the fact that
> accidentally overwriting or modifying the `xpkg` layer contents in subsequent
> layers when constructing an image could cause the package to be invalid.
## package.yaml Contents
Depending on the type of package, the YAML stream in the `xpkg` base layer
`package.yaml` may contain different content. Additionally, the objects in the
YAML stream may contain common annotations that are suitable for the given
object type.
### Configuration Package Requirements
The `package.yaml` for Configuration packages must adhere to the following
requirements:
- One (1) and only one `Configuration.meta.pkg.crossplane.io` object MUST be
defined in the YAML stream.
- Zero (0) or more `CompositeResourceDefinition.apiextensions.crossplane.io`
objects MAY be defined in the YAML stream.
- Zero (0) or more `Composition.apiextensions.crossplane.io` objects MAY be
defined in the YAML stream.
- Zero (0) other object types may be defined in the YAML stream.
### Provider Package Requirements
The `package.yaml` for Provider packages must adhere to the following
requirements:
- One (1) and only one `Provider.meta.pkg.crossplane.io` object MUST be defined
in the YAML stream.
- Zero (0) or more `CustomResourceDefinition.apiextensions.k8s.io` objects MAY
be defined in the YAML stream.
- Zero (0) or more `AdmissionWebhookConfiguration.admissionregistration.k8s.io`
objects MAY be defined in the YAML stream.
- Zero (0) or more `MutatingWebhookConfiguration.admissionregistration.k8s.io`
objects MAY be defined in the YAML stream.
- Zero (0) other object types may be defined in the YAML stream.
### Object Annotations
Though not used directly by Crossplane, the following object metadata
annotations (not to be confused with descriptor annotations in an OCI image
manifest) are defined for `Configuration.meta.pkg.crossplane.io` and
`Provider.meta.pkg.crossplane.io` and should be honored over any competing
annotations by third-party consumers of Crossplane packages:
- `meta.crossplane.io/maintainer`: The package's maintainers, as a short opaque
text string.
- `meta.crossplane.io/source`: The URL at which the package's source can be
found.
- `meta.crossplane.io/license`: The license under which the package's source is
released. This should be a valid [SPDX License Identifier].
- `meta.crossplane.io/description`: A one sentence description of the package.
- `meta.crossplane.io/readme`: A longer description, documentation, etc.
Third party consumers may define additional arbitrary annotations with any key
and value on any object in a package. All annotations on "meta" types (i.e.
`Configuration.meta.pkg.crossplane.io` and `Provider.meta.pkg.crossplane.io`)
are propagated to the respective package revision (i.e.
`ConfigurationRevision.pkg.crossplane.io` and
`ProviderRevision.pkg.crossplane.io`) on package install. Annotations on all
other objects in a package are propagated to their in-cluster representation
unmodified.
<!-- Named Links -->
[packages]: {{<ref "../concepts/packages" >}}
[OCI images]: https://github.com/opencontainers/image-spec
[OCI image specification]: https://github.com/opencontainers/image-spec/blob/main/spec.md
[YAML]: https://yaml.org/spec/1.2.2/
[YAML stream]: https://yaml.org/spec/1.2.2/#92-streams
[manifests]: https://github.com/opencontainers/image-spec/blob/main/manifest.md
[configuration]: https://github.com/opencontainers/image-spec/blob/main/config.md
[layers]: https://github.com/opencontainers/image-spec/blob/main/layer.md
[index]: https://github.com/opencontainers/image-spec/blob/main/image-index.md
[annotation]: https://github.com/opencontainers/image-spec/blob/main/annotations.md
[applying changesets]: https://github.com/opencontainers/image-spec/blob/main/layer.md#applying-changesets
[SPDX License Identifier]: https://spdx.org/licenses/

View File

@ -1,13 +0,0 @@
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
name: my-db
namespace: default
spec:
parameters:
storageGB: 20
compositionSelector:
matchLabels:
provider: aws
writeConnectionSecretToRef:
name: db-conn

View File

@ -1,13 +0,0 @@
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
name: my-db
namespace: default
spec:
parameters:
storageGB: 20
compositionSelector:
matchLabels:
provider: azure
writeConnectionSecretToRef:
name: db-conn

View File

@ -1,13 +0,0 @@
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
name: my-db
namespace: default
spec:
parameters:
storageGB: 20
compositionSelector:
matchLabels:
provider: gcp
writeConnectionSecretToRef:
name: db-conn

View File

@ -1,34 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
name: see-db
namespace: default
spec:
containers:
- name: see-db
image: postgres:12
command: ['psql']
args: ['-c', 'SELECT current_database();']
env:
- name: PGDATABASE
value: postgres
- name: PGHOST
valueFrom:
secretKeyRef:
name: db-conn
key: endpoint
- name: PGUSER
valueFrom:
secretKeyRef:
name: db-conn
key: username
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: db-conn
key: password
- name: PGPORT
valueFrom:
secretKeyRef:
name: db-conn
key: port

View File

@ -1,12 +0,0 @@
---
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds
key: creds

View File

@ -1,53 +0,0 @@
#!/usr/bin/env bash
#
# This is a helper script that uses ~/.aws/credentials and ~/.aws/config
# to build an aws provider object
#
# aws configuration (credentials and default region) is required for this
# script
set -e -o pipefail
# change to script directory
cd "$( cd "$( dirname "${BASH_SOURCE[0]}")" && pwd )"
aws_profile=
while (( "$#" )); do
if test -z "$2"; then
echo "invalid value for $1 option"
exit -1
fi
case "$1" in
-p|--profile)
aws_profile=$2
shift 2
;;
*)
shift
;;
esac
done
# make sure kubectl is configured
kubectl cluster-info > /dev/null || echo "KUBECONFIG is not configured properly"
# if aws_profile is not provided, use default
aws_profile="${aws_profile:-default}"
# retrieve aws profile credentials, save it under 'default' profile, and base64 encode it
AWS_CREDS_BASE64=$(echo -e "[default]\naws_access_key_id = $(aws configure get aws_access_key_id --profile $aws_profile)\naws_secret_access_key = $(aws configure get aws_secret_access_key --profile $aws_profile)" | base64 | tr -d "\n")
if test -z "$AWS_CREDS_BASE64"; then
echo "error reading credentials from aws config"
exit 1
fi
echo "apiVersion: v1
data:
creds: $AWS_CREDS_BASE64
kind: Secret
metadata:
name: aws-creds
namespace: crossplane-system
type: Opaque" | kubectl apply -f -

View File

@ -1,12 +0,0 @@
---
apiVersion: azure.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: azure-creds
key: creds

View File

@ -1,84 +0,0 @@
#!/usr/bin/env bash
#
# This is a helper script to create a project, service account, and credentials.json
# file for use in Crossplane GCP examples
#
# gcloud is required for use and must be configured with privileges to perform these tasks
#
set -e -o pipefail
ROLES=(roles/iam.serviceAccountUser roles/cloudsql.admin roles/container.admin roles/redis.admin roles/compute.networkAdmin roles/storage.admin)
SERVICES=(container.googleapis.com sqladmin.googleapis.com redis.googleapis.com compute.googleapis.com servicenetworking.googleapis.com)
KEYFILE=crossplane-gcp-provider-key.json
RAND=$RANDOM
if ! command -v gcloud > /dev/null; then
echo "Please install gcloud: https://cloud.google.com/sdk/install"
exit 1
fi
tab () { sed 's/^/ /' ; }
# list your organizations (if applicable), take note of the specific organization ID you want to use
# if you have more than one organization (not common)
gcloud organizations list --format '[box]' 2>&1 | tab
ORGANIZATION_ID=$(gcloud organizations list --format 'value(ID)' --limit 1)
read -e -p "Choose an Organization ID [$ORGANIZATION_ID]: " PROMPT_ORGANIZATION_ID
ORGANIZATION_ID=${PROMPT_ORGANIZATION_ID:-$ORGANIZATION_ID}
gcloud projects list --format '[box]' 2>&1 | tab
# create a new id
EXAMPLE_PROJECT_ID="crossplane-example-$RAND"
read -e -p "Choose or create a Project ID [$EXAMPLE_PROJECT_ID]: " PROMPT_EXAMPLE_PROJECT_ID
EXAMPLE_PROJECT_ID=${PROMPT_EXAMPLE_PROJECT_ID:-$EXAMPLE_PROJECT_ID}
EXAMPLE_PROJECT_ID_FOUND=$(gcloud projects list --filter PROJECT_ID="$EXAMPLE_PROJECT_ID" --format="value(PROJECT_ID)")
if [[ -z $EXAMPLE_PROJECT_ID_FOUND ]]; then
ACCOUNT_ID=$(gcloud beta billing accounts list --format 'value(ACCOUNT_ID)' --limit 1)
gcloud beta billing accounts list --format '[box]' 2>&1 | tab
read -e -p "Choose a Billing Account ID [$ACCOUNT_ID]: " PROMPT_ACCOUNT_ID
ACCOUNT_ID=${PROMPT_ACCOUNT_ID:-$ACCOUNT_ID}
echo -e "\n* Creating Project $EXAMPLE_PROJECT_ID ... "
gcloud projects create $EXAMPLE_PROJECT_ID --enable-cloud-apis --organization $ORGANIZATION_ID 2>&1 | tab
echo "* Linking Billing Account $ACCOUNT_ID with Project $EXAMPLE_PROJECT_ID ... "
gcloud beta billing projects link $EXAMPLE_PROJECT_ID --billing-account=$ACCOUNT_ID 2>&1 | tab
else
echo -n "\n* Using Project $EXAMPLE_PROJECT_NAME ... $EXAMPLE_PROJECT_ID"
fi
# enable Kubernetes API
for service in "${SERVICES[@]}"; do
# enable Google API
echo "* Enabling Service $service on $EXAMPLE_PROJECT_ID"
gcloud --project $EXAMPLE_PROJECT_ID services enable $service 2>&1 | tab
done
# create service account
SA_NAME="example-$RAND"
echo " * Creating a Service Account"
gcloud --project $EXAMPLE_PROJECT_ID iam service-accounts create $SA_NAME --display-name "Crossplane Example" 2>&1 | tab
# export service account email
EXAMPLE_SA="${SA_NAME}@${EXAMPLE_PROJECT_ID}.iam.gserviceaccount.com"
# assign roles
for role in "${ROLES[@]}"; do
echo "* Adding Role $role to $EXAMPLE_SA on $EXAMPLE_PROJECT_ID"
gcloud projects add-iam-policy-binding $EXAMPLE_PROJECT_ID --member "serviceAccount:$EXAMPLE_SA" --role="$role" 2>&1 | tab
done
# create service account key (this will create a `crossplane-gcp-provider-key.json` file in your current working directory)
echo " * Creating $EXAMPLE_SA Key File $KEYFILE"
gcloud --project $EXAMPLE_PROJECT_ID iam service-accounts keys create --iam-account $EXAMPLE_SA $KEYFILE 2>&1 | tab
cat <<EOS
#
# Run the following for the variables that are used throughout the GCP example projects
#
export ORGANIZATION_ID=$ORGANIZATION_ID
export PROJECT_ID=$EXAMPLE_PROJECT_ID
export EXAMPLE_SA=$EXAMPLE_SA
export BASE64ENCODED_GCP_PROVIDER_CREDS=\$(base64 $KEYFILE | tr -d "\n")
EOS

View File

@ -1,160 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: vpcpostgresqlinstances.aws.database.example.org
labels:
provider: aws
guide: quickstart
vpc: new
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: vpc
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: VPC
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.0.0/16
enableDnsSupport: true
enableDnsHostNames: true
- name: subnet-a
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1a
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.64.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1a
- name: subnet-b
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1b
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.128.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1b
- name: subnet-c
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
metadata:
labels:
zone: us-east-1c
spec:
forProvider:
region: us-east-1
cidrBlock: 192.168.192.0/18
vpcIdSelector:
matchControllerRef: true
availabilityZone: us-east-1c
- name: dbsubnetgroup
base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: DBSubnetGroup
spec:
forProvider:
region: us-east-1
description: An excellent formation of subnetworks.
subnetIdSelector:
matchControllerRef: true
- name: internetgateway
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: InternetGateway
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
- name: routetable
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: RouteTable
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
routes:
- destinationCidrBlock: 0.0.0.0/0
gatewayIdSelector:
matchControllerRef: true
associations:
- subnetIdSelector:
matchLabels:
zone: us-east-1a
- subnetIdSelector:
matchLabels:
zone: us-east-1b
- subnetIdSelector:
matchLabels:
zone: us-east-1c
- name: securitygroup
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: SecurityGroup
spec:
forProvider:
region: us-east-1
vpcIdSelector:
matchControllerRef: true
groupName: crossplane-getting-started
description: Allow access to PostgreSQL
ingress:
- fromPort: 5432
toPort: 5432
ipProtocol: tcp
ipRanges:
- cidrIp: 0.0.0.0/0
description: Everywhere
- name: rdsinstance
base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
spec:
forProvider:
region: us-east-1
dbSubnetGroupNameSelector:
matchControllerRef: true
vpcSecurityGroupIDSelector:
matchControllerRef: true
dbInstanceClass: db.t2.small
masterUsername: masteruser
engine: postgres
engineVersion: "12"
skipFinalSnapshotBeforeDeletion: true
publiclyAccessible: true
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.allocatedStorage"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- fromConnectionSecretKey: port

View File

@ -1,29 +0,0 @@
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-aws-with-vpc
annotations:
meta.crossplane.io/maintainer: Crossplane Maintainers <info@crossplane.io>
meta.crossplane.io/source: github.com/crossplane/crossplane
meta.crossplane.io/license: Apache-2.0
meta.crossplane.io/description: |
An introductory example to Crossplane and Composition for AWS.
meta.crossplane.io/readme: |
An introductory example to Crossplane and Composition for AWS.
This will enable provisioning of an RDS database instance.
The example also illustrates how to specify a non-default VPC.
[Install &
Configure](https://crossplane.io/docs/master/getting-started/install-configure.html)
[Provision a PostgreSQL RDS
Database](https://crossplane.io/docs/master/getting-started/provision-infrastructure.html)
guide: quickstart
provider: aws
vpc: new
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-aws
version: ">=v0.24.1"

View File

@ -1,40 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
description: "The OpenAPIV3Schema of this Composite Resource Definition."
properties:
parameters:
type: object
properties:
storageGB:
type: integer
description: "The desired storage capacity of the database, in GB."
required:
- storageGB
required:
- parameters

View File

@ -1,44 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgresqlinstances.aws.database.example.org
labels:
provider: aws
guide: quickstart
vpc: default
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: rdsinstance
base:
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
spec:
forProvider:
region: us-east-1
dbInstanceClass: db.t2.small
masterUsername: masteruser
engine: postgres
engineVersion: "12"
skipFinalSnapshotBeforeDeletion: true
publiclyAccessible: true
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.allocatedStorage"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- fromConnectionSecretKey: port

View File

@ -1,29 +0,0 @@
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-aws
annotations:
meta.crossplane.io/maintainer: Crossplane Maintainers <info@crossplane.io>
meta.crossplane.io/source: github.com/crossplane/crossplane
meta.crossplane.io/license: Apache-2.0
meta.crossplane.io/description: |
An introductory example to Crossplane and Composition for AWS.
meta.crossplane.io/readme: |
An introductory example to Crossplane and Composition for AWS.
This will enable provisioning of an RDS database instance.
[Install &
Configure](https://crossplane.io/docs/master/getting-started/install-configure.html)
[Provision a PostgreSQL RDS
Database](https://crossplane.io/docs/master/getting-started/provision-infrastructure.html)
labels:
guide: quickstart
provider: aws
vpc: default
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-aws
version: ">=v0.24.1"

View File

@ -1,40 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
description: "The OpenAPIV3Schema of this Composite Resource Definition."
properties:
parameters:
type: object
properties:
storageGB:
type: integer
description: "The desired storage capacity of the database, in GB."
required:
- storageGB
required:
- parameters

View File

@ -1,73 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgresqlinstances.azure.database.example.org
labels:
provider: azure
guide: quickstart
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: resourcegroup
base:
apiVersion: azure.crossplane.io/v1alpha3
kind: ResourceGroup
spec:
location: West US 2
- name: postgresqlserver
base:
apiVersion: database.azure.crossplane.io/v1beta1
kind: PostgreSQLServer
spec:
forProvider:
administratorLogin: myadmin
resourceGroupNameSelector:
matchControllerRef: true
location: West US 2
sslEnforcement: Disabled
version: "11"
storageProfile:
storageMB: 5120
sku:
tier: GeneralPurpose
capacity: 2
family: Gen5
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.storageProfile.storageMB"
transforms:
- type: math
math:
multiply: 1024
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- type: FromValue
name: port
value: "5432"
- name: firewallrule
base:
apiVersion: database.azure.crossplane.io/v1alpha3
kind: PostgreSQLServerFirewallRule
spec:
forProvider:
serverNameSelector:
matchControllerRef: true
resourceGroupNameSelector:
matchControllerRef: true
properties:
startIpAddress: 0.0.0.0
endIpAddress: 255.255.255.254

View File

@ -1,27 +0,0 @@
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-azure
annotations:
meta.crossplane.io/maintainer: Crossplane Maintainers <info@crossplane.io>
meta.crossplane.io/source: github.com/crossplane/crossplane
meta.crossplane.io/license: Apache-2.0
meta.crossplane.io/description: |
An introductory example to Crossplane and Composition for Azure.
meta.crossplane.io/readme: |
An introductory example to Crossplane and Composition for Azure.
This will enable provisioning of an Azure SQL database instance.
[Install &
Configure](https://crossplane.io/docs/master/getting-started/install-configure.html)
[Provision a PostgreSQL Azure SQL
Database](https://crossplane.io/docs/master/getting-started/provision-infrastructure.html)
guide: quickstart
provider: azure
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-azure
version: ">=v0.18.1"

View File

@ -1,40 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
description: "The OpenAPIV3Schema of this Composite Resource Definition."
properties:
parameters:
type: object
properties:
storageGB:
type: integer
description: "The desired storage capacity of the database, in GB."
required:
- storageGB
required:
- parameters

View File

@ -1,38 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
parameters:
type: object
properties:
storageGB:
type: integer
required:
- storageGB
required:
- parameters

View File

@ -1,47 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgresqlinstances.gcp.database.example.org
labels:
provider: gcp
guide: quickstart
spec:
writeConnectionSecretsToNamespace: crossplane-system
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: cloudsqlinstance
base:
apiVersion: database.gcp.crossplane.io/v1beta1
kind: CloudSQLInstance
spec:
forProvider:
databaseVersion: POSTGRES_12
region: us-central1
settings:
tier: db-custom-1-3840
dataDiskType: PD_SSD
ipConfiguration:
ipv4Enabled: true
authorizedNetworks:
- value: "0.0.0.0/0"
writeConnectionSecretToRef:
namespace: crossplane-system
patches:
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.writeConnectionSecretToRef.name"
transforms:
- type: string
string:
fmt: "%s-postgresql"
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.settings.dataDiskSizeGb"
connectionDetails:
- fromConnectionSecretKey: username
- fromConnectionSecretKey: password
- fromConnectionSecretKey: endpoint
- type: FromValue
name: port
value: "5432"

View File

@ -1,27 +0,0 @@
apiVersion: meta.pkg.crossplane.io/v1alpha1
kind: Configuration
metadata:
name: getting-started-with-gcp
annotations:
meta.crossplane.io/maintainer: Crossplane Maintainers <info@crossplane.io>
meta.crossplane.io/source: github.com/crossplane/crossplane
meta.crossplane.io/license: Apache-2.0
meta.crossplane.io/description: |
An introductory example to Crossplane and Composition for GCP.
meta.crossplane.io/readme: |
An introductory example to Crossplane and Composition for GCP.
This will enable provisioning of a Cloud SQL database instance.
[Install &
Configure](https://crossplane.io/docs/master/getting-started/install-configure.html)
[Provision a PostgreSQL Cloud SQL
Database](https://crossplane.io/docs/master/getting-started/provision-infrastructure.html)
guide: quickstart
provider: gcp
spec:
crossplane:
version: ">=v1.4.0-0"
dependsOn:
- provider: xpkg.upbound.io/crossplane-contrib/provider-gcp
version: ">=v0.20.0"

View File

@ -1,40 +0,0 @@
---
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
connectionSecretKeys:
- username
- password
- endpoint
- port
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
description: "The OpenAPIV3Schema of this Composite Resource Definition."
properties:
parameters:
type: object
properties:
storageGB:
type: integer
description: "The desired storage capacity of the database, in GB."
required:
- storageGB
required:
- parameters

View File

@ -1,16 +0,0 @@
apiVersion: database.aws.crossplane.io/v1beta1
kind: RDSInstance
metadata:
name: rdspostgresql
spec:
forProvider:
region: us-east-1
dbInstanceClass: db.t2.small
masterUsername: masteruser
allocatedStorage: 20
engine: postgres
engineVersion: "12"
skipFinalSnapshotBeforeDeletion: true
writeConnectionSecretToRef:
namespace: crossplane-system
name: aws-rdspostgresql-conn

View File

@ -1,28 +0,0 @@
apiVersion: azure.crossplane.io/v1alpha3
kind: ResourceGroup
metadata:
name: sqlserverpostgresql-rg
spec:
location: West US 2
---
apiVersion: database.azure.crossplane.io/v1beta1
kind: PostgreSQLServer
metadata:
name: sqlserverpostgresql
spec:
forProvider:
administratorLogin: myadmin
resourceGroupNameRef:
name: sqlserverpostgresql-rg
location: West US 2
sslEnforcement: Disabled
version: "11"
sku:
tier: GeneralPurpose
capacity: 2
family: Gen5
storageProfile:
storageMB: 20480
writeConnectionSecretToRef:
namespace: crossplane-system
name: sqlserverpostgresql-conn

View File

@ -1,15 +0,0 @@
apiVersion: database.gcp.crossplane.io/v1beta1
kind: CloudSQLInstance
metadata:
name: cloudsqlpostgresql
spec:
forProvider:
databaseVersion: POSTGRES_12
region: us-central1
settings:
tier: db-custom-1-3840
dataDiskType: PD_SSD
dataDiskSizeGb: 10
writeConnectionSecretToRef:
namespace: crossplane-system
name: cloudsqlpostgresql-conn

View File

@ -6,7 +6,7 @@
[[redirects]]
from = "/latest/*"
to = "/v1.11/:splat"
to = "/v1.12/:splat"
status = 302
[[redirects]]