Crossplane Deployment: Multicloud Control Plane

Suraj Solanki
6 min readOct 15, 2024

--

Managing infrastructure across multiple cloud providers has become more challenging and complex in the rapidly evolving cloud-native ecosystem. As organizations adopt multi-cloud strategies, the overhead of managing infrastructure across platforms like AWS, Azure, and Google Cloud increases. This is where Crossplane steps in.

In this blog, we will discuss how Crossplane works, its key benefits, and a step-by-step guide to deploying Crossplane and using it to manage cloud infrastructure across multiple providers.

What is Crossplane?

Crossplane was designed to bridge the gap between traditional Infrastructure as Code (IaC) tools and Kubernetes. While tools like Terraform and CloudFormation are powerful, they operate outside the Kubernetes ecosystem. Crossplane brings infrastructure management into Kubernetes, allowing for a unified approach to managing both applications and infrastructure.

It extends Kubernetes by introducing Custom Resource Definitions (CRDs) that represent cloud infrastructure resources such as storage, databases, virtual machines, and more. These CRDs can represent resources from any cloud provider — AWS, Azure, Google Cloud, etc. — making Crossplane a truly multi-cloud control plane. You define what you need in YAML files, and Kubernetes, through Crossplane, ensures that your desired cloud infrastructure state is achieved and maintained.

Key Features of Crossplane:

  1. Unified API for Cloud Resources: Crossplane integrates cloud resources into Kubernetes using CRDs. This means you can manage cloud infrastructure alongside Kubernetes workloads using a single API.
  2. Multi-Cloud Management: Crossplane supports multiple cloud providers like AWS, Azure, and Google Cloud. You can use the same API to manage resources across different cloud platforms.
  3. Declarative Infrastructure Management: Like Kubernetes resources, Crossplane allows you to define your desired infrastructure state declaratively. Once defined, Crossplane continuously reconciles your infrastructure to match this state.
  4. Composable Infrastructure: Crossplane lets you bundle multiple cloud resources together into higher-level abstractions, called Compositions and Composite Resources (XRs), allowing for reusable and simplified infrastructure components.
  5. Kubernetes-Native GitOps: Crossplane works well with GitOps practices, enabling teams to manage cloud infrastructure in the same way they manage Kubernetes workloads: declaratively and with continuous reconciliation.
  6. Community and Ecosystem: Being an open-source project, Crossplane has a growing community and a rich ecosystem of providers and compositions that you can leverage.

Why Use Crossplane?

Crossplane significantly reduces the operational overhead of managing infrastructure across multiple cloud providers by centralizing all operations within the Kubernetes control plane. Here are the key benefits:

  • No need to switch between tools: With Crossplane, you don’t need to use separate tools or dashboards for each cloud provider. Kubernetes becomes your universal control plane for both applications and infrastructure.
  • No manual intervention: Crossplane’s continuous reconciliation ensures that the actual state of cloud resources matches the desired state, minimizing the need for manual checks and interventions.
  • Simplified multi-cloud management: Crossplane allows you to manage cloud infrastructure and applications from a single platform — Kubernetes — across AWS, Azure, Google Cloud, and more.

Installation: Setting Up Crossplane

In this section, we will walk through the steps to install Crossplane and connect it to a cloud provider (in this case, Azure) to manage resources like storage accounts and resource groups.

1. Install Crossplane on Kubernetes

The first step is to install the Crossplane core on your Kubernetes cluster. You can do this using Helm or by applying the official manifests.

kubectl create namespace crossplane-system
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm install crossplane --namespace crossplane-system crossplane-stable/crossplane

This installs the Crossplane controller in your Kubernetes cluster, enabling it to manage cloud resources.

Note: In addition to using the Helm commands to deploy Crossplane, many organizations now prefer automating the deployment and management of Crossplane components and resources using GitOps tools.

2. Install a Cloud Provider (Azure Provider)

To manage Azure resources, you need to install the Azure provider for Crossplane. Providers in Crossplane are essentially extensions that allow Crossplane to communicate with cloud providers and manage their resources.

apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: upbound-provider-azure
spec:
package: xpkg.upbound.io/upbound/provider-azure:v0.32.0



$kubectl apply -f provider-azure.yaml

3. Configure Provider Credentials

You will need to configure credentials to allow Crossplane to interact with your Azure account. Here’s how you can configure Azure credentials:

apiVersion: azure.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: azure-credentials
key: credentials

To create the secret for your Azure credentials, follow these steps:

  1. Generate a service principal and authentication file:
az ad sp create-for-rbac --sdk-auth --role Owner --scopes /subscriptions/<sub-id>

2. Save the Azure JSON output as azure-credentials.json.

3. Create a Kubernetes secret with the Azure credentials:

kubectl create secret generic azure-credentials --namespace crossplane-system --from-file=credentials=./azure-credentials.json

4. Create a Storage Account and Container Using Crossplane

Once the provider is configured, you can start defining cloud resources. Here’s how to define a Resource Group, Storage Account, and Storage Container in Azure using Crossplane:

# Resource Group
apiVersion: azure.crossplane.io/v1alpha3
kind: ResourceGroup
metadata:
name: rg-crossplane
spec:
location: eastus
---

# Storage Account
apiVersion: storage.azure.crossplane.io/v1alpha3
kind: Account
metadata:
name: crossplane-storage-account
spec:
resourceGroupName: rg-crossplane
storageAccountSpec:
kind: Storage
location: eastus
sku:
name: Standard_LRS
writeConnectionSecretToRef:
namespace: default
name: storageaccount-connection-secret
---

# Storage Container
apiVersion: storage.azure.crossplane.io/v1alpha3
kind: Container
metadata:
name: blob-container
spec:
writeConnectionSecretToRef:
name: blob-container
namespace: crossplane
providerConfigRef:
name: default


kubectl apply -f managed_resources.yaml

Advanced Resource Management

we will explore advanced resource management techniques with Crossplane. This includes composing resources, using Crossplane compositions, and implementing custom resources.

5. Why Use CRD/Composition?

Imagine a scenario where a developer is using Kubernetes to test an application. They need a storage container and ask the platform team to create it and provide the necessary connection details. Instead of managing this request manually, Crossplane’s Custom Resource Definitions (CRDs), Compositions, and Claims come into play, automating the process.

Composite Resource Definition (XRD)

A Composite Resource Definition (XRD) is a schema that defines a composite resource. A composite resource in Crossplane aggregates multiple underlying cloud resources (e.g., Storage Accounts, Resource Groups) into a single, unified API object. It defines how claims are fulfilled and what parameters the composite resource will expose.

For example, We use an XRD to create a composite resource representing an Azure Storage Account. The composite resource can include a storage account and a container grouped as a Kubernetes object.

apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xazurestorageaccounts.azure.org.io >> you can modify it
spec:
claimNames:
kind: AzureStorageAccount
plural: azurestorageaccounts
connectionSecretKeys:
- azure_storage_connection_string
group: azure.org.io
names:
kind: XAzureStorageAccount
plural: xazurestorageaccounts
versions:
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
properties:
spec:
properties:
parameters:
properties:
storage_account_name:
type: string
container_name:
type: string
required:
- storage_account_name
- container_name
type: object
type: object
required:
- parameters

Composition

A Composition in Crossplane defines how to map composite resources to actual managed resources (e.g., Azure Storage Accounts, Resource Groups). It specifies the underlying cloud resources that need to be created and how data from the composite resource is used to configure them.

the composition for a Storage Account includes resources like: resource group, storage account and storage container

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: composition-storageaccount
spec:
writeConnectionSecretsToNamespace: crossplane
patchSets:
- name: metadata
patches:
- fromFieldPath: metadata.labels
compositeTypeRef:
apiVersion: azure.org.io/v1alpha1
kind: XAzureStorageAccount
resources:
- name: resourcegroup
base:
apiVersion: azure.upbound.io/v1beta1
kind: ResourceGroup
metadata:
labels:
key: crossplane
spec:
forProvider:
location: westus3
tags:
provisioner: crossplane
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.container_name
toFieldPath: metadata.annotations[crossplane.io/external-name]

- name: storageaccount
base:
apiVersion: storage.azure.upbound.io/v1beta1
kind: Account
metadata:
labels:
sm: storageaccount
spec:
forProvider:
accountReplicationType: LRS
accountTier: Standard
location: westus3
resourceGroupNameSelector:
matchControllerRef: true
tags:
provisioner: crossplane
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.storage_account_name
toFieldPath: spec.writeConnectionSecretToRef.name
- type: FromCompositeFieldPath
fromFieldPath: spec.claimRef.namespace
toFieldPath: spec.writeConnectionSecretToRef.namespace
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.storage_account_name
toFieldPath: metadata.annotations[crossplane.io/external-name]
connectionDetails:
- name: azure_storage_connection_string
fromConnectionSecretKey: attribute.primary_connection_string

- name: containername
base:
apiVersion: storage.azure.upbound.io/v1beta1
kind: Container
metadata:
spec:
forProvider:
containerAccessType: private
storageAccountNameSelector:
matchControllerRef: true
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.container_name
toFieldPath: metadata.annotations[crossplane.io/external-name]

Note: You can update the existing composition to add more resources or modify existing ones

Claim

Claims are abstractions that represent a higher-level API for end-users (developers) to request infrastructure. The claim hides the complexity of underlying infrastructure resources by enabling users to interact with simple and Kubernetes-native Custom Resource Definitions (CRDs).

A claim binds to a composite resource, which then provisions the underlying infrastructure.

The claim is used to create Azure resources like Storage Accounts and Storage Containers. Below is an example of a claim used to request an Azure Storage Account.

apiVersion: azure.org.io/v1alpha1
kind: XAzureStorageAccount
metadata:
name: storage-environment-test
spec:
compositionRef:
name: azure-storage-account-composition
parameters:
container_name: storage-container-name
storage_account_name: storage-account-name

$kubectl apply -f claim.yaml

This will create a storage account and container in Azure using Crossplane’s control plane.

Conclusion

Crossplane makes it easy to manage cloud resources like AWS, Azure, and Google Cloud using the same Kubernetes tools you’re already familiar with. By combining application and infrastructure management in one place (Kubernetes), Crossplane saves you time and effort by eliminating the need for separate tools for different cloud providers.

I hope that you find this article and my experience helpful, and thanks for taking the time to read my article.

If you have any questions or feedback, feel free to comment.

About The Author
Suraj Solanki
Senior DevOps Engineer
LinkedIn: https://www.linkedin.com/in/suraj-solanki
Topmate: https://topmate.io/suraj_solanki

--

--

Suraj Solanki
Suraj Solanki

Written by Suraj Solanki

Senior DevOps Engineer | Enthusiast of cloud & automation | Always learning & sharing insights | Connect me on https://www.linkedin.com/in/suraj-solanki

Responses (1)