docs/content/v1.11/getting-started/provider-aws-part-3.md

639 lines
18 KiB
Markdown

---
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 called `aws-credentials.txt` with your AWS keys
{{< editCode >}}
```ini {copy-lines="all"}
[default]
aws_access_key_id = $@<aws_access_key>$@
aws_secret_access_key = $@<aws_secret_key>$@
```
{{</ editCode >}}
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: dynamodb-with-bucket
spec:
compositeTypeRef:
apiVersion: custom-api.example.org/v1alpha1
kind: XDatabase
resources:
- name: s3-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: "us-east-2"
- name: dynamodb
base:
apiVersion: dynamodb.aws.upbound.io/v1beta1
kind: Table
spec:
forProvider:
region: "us-east-2"
writeCapacity: 1
readCapacity: 1
attribute:
- name: S3ID
type: S
hashKey: S3ID
EOF
```
7. Create a _composite resource definition_
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xdatabases.custom-api.example.org
spec:
group: custom-api.example.org
names:
kind: XDatabase
plural: xdatabases
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
region:
type: string
oneOf:
- pattern: '^EU$'
- pattern: '^US$'
required:
- region
claimNames:
kind: Database
plural: 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 example _composition_ has two _managed resources_, a
{{<hover label="compResources" line="8">}}bucket{{</hover>}} and a
{{<hover label="compResources" line="15">}}table{{</hover>}}.
```yaml {label="compResources"}
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
# Removed for Brevity
resources:
- name: s3-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: "us-east-2"
- name: dynamodb
base:
apiVersion: dynamodb.aws.upbound.io/v1beta1
kind: Table
spec:
forProvider:
region: "us-east-2"
writeCapacity: 1
readCapacity: 1
attribute:
- name: S3ID
type: S
hashKey: S3ID
```
<!-- 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: XDatabase
# 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: s3-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
spec:
forProvider:
region: "us-east-2"
patches:
- fromFieldPath: "region"
toFieldPath: "spec.forProvider.region"
transforms:
- type: map
map:
EU: "eu-north-1"
US: "us-east-2"
```
<!-- vale Google.We = NO -->
Patching is a powerful tool enabling simpler or abstracted APIs. A developer
isn't required to know the specific AWS region identifier, only the abstracted
option of "EU" or "US."
<!-- vale Google.We = YES -->
### Apply the updated composition
Apply the same `patch` to the `Table` _managed resource_ and apply the updated
_composition_.
```yaml
cat <<EOF | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: dynamodb-with-bucket
spec:
compositeTypeRef:
apiVersion: custom-api.example.org/v1alpha1
kind: XDatabase
resources:
- name: s3-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
kind: 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
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: Database
metadata:
name: claimed-eu-database
namespace: test
spec:
region: "EU"
EOF
```
View the _claim_ with `kubectl get claim`
```shell {copy-lines="1"}
kubectl get database -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 {copy-lines="1"}
kubectl describe table | grep arn:aws
Arn: arn:aws:dynamodb:eu-north-1:622343227358:table/claimed-eu-database-2sh9w-dhvw6
```
<!-- vale Google.We = NO -->
Using {{<hover label="claim" line="8" >}}region: "EU"{{</hover >}} patches the
_composite resource_, updating the AWS region from `us-east-2` to `eu-north-1`.
The developer creating the claim isn't required to know which specific AWS
region or the naming conventions. Using the abstract API options of "EU" or "US"
the developer places their resources in the desired location.
<!-- vale Google.We = YES -->
Deleting the claim removes the _managed resources_.
{{<hint "note" >}}
The _managed resources_ take up to 5 minutes to delete.
{{< /hint >}}
```shell
kubectl delete database claimed-eu-database -n test
```
## Create a Crossplane configuration package
Crossplane _configuration packages_ allow users to combine their _custom
resource definition_ and _composition_ files into an OCI image.
{{< hint "note" >}}
The [Open Container Initiative](https://opencontainers.org/faq/)
defines the OCI image standard.
An OCI images is a standard way to package data.
{{< /hint >}}
You can host configuration packages in image registries like
[Docker Hub](https://hub.docker.com/) or the
[Upbound Marketplace](https://marketplace.upbound.io/).
Crossplane can download and install configuration packages into a Kubernetes
cluster.
Creating a configuration package makes your Crossplane custom APIs portable
and versioned.
Building and installing configuration packages requires an OCI image compatible
tool.
{{< hint "note" >}}
You can use any software that builds OCI images. This includes
[Docker](https://www.docker.com/) or
[Upbound's Up CLI)](https://github.com/upbound/up).
{{< /hint >}}
A configuration package includes three files:
* `crossplane.yaml` defines the metadata of the package.
* `definition.yaml` is the _composite resource definition_ for the package.
* `composition.yaml` is the _composition_ template for the package.
<!-- vale gitlab.Substitutions = NO -->
<!-- yaml is in the filename -->
### Create a crossplane.yaml file
<!-- vale gitlab.Substitutions = YES -->
Configuration packages describe their contents and requirements with a
`crossplane.yaml` file.
The `crossplane.yaml` file lists the required Crossplane _providers_ and their
compatible versions as well as the required Crossplane version.
The Crossplane
{{<hover label="xpyaml" line="1" >}}meta.pkg{{</hover>}} API defines the schema
for a
{{<hover label="xpyaml" line="2" >}}Configuration{{</hover>}}.
Inside the {{<hover label="xpyaml" line="5" >}}spec{{</hover>}} define the
required Crossplane
{{<hover label="xpyaml" line="7" >}}version{{</hover>}}.
The {{<hover label="xpyaml" line="8" >}}dependsOn{{</hover>}} section lists the
dependencies for a package.
This package lists the Upbound
{{<hover label="xpyaml" line="9" >}}provider-aws{{</hover>}}
version {{<hover label="xpyaml" line="10" >}}0.27.0{{</hover>}} or later as a
dependency.
{{<hint "tip" >}}
Crossplane automatically installs dependencies. Dependencies can include other
configuration packages.
{{< /hint >}}
```yaml {label="xpyaml"}
apiVersion: meta.pkg.crossplane.io/v1
kind: Configuration
metadata:
name: crossplane-aws-quickstart
spec:
crossplane:
version: ">=v1.11.0"
dependsOn:
- provider: xpkg.upbound.io/upbound/provider-aws
version: ">=v0.27.0"
```
Create a new directory and save the `crossplane.yaml` file.
```yaml
mkdir crossplane-aws-quickstart
cat <<EOF > crossplane-aws-quickstart/crossplane.yaml
apiVersion: meta.pkg.crossplane.io/v1
kind: Configuration
metadata:
name: crossplane-aws-quickstart
spec:
crossplane:
version: ">=v1.11.0"
dependsOn:
- provider: xpkg.upbound.io/upbound/provider-aws
version: ">=v0.27.0"
EOF
```
<!-- vale gitlab.Substitutions = NO -->
<!-- yaml is in the filename -->
### Create a definition.yaml file
<!-- vale gitlab.Substitutions = YES -->
A configuration package requires a _composite resource definition_ (XRD) to define the
custom API.
Save the _XRD_ as `definition.yaml` in the same directory as the
`crossplane.yaml` file.
```yaml
cat <<EOF > crossplane-aws-quickstart/definition.yaml
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xdatabases.custom-api.example.org
spec:
group: custom-api.example.org
names:
kind: XDatabase
plural: xdatabases
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
region:
type: string
oneOf:
- pattern: '^EU$'
- pattern: '^US$'
required:
- region
claimNames:
kind: Database
plural: 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: dynamodb-with-bucket
spec:
compositeTypeRef:
apiVersion: custom-api.example.org/v1alpha1
kind: XDatabase
resources:
- name: s3-bucket
base:
apiVersion: s3.aws.upbound.io/v1beta1
kind: 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
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
wget "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh"
chmod +x install.sh
./install.sh
sudo mv crossplane /usr/local/bin
```
Verify the Crossplane command-line installed with `crossplane --help`
```shell
crossplane --help
Usage: 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 `crossplane` CLI to create an `.xpkg` file containing the
custom APIs and Crossplane configuration.
```shell
crossplane build configuration -f crossplane-aws-quickstart/ --name="crossplane-aws-quickstart"
```
Now an `.xpkg` OCI image is inside the `crossplane-aws-quickstart` directory.
```shell
ls crossplane-aws-quickstart/
composition.yaml crossplane-aws-quickstart.xpkg crossplane.yaml definition.yaml
```
## Next steps
* Explore AWS resources that Crossplane can configure in the [Provider CRD reference](https://marketplace.upbound.io/providers/upbound/provider-family-aws/).
* Join the [Crossplane Slack](https://slack.crossplane.io/) and connect with Crossplane users and contributors.
* Read more about [Crossplane concepts]({{<ref "../concepts" >}})