Skip to content

Commit

Permalink
Various fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
niallthomson committed Oct 28, 2024
1 parent feb87ce commit 5d41bfa
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Now we need to restart the carts Pods to pick up our new ConfigMap contents:
```bash
$ kubectl rollout restart -n carts deployment/carts
deployment.apps/carts restarted
$ kubectl rollout status -n carts deployment/carts --timeout=20s
$ kubectl rollout status -n carts deployment/carts --timeout=40s
Waiting for deployment "carts" rollout to finish: 1 old replicas are pending termination...
deployment "carts" successfully rolled out
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ title: "Claims"
sidebar_position: 20
---

Once weve configured Crossplane with the details of the new XR we can either create one directly or use a Claim. Typically only the team 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).
Once we've configured Crossplane with the details of the new XR, we can either create one directly or use a Claim. Typically, only the team responsible for configuring Crossplane (often a platform or SRE team) has permission to create XRs directly. Everyone else manages XRs via a lightweight proxy resource called a Composite Resource Claim (or claim for short).

With this claim the developer only needs to specify a default **DynamoDB table name, hash keys, global index name** to create the table. This allows the platform or SRE team to standardize on aspects such as billing mode, default read/write capacity, projection type, cost and infrastructure related tags.
With this claim, the developer only needs to specify a default **DynamoDB table name, hash keys, and global index name** to create the table. This allows the platform or SRE team to standardize aspects such as billing mode, default read/write capacity, projection type, and cost and infrastructure-related tags.

```file
manifests/modules/automation/controlplanes/crossplane/compositions/claim/claim.yaml
```

Cleanup the Dynamodb table created from the previous Managed Resource section.
Let's start by cleaning up the DynamoDB table created in the previous Managed Resource section:

```bash
$ kubectl delete tables.dynamodb.aws.upbound.io --all --ignore-not-found=true
$ kubectl wait --for=delete tables.dynamodb.aws.upbound.io --all --timeout=5m
```

Create the table by creating a `Claim`:
Now, we can re-create the table by creating a `Claim`:

```bash timeout=400
$ cat ~/environment/eks-workshop/modules/automation/controlplanes/crossplane/compositions/claim/claim.yaml \
Expand All @@ -28,19 +28,19 @@ $ kubectl wait dynamodbtables.awsblueprints.io ${EKS_CLUSTER_NAME}-carts-crosspl
--for=condition=Ready --timeout=5m
```

It takes some time to provision the AWS managed services, in the case of DynamoDB up to 2 minutes. Crossplane will report the status of the reconciliation in the `SYNCED` field of the Kubernetes Composite and Managed resource.
It takes some time to provision AWS managed services, in the case of DynamoDB up to 2 minutes. Crossplane will report the status of the reconciliation in the `SYNCED` field of the Kubernetes Composite and Managed resource.

```bash
$ kubectl get table
NAME READY SYNCED EXTERNAL-NAME AGE
eks-workshop-carts-crossplane-bt28w-lnb4r True True eks-workshop-carts-crossplane 6s
```

Now, lets try to understand how the DynamoDB table is deployed using this claim:
Now, let's understand how the DynamoDB table is deployed using this claim:

![Crossplane reconciler concept](../assets/ddb-claim-architecture.webp)

On querying the claim `DynamoDBTable` deployed in the carts namespace, we can observe that it points to and creates a Composite Resource (XR) `XDynamoDBTable`
When querying the claim `DynamoDBTable` deployed in the carts namespace, we can observe that it points to and creates a Composite Resource (XR) `XDynamoDBTable`:

```bash
$ kubectl get DynamoDBTable -n carts -o yaml | grep "resourceRef:" -A 3
Expand All @@ -51,15 +51,15 @@ $ kubectl get DynamoDBTable -n carts -o yaml | grep "resourceRef:" -A 3
name: eks-workshop-carts-crossplane-bt28w
```

The Composition `table.dynamodb.awsblueprints.io` shows Composite Resource Kind (XR-KIND) as `XDynamoDBTable`. This Composition lets Crossplane know what to do when we created the `XDynamoDBTable` XR. Each Composition creates a link between an XR and a set of one or more Managed Resources.
The Composition `table.dynamodb.awsblueprints.io` shows Composite Resource Kind (XR-KIND) as `XDynamoDBTable`. This Composition informs Crossplane what to do when we create the `XDynamoDBTable` XR. Each Composition creates a link between an XR and a set of one or more Managed Resources.

```bash
$ kubectl get composition
NAME XR-KIND XR-APIVERSION AGE
table.dynamodb.awsblueprints.io XDynamoDBTable awsblueprints.io/v1alpha1 143m
```

On querying the `XDynamoDBTable` XR which is not confined to any namespace, we can observe that it creates DynamoDB Managed Resource `Table`.
When querying the `XDynamoDBTable` XR, which is not confined to any namespace, we can observe that it creates a DynamoDB managed resource `Table`:

```bash
$ kubectl get XDynamoDBTable -o yaml | grep "resourceRefs:" -A 3
Expand All @@ -69,58 +69,3 @@ $ kubectl get XDynamoDBTable -o yaml | grep "resourceRefs:" -A 3
kind: Table
name: eks-workshop-carts-crossplane-bt28w-lnb4r
```

---

When new resources are created or updated, application configurations also need to be updated to use these new resources. We've already configured the workload to use the correct table name in the previous section so lets just restart the pods:

```bash
$ kubectl rollout restart -n carts deployment/carts
$ kubectl rollout status -n carts deployment/carts --timeout=2m
deployment "carts" successfully rolled out
```

---

Now, how do we know that the application is working with the new DynamoDB table?

An NLB has been created to expose the sample application for testing, allowing us to directly interact with the application through the browser:

```bash
$ kubectl get service -n ui ui-nlb -o jsonpath="{.status.loadBalancer.ingress[*].hostname}{'\n'}"
k8s-ui-uinlb-a9797f0f61.elb.us-west-2.amazonaws.com
```

:::info
Please note that the actual endpoint will be different when you run this command as a new Network Load Balancer endpoint will be provisioned.
:::

To wait until the load balancer has finished provisioning you can run this command:

```bash timeout=610
$ wait-for-lb $(kubectl get service -n ui ui-nlb -o jsonpath="{.status.loadBalancer.ingress[*].hostname}{'\n'}")
```

Once the load balancer is provisioned you can access it by pasting the URL in your web browser. You will see the UI from the web store displayed and will be able to navigate around the site as a user.

<Browser url="http://k8s-ui-uinlb-a9797f0f61.elb.us-west-2.amazonaws.com">
<img src={require('@site/static/img/sample-app-screens/home.webp').default}/>
</Browser>

To verify that the **Carts** module is in fact using the DynamoDB table we just provisioned, try adding a few items to the cart.

![Cart screenshot](../assets/cart-items-present.webp)

And to check if items are in the DynamoDB table as well, run

```bash
$ aws dynamodb scan --table-name "${EKS_CLUSTER_NAME}-carts-crossplane" --query 'Items[].{itemId:itemId,Price:unitPrice}' --output text
PRICE 795
ITEMID 510a0d7e-8e83-4193-b483-e27e09ddc34d
PRICE 385
ITEMID 6d62d909-f957-430e-8689-b5129c0bb75e
PRICE 50
ITEMID a0a4f044-b040-410d-8ead-4de0446aec7e
```

Congratulations! You've successfully created AWS Resources without leaving the confines of the Kubernetes API!
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ title: "Creating a Composition"
sidebar_position: 10
---

A `CompositeResourceDefinition` (or XRD) defines the type and schema of your Composite Resource (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"](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/).
A `CompositeResourceDefinition` (XRD) defines the type and schema of your Composite Resource (XR). It informs Crossplane about the desired XR and its fields. An XRD is similar to a CustomResourceDefinition (CRD) but with a more opinionated structure. Creating an XRD primarily involves specifying an OpenAPI ["structural schema"](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/).

First, lets provide a definition that can be used to create a DynamoDB table by members of the application team in their corresponding namespace. In this example the user only needs to specify **name**, **key attributes** and **index name** fields.
Let's start by providing a definition that allows application team members to create a DynamoDB table in their respective namespaces. In this example, users only need to specify the **name**, **key attributes**, and **index name** fields.

```file
manifests/modules/automation/controlplanes/crossplane/compositions/composition/definition.yaml
```

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.
A Composition informs Crossplane about the actions to take when a Composite Resource is created. Each Composition establishes a link between an XR and a set of one or more Managed Resources. When the XR is created, updated, or deleted, the associated Managed Resources are correspondingly created, updated, or deleted.

The following Composition provisions the managed resources `Table`
The following Composition provisions the managed resource `Table`:

```file
manifests/modules/automation/controlplanes/crossplane/compositions/composition/table.yaml
```

Apply this to our EKS cluster:
Let's apply this configuration to our EKS cluster:

```bash
$ kubectl apply -k ~/environment/eks-workshop/modules/automation/controlplanes/crossplane/compositions/composition
compositeresourcedefinition.apiextensions.crossplane.io/xdynamodbtables.awsblueprints.io created
composition.apiextensions.crossplane.io/table.dynamodb.awsblueprints.io created
```

With these resources in place, we've successfully set up a Crossplane Composition for creating DynamoDB tables. This abstraction allows application developers to provision standardized DynamoDB tables without needing to understand the underlying AWS-specific details.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@ title: "Compositions"
sidebar_position: 30
---

In addition to provisioning individual cloud resources, Crossplane offers a higher abstraction layer called Compositions. Compositions allow users to build opinionated templates for deploying cloud resources. For example, organizations may require certain tags to be present to all AWS resources or add specific encryption keys for all Amazon Simple Storage (S3) buckets. Platform teams can define these self-service API abstractions within Compositions and ensure that all the resources created through these Compositions meet the organization’s requirements.
In addition to provisioning individual cloud resources, Crossplane offers a higher level of abstraction called Compositions. Compositions enable users to create opinionated templates for deploying cloud resources. This feature is particularly useful for organizations that need to enforce specific requirements across their infrastructure, such as:

In this section of the lab we'll see how to package our DynamoDB table as a Crossplane Composition for easier consumption by development teams.
- Ensuring all AWS resources have certain tags
- Applying specific encryption keys to all Amazon Simple Storage Service (S3) buckets
- Standardizing resource configurations across the organization

With Compositions, platform teams can define self-service API abstractions that guarantee all resources created through these templates meet the organization's requirements. This approach simplifies resource management and ensures consistency across deployments.

In this section of the lab, we'll explore how to package our Amazon DynamoDB table as a Crossplane Composition. This will demonstrate how to create a more easily consumable resource for development teams, while maintaining control over the underlying configuration.

By leveraging Compositions, we'll see how to:

1. Define a standardized template for DynamoDB tables
2. Simplify the resource creation process for developers
3. Ensure compliance with organizational policies and best practices

Through this exercise, you'll gain hands-on experience with Crossplane Compositions and understand their benefits in managing cloud resources within a Kubernetes environment.
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,43 @@ title: "Testing the application"
sidebar_position: 40
---

We've already configured the workload to use the correct table name in the previous section so lets just restart the pods:
Now that we've provisioned our DynamoDB table using Crossplane Compositions, let's test the application to ensure it's working correctly with the new table.

First, we need to restart the pods to ensure they're using the updated configuration:

```bash
$ kubectl rollout restart -n carts deployment/carts
$ kubectl rollout status -n carts deployment/carts --timeout=2m
deployment "carts" successfully rolled out
```

The load balancer used to access the application will be the same as the last section:
To access the application, we'll use the same load balancer as in the previous section. Let's retrieve its hostname:

```bash
$ LB_HOSTNAME=$(kubectl -n ui get service ui-nlb -o jsonpath='{.status.loadBalancer.ingress[*].hostname}{"\n"}')
$ echo "http://$LB_HOSTNAME"
http://k8s-ui-uinlb-647e781087-6717c5049aa96bd9.elb.us-west-2.amazonaws.com
```

Access it by pasting the URL in your web browser. You will see the UI from the web store displayed and will be able to navigate around the site as a user.
You can now access the application by copying this URL into your web browser. You'll see the web store's user interface, allowing you to navigate the site as a user would.

<Browser url="http://k8s-ui-uinlb-a9797f0f61.elb.us-west-2.amazonaws.com">
<img src={require('@site/static/img/sample-app-screens/home.webp').default}/>
</Browser>

To verify that the **Carts** module is in fact using the DynamoDB table we just provisioned, try adding a few items to the cart.
To verify that the **Carts** module is indeed using the newly provisioned DynamoDB table, follow these steps:

1. Add a few items to your cart in the web interface.
2. Observe that the items appear in your cart, as shown in the screenshot below:

![Cart screenshot](../assets/cart-items-present.webp)
![Cart screenshot showing added items](../assets/cart-items-present.webp)

And to check if items are in the DynamoDB table as well, run:
To confirm that these items are being stored in the DynamoDB table, run the following command:

```bash
$ aws dynamodb scan --table-name "${EKS_CLUSTER_NAME}-carts-crossplane"
```

We've now successfully created AWS resources using Crossplane Compositions!
This command will display the contents of the DynamoDB table, which should include the items you've added to your cart.

Congratulations! You've successfully created AWS resources using Crossplane Compositions and verified that your application is working correctly with these resources. This demonstrates the power of using Crossplane to manage cloud resources directly from your Kubernetes cluster.
Loading

0 comments on commit 5d41bfa

Please sign in to comment.