DEV Community

Cover image for Deploy AWS Resources using Crossplane on Kubernetes
Arthur Azrieli for MeteorOps

Posted on • Originally published at meteorops.com

Deploy AWS Resources using Crossplane on Kubernetes

In this article we will be talking about Crossplane as an Infrastructure as Code (IaC) tool that is running on Kubernetes, why should we use it and how you configure AWS provider to start creating resources, we will be going through a full step by step example for you to be able to create your first resource with Crossplane

Who is this article for?

  • DevOps engineers interested in learning another IaC tool
  • Developers that want to take more Ops responsibility and provision their own infrastructure
  • Engineering managers that are looking to implement an IaC tool in their company/startup

Why am I writing this?

I had some discussions with engineers that had some trouble to get started with Crossplane, it may be a little less straightforward than a well established tool like Terraform, some documentation isn’t precise for different use cases and providers and even ChatGPT’s code doesn’t seem to work at times. And here I am saving the day to make your life easier by giving you a step by step guide where you install and configure everything and deploy your first AWS resource using Crossplane.

Why should you even use Crossplane then?

There are certain use cases where Crossplane provides very powerful capabilities being able to create both applications and cloud resources, those can be used for ephemeral environments for example or for having a SaaS company provide full environments that could be self created by a tenant. Those environments could be created by just applying a Kubernetes manifest which is much simpler than starting to run traditional IaC plan and apply commands.

How this article works

Prerequisites

1. Clone the repository and step into it

git clone https://github.com/MeteorOps/crossplane-aws-provider-bootstrap.git cd crossplane-aws-provider-bootstrap
Enter fullscreen mode Exit fullscreen mode

2. Make sure you have the required CLIs:

  1. Install the AWS CLI & Authenticate it with your AWS Account
  2. Install the Kubectl CLI
  3. Install the Helm CLI
  4. An existing Kubernetes cluster (we’ll be using kind)

Optional: Start a local kind cluster

brew install kind

kind create cluster

open /Applications/Docker.app

kubectl cluster-info --context kind-kind
Enter fullscreen mode Exit fullscreen mode

Repository Overview

Link to the Github Repository: https://github.com/MeteorOps/crossplane-aws-provider-bootstrap.git

  1. creds file‍ AWS credentials - should be filled with your own AWS credentials
  2. crossplane-provider-conf file ‍Uses the creds file to create a Crossplane ProviderConfig (separated into a different file because it takes time for this resource to be ready)
  3. crossplane-provider-bootstrap file ‍Creates the Crossplane AWS Provider, which enables creating AWS resources using Crossplane (and its dependencies):ServiceAccount, DeploymentRuntimeConfig, Provider, ClusterRole & ClusterRoleBindings
  4. bucket-definitions & bucket-crd files ‍The Kubernetes Crossplane manifests that create a CompositeResourceDefinition and a Composition resource, which together define how to create a S3 Bucket (like a Terraform Module would). Note: The ‘Composition’ resource relies on the ‘CompositeResourceDefinition’.
  5. bucket-example file ‍The Kubernetes Crossplane manifest we’ll apply at the end to create a S3 bucket using Crossplane

Deploy Crossplane

1. Fill the creds file with your AWS access keys
Get your AWS IAM User (not an SSO user as it requires a token to work) access keys and fill them in the credentials file

  • NOTE: for production usage, please create a Crossplane IAM user and use its access keys, or preferably use something like IRSA

2. Deploy the Crossplane Helm Chart
Add the Helm repository from which the Crossplane Helm Charts will be fetched

helm repo add crossplane-stable https://charts.crossplane.io/stable
Enter fullscreen mode Exit fullscreen mode

Deploy Crossplane on your Kubernetes cluster in a new namespace named crossplane-system

helm install crossplane crossplane-stable/crossplane --namespace crossplane-system --create-namespace
Enter fullscreen mode Exit fullscreen mode

3. Examine your Crossplane Deployment

  • Run the following command to get Crossplane's pods:

    kubectl get pods -n crossplane-system

Then, you should see 2 pods: crossplane & crossplane-rbac-manager

Image description

4. Provide Crossplane AWS access by creating a Kubernetes Secret
Insert your AWS credentials to the creds file and run the following from the same folder:

kubectl create secret generic aws-credentials -n crossplane-system --from-file=creds=./creds
Enter fullscreen mode Exit fullscreen mode

Make sure the secret was created as expected:

  • Run the following command:

    kubectl get secret aws-credentials -n crossplane-system

You should see the aws-credentials secret:

Image description

5. Deploy the Crossplane AWS Provider
‍Creating a Crossplane AWS Provider requires creating a bunch of resources: ServiceAccount, DeploymentRuntimeConfig, Provider, ClusterRole & ClusterRoleBindings, and ProviderConfig
We divided the resources creation into 2 phases:

1 - crossplane-provider-bootstrap.yaml:
ServiceAccount, DeploymentRuntimeConfig, Provider, ClusterRole & ClusterRoleBindings

2- crossplane-provider-conf.yaml:
ProviderConfig

The reason for dividing it into 2 phases is that the creation of the ProviderConfig fails if we attempt to create it before the first set of Provider resources and dependencies is ready

Create the Provider Kubernetes resources using the bootstrap YAML file:

  • Run the following command:

    kubectl apply -f crossplane-provider-bootstrap.yaml

Validate the creation readiness of the Provider & wait for it to be ready:

  • Run the following command to see the AWS Provider resource:

    kubectl get provider

You should see something like this:

Image description

It might take 1-2 minutes to become Healthy.

Create the ProviderConfig resource & Validate its creation:

  • Run the following command:

    kubectl apply -f crossplane-provider-conf.yaml && kubectl get providerconfig

Image description

Create a S3 Bucket using Crossplane

Create the CompositeResourceDefinition to define a S3 Bucket:

  • Run the following command:

    kubectl apply -f bucket-definitions.yaml

Image description

Create the Composition to define a S3 Bucket:

  • Run the following command:

    kubectl apply -f bucket-crd.yaml

Image description

Create the S3 Bucket Crossplane resource in Kubernetes:

kubectl apply -f bucket-example.yaml
Enter fullscreen mode Exit fullscreen mode

When we installed the AWS Provider, it was installed with some Crossplane CRDs of the AWS Provider.
One of those CRDs is ‘bucket’.

Now we can check if the bucket was created by running kubectl get bucket against our Kubernetes cluster

Image description

Check if the S3 Bucket was created in AWS:

  • ‍List you AWS S3 buckets and search for the newly created one:

    aws s3 ls

Image description

Teardown & Cleanup

We’ll start by deleting the S3 Bucket Crossplane resource in Kubernetes, which will end up deleting the resource in AWS.
Eventually, if we used kind to spin up a local Kubernetes cluster, we’ll terminate the cluster to keep our workstation nice and clean.

Delete the S3 Bucket resource:

kubectl delete -f bucket-example.yaml
Enter fullscreen mode Exit fullscreen mode

If used kind delete the cluster:

kind delete cluster
Enter fullscreen mode Exit fullscreen mode

Useful Debugging Commands

kubectl get provider


kubectl logs -n crossplane-system deploy/crossplane -c crossplane


kubectl logs -n crossplane-system -l pkg.crossplane.io/provider=provider-aws
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
whimsicalbison profile image
Jack

Thank you for writing this article. I work with Kubernetes and Terraform daily to manage AWS resources, but they remain fairly separate in my workflow. Crossplane caught my interest as a way to bridge this gap, allowing more direct interaction between Kubernetes and AWS, rather than having to update Terraform whenever Kubernetes resources change. I really appreciate the repository and the clear instructions for getting everything up and running in your article.

One thing that stood out to me as a potential concern was the use of Kubernetes secrets to store an IAM user's access keys. A more secure approach would be to create a service account tied to an IAM role. However, I understand the challenges involved in setting up such a solution, particularly when dealing with a "chicken and egg" scenario. I assume this method was used for the sake of simplicity in the article. It might be helpful to note that this isn’t the ideal long-term solution and to reference more secure alternatives for handling authentication even if they're not fully detailed.

While I felt like I was beginning to grasp Crossplane, this article made me realize how much I still have to learn and clarified some misconceptions I had. I guess it’s time to dive deeper and fully immerse myself in it!

Collapse
 
michaelzion profile image
Michael Zion

awesome article @arthurazr_46 !